1use defmt::{Format, Formatter, println};
6use heapless::Vec;
7use micropb::{MessageEncode, PbEncoder};
8use num_enum::TryFromPrimitive;
9
10pub use crate::proto_data::RpcId;
11use crate::{
12 EspError, RpcP,
13 esp_errors::EspCode,
14 header::build_frame_wifi,
15 proto_data::EventHeartbeat,
16 transport::{RPC_EP_NAME_EVT, RPC_EP_NAME_RSP},
17 wifi::WifiApRecord,
18};
19
20pub(crate) const MAX_RPC_SIZE: usize = 500;
22pub(crate) const RPC_MIN_SIZE: usize = 10;
23
24pub enum RpcPayload {
26 EventHeartbeat(EventHeartbeat),
27 EventWifiScanGetApRecord(WifiApRecord),
28 EventWifiScanGetApRecords(Vec<WifiApRecord, 30>),
30}
31
32impl Format for RpcPayload {
33 fn format(&self, _fmt: Formatter<'_>) {
34 }
40}
41
42#[derive(Format)]
44pub struct Rpc {
45 pub msg_type: RpcType,
47 pub msg_id: RpcId,
49 pub uid: u32,
51 pub payload: Option<RpcPayload>, }
57
58impl Rpc {
59 pub fn new_req(msg_id: RpcId, uid: u32) -> Self {
60 Self {
61 msg_type: RpcType::Req,
62 msg_id,
63 uid,
64 payload: None,
65 }
66 }
67
68 pub fn to_bytes(&self, buf: &mut [u8], data: &[u8]) -> usize {
70 let mut i = 0;
71 let data_len = data.len();
72
73 write_rpc(buf, 1, WireType::Varint, self.msg_type as u64, &mut i);
74 write_rpc(buf, 2, WireType::Varint, self.msg_id as u64, &mut i);
75 write_rpc(buf, 3, WireType::Varint, self.uid as u64, &mut i);
76
77 write_rpc(
81 buf,
82 self.msg_id as u16,
83 WireType::Len,
84 data_len as u64,
85 &mut i,
86 );
87
88 buf[i..i + data_len].copy_from_slice(data);
89 i += data_len;
90
91 i
92 }
93
94 pub fn from_bytes(buf: &[u8]) -> Result<(Self, usize, usize), EspError> {
96 if buf.len() < 2 {
98 return Err(EspError::InvalidData);
99 }
100 let msg_type = buf[1].try_into().map_err(|_| EspError::InvalidData)?;
101
102 let (rpc_id, rpc_id_size) = decode_varint(&buf[3..])?;
103 let msg_id = (rpc_id as u16)
104 .try_into()
105 .map_err(|_| EspError::InvalidData)?;
106
107 let mut i = 3 + rpc_id_size;
108
109 let mut uid = 0; if buf[3 + rpc_id_size] == 16 {
112 i += 1; let (uid_, uid_size) = decode_varint(&buf[i..])?;
115 uid = uid_;
116 i += uid_size;
117 }
118
119 let result = Self {
120 msg_type,
121 msg_id,
122 uid: uid as u32,
123 payload: None, };
125
126 let (_data_tag, data_tag_size) = decode_varint(&buf[i..])?;
127 i += data_tag_size;
128
129 let (data_len, data_len_size) = decode_varint(&buf[i..])?;
130 i += data_len_size;
131
132 if data_len == 3 && buf[i] == 8 {
134 let (err_code, _) = decode_varint(&buf[i + 1..])?;
135 match EspCode::try_from(err_code as u16) {
136 Ok(c) => {
137 return Err(EspError::Esp(c));
138 }
139 Err(_) => (),
140 }
141 }
142
143 Ok((result, i, data_len as usize))
144 }
145}
146
147#[derive(Clone, Copy, Default, PartialEq, Format, TryFromPrimitive)]
149#[repr(u8)]
150pub enum WireType {
151 #[default]
152 Varint = 0,
154 I64 = 1,
156 Len = 2,
158 I32 = 5,
160}
161
162#[derive(Clone, Copy, PartialEq, TryFromPrimitive, Format)]
163#[repr(u8)]
164pub(crate) enum Rpc_WifiBw {
166 BW_Invalid = 0,
167 HT20 = 1,
168 HT40 = 2,
169}
170
171#[derive(Clone, Copy, PartialEq, TryFromPrimitive, Format)]
172#[repr(u8)]
173pub(crate) enum Rpc_WifiPowerSave {
175 PS_Invalid = 0,
176 MIN_MODEM = 1,
177 MAX_MODEM = 2,
178}
179
180#[derive(Clone, Copy, PartialEq, TryFromPrimitive, Format)]
181#[repr(u8)]
182pub(crate) enum Rpc_WifiSecProt {
184 Open = 0,
185 WEP = 1,
186 WPA_PSK = 2,
187 WPA2_PSK = 3,
188 WPA_WPA2_PSK = 4,
189 WPA2_ENTERPRISE = 5,
190 WPA3_PSK = 6,
191 WPA2_WPA3_PSK = 7,
192}
193
194#[derive(Clone, Copy, PartialEq, TryFromPrimitive, Format)]
195#[repr(u8)]
196pub(crate) enum Rpc_Status {
198 Connected = 0,
199 Not_Connected = 1,
200 No_AP_Found = 2,
201 Connection_Fail = 3,
202 Invalid_Argument = 4,
203 Out_Of_Range = 5,
204}
205
206#[derive(Clone, Copy, PartialEq, TryFromPrimitive, Format)]
207#[repr(u8)]
208pub enum RpcType {
211 MsgType_Invalid = 0,
212 Req = 1,
213 Resp = 2,
214 Event = 3,
215 MsgType_Max = 4,
216}
217
218#[derive(Clone, Copy, PartialEq, TryFromPrimitive)]
219#[repr(u8)]
220pub(crate) enum EndpointType {
222 EndpointName = 0x01,
224 Data = 0x02,
226}
227
228#[derive(Clone, Copy, PartialEq, TryFromPrimitive)]
229#[repr(u8)]
230pub(crate) enum RpcEndpoint {
234 CtrlResp,
235 CtrlEvent,
236}
237
238impl RpcEndpoint {
239 pub fn as_bytes(&self) -> &'static [u8] {
240 match self {
241 Self::CtrlResp => RPC_EP_NAME_RSP,
243 Self::CtrlEvent => RPC_EP_NAME_EVT,
245 }
246 .as_bytes()
247 }
248}
249
250pub fn setup_rpc(buf: &mut [u8], rpc: &Rpc, data: &[u8]) -> usize {
254 let mut rpc_buf = [0; MAX_RPC_SIZE];
256
257 let mut i = 0;
258 i += rpc.to_bytes(&mut rpc_buf, data);
259
260 build_frame_wifi(buf, &rpc_buf[..i])
261}
262
263pub fn setup_rpc_proto(buf: &mut [u8], message: RpcP) -> Result<usize, EspError> {
266 let mut rpc_buf = Vec::<u8, MAX_RPC_SIZE>::new();
267
268 let mut encoder = PbEncoder::new(&mut rpc_buf);
269 message.encode(&mut encoder).map_err(|_| EspError::Proto)?;
270
271 Ok(build_frame_wifi(buf, &rpc_buf[..rpc_buf.len()]))
272}
273
274pub fn write_rpc_proto<W>(buf: &mut [u8], mut write: W, msg: RpcP) -> Result<(), EspError>
276where
277 W: FnMut(&[u8]) -> Result<(), EspError>,
278{
279 let frame_len = setup_rpc_proto(buf, msg)?;
280 write(&buf[..frame_len])?;
281
282 Ok(())
283}
284
285pub(crate) fn write_rpc(buf: &mut [u8], field: u16, wire_type: WireType, val: u64, i: &mut usize) {
288 let tag = encode_tag(field, wire_type);
289 *i += encode_varint(tag as u64, &mut buf[*i..]);
290 *i += encode_varint(val, &mut buf[*i..]);
291}
292
293pub(crate) fn encode_tag(field: u16, wire_type: WireType) -> u16 {
295 (field << 3) | (wire_type as u16)
296}
297
298pub(crate) fn decode_tag(val: u16) -> (u16, WireType) {
299 (
300 val >> 3,
301 ((val & 0b111) as u8).try_into().unwrap_or_default(),
302 )
303}
304
305pub(crate) fn encode_varint(mut v: u64, out: &mut [u8]) -> usize {
308 let mut idx = 0;
309 if out.len() == 0 {
310 println!("Error: Empty buf when encoding a varint."); return 0;
313 }
314
315 loop {
316 let byte = (v & 0x7F) as u8;
317 v >>= 7;
318 if v == 0 {
319 out[idx] = byte; idx += 1;
321 break;
322 } else {
323 out[idx] = byte | 0x80; idx += 1;
325 }
326 }
327 idx
328}
329
330pub(crate) fn decode_varint(input: &[u8]) -> Result<(u64, usize), EspError> {
333 let mut val = 0u64;
334 let mut shift = 0;
335 for (idx, &byte) in input.iter().enumerate() {
336 val |= ((byte & 0x7F) as u64) << shift;
337 if byte & 0x80 == 0 {
338 return Ok((val, idx + 1));
339 }
340 shift += 7;
341 }
342
343 Err(EspError::InvalidData)
344}