1use defmt::{Format, Formatter};
6use heapless::Vec;
7use micropb::{MessageEncode, PbEncoder};
8use num_enum::TryFromPrimitive;
9
10pub use crate::proto_data::RpcId;
11use crate::{
12 EspError, RpcP,
13 header::build_frame,
14 proto_data::EventHeartbeat,
15 transport::{RPC_EP_NAME_EVT, RPC_EP_NAME_RSP},
16 wifi::WifiApRecord,
17};
18
19pub(crate) const MAX_RPC_SIZE: usize = 500;
21pub(crate) const RPC_MIN_SIZE: usize = 10;
22
23pub enum RpcPayload {
25 EventHeartbeat(EventHeartbeat),
26 EventWifiScanGetApRecord(WifiApRecord),
27 EventWifiScanGetApRecords(Vec<WifiApRecord, 30>),
29}
30
31impl Format for RpcPayload {
32 fn format(&self, fmt: Formatter<'_>) {
33 }
39}
40
41#[derive(Format)]
43pub struct Rpc {
44 pub msg_type: RpcType,
46 pub msg_id: RpcId,
48 pub uid: u32,
50 pub payload: Option<RpcPayload>, }
56
57impl Rpc {
58 pub fn new_req(msg_id: RpcId, uid: u32) -> Self {
59 Self {
60 msg_type: RpcType::Req,
61 msg_id,
62 uid,
63 payload: None,
64 }
65 }
66
67 pub fn to_bytes(&self, buf: &mut [u8], data: &[u8]) -> usize {
69 let mut i = 0;
70 let data_len = data.len();
71
72 write_rpc(buf, 1, WireType::Varint, self.msg_type as u64, &mut i);
73 write_rpc(buf, 2, WireType::Varint, self.msg_id as u64, &mut i);
74 write_rpc(buf, 3, WireType::Varint, self.uid as u64, &mut i);
75
76 write_rpc(
80 buf,
81 self.msg_id as u16,
82 WireType::Len,
83 data_len as u64,
84 &mut i,
85 );
86
87 buf[i..i + data_len].copy_from_slice(data);
88 i += data_len;
89
90 i
91 }
92
93 pub fn from_bytes(buf: &[u8]) -> Result<(Self, usize, usize), EspError> {
95 let msg_type = buf[1].try_into().map_err(|e| EspError::InvalidData)?;
97
98 let (rpc_id, rpc_id_size) = decode_varint(&buf[3..])?;
99 let msg_id = (rpc_id as u16)
100 .try_into()
101 .map_err(|e| EspError::InvalidData)?;
102
103 let mut i = 3 + rpc_id_size;
104
105 let mut uid = 0; if buf[3 + rpc_id_size] == 16 {
108 i += 1; let (uid_, uid_size) = decode_varint(&buf[i..])?;
111 uid = uid_;
112 i += uid_size;
113 }
114
115 let result = Self {
116 msg_type,
117 msg_id,
118 uid: uid as u32,
119 payload: None, };
121
122 let (_data_tag, data_tag_size) = decode_varint(&buf[i..])?;
123 i += data_tag_size;
124
125 let (data_len, data_len_size) = decode_varint(&buf[i..])?;
126 i += data_len_size;
127
128 Ok((result, i, data_len as usize))
129 }
130}
131
132#[derive(Clone, Copy, Default, PartialEq, Format, TryFromPrimitive)]
134#[repr(u8)]
135pub enum WireType {
136 #[default]
137 Varint = 0,
139 I64 = 1,
141 Len = 2,
143 I32 = 5,
145}
146
147#[derive(Clone, Copy, PartialEq, TryFromPrimitive, Format)]
148#[repr(u8)]
149pub(crate) enum Rpc_WifiBw {
151 BW_Invalid = 0,
152 HT20 = 1,
153 HT40 = 2,
154}
155
156#[derive(Clone, Copy, PartialEq, TryFromPrimitive, Format)]
157#[repr(u8)]
158pub(crate) enum Rpc_WifiPowerSave {
160 PS_Invalid = 0,
161 MIN_MODEM = 1,
162 MAX_MODEM = 2,
163}
164
165#[derive(Clone, Copy, PartialEq, TryFromPrimitive, Format)]
166#[repr(u8)]
167pub(crate) enum Rpc_WifiSecProt {
169 Open = 0,
170 WEP = 1,
171 WPA_PSK = 2,
172 WPA2_PSK = 3,
173 WPA_WPA2_PSK = 4,
174 WPA2_ENTERPRISE = 5,
175 WPA3_PSK = 6,
176 WPA2_WPA3_PSK = 7,
177}
178
179#[derive(Clone, Copy, PartialEq, TryFromPrimitive, Format)]
180#[repr(u8)]
181pub(crate) enum Rpc_Status {
183 Connected = 0,
184 Not_Connected = 1,
185 No_AP_Found = 2,
186 Connection_Fail = 3,
187 Invalid_Argument = 4,
188 Out_Of_Range = 5,
189}
190
191#[derive(Clone, Copy, PartialEq, TryFromPrimitive, Format)]
192#[repr(u8)]
193pub enum RpcType {
196 MsgType_Invalid = 0,
197 Req = 1,
198 Resp = 2,
199 Event = 3,
200 MsgType_Max = 4,
201}
202
203#[derive(Clone, Copy, PartialEq, TryFromPrimitive)]
204#[repr(u8)]
205pub(crate) enum EndpointType {
207 EndpointName = 0x01,
209 Data = 0x02,
211}
212
213#[derive(Clone, Copy, PartialEq, TryFromPrimitive)]
214#[repr(u8)]
215pub(crate) enum RpcEndpoint {
219 CtrlResp,
220 CtrlEvent,
221}
222
223impl RpcEndpoint {
224 pub fn as_bytes(&self) -> &'static [u8] {
225 match self {
226 Self::CtrlResp => RPC_EP_NAME_RSP,
228 Self::CtrlEvent => RPC_EP_NAME_EVT,
230 }
231 .as_bytes()
232 }
233}
234
235pub fn setup_rpc(buf: &mut [u8], rpc: &Rpc, data: &[u8]) -> usize {
239 let mut rpc_buf = [0; MAX_RPC_SIZE];
241
242 let mut i = 0;
243 i += rpc.to_bytes(&mut rpc_buf, data);
244
245 build_frame(buf, &rpc_buf[..i])
246}
247
248pub fn setup_rpc_proto(buf: &mut [u8], message: RpcP) -> Result<usize, EspError> {
251 let mut rpc_buf = Vec::<u8, MAX_RPC_SIZE>::new();
252
253 let mut encoder = PbEncoder::new(&mut rpc_buf);
254 message.encode(&mut encoder).map_err(|_| EspError::Proto)?;
255
256 Ok(build_frame(buf, &rpc_buf[..rpc_buf.len()]))
257}
258
259pub fn write_rpc_raw<W>(buf: &mut [u8], mut write: W, msg: RpcP) -> Result<(), EspError>
261where
262 W: FnMut(&[u8]) -> Result<(), EspError>,
263{
264 let frame_len = setup_rpc_proto(buf, msg)?;
265 write(&buf[..frame_len])?;
266
267 Ok(())
268}
269
270pub(crate) fn write_rpc(buf: &mut [u8], field: u16, wire_type: WireType, val: u64, i: &mut usize) {
273 let tag = encode_tag(field, wire_type);
274 *i += encode_varint(tag as u64, &mut buf[*i..]);
275 *i += encode_varint(val, &mut buf[*i..]);
276}
277
278pub(crate) fn encode_tag(field: u16, wire_type: WireType) -> u16 {
280 (field << 3) | (wire_type as u16)
281}
282
283pub(crate) fn decode_tag(val: u16) -> (u16, WireType) {
284 (
285 val >> 3,
286 ((val & 0b111) as u8).try_into().unwrap_or_default(),
287 )
288}
289
290pub(crate) fn encode_varint(mut v: u64, out: &mut [u8]) -> usize {
293 let mut idx = 0;
294 loop {
295 let byte = (v & 0x7F) as u8;
296 v >>= 7;
297 if v == 0 {
298 out[idx] = byte; idx += 1;
300 break;
301 } else {
302 out[idx] = byte | 0x80; idx += 1;
304 }
305 }
306 idx
307}
308
309pub(crate) fn decode_varint(input: &[u8]) -> Result<(u64, usize), EspError> {
312 let mut val = 0u64;
313 let mut shift = 0;
314 for (idx, &byte) in input.iter().enumerate() {
315 val |= ((byte & 0x7F) as u64) << shift;
316 if byte & 0x80 == 0 {
317 return Ok((val, idx + 1));
318 }
319 shift += 7;
320 }
321
322 Err(EspError::InvalidData)
323}