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