use defmt::{Format, println};
use heapless::Vec;
use num_enum::TryFromPrimitive;
use crate::{
EspError,
WireType::{Len, Varint},
proto_data::{RpcId, RpcReqWifiInit, RpcReqWifiScanStart},
rpc::{Rpc, WireType, decode_tag, decode_varint, setup_rpc, write_rpc},
util::write_empty_msg,
};
const MAX_AP_RECORDS: usize = 30;
pub fn parse_ap_records(data: &[u8]) -> Result<Vec<WifiApRecord, MAX_AP_RECORDS>, EspError> {
let mut result = Vec::new();
let mut i = 1; if data.len() == 0 {
println!("Empty data on parsing AP records.");
return Err(EspError::InvalidData);
}
let (num_records, nr_len) = decode_varint(&data[i..])?;
i += nr_len;
for _ in 0..num_records {
i += 1;
if i >= data.len() {
return Err(EspError::InvalidData);
}
let (record_len, record_len_len) = decode_varint(&data[i..])?;
i += record_len_len;
let (record, _record_size) = WifiApRecord::from_bytes(&data[i..i + record_len as usize])?;
i += record_len as usize;
result.push(record).map_err(|_| EspError::Capacity)?;
}
Ok(result)
}
#[derive(Clone, Format)]
pub struct InitConfig {
pub static_rx_buf_num: i32,
pub dynamic_rx_buf_num: i32,
pub tx_buf_type: i32,
pub static_tx_buf_num: i32,
pub dynamic_tx_buf_num: i32,
pub cache_tx_buf_num: i32,
pub csi_enable: i32,
pub ampdu_rx_enable: i32,
pub ampdu_tx_enable: i32,
pub amsdu_tx_enable: i32,
pub nvs_enable: i32,
pub nano_enable: i32,
pub rx_ba_win: i32,
pub wifi_task_core_id: i32,
pub beacon_max_len: i32,
pub mgmt_sbuf_num: i32,
pub feature_caps: u64,
pub sta_disconnected_pm: bool,
pub espnow_max_encrypt_num: i32,
pub magic: i32,
}
impl Default for InitConfig {
fn default() -> Self {
Self {
static_rx_buf_num: 10,
dynamic_rx_buf_num: 32,
tx_buf_type: 3, static_tx_buf_num: 0,
dynamic_tx_buf_num: 32,
cache_tx_buf_num: 32,
csi_enable: 0,
ampdu_rx_enable: 1,
ampdu_tx_enable: 1,
amsdu_tx_enable: 1,
nvs_enable: 1, nano_enable: 0,
rx_ba_win: 6, wifi_task_core_id: 0,
beacon_max_len: 752, mgmt_sbuf_num: 32,
feature_caps: 0,
sta_disconnected_pm: false,
espnow_max_encrypt_num: 7,
magic: 0x1F2F3F4F, }
}
}
impl InitConfig {
pub fn new_promiscuous() -> Self {
Self {
static_rx_buf_num: 10,
dynamic_rx_buf_num: 64,
tx_buf_type: 1,
static_tx_buf_num: 0,
dynamic_tx_buf_num: 32, cache_tx_buf_num: 0,
csi_enable: 0,
ampdu_rx_enable: 0,
ampdu_tx_enable: 0,
amsdu_tx_enable: 0,
nvs_enable: 0, nano_enable: 0,
rx_ba_win: 6, wifi_task_core_id: 0,
beacon_max_len: 752, mgmt_sbuf_num: 32,
feature_caps: 0,
sta_disconnected_pm: false,
espnow_max_encrypt_num: 0,
magic: 0x1F2F3F4F, }
}
pub fn to_bytes(&self, buf: &mut [u8]) -> usize {
let c = &self;
let v = WireType::Varint;
let mut i = 0;
write_rpc(buf, 1, v, c.static_rx_buf_num as u64, &mut i);
write_rpc(buf, 2, v, c.dynamic_rx_buf_num as u64, &mut i);
write_rpc(buf, 3, v, c.tx_buf_type as u64, &mut i);
write_rpc(buf, 4, v, c.static_tx_buf_num as u64, &mut i);
write_rpc(buf, 5, v, c.dynamic_tx_buf_num as u64, &mut i);
write_rpc(buf, 6, v, c.cache_tx_buf_num as u64, &mut i);
write_rpc(buf, 7, v, c.csi_enable as u64, &mut i);
write_rpc(buf, 8, v, c.ampdu_rx_enable as u64, &mut i);
write_rpc(buf, 9, v, c.ampdu_tx_enable as u64, &mut i);
write_rpc(buf, 10, v, c.amsdu_tx_enable as u64, &mut i);
write_rpc(buf, 11, v, c.nvs_enable as u64, &mut i);
write_rpc(buf, 12, v, c.nano_enable as u64, &mut i);
write_rpc(buf, 13, v, c.rx_ba_win as u64, &mut i);
write_rpc(buf, 14, v, c.wifi_task_core_id as u64, &mut i);
write_rpc(buf, 15, v, c.beacon_max_len as u64, &mut i);
write_rpc(buf, 16, v, c.mgmt_sbuf_num as u64, &mut i);
write_rpc(buf, 17, v, c.feature_caps, &mut i);
write_rpc(buf, 18, v, c.sta_disconnected_pm as u64, &mut i);
write_rpc(buf, 19, v, c.espnow_max_encrypt_num as u64, &mut i);
write_rpc(buf, 20, v, c.magic as u64, &mut i);
i
}
}
#[derive(Clone, Default, Format)]
pub struct ActiveScanTime {
pub min: u32,
pub max: u32,
}
impl ActiveScanTime {
pub fn to_bytes(&self, buf: &mut [u8]) -> usize {
let mut i = 0;
write_rpc(buf, 1, Varint, self.min as u64, &mut i);
write_rpc(buf, 2, Varint, self.max as u64, &mut i);
i
}
}
#[derive(Clone, Default)]
pub struct ScanTime {
pub active: ActiveScanTime,
pub passive: u32,
}
impl ScanTime {
pub fn to_bytes(&self, buf: &mut [u8]) -> usize {
let mut i = 0;
let mut scan_time_buf = [0; 8]; let active_size = self.active.to_bytes(&mut scan_time_buf);
write_rpc(buf, 1, Len, active_size as u64, &mut i);
buf[i..i + active_size].copy_from_slice(&scan_time_buf[..active_size]);
i += active_size;
write_rpc(buf, 2, Varint, self.passive as u64, &mut i);
i
}
}
#[derive(Clone, Copy, PartialEq, Default, TryFromPrimitive, Format)]
#[repr(u8)]
pub enum ScanType {
#[default]
Active = 0,
Passive = 1,
}
#[derive(Default)]
pub struct ScanConfig {
pub ssid: Vec<u8, 33>,
pub bssid: Vec<u8, 6>,
pub channel: u8,
pub show_hidden: bool,
pub scan_type: ScanType,
pub scan_time: ScanTime,
pub home_chan_dwell_time: u8,
}
impl ScanConfig {
pub fn to_bytes(&self, buf: &mut [u8]) -> usize {
let mut i = 0;
write_rpc(buf, 1, Len, self.ssid.len() as u64, &mut i);
buf[i..i + self.ssid.len()].copy_from_slice(&self.ssid);
i += self.ssid.len();
write_rpc(buf, 2, Len, self.bssid.len() as u64, &mut i);
buf[i..i + self.bssid.len()].copy_from_slice(&self.bssid);
i += self.bssid.len();
write_rpc(buf, 3, Varint, self.channel as u64, &mut i);
write_rpc(buf, 4, Varint, self.show_hidden as u64, &mut i);
write_rpc(buf, 5, Varint, self.scan_type as u64, &mut i);
let mut scan_time_buf = [0; 14]; let scan_time_size = self.scan_time.to_bytes(&mut scan_time_buf);
write_rpc(buf, 6, Len, scan_time_size as u64, &mut i);
buf[i..i + scan_time_size].copy_from_slice(&scan_time_buf[..scan_time_size]);
i += scan_time_size;
write_rpc(buf, 7, Varint, self.home_chan_dwell_time as u64, &mut i);
i
}
}
#[derive(Clone, Copy, PartialEq, Default, Format, TryFromPrimitive)]
#[repr(u8)]
pub enum WifiSecondChan {
#[default]
None = 0,
Above = 1,
Below = 2,
}
#[derive(Clone, Copy, PartialEq, Default, Format, TryFromPrimitive)]
#[repr(u8)]
pub enum WifiAuthMode {
#[default]
Open = 0,
WEP = 1,
WPA_PSK = 2,
WPA2_PSK = 3,
WPA_WPA2_PSK = 4,
ENTERPRISE = 5,
WPA2_ENTERPRISE = 6,
WPA3_PSK = 7,
}
#[derive(Clone, Copy, PartialEq, Default, Format, TryFromPrimitive)]
#[repr(u8)]
pub enum WifiCipher {
#[default]
None = 0,
WEP40 = 1,
WEP104 = 2,
TKIP = 3,
CCMP = 4,
TKIP_CCMP = 5,
AES_CMAC128 = 6,
SMS4 = 7,
GCMP = 8,
GCMP256 = 9,
AES_GMAC128 = 10,
AES_GMAC256 = 11,
UNKNOWN = 12, }
#[derive(Clone, Copy, PartialEq, Default, Format, TryFromPrimitive)]
#[repr(u8)]
pub enum WifiAnt {
#[default]
Ant0 = 0,
Ant1 = 1,
Max = 2,
}
#[derive(Default, Format)]
pub struct WifiCountry {
pub cc: [u8; 3],
pub schan: u8,
pub nchan: u8,
pub max_tx_power: i8,
pub policy: u8,
}
#[derive(Clone, Copy, PartialEq, Default, Format, TryFromPrimitive)]
#[repr(u8)]
pub enum WifiBandwidth {
#[default]
HT20 = 0,
BW20 = 1,
BW_HT40 = 2,
BW40 = 3,
BW80 = 4,
BW160 = 5,
BW80_BW80 = 6,
}
#[derive(Default, Format)]
pub struct WifiHeApInfo {
pub bitmask: u32,
pub bssid_index: u32,
}
#[derive(Default)]
pub struct WifiApRecord {
pub bssid: [u8; 6],
pub ssid: Vec<u8, 33>,
pub primary: u8,
pub second: WifiSecondChan,
pub rssi: i8,
pub authmode: WifiAuthMode,
pub pairwise_cipher: WifiCipher,
pub group_cipher: WifiCipher,
pub ant: WifiAnt,
pub bitmask: u32,
pub country: WifiCountry,
pub he_ap: WifiHeApInfo,
pub bandwidth: WifiBandwidth,
pub vht_ch_freq1: u8,
pub vht_ch_freq2: u8,
}
impl WifiApRecord {
pub fn from_bytes(buf: &[u8]) -> Result<(Self, usize), EspError> {
let mut i = 0;
let mut result = Self::default();
loop {
if i >= buf.len() {
break;
}
let (tag, tag_len) = decode_varint(&buf[i..])?;
i += tag_len;
let (field, _wire_type) = decode_tag(tag as u16);
match field {
1 => {
let (field_len, field_len_len) = decode_varint(&buf[i..])?;
i += field_len_len;
if i + field_len as usize >= buf.len() {
return Err(EspError::Capacity);
}
result
.bssid
.copy_from_slice(&buf[i..i + field_len as usize]);
i += field_len as usize;
}
2 => {
let (field_len, field_len_len) = decode_varint(&buf[i..])?;
i += field_len_len;
if i + field_len as usize >= buf.len() {
return Err(EspError::Capacity);
}
result.ssid = Vec::<_, 33>::from_slice(&buf[i..i + field_len as usize])
.map_err(|_| EspError::InvalidData)?;
i += field_len as usize;
}
3 => {
result.primary = buf[i];
i += 1;
}
4 => {
result.second = buf[i].try_into().unwrap_or_default();
i += 1;
}
5 => {
result.rssi = buf[i] as i8;
i += 10; }
6 => {
result.authmode = buf[i].try_into().unwrap_or_default();
i += 1;
}
7 => {
result.pairwise_cipher = buf[i].try_into().unwrap_or_default();
i += 1;
}
8 => {
result.group_cipher = buf[i].try_into().unwrap_or_default();
i += 1;
}
9 => {
result.ant = buf[i].try_into().unwrap_or_default();
i += 1;
}
10 => {
let (val, len) = decode_varint(&buf[i..])?;
result.bitmask = val as u32;
i += len;
}
11 => {
let (country_len, country_len_len) = decode_varint(&buf[i..])?;
i += country_len_len;
i += country_len as usize;
}
12 => {
let (he_ap_len, he_ap_len_len) = decode_varint(&buf[i..])?;
i += he_ap_len_len;
i += he_ap_len as usize;
}
13 => {
result.bandwidth = buf[i].try_into().unwrap_or_default();
i += 1;
}
14 => {
result.vht_ch_freq1 = buf[i];
i += 1;
}
15 => {
result.vht_ch_freq2 = buf[i];
i += 1;
}
_ => {
println!("Unparsed field: {:?}", field);
}
}
}
Ok((result, i))
}
}
#[derive(Clone, Copy, Format)]
#[repr(u8)]
pub enum InterfaceType {
Station = 0,
Ap = 1,
}
#[derive(Clone, Copy, Format)]
#[repr(u8)]
pub enum WifiMode {
Null = 0,
Station = 1,
SoftAp = 2,
ApStation = 3,
}
pub fn start<W>(buf: &mut [u8], write: W, uid: u32) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
write_empty_msg(buf, write, uid, RpcId::ReqWifiStart)
}
pub fn stop<W>(buf: &mut [u8], write: W, uid: u32) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
write_empty_msg(buf, write, uid, RpcId::ReqWifiStop)
}
pub fn scan_get_ap_num<W>(buf: &mut [u8], write: W, uid: u32) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
write_empty_msg(buf, write, uid, RpcId::ReqWifiScanGetApNum)
}
pub fn scan_get_ap_record<W>(buf: &mut [u8], write: W, uid: u32) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
write_empty_msg(buf, write, uid, RpcId::ReqWifiScanGetApRecord)
}
pub fn clear_ap_list<W>(buf: &mut [u8], write: W, uid: u32) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
write_empty_msg(buf, write, uid, RpcId::ReqWifiClearApList)
}
pub fn scan_get_ap_records<W>(
buf: &mut [u8],
mut write: W,
uid: u32,
max_number: u8,
) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
let rpc = Rpc::new_req(RpcId::ReqWifiScanGetApRecords, uid);
let mut data = [0; 2];
let mut i = 0;
write_rpc(&mut data, 1, WireType::Varint, max_number as u64, &mut i);
let frame_len = setup_rpc(buf, &rpc, &data[..i]);
write(&buf[..frame_len])?;
Ok(())
}
pub fn ap_get_sta_list<W>(buf: &mut [u8], write: W, uid: u32) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
write_empty_msg(buf, write, uid, RpcId::ReqWifiApGetStaList)
}
pub fn get_mode<W>(buf: &mut [u8], write: W, uid: u32) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
write_empty_msg(buf, write, uid, RpcId::ReqGetWifiMode)
}
pub fn set_mode<W>(buf: &mut [u8], mut write: W, uid: u32, mode: WifiMode) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
let rpc = Rpc::new_req(RpcId::ReqSetWifiMode, uid);
let mut data = [0; 2];
let mut i = 0;
write_rpc(&mut data, 1, WireType::Varint, mode as u64, &mut i);
let frame_len = setup_rpc(buf, &rpc, &data[..i]);
write(&buf[..frame_len])?;
Ok(())
}
pub fn init<W>(buf: &mut [u8], mut write: W, uid: u32, cfg: &InitConfig) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
let rpc = Rpc::new_req(RpcId::ReqWifiInit, uid);
let mut data = [0; 85];
let pl = RpcReqWifiInit {
cfg: cfg.clone(), };
let data_len = pl.to_bytes(&mut data);
let frame_len = setup_rpc(buf, &rpc, &data[..data_len]);
write(&buf[..frame_len])?;
Ok(())
}
pub fn deinit<W>(buf: &mut [u8], write: W, uid: u32) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
write_empty_msg(buf, write, uid, RpcId::ReqWifiDeinit)
}
#[derive(Clone, Copy, PartialEq, Format)]
#[repr(u8)]
pub enum PromiscuousPktType {
Mgmt = 0,
Ctrl = 1,
Data = 2,
Misc = 3,
}
#[derive(Format, Default)]
pub struct PromiscuousFilter {
pub mgmt: bool,
pub ctrl: bool,
pub data: bool,
pub misc: bool,
pub data_mpdu: bool,
pub data_ampdu: bool,
pub fcsfail: bool,
}
impl PromiscuousFilter {
pub fn val(&self) -> u32 {
let mut result = 0;
if self.mgmt {
result |= 1 << 0;
}
if self.ctrl {
result |= 1 << 1;
}
if self.data {
result |= 1 << 2;
}
if self.misc {
result |= 1 << 3;
}
if self.data_mpdu {
result |= 1 << 4;
}
if self.data_ampdu {
result |= 1 << 5;
}
if self.fcsfail {
result |= 1 << 6;
}
result
}
}
#[derive(Format, Default)]
pub struct PromiscuousCtrlFilter {
pub wrapper: bool,
pub bar: bool,
pub ba: bool,
pub pspoll: bool,
pub rts: bool,
pub cts: bool,
pub ack: bool,
pub cfend: bool,
pub cfendack: bool,
}
impl PromiscuousCtrlFilter {
pub fn val(&self) -> u32 {
let mut result = 0;
if self.wrapper {
result |= 1 << 0;
}
if self.bar {
result |= 1 << 1;
}
if self.ba {
result |= 1 << 2;
}
if self.pspoll {
result |= 1 << 3;
}
if self.rts {
result |= 1 << 4;
}
if self.cts {
result |= 1 << 5;
}
if self.ack {
result |= 1 << 6;
}
if self.cfend {
result |= 1 << 7;
}
if self.cfendack {
result |= 1 << 8;
}
result
}
}
pub fn set_promiscuous<W>(
buf: &mut [u8],
mut write: W,
uid: u32,
enabled: bool,
filter: &PromiscuousFilter,
ctrl_filter: Option<&PromiscuousCtrlFilter>,
) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
let rpc = Rpc::new_req(RpcId::ReqWifiSetPromiscuous, uid);
let mut data = [0; 6];
let mut i = 0;
write_rpc(&mut data, 1, WireType::Varint, enabled as u64, &mut i);
let frame_len = setup_rpc(buf, &rpc, &data[..i]);
write(&buf[..frame_len])?;
let rpc = Rpc::new_req(RpcId::ReqWifiSetPromiscuousFilter, uid);
let mut i = 0;
write_rpc(&mut data, 1, WireType::Len, 1, &mut i);
write_rpc(&mut data, 1, WireType::Varint, 1, &mut i);
write_rpc(&mut data, 1, WireType::Varint, filter.val() as u64, &mut i);
let frame_len = setup_rpc(buf, &rpc, &data[..i]);
write(&buf[..frame_len])?;
if let Some(f) = ctrl_filter {
let rpc = Rpc::new_req(RpcId::ReqWifiSetPromiscuousCtrlFilter, uid);
let mut i = 0;
write_rpc(&mut data, 1, WireType::Len, 1, &mut i);
write_rpc(&mut data, 1, WireType::Varint, 1, &mut i);
write_rpc(&mut data, 1, WireType::Varint, f.val() as u64, &mut i);
let frame_len = setup_rpc(buf, &rpc, &data[..i]);
write(&buf[..frame_len])?;
}
Ok(())
}
pub fn get_promiscuous<W>(buf: &mut [u8], write: W, uid: u32) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
write_empty_msg(buf, write, uid, RpcId::ReqWifiGetPromiscuous)
}
pub fn get_promiscuous_filter<W>(buf: &mut [u8], write: W, uid: u32) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
write_empty_msg(buf, write, uid, RpcId::ReqWifiGetPromiscuousFilter)
}
pub fn get_promiscuous_ctrl_filter<W>(buf: &mut [u8], write: W, uid: u32) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
write_empty_msg(buf, write, uid, RpcId::ReqWifiGetPromiscuousCtrlFilter)
}
pub fn scan_start<W>(
buf: &mut [u8],
mut write: W,
uid: u32,
scan_start: &RpcReqWifiScanStart,
) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
let rpc = Rpc::new_req(RpcId::ReqWifiScanStart, uid);
let mut data = [0; 100];
let data_size = scan_start.to_bytes(&mut data);
let frame_len = setup_rpc(buf, &rpc, &data[..data_size]);
write(&buf[..frame_len])?;
Ok(())
}
pub fn scan_stop<W>(buf: &mut [u8], write: W, uid: u32) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
write_empty_msg(buf, write, uid, RpcId::ReqWifiScanStop)
}
#[derive(Format)]
pub struct Protocols {
pub p_11b: bool,
pub p_11g: bool,
pub p_11n: bool,
pub p_lr: bool,
pub p_11ax: bool,
pub wps: bool,
pub p_11a: bool,
pub p_11ac: bool,
}
impl Default for Protocols {
fn default() -> Self {
Self {
p_11b: true,
p_11g: true,
p_11n: true,
p_lr: false,
p_11ax: false,
wps: false,
p_11a: false,
p_11ac: false,
}
}
}
impl Protocols {
pub fn to_byte(&self) -> u8 {
(self.p_11b as u8)
| ((self.p_11g as u8) << 1)
| ((self.p_11n as u8) << 2)
| ((self.p_lr as u8) << 3)
| ((self.p_11ac as u8) << 5)
| ((self.p_11ax as u8) << 6)
}
pub fn from_byte(b: u8) -> Self {
Self {
p_11b: b & 1 != 0,
p_11g: (b >> 1) & 1 != 0,
p_11n: (b >> 2) & 1 != 0,
p_lr: (b >> 3) & 1 != 0,
p_11ax: (b >> 4) & 1 != 0,
wps: (b >> 5) & 1 != 0,
p_11a: false,
p_11ac: false,
}
}
}
pub fn set_protocol<W>(
buf: &mut [u8],
mut write: W,
uid: u32,
ifx: InterfaceType,
protocols: &Protocols,
) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
let rpc = Rpc::new_req(RpcId::ReqWifiSetProtocol, uid);
let mut data = [0; 4];
let mut i = 0;
write_rpc(&mut data, 1, WireType::Varint, ifx as u64, &mut i);
write_rpc(
&mut data,
2,
WireType::Varint,
protocols.to_byte() as u64,
&mut i,
);
let frame_len = setup_rpc(buf, &rpc, &data[0..i]);
write(&buf[..frame_len])?;
Ok(())
}
pub fn get_protocol<W>(buf: &mut [u8], mut write: W, uid: u32) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
let rpc = Rpc::new_req(RpcId::ReqWifiGetProtocol, uid);
let mut data = [0; 4];
let mut i = 0;
let interface_num = 0; write_rpc(&mut data, 1, WireType::Varint, interface_num, &mut i);
let frame_len = setup_rpc(buf, &rpc, &data[..i]);
write(&buf[..frame_len])?;
Ok(())
}
pub fn set_power_save<W>(
buf: &mut [u8],
mut write: W,
uid: u32,
power_save_type: u8,
) -> Result<(), EspError>
where
W: FnMut(&[u8]) -> Result<(), EspError>,
{
let rpc = Rpc::new_req(RpcId::ReqWifiSetPs, uid);
let mut data = [0; 4];
let mut i = 0;
write_rpc(
&mut data,
1,
WireType::Varint,
power_save_type as u64,
&mut i,
);
let frame_len = setup_rpc(buf, &rpc, &data[..i]);
write(&buf[..frame_len])?;
Ok(())
}