#[allow(dead_code)]
use super::{codec, ids, Err};
use generic_array::{ArrayLength, GenericArray};
use heapless::{
consts::{U18, U64},
String,
};
use nom::{
bytes::streaming::take, lib::std::ops::RangeFrom, lib::std::ops::RangeTo, number::streaming,
InputIter, InputLength, Slice,
};
pub struct GetMacAddress {}
impl super::RPC for GetMacAddress {
type ReturnValue = String<U18>;
type Error = i32;
fn header(&self, seq: u32) -> codec::Header {
codec::Header {
sequence: seq,
msg_type: ids::MsgType::Invocation,
service: ids::Service::Wifi,
request: ids::WifiRequest::GetMacAddress.into(),
}
}
fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
let (data, hdr) = codec::Header::parse(data)?;
if hdr.msg_type != ids::MsgType::Reply
|| hdr.service != ids::Service::Wifi
|| hdr.request != ids::WifiRequest::GetMacAddress.into()
{
return Err(Err::NotOurs);
}
if data.input_len() < 18 {
return Err(Err::RPCErr(-1));
}
let mut mac: String<U18> = String::new();
for b in data.slice(RangeTo { end: 17 }).iter_elements() {
mac.push(b as char).map_err(|_| Err::ResponseOverrun)?;
}
let (_, result) = streaming::le_u32(data.slice(RangeFrom { start: 18 }))?;
if result != 0 {
Err(Err::RPCErr(result as i32))
} else {
Ok(mac)
}
}
}
pub struct IsScanning {}
impl super::RPC for IsScanning {
type ReturnValue = bool;
type Error = ();
fn header(&self, seq: u32) -> codec::Header {
codec::Header {
sequence: seq,
msg_type: ids::MsgType::Invocation,
service: ids::Service::Wifi,
request: ids::WifiRequest::IsScanning.into(),
}
}
fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
let (data, hdr) = codec::Header::parse(data)?;
if hdr.msg_type != ids::MsgType::Reply
|| hdr.service != ids::Service::Wifi
|| hdr.request != ids::WifiRequest::IsScanning.into()
{
return Err(Err::NotOurs);
}
if data.input_len() < 1 {
return Err(Err::RPCErr(()));
}
Ok(data.iter_elements().nth(0) != Some(0))
}
}
#[derive(Copy, Clone)]
pub struct ScanResult {
pub ssid: super::SSID,
pub bssid: super::BSSID,
pub rssi: i16,
pub bss_type: super::BssType,
pub security: super::Security,
pub wps: super::WPS,
pub chan: u32,
pub band: super::Band,
}
impl core::fmt::Debug for ScanResult {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
#[allow(unused_unsafe)]
unsafe {
if self.ssid.len > 0 {
f.debug_struct("ScanResult")
.field("ssid", &self.ssid)
.field("bssid", &self.bssid)
.field("rssi", &self.rssi)
.field("type", &self.bss_type)
.field("security", &self.security)
.field("wps", &self.wps)
.field("channel", &self.chan)
.field("band", &self.band)
.finish()
} else {
f.debug_struct("ScanResult")
.field("bssid", &self.bssid)
.field("rssi", &self.rssi)
.field("type", &self.bss_type)
.field("security", &self.security)
.field("wps", &self.wps)
.field("channel", &self.chan)
.field("band", &self.band)
.finish()
}
}
}
}
impl Default for ScanResult {
fn default() -> Self {
Self {
ssid: super::SSID {
len: 0,
value: [0u8; 33],
},
bssid: super::BSSID([0u8; 6]),
rssi: 0,
bss_type: super::BssType::Any,
security: super::Security::empty(),
wps: super::WPS::Default,
chan: 0,
band: super::Band::_24Ghz,
}
}
}
pub struct ScanGetAP<N: ArrayLength<ScanResult>> {
m: core::marker::PhantomData<N>,
}
impl<N: ArrayLength<ScanResult>> ScanGetAP<N> {
pub fn new() -> Self {
Self {
m: core::marker::PhantomData,
}
}
}
impl<N: ArrayLength<ScanResult>> super::RPC for ScanGetAP<N> {
type ReturnValue = (GenericArray<ScanResult, N>, i32);
type Error = usize;
fn header(&self, seq: u32) -> codec::Header {
codec::Header {
sequence: seq,
msg_type: ids::MsgType::Invocation,
service: ids::Service::Wifi,
request: ids::WifiRequest::ScanGetAP.into(),
}
}
fn args(&self, buff: &mut heapless::Vec<u8, heapless::consts::U64>) {
let num = N::to_u16().to_le_bytes();
buff.extend_from_slice(&num).ok();
}
fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
let (data, hdr) = codec::Header::parse(data)?;
if hdr.msg_type != ids::MsgType::Reply
|| hdr.service != ids::Service::Wifi
|| hdr.request != ids::WifiRequest::ScanGetAP.into()
{
return Err(Err::NotOurs);
}
let (mut data, l) = streaming::le_u32(data)?;
if l as usize != (62 * N::to_usize()) {
return Err(Err::ResponseOverrun);
}
use core::convert::TryInto;
let mut res = GenericArray::<ScanResult, N>::default();
for i in 0..N::to_usize() {
let (d, ssid_len) = streaming::le_u8(data)?;
let (d, ssid_data) = take(33usize)(d)?;
let (d, bssid) = take(6usize)(d)?;
let (d, rssi) = streaming::le_i16(d)?;
let (d, bss_type) = streaming::le_u32(d)?;
let (d, security) = streaming::le_u32(d)?;
let (d, wps) = streaming::le_u32(d)?;
let (d, chan) = streaming::le_u32(d)?;
let (d, band) = streaming::le_u32(d)?;
res[i] = ScanResult {
ssid: super::SSID {
len: ssid_len,
value: ssid_data.try_into().unwrap(),
},
bssid: super::BSSID(bssid.try_into().unwrap()),
rssi,
bss_type: bss_type.into(),
security: super::Security::from_bits_truncate(security),
wps: wps.into(),
chan,
band: band.into(),
};
data = d;
}
let (_, ret_val) = streaming::le_i32(data)?;
Ok((res, ret_val))
}
}
pub struct ScanGetNumAPs {}
impl super::RPC for ScanGetNumAPs {
type ReturnValue = u16;
type Error = ();
fn header(&self, seq: u32) -> codec::Header {
codec::Header {
sequence: seq,
msg_type: ids::MsgType::Invocation,
service: ids::Service::Wifi,
request: ids::WifiRequest::ScanGetNumAPs.into(),
}
}
fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
let (data, hdr) = codec::Header::parse(data)?;
if hdr.msg_type != ids::MsgType::Reply
|| hdr.service != ids::Service::Wifi
|| hdr.request != ids::WifiRequest::ScanGetNumAPs.into()
{
return Err(Err::NotOurs);
}
if data.input_len() < 2 {
return Err(Err::RPCErr(()));
}
let (_, num) = streaming::le_u16(data)?;
Ok(num)
}
}
pub struct ScanStart {}
impl super::RPC for ScanStart {
type ReturnValue = i32;
type Error = ();
fn header(&self, seq: u32) -> codec::Header {
codec::Header {
sequence: seq,
msg_type: ids::MsgType::Invocation,
service: ids::Service::Wifi,
request: ids::WifiRequest::ScanStart.into(),
}
}
fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
let (data, hdr) = codec::Header::parse(data)?;
if hdr.msg_type != ids::MsgType::Reply
|| hdr.service != ids::Service::Wifi
|| hdr.request != ids::WifiRequest::ScanStart.into()
{
return Err(Err::NotOurs);
}
let (_, num) = streaming::le_i32(data)?;
Ok(num)
}
}
pub struct WifiOn {
pub mode: super::WifiMode,
}
impl super::RPC for WifiOn {
type ReturnValue = i32;
type Error = ();
fn args(&self, buff: &mut heapless::Vec<u8, heapless::consts::U64>) {
let mode = self.mode as u32;
buff.extend_from_slice(&mode.to_le_bytes()).ok();
}
fn header(&self, seq: u32) -> codec::Header {
codec::Header {
sequence: seq,
msg_type: ids::MsgType::Invocation,
service: ids::Service::Wifi,
request: ids::WifiRequest::TurnOn.into(),
}
}
fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
let (data, hdr) = codec::Header::parse(data)?;
if hdr.msg_type != ids::MsgType::Reply
|| hdr.service != ids::Service::Wifi
|| hdr.request != ids::WifiRequest::TurnOn.into()
{
return Err(Err::NotOurs);
}
let (_, num) = streaming::le_i32(data)?;
Ok(num)
}
}
pub struct WifiOff {}
impl super::RPC for WifiOff {
type ReturnValue = i32;
type Error = ();
fn header(&self, seq: u32) -> codec::Header {
codec::Header {
sequence: seq,
msg_type: ids::MsgType::Invocation,
service: ids::Service::Wifi,
request: ids::WifiRequest::TurnOff.into(),
}
}
fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
let (data, hdr) = codec::Header::parse(data)?;
if hdr.msg_type != ids::MsgType::Reply
|| hdr.service != ids::Service::Wifi
|| hdr.request != ids::WifiRequest::TurnOff.into()
{
return Err(Err::NotOurs);
}
let (_, num) = streaming::le_i32(data)?;
Ok(num)
}
}
pub struct WifiConnect {
pub ssid: String<U64>,
pub password: String<U64>,
pub security: super::Security,
pub semaphore: u32,
}
impl super::RPC for WifiConnect {
type ReturnValue = i32;
type Error = ();
fn args(&self, buff: &mut heapless::Vec<u8, U64>) {
buff.extend_from_slice(&(self.ssid.len() as u32).to_le_bytes())
.ok();
buff.extend_from_slice(self.ssid.as_ref()).ok();
buff.push(if self.password.len() > 0 { 0u8 } else { 1u8 })
.ok();
if self.password.len() > 0 {
buff.extend_from_slice(&(self.password.len() as u32).to_le_bytes())
.ok();
buff.extend_from_slice(self.password.as_ref()).ok();
}
buff.extend_from_slice(&(self.security.bits()).to_le_bytes())
.ok();
buff.extend_from_slice(&(0u32.wrapping_sub(1)).to_le_bytes())
.ok();
buff.extend_from_slice(&(self.semaphore).to_le_bytes()).ok();
}
fn header(&self, seq: u32) -> codec::Header {
codec::Header {
sequence: seq,
msg_type: ids::MsgType::Invocation,
service: ids::Service::Wifi,
request: ids::WifiRequest::Connect.into(),
}
}
fn parse(&mut self, data: &[u8]) -> Result<Self::ReturnValue, Err<Self::Error>> {
let (data, hdr) = codec::Header::parse(data)?;
if hdr.msg_type != ids::MsgType::Reply
|| hdr.service != ids::Service::Wifi
|| hdr.request != ids::WifiRequest::Connect.into()
{
return Err(Err::NotOurs);
}
let (_, num) = streaming::le_i32(data)?;
Ok(num)
}
}