1use crate::*;
2
3use alloc::vec::Vec;
4
5#[derive(Copy, Clone, Eq, PartialEq, Debug)]
6#[cfg_attr(feature = "defmt", derive(defmt::Format))]
7pub struct TerminalInformation {
8 mac_address: u64,
9 pan_id: u16,
10 rssi: i8,
11}
12
13#[derive(Clone, Eq, PartialEq, Debug)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15pub enum Response {
16 GetStatus {
17 result: u8,
18 global_block: GlobalBlockStatus,
19 route_b_block: RouteBBlockStatus,
20 han_block: HanBlockStatus,
21 },
22 GetOperationMode {
23 result: u8,
24 mode: OperationMode,
25 han_sleep: bool,
26 channel: Channel,
27 tx_power: TxPower,
28 },
29
30 SetOperationMode {
31 result: u8,
32 },
33 SetNeighborDiscoverySettings {
34 result: u8,
35 },
36 SetUartSettings {
37 result: u8,
38 },
39
40 OpenUdpPort {
41 result: u8,
42 },
43 CloseUdpPort {
44 result: u8,
45 },
46 TransmitData {
47 result: u8,
48 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
49 result_udp: Option<(u8, Vec<u8>)>,
50 },
51 DoActiveScan {
52 result: u8,
53 },
54
55 NotificationActiveScan {
56 channel: Channel,
57 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
58 terminal: Vec<TerminalInformation>,
59 },
60
61 GetVersionInformation {
62 result: u8,
63 firmware_id: u16,
64 major: u8,
65 minor: u8,
66 revision: u32,
67 },
68
69 NotificationUdpReceived {
70 source_address: u128,
71 source_port: u16,
72 destination_port: u16,
73 source_pan_id: u16,
74 source_type: u8,
75 encryption: u8,
76 rssi: i8,
77 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
78 data: Vec<u8>,
79 },
80 NotificationPoweredOn,
81 NotificationConnectionChanged {
82 state: u8,
83 mac_address: u64,
84 rssi: i8,
85 },
86 NotificationPanaAuthentication {
87 result: u8,
88 mac_address: u64,
89 },
90
91 GetRouteBEncryptionKey {
92 result: u8,
93 encryption_key: [u8; 16],
94 },
95 GetRouteBPanId {
96 result: u8,
97 pan_id: u16,
98 },
99
100 SetRouteBPanaAuthenticationInformation {
101 result: u8,
102 },
103
104 StartRouteBOperation {
105 result: u8,
106 terminal: Option<(Channel, TerminalInformation)>,
107 },
108 StartRouteBPana {
109 result: u8,
110 },
111 TerminateRouteBPana {
112 result: u8,
113 },
114 TerminateRouteBOperation {
115 result: u8,
116 },
117 RedoRouteBPanaAuthentication {
118 result: u8,
119 },
120
121 Unknown {
122 code: u16,
123 #[cfg_attr(feature = "defmt", defmt(Debug2Format))]
124 data: Vec<u8>,
125 },
126}
127
128fn make_response(code: u16, data: &[u8]) -> Response {
129 match (code, data) {
130 (0x2001, _) if data.len() == 4 => Response::GetStatus {
131 result: data[0],
132 global_block: data[1].into(),
133 route_b_block: data[2].into(),
134 han_block: data[3].into(),
135 },
136
137 (0x2107, _) if data.len() == 5 => Response::GetOperationMode {
138 result: data[0],
139 mode: data[1].into(),
140 han_sleep: data[2] != 0,
141 channel: data[3].into(),
142 tx_power: data[4].into(),
143 },
144
145 (0x205f, [d0]) => Response::SetOperationMode { result: *d0 },
146
147 (0x2101, [d0]) => Response::SetNeighborDiscoverySettings { result: *d0 },
148
149 (0x210a, [d0]) => Response::SetUartSettings { result: *d0 },
150
151 (0x2005, [d0]) => Response::OpenUdpPort { result: *d0 },
152
153 (0x2006, [d0]) => Response::CloseUdpPort { result: *d0 },
154
155 (0x2008, [result @ 0x01, result_udp, data @ ..]) if !data.is_empty() => {
156 Response::TransmitData {
157 result: *result,
158 result_udp: Some((*result_udp, data.into())),
159 }
160 }
161
162 (0x2008, [result]) => Response::TransmitData {
163 result: *result,
164 result_udp: None,
165 },
166
167 (0x2051, [d0]) => Response::DoActiveScan { result: *d0 },
168
169 (0x4051, [0x00, channel, n, data @ ..]) if data.len() == 11_usize * *n as usize => {
170 Response::NotificationActiveScan {
171 channel: (*channel).into(),
172 terminal: data
173 .chunks_exact(11)
174 .map(|b| TerminalInformation {
175 mac_address: u64::from_be_bytes(b[0..8].try_into().unwrap()),
176 pan_id: u16::from_be_bytes(b[8..10].try_into().unwrap()),
177 rssi: b[10] as _,
178 })
179 .collect(),
180 }
181 }
182
183 (0x4051, [0x01, channel]) => Response::NotificationActiveScan {
184 channel: (*channel).into(),
185 terminal: Vec::new(),
186 },
187
188 (0x206b, _) if data.len() == 9 => {
189 let result = data[0];
190 let firmware_id = u16::from_be_bytes(data[1..3].try_into().unwrap());
191 let major = data[3];
192 let minor = data[4];
193 let revision = u32::from_be_bytes(data[5..9].try_into().unwrap());
194 Response::GetVersionInformation {
195 result,
196 firmware_id,
197 major,
198 minor,
199 revision,
200 }
201 }
202
203 (0x6018, _)
204 if data
205 .get(25..27)
206 .and_then(|s| s.try_into().ok())
207 .map(|s| u16::from_be_bytes(s) as usize + 27)
208 == Some(data.len()) =>
209 {
210 Response::NotificationUdpReceived {
211 source_address: u128::from_be_bytes(data[0..16].try_into().unwrap()),
212 source_port: u16::from_be_bytes(data[16..18].try_into().unwrap()),
213 destination_port: u16::from_be_bytes(data[18..20].try_into().unwrap()),
214 source_pan_id: u16::from_be_bytes(data[20..22].try_into().unwrap()),
215 source_type: data[22],
216 encryption: data[23],
217 rssi: data[24] as _,
218 data: data[27..].into(),
219 }
220 }
221
222 (0x6019, []) => Response::NotificationPoweredOn,
223
224 (0x601a, _) if data.len() == 10 => Response::NotificationConnectionChanged {
225 state: data[0],
226 mac_address: u64::from_be_bytes(data[1..9].try_into().unwrap()),
227 rssi: data[9] as _,
228 },
229
230 (0x6028, _) if data.len() == 9 => Response::NotificationPanaAuthentication {
231 result: data[0],
232 mac_address: u64::from_be_bytes(data[1..9].try_into().unwrap()),
233 },
234
235 (0x2059, _) if data.len() == 17 => Response::GetRouteBEncryptionKey {
236 result: data[0],
237 encryption_key: {
238 let mut arr = [0; 16];
239 arr.copy_from_slice(&data[1..17]);
240 arr
241 },
242 },
243
244 (0x205e, _) if data.len() == 3 => {
245 let result = data[0];
246 let pan_id = u16::from_be_bytes(data[1..3].try_into().unwrap());
247 Response::GetRouteBPanId { result, pan_id }
248 }
249
250 (0x2054, [d0]) if data.len() == 1 => {
251 Response::SetRouteBPanaAuthenticationInformation { result: *d0 }
252 }
253
254 (0x2053, [result @ 0x01, data @ ..]) if data.len() == 12 => {
255 Response::StartRouteBOperation {
256 result: *result,
257 terminal: Some((
258 data[0].into(),
259 TerminalInformation {
260 pan_id: u16::from_be_bytes(data[1..3].try_into().unwrap()),
261 mac_address: u64::from_be_bytes(data[3..11].try_into().unwrap()),
262 rssi: data[11] as _,
263 },
264 )),
265 }
266 }
267
268 (0x2053, [d0]) => Response::StartRouteBOperation {
269 result: *d0,
270 terminal: None,
271 },
272
273 (0x2056, [d0]) => Response::StartRouteBPana { result: *d0 },
274
275 (0x2057, [d0]) => Response::TerminateRouteBPana { result: *d0 },
276
277 (0x2058, [d0]) => Response::TerminateRouteBOperation { result: *d0 },
278
279 (0x20d2, [d0]) => Response::RedoRouteBPanaAuthentication { result: *d0 },
280
281 _ => Response::Unknown {
282 code,
283 data: Vec::from(data),
284 },
285 }
286}
287
288#[derive(Copy, Clone, Debug)]
289#[cfg_attr(feature = "defmt", derive(defmt::Format))]
290pub enum State {
291 UniqueCode(u8),
292 Header {
293 ptr: usize,
294 },
295 Data {
296 ptr: usize,
297 code: u16,
298 sum: u16,
299 sum_current: u16,
300 len: usize,
301 },
302 Ready {
303 len: usize,
304 code: u16,
305 },
306}
307
308#[derive(Debug)]
309#[cfg_attr(feature = "defmt", derive(defmt::Format))]
310pub struct Parser {
311 buffer: [u8; 2048],
312 state: State,
313}
314
315const UNIQUE_CODE0: u8 = 0xd0;
316const UNIQUE_CODE1: u8 = 0xf9;
317const UNIQUE_CODE2: u8 = 0xee;
318const UNIQUE_CODE3: u8 = 0x5d;
319
320const HEADER_SUM_INIT: u16 =
321 UNIQUE_CODE0 as u16 + UNIQUE_CODE1 as u16 + UNIQUE_CODE2 as u16 + UNIQUE_CODE3 as u16;
322
323impl Default for State {
324 fn default() -> Self {
325 State::UniqueCode(UNIQUE_CODE0)
326 }
327}
328
329impl State {
330 fn next(self, buffer: &mut [u8], c: u8) -> State {
331 match self {
332 State::Ready { .. } => {
333 if c == UNIQUE_CODE0 {
334 State::UniqueCode(UNIQUE_CODE1)
335 } else {
336 State::default()
337 }
338 }
339
340 State::UniqueCode(expected) => match (c, expected) {
341 (UNIQUE_CODE0, UNIQUE_CODE0) => State::UniqueCode(UNIQUE_CODE1),
342 (UNIQUE_CODE1, UNIQUE_CODE1) => State::UniqueCode(UNIQUE_CODE2),
343 (UNIQUE_CODE2, UNIQUE_CODE2) => State::UniqueCode(UNIQUE_CODE3),
344 (UNIQUE_CODE3, UNIQUE_CODE3) => State::Header { ptr: 0 },
345 _ => State::default(),
346 },
347
348 State::Header { ptr } if ptr + 1 < 8 => {
349 buffer[ptr] = c;
350 State::Header { ptr: ptr + 1 }
351 }
352
353 State::Header { ptr } => {
354 buffer[ptr] = c;
355
356 let sum_header = u16::from_be_bytes([buffer[4], buffer[5]]);
357 if buffer[..4]
358 .iter()
359 .fold(HEADER_SUM_INIT, |acc, &x| acc + x as u16)
360 != sum_header
361 {
362 return State::default();
363 }
364
365 let len = u16::from_be_bytes([buffer[2], buffer[3]]);
366 if len < 4 || len as usize > buffer.len() {
367 return State::default();
368 }
369
370 let code = u16::from_be_bytes([buffer[0], buffer[1]]);
371 let sum_data = u16::from_be_bytes([buffer[6], buffer[7]]);
372 if len == 4 && sum_data == 0 {
373 State::Ready { len: 0, code }
374 } else {
375 State::Data {
376 ptr: 0,
377 code,
378 sum: sum_data,
379 sum_current: 0,
380 len: (len - 4).into(),
381 }
382 }
383 }
384
385 State::Data {
386 ptr,
387 code,
388 sum,
389 sum_current,
390 len,
391 } if ptr + 1 < len => {
392 buffer[ptr] = c;
393 State::Data {
394 ptr: ptr + 1,
395 code,
396 sum,
397 sum_current: sum_current + c as u16,
398 len,
399 }
400 }
401
402 State::Data {
403 ptr,
404 code,
405 sum,
406 sum_current,
407 len,
408 } => {
409 buffer[ptr] = c;
410 if sum_current + c as u16 != sum {
411 return State::default();
412 }
413 State::Ready { len, code }
414 }
415 }
416 }
417}
418
419impl Default for Parser {
420 fn default() -> Self {
421 Parser {
422 buffer: [0; 2048],
423 state: State::default(),
424 }
425 }
426}
427
428impl Parser {
429 pub fn parse(&mut self, c: u8) -> Option<Response> {
430 self.state = self.state.next(&mut self.buffer, c);
431 match self.state {
432 State::Ready { len, code } => Some(make_response(code, &self.buffer[0..len])),
433 _ => None,
434 }
435 }
436}
437
438#[cfg(test)]
439mod tests {
440 extern crate std;
441 use crate::response::*;
442 use alloc::vec;
443
444 #[test]
445 fn test_parser() {
446 let mut p = Parser::default();
447
448 assert_eq!(p.parse(0xd0), None);
449 assert_eq!(p.parse(0xf9), None);
450 assert_eq!(p.parse(0xee), None);
451 assert_eq!(p.parse(0x5d), None);
452 assert_eq!(p.parse(0x20), None);
453 assert_eq!(p.parse(0x01), None);
454 assert_eq!(p.parse(0x00), None);
455 assert_eq!(p.parse(0x08), None);
456 assert_eq!(p.parse(0x03), None);
457 assert_eq!(p.parse(0x3d), None);
458 assert_eq!(p.parse(0x00), None);
459 assert_eq!(p.parse(0x07), None);
460 assert_eq!(p.parse(0x01), None);
461 assert_eq!(p.parse(0x02), None);
462 assert_eq!(p.parse(0x01), None);
463 assert_eq!(
464 p.parse(0x03),
465 Some(Response::GetStatus {
466 result: 0x01,
467 global_block: GlobalBlockStatus::Inactive,
468 route_b_block: RouteBBlockStatus::Inactive,
469 han_block: HanBlockStatus::Authentication,
470 })
471 );
472
473 assert_eq!(p.parse(0xd0), None);
474 assert_eq!(p.parse(0xf9), None);
475 assert_eq!(p.parse(0xee), None);
476 assert_eq!(p.parse(0x5d), None);
477 assert_eq!(p.parse(0x20), None);
478 assert_eq!(p.parse(0x5f), None);
479 assert_eq!(p.parse(0x00), None);
480 assert_eq!(p.parse(0x05), None);
481 assert_eq!(p.parse(0x03), None);
482 assert_eq!(p.parse(0x98), None);
483 assert_eq!(p.parse(0x00), None);
484 assert_eq!(p.parse(0x01), None);
485 assert_eq!(
486 p.parse(0x01),
487 Some(Response::SetOperationMode { result: 0x01 })
488 );
489
490 assert_eq!(p.parse(0xd0), None);
491 assert_eq!(p.parse(0xf9), None);
492 assert_eq!(p.parse(0xee), None);
493 assert_eq!(p.parse(0x5d), None);
494 assert_eq!(p.parse(0x21), None);
495 assert_eq!(p.parse(0x01), None);
496 assert_eq!(p.parse(0x00), None);
497 assert_eq!(p.parse(0x05), None);
498 assert_eq!(p.parse(0x03), None);
499 assert_eq!(p.parse(0x3b), None);
500 assert_eq!(p.parse(0x00), None);
501 assert_eq!(p.parse(0x01), None);
502 assert_eq!(
503 p.parse(0x01),
504 Some(Response::SetNeighborDiscoverySettings { result: 0x01 })
505 );
506
507 assert_eq!(p.parse(0xd0), None);
508 assert_eq!(p.parse(0xf9), None);
509 assert_eq!(p.parse(0xee), None);
510 assert_eq!(p.parse(0x5d), None);
511 assert_eq!(p.parse(0x21), None);
512 assert_eq!(p.parse(0x0a), None);
513 assert_eq!(p.parse(0x00), None);
514 assert_eq!(p.parse(0x05), None);
515 assert_eq!(p.parse(0x03), None);
516 assert_eq!(p.parse(0x44), None);
517 assert_eq!(p.parse(0x00), None);
518 assert_eq!(p.parse(0x01), None);
519 assert_eq!(
520 p.parse(0x01),
521 Some(Response::SetUartSettings { result: 0x01 })
522 );
523
524 assert_eq!(p.parse(0xd0), None);
525 assert_eq!(p.parse(0xf9), None);
526 assert_eq!(p.parse(0xee), None);
527 assert_eq!(p.parse(0x5d), None);
528 assert_eq!(p.parse(0x20), None);
529 assert_eq!(p.parse(0x05), None);
530 assert_eq!(p.parse(0x00), None);
531 assert_eq!(p.parse(0x05), None);
532 assert_eq!(p.parse(0x03), None);
533 assert_eq!(p.parse(0x3e), None);
534 assert_eq!(p.parse(0x00), None);
535 assert_eq!(p.parse(0x01), None);
536 assert_eq!(p.parse(0x01), Some(Response::OpenUdpPort { result: 0x01 }));
537
538 assert_eq!(p.parse(0xd0), None);
539 assert_eq!(p.parse(0xf9), None);
540 assert_eq!(p.parse(0xee), None);
541 assert_eq!(p.parse(0x5d), None);
542 assert_eq!(p.parse(0x20), None);
543 assert_eq!(p.parse(0x06), None);
544 assert_eq!(p.parse(0x00), None);
545 assert_eq!(p.parse(0x05), None);
546 assert_eq!(p.parse(0x03), None);
547 assert_eq!(p.parse(0x3f), None);
548 assert_eq!(p.parse(0x00), None);
549 assert_eq!(p.parse(0x01), None);
550 assert_eq!(p.parse(0x01), Some(Response::CloseUdpPort { result: 0x01 }));
551
552 assert_eq!(p.parse(0xd0), None);
553 assert_eq!(p.parse(0xf9), None);
554 assert_eq!(p.parse(0xee), None);
555 assert_eq!(p.parse(0x5d), None);
556 assert_eq!(p.parse(0x20), None);
557 assert_eq!(p.parse(0x08), None);
558 assert_eq!(p.parse(0x00), None);
559 assert_eq!(p.parse(0x05), None);
560 assert_eq!(p.parse(0x03), None);
561 assert_eq!(p.parse(0x41), None);
562 assert_eq!(p.parse(0x00), None);
563 assert_eq!(p.parse(0x02), None);
564 assert_eq!(
565 p.parse(0x02),
566 Some(Response::TransmitData {
567 result: 0x02,
568 result_udp: None,
569 })
570 );
571
572 assert_eq!(p.parse(0xd0), None);
573 assert_eq!(p.parse(0xf9), None);
574 assert_eq!(p.parse(0xee), None);
575 assert_eq!(p.parse(0x5d), None);
576 assert_eq!(p.parse(0x20), None);
577 assert_eq!(p.parse(0x08), None);
578 assert_eq!(p.parse(0x00), None);
579 assert_eq!(p.parse(0x09), None);
580 assert_eq!(p.parse(0x03), None);
581 assert_eq!(p.parse(0x45), None);
582 assert_eq!(p.parse(0x02), None);
583 assert_eq!(p.parse(0x7a), None);
584 assert_eq!(p.parse(0x01), None);
585 assert_eq!(p.parse(0x12), None);
586 assert_eq!(p.parse(0xab), None);
587 assert_eq!(p.parse(0xcd), None);
588 assert_eq!(
589 p.parse(0xef),
590 Some(Response::TransmitData {
591 result: 0x01,
592 result_udp: Some((0x12, vec![0xab, 0xcd, 0xef])),
593 })
594 );
595
596 assert_eq!(p.parse(0xd0), None);
597 assert_eq!(p.parse(0xf9), None);
598 assert_eq!(p.parse(0xee), None);
599 assert_eq!(p.parse(0x5d), None);
600 assert_eq!(p.parse(0x20), None);
601 assert_eq!(p.parse(0x51), None);
602 assert_eq!(p.parse(0x00), None);
603 assert_eq!(p.parse(0x05), None);
604 assert_eq!(p.parse(0x03), None);
605 assert_eq!(p.parse(0x8a), None);
606 assert_eq!(p.parse(0x00), None);
607 assert_eq!(p.parse(0x01), None);
608 assert_eq!(p.parse(0x01), Some(Response::DoActiveScan { result: 0x01 }));
609
610 assert_eq!(p.parse(0xd0), None);
611 assert_eq!(p.parse(0xf9), None);
612 assert_eq!(p.parse(0xee), None);
613 assert_eq!(p.parse(0x5d), None);
614 assert_eq!(p.parse(0x40), None);
615 assert_eq!(p.parse(0x51), None);
616 assert_eq!(p.parse(0x00), None);
617 assert_eq!(p.parse(0x06), None);
618 assert_eq!(p.parse(0x03), None);
619 assert_eq!(p.parse(0xab), None);
620 assert_eq!(p.parse(0x00), None);
621 assert_eq!(p.parse(0x08), None);
622 assert_eq!(p.parse(0x01), None);
623 assert_eq!(
624 p.parse(0x07),
625 Some(Response::NotificationActiveScan {
626 channel: Channel::Ch7F923p7MHz,
627 terminal: Vec::new()
628 })
629 );
630
631 assert_eq!(p.parse(0xd0), None);
632 assert_eq!(p.parse(0xf9), None);
633 assert_eq!(p.parse(0xee), None);
634 assert_eq!(p.parse(0x5d), None);
635 assert_eq!(p.parse(0x40), None);
636 assert_eq!(p.parse(0x51), None);
637 assert_eq!(p.parse(0x00), None);
638 assert_eq!(p.parse(0x1d), None);
639 assert_eq!(p.parse(0x03), None);
640 assert_eq!(p.parse(0xc2), None);
641 assert_eq!(p.parse(0x05), None);
642 assert_eq!(p.parse(0x1e), None);
643 assert_eq!(p.parse(0x00), None); assert_eq!(p.parse(0x0c), None); assert_eq!(p.parse(0x02), None); assert_eq!(p.parse(0x00), None); assert_eq!(p.parse(0x01), None);
648 assert_eq!(p.parse(0x02), None);
649 assert_eq!(p.parse(0x03), None);
650 assert_eq!(p.parse(0x04), None);
651 assert_eq!(p.parse(0x05), None);
652 assert_eq!(p.parse(0x06), None);
653 assert_eq!(p.parse(0x07), None);
654 assert_eq!(p.parse(0xab), None); assert_eq!(p.parse(0xcd), None);
656 assert_eq!(p.parse(0xde), None); assert_eq!(p.parse(0x00), None); assert_eq!(p.parse(0x10), None);
659 assert_eq!(p.parse(0x20), None);
660 assert_eq!(p.parse(0x30), None);
661 assert_eq!(p.parse(0x40), None);
662 assert_eq!(p.parse(0x50), None);
663 assert_eq!(p.parse(0x60), None);
664 assert_eq!(p.parse(0x70), None);
665 assert_eq!(p.parse(0x12), None); assert_eq!(p.parse(0x34), None);
667 assert_eq!(
668 p.parse(0x98), Some(Response::NotificationActiveScan {
670 channel: Channel::Ch12F925p7MHz,
671 terminal: vec![
672 TerminalInformation {
673 mac_address: 0x0001020304050607,
674 pan_id: 0xabcd,
675 rssi: 0xde_u8 as i8,
676 },
677 TerminalInformation {
678 mac_address: 0x0010203040506070,
679 pan_id: 0x1234,
680 rssi: 0x98_u8 as i8,
681 },
682 ],
683 })
684 );
685
686 assert_eq!(p.parse(0xd0), None);
687 assert_eq!(p.parse(0xf9), None);
688 assert_eq!(p.parse(0xee), None);
689 assert_eq!(p.parse(0x5d), None);
690 assert_eq!(p.parse(0x20), None);
691 assert_eq!(p.parse(0x6b), None);
692 assert_eq!(p.parse(0x00), None);
693 assert_eq!(p.parse(0x0d), None);
694 assert_eq!(p.parse(0x03), None);
695 assert_eq!(p.parse(0xac), None);
696 assert_eq!(p.parse(0x00), None);
697 assert_eq!(p.parse(0xa8), None);
698 assert_eq!(p.parse(0x01), None);
699 assert_eq!(p.parse(0x04), None);
700 assert_eq!(p.parse(0x00), None);
701 assert_eq!(p.parse(0x01), None);
702 assert_eq!(p.parse(0x03), None);
703 assert_eq!(p.parse(0x00), None);
704 assert_eq!(p.parse(0x00), None);
705 assert_eq!(p.parse(0x15), None);
706 assert_eq!(
707 p.parse(0x8a),
708 Some(Response::GetVersionInformation {
709 result: 0x01,
710 firmware_id: 0x400,
711 major: 0x01,
712 minor: 0x03,
713 revision: 0x0000158a,
714 })
715 );
716
717 assert_eq!(p.parse(0xd0), None);
718 assert_eq!(p.parse(0xf9), None);
719 assert_eq!(p.parse(0xee), None);
720 assert_eq!(p.parse(0x5d), None);
721 assert_eq!(p.parse(0x60), None);
722 assert_eq!(p.parse(0x18), None);
723 assert_eq!(p.parse(0x00), None);
724 assert_eq!(p.parse(0x23), None);
725 assert_eq!(p.parse(0x03), None);
726 assert_eq!(p.parse(0xaf), None);
727 assert_eq!(p.parse(0x06), None);
728 assert_eq!(p.parse(0xde), None);
729 assert_eq!(p.parse(0xfe), None); assert_eq!(p.parse(0x80), None);
731 assert_eq!(p.parse(0x00), None);
732 assert_eq!(p.parse(0x01), None);
733 assert_eq!(p.parse(0x02), None);
734 assert_eq!(p.parse(0x03), None);
735 assert_eq!(p.parse(0x04), None);
736 assert_eq!(p.parse(0x05), None);
737 assert_eq!(p.parse(0x06), None);
738 assert_eq!(p.parse(0x07), None);
739 assert_eq!(p.parse(0x08), None);
740 assert_eq!(p.parse(0x09), None);
741 assert_eq!(p.parse(0x0a), None);
742 assert_eq!(p.parse(0x0b), None);
743 assert_eq!(p.parse(0x0c), None);
744 assert_eq!(p.parse(0x0d), None);
745 assert_eq!(p.parse(0xab), None); assert_eq!(p.parse(0xcd), None);
747 assert_eq!(p.parse(0x12), None); assert_eq!(p.parse(0x34), None);
749 assert_eq!(p.parse(0x56), None); assert_eq!(p.parse(0x78), None);
751 assert_eq!(p.parse(0x01), None); assert_eq!(p.parse(0x02), None); assert_eq!(p.parse(0xde), None); assert_eq!(p.parse(0x00), None); assert_eq!(p.parse(0x04), None);
756 assert_eq!(p.parse(0x98), None); assert_eq!(p.parse(0x76), None);
758 assert_eq!(p.parse(0x54), None);
759 assert_eq!(
760 p.parse(0x32),
761 Some(Response::NotificationUdpReceived {
762 source_address: 0xfe80000102030405060708090a0b0c0d,
763 source_port: 0xabcd,
764 destination_port: 0x1234,
765 source_pan_id: 0x5678,
766 source_type: 0x01,
767 encryption: 0x02,
768 rssi: 0xde_u8 as i8,
769 data: vec![0x98, 0x76, 0x54, 0x32],
770 })
771 );
772
773 assert_eq!(p.parse(0xd0), None);
774 assert_eq!(p.parse(0xf9), None);
775 assert_eq!(p.parse(0xee), None);
776 assert_eq!(p.parse(0x5d), None);
777 assert_eq!(p.parse(0x60), None);
778 assert_eq!(p.parse(0x19), None);
779 assert_eq!(p.parse(0x00), None);
780 assert_eq!(p.parse(0x04), None);
781 assert_eq!(p.parse(0x03), None);
782 assert_eq!(p.parse(0x91), None);
783 assert_eq!(p.parse(0x00), None);
784 assert_eq!(p.parse(0x00), Some(Response::NotificationPoweredOn));
785
786 assert_eq!(p.parse(0xd0), None);
787 assert_eq!(p.parse(0xf9), None);
788 assert_eq!(p.parse(0xee), None);
789 assert_eq!(p.parse(0x5d), None);
790 assert_eq!(p.parse(0x60), None);
791 assert_eq!(p.parse(0x1a), None);
792 assert_eq!(p.parse(0x00), None);
793 assert_eq!(p.parse(0x0e), None);
794 assert_eq!(p.parse(0x03), None);
795 assert_eq!(p.parse(0x9c), None);
796 assert_eq!(p.parse(0x00), None);
797 assert_eq!(p.parse(0xfb), None);
798 assert_eq!(p.parse(0x01), None); assert_eq!(p.parse(0x00), None); assert_eq!(p.parse(0x01), None);
801 assert_eq!(p.parse(0x02), None);
802 assert_eq!(p.parse(0x03), None);
803 assert_eq!(p.parse(0x04), None);
804 assert_eq!(p.parse(0x05), None);
805 assert_eq!(p.parse(0x06), None);
806 assert_eq!(p.parse(0x07), None);
807 assert_eq!(
808 p.parse(0xde), Some(Response::NotificationConnectionChanged {
810 state: 0x01,
811 mac_address: 0x0001020304050607,
812 rssi: 0xde_u8 as i8,
813 })
814 );
815
816 assert_eq!(p.parse(0xd0), None);
817 assert_eq!(p.parse(0xf9), None);
818 assert_eq!(p.parse(0xee), None);
819 assert_eq!(p.parse(0x5d), None);
820 assert_eq!(p.parse(0x60), None);
821 assert_eq!(p.parse(0x28), None);
822 assert_eq!(p.parse(0x00), None);
823 assert_eq!(p.parse(0x0d), None);
824 assert_eq!(p.parse(0x03), None);
825 assert_eq!(p.parse(0xa9), None);
826 assert_eq!(p.parse(0x00), None);
827 assert_eq!(p.parse(0x1d), None);
828 assert_eq!(p.parse(0x01), None); assert_eq!(p.parse(0x00), None); assert_eq!(p.parse(0x01), None);
831 assert_eq!(p.parse(0x02), None);
832 assert_eq!(p.parse(0x03), None);
833 assert_eq!(p.parse(0x04), None);
834 assert_eq!(p.parse(0x05), None);
835 assert_eq!(p.parse(0x06), None);
836 assert_eq!(
837 p.parse(0x07),
838 Some(Response::NotificationPanaAuthentication {
839 result: 0x01,
840 mac_address: 0x0001020304050607,
841 })
842 );
843
844 assert_eq!(p.parse(0xd0), None);
845 assert_eq!(p.parse(0xf9), None);
846 assert_eq!(p.parse(0xee), None);
847 assert_eq!(p.parse(0x5d), None);
848 assert_eq!(p.parse(0x20), None);
849 assert_eq!(p.parse(0x59), None);
850 assert_eq!(p.parse(0x00), None);
851 assert_eq!(p.parse(0x15), None);
852 assert_eq!(p.parse(0x03), None);
853 assert_eq!(p.parse(0xa2), None);
854 assert_eq!(p.parse(0x00), None);
855 assert_eq!(p.parse(0x79), None);
856 assert_eq!(p.parse(0x01), None);
857 assert_eq!(p.parse(0x00), None);
858 assert_eq!(p.parse(0x01), None);
859 assert_eq!(p.parse(0x02), None);
860 assert_eq!(p.parse(0x03), None);
861 assert_eq!(p.parse(0x04), None);
862 assert_eq!(p.parse(0x05), None);
863 assert_eq!(p.parse(0x06), None);
864 assert_eq!(p.parse(0x07), None);
865 assert_eq!(p.parse(0x08), None);
866 assert_eq!(p.parse(0x09), None);
867 assert_eq!(p.parse(0x0a), None);
868 assert_eq!(p.parse(0x0b), None);
869 assert_eq!(p.parse(0x0c), None);
870 assert_eq!(p.parse(0x0d), None);
871 assert_eq!(p.parse(0x0e), None);
872 assert_eq!(
873 p.parse(0x0f),
874 Some(Response::GetRouteBEncryptionKey {
875 result: 0x01,
876 encryption_key: [
877 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
878 0x0d, 0x0e, 0x0f
879 ]
880 })
881 );
882
883 assert_eq!(p.parse(0xd0), None);
884 assert_eq!(p.parse(0xf9), None);
885 assert_eq!(p.parse(0xee), None);
886 assert_eq!(p.parse(0x5d), None);
887 assert_eq!(p.parse(0x20), None);
888 assert_eq!(p.parse(0x5e), None);
889 assert_eq!(p.parse(0x00), None);
890 assert_eq!(p.parse(0x07), None);
891 assert_eq!(p.parse(0x03), None);
892 assert_eq!(p.parse(0x99), None);
893 assert_eq!(p.parse(0x00), None);
894 assert_eq!(p.parse(0x06), None);
895 assert_eq!(p.parse(0x01), None);
896 assert_eq!(p.parse(0x02), None);
897 assert_eq!(
898 p.parse(0x03),
899 Some(Response::GetRouteBPanId {
900 result: 0x01,
901 pan_id: 0x0203,
902 })
903 );
904
905 assert_eq!(p.parse(0xd0), None);
906 assert_eq!(p.parse(0xf9), None);
907 assert_eq!(p.parse(0xee), None);
908 assert_eq!(p.parse(0x5d), None);
909 assert_eq!(p.parse(0x20), None);
910 assert_eq!(p.parse(0x54), None);
911 assert_eq!(p.parse(0x00), None);
912 assert_eq!(p.parse(0x05), None);
913 assert_eq!(p.parse(0x03), None);
914 assert_eq!(p.parse(0x8d), None);
915 assert_eq!(p.parse(0x00), None);
916 assert_eq!(p.parse(0x01), None);
917 assert_eq!(
918 p.parse(0x01),
919 Some(Response::SetRouteBPanaAuthenticationInformation { result: 0x01 })
920 );
921
922 assert_eq!(p.parse(0xd0), None);
923 assert_eq!(p.parse(0xf9), None);
924 assert_eq!(p.parse(0xee), None);
925 assert_eq!(p.parse(0x5d), None);
926 assert_eq!(p.parse(0x20), None);
927 assert_eq!(p.parse(0x53), None);
928 assert_eq!(p.parse(0x00), None);
929 assert_eq!(p.parse(0x05), None);
930 assert_eq!(p.parse(0x03), None);
931 assert_eq!(p.parse(0x8c), None);
932 assert_eq!(p.parse(0x00), None);
933 assert_eq!(p.parse(0x02), None);
934 assert_eq!(
935 p.parse(0x02),
936 Some(Response::StartRouteBOperation {
937 result: 0x02,
938 terminal: None,
939 })
940 );
941
942 assert_eq!(p.parse(0xd0), None);
943 assert_eq!(p.parse(0xf9), None);
944 assert_eq!(p.parse(0xee), None);
945 assert_eq!(p.parse(0x5d), None);
946 assert_eq!(p.parse(0x20), None);
947 assert_eq!(p.parse(0x53), None);
948 assert_eq!(p.parse(0x00), None);
949 assert_eq!(p.parse(0x11), None);
950 assert_eq!(p.parse(0x03), None);
951 assert_eq!(p.parse(0x98), None);
952 assert_eq!(p.parse(0x02), None);
953 assert_eq!(p.parse(0x7b), None);
954 assert_eq!(p.parse(0x01), None);
955 assert_eq!(p.parse(0x08), None); assert_eq!(p.parse(0xab), None); assert_eq!(p.parse(0xcd), None);
958 assert_eq!(p.parse(0x00), None); assert_eq!(p.parse(0x01), None);
960 assert_eq!(p.parse(0x02), None);
961 assert_eq!(p.parse(0x03), None);
962 assert_eq!(p.parse(0x04), None);
963 assert_eq!(p.parse(0x05), None);
964 assert_eq!(p.parse(0x06), None);
965 assert_eq!(p.parse(0x07), None);
966 assert_eq!(
967 p.parse(0xde), Some(Response::StartRouteBOperation {
969 result: 0x01,
970 terminal: Some((
971 Channel::Ch8F924p1MHz,
972 TerminalInformation {
973 mac_address: 0x0001020304050607,
974 pan_id: 0xabcd,
975 rssi: 0xde_u8 as i8,
976 }
977 )),
978 })
979 );
980
981 assert_eq!(p.parse(0xd0), None);
982 assert_eq!(p.parse(0xf9), None);
983 assert_eq!(p.parse(0xee), None);
984 assert_eq!(p.parse(0x5d), None);
985 assert_eq!(p.parse(0x20), None);
986 assert_eq!(p.parse(0x56), None);
987 assert_eq!(p.parse(0x00), None);
988 assert_eq!(p.parse(0x05), None);
989 assert_eq!(p.parse(0x03), None);
990 assert_eq!(p.parse(0x8f), None);
991 assert_eq!(p.parse(0x00), None);
992 assert_eq!(p.parse(0x01), None);
993 assert_eq!(
994 p.parse(0x01),
995 Some(Response::StartRouteBPana { result: 0x01 })
996 );
997
998 assert_eq!(p.parse(0xd0), None);
999 assert_eq!(p.parse(0xf9), None);
1000 assert_eq!(p.parse(0xee), None);
1001 assert_eq!(p.parse(0x5d), None);
1002 assert_eq!(p.parse(0x20), None);
1003 assert_eq!(p.parse(0x57), None);
1004 assert_eq!(p.parse(0x00), None);
1005 assert_eq!(p.parse(0x05), None);
1006 assert_eq!(p.parse(0x03), None);
1007 assert_eq!(p.parse(0x90), None);
1008 assert_eq!(p.parse(0x00), None);
1009 assert_eq!(p.parse(0x01), None);
1010 assert_eq!(
1011 p.parse(0x01),
1012 Some(Response::TerminateRouteBPana { result: 0x01 })
1013 );
1014
1015 assert_eq!(p.parse(0xd0), None);
1016 assert_eq!(p.parse(0xf9), None);
1017 assert_eq!(p.parse(0xee), None);
1018 assert_eq!(p.parse(0x5d), None);
1019 assert_eq!(p.parse(0x20), None);
1020 assert_eq!(p.parse(0x58), None);
1021 assert_eq!(p.parse(0x00), None);
1022 assert_eq!(p.parse(0x05), None);
1023 assert_eq!(p.parse(0x03), None);
1024 assert_eq!(p.parse(0x91), None);
1025 assert_eq!(p.parse(0x00), None);
1026 assert_eq!(p.parse(0x01), None);
1027 assert_eq!(
1028 p.parse(0x01),
1029 Some(Response::TerminateRouteBOperation { result: 0x01 })
1030 );
1031
1032 assert_eq!(p.parse(0xd0), None);
1033 assert_eq!(p.parse(0xf9), None);
1034 assert_eq!(p.parse(0xee), None);
1035 assert_eq!(p.parse(0x5d), None);
1036 assert_eq!(p.parse(0x20), None);
1037 assert_eq!(p.parse(0xd2), None);
1038 assert_eq!(p.parse(0x00), None);
1039 assert_eq!(p.parse(0x05), None);
1040 assert_eq!(p.parse(0x04), None);
1041 assert_eq!(p.parse(0x0b), None);
1042 assert_eq!(p.parse(0x00), None);
1043 assert_eq!(p.parse(0x01), None);
1044 assert_eq!(
1045 p.parse(0x01),
1046 Some(Response::RedoRouteBPanaAuthentication { result: 0x01 })
1047 );
1048 }
1049}