#![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 })
}