wardriving-driver 0.1.0

HackXPansion driver for war driving module
#![no_std]

use xpanse_api::{
    bus::allocator::BusAllocator,
    driver::{Driver, DriverError, DriverMeta},
    gpio_bank::{BankPins, GpioBank},
    metadata::{ModuleDetectResistor, ModuleID, ModuleSlot},
    registry::Registry,
};

use embedded_io_async::Read;
use heapless::String;


#[derive(Clone)]
pub struct ScanResult {
    pub ssid: String<32>,
    pub bssid: [u8; 6],
    pub rssi: i8,
    pub channel: u8,
    pub lat: Option<f32>,
    pub lon: Option<f32>,
}

pub struct WarDrivingHandle {
    uart: xpanse_api::bus::uart::UartBusHandle,
}

impl WarDrivingHandle {
    pub async fn next_scan(&mut self) -> Option<ScanResult> {
        let mut line_buf = [0u8; 96];
        let mut len = 0usize;

        loop {
            let mut byte = [0u8; 1];
            self.uart.read(&mut byte).await.ok()?;

            if byte[0] == b'\n' {
                return parse_line(&line_buf[..len]);
            }

            if len < line_buf.len() {
                line_buf[len] = byte[0];
                len += 1;
            }
        }
    }
}



pub struct WarDrivingDriver;

impl DriverMeta for WarDrivingDriver {
    const ID: ModuleID = ModuleID {
        md0: ModuleDetectResistor::R1K,
        md1: ModuleDetectResistor::R10K,
    };
}

impl<G: BankPins> Driver<G> for WarDrivingDriver {
    async fn create(
        gpio_bank: GpioBank<G>,
        slot: ModuleSlot,
        registry: &mut Registry,
        bus_allocator: &mut BusAllocator,
    ) -> Result<(), DriverError> {
        let uart = bus_allocator
            .create_uart_no_hardware(gpio_bank.gpio5, gpio_bank.gpio6, 115_200)
            .map_err(|_| DriverError::InitFailed)?;

        registry.register(slot, WarDrivingDriver::ID, WarDrivingHandle { uart });

        Ok(())
    }
}

fn parse_line(line: &[u8]) -> Option<ScanResult> {
    let text = core::str::from_utf8(line).ok()?;
    let mut fields = text.trim_end_matches('\r').split(',');

    let ssid_str = fields.next()?;
    let bssid_str = fields.next()?;
    let rssi_str = fields.next()?;
    let channel_str = fields.next()?;
    let lat_str = fields.next()?;
    let lon_str = fields.next()?;

    let mut ssid: String<32> = String::new();
    let _ = ssid.push_str(ssid_str);

    let mut bssid = [0u8; 6];
    for (i, part) in bssid_str.split(':').enumerate().take(6) {
        bssid[i] = u8::from_str_radix(part, 16).ok()?;
    }

    let rssi: i8 = rssi_str.parse().ok()?;
    let channel: u8 = channel_str.parse().ok()?;
    let lat = lat_str.parse::<f32>().ok();
    let lon = lon_str.parse::<f32>().ok();

    Some(ScanResult { ssid, bssid, rssi, channel, lat, lon })
}