bp35c0_j11/
response.rs

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); // result
644        assert_eq!(p.parse(0x0c), None); // channel
645        assert_eq!(p.parse(0x02), None); // # of scans
646        assert_eq!(p.parse(0x00), None); // terminal[0].mac_address
647        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); // terminal[0].pan_id
655        assert_eq!(p.parse(0xcd), None);
656        assert_eq!(p.parse(0xde), None); // terminal[0].rssi
657        assert_eq!(p.parse(0x00), None); // terminal[1].mac_address
658        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); // terminal[1].pan_id
666        assert_eq!(p.parse(0x34), None);
667        assert_eq!(
668            p.parse(0x98), // terminal[1].rssi
669            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); // source_address
730        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); // source_port
746        assert_eq!(p.parse(0xcd), None);
747        assert_eq!(p.parse(0x12), None); // destination_port
748        assert_eq!(p.parse(0x34), None);
749        assert_eq!(p.parse(0x56), None); // source_pan_id
750        assert_eq!(p.parse(0x78), None);
751        assert_eq!(p.parse(0x01), None); // source_type
752        assert_eq!(p.parse(0x02), None); // encryption
753        assert_eq!(p.parse(0xde), None); // rssi
754        assert_eq!(p.parse(0x00), None); // len
755        assert_eq!(p.parse(0x04), None);
756        assert_eq!(p.parse(0x98), None); // data
757        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); // state
799        assert_eq!(p.parse(0x00), None); // mac_address
800        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), // terminal[0].rssi
809            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); // result
829        assert_eq!(p.parse(0x00), None); // mac_address
830        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); // channel
956        assert_eq!(p.parse(0xab), None); // pan_id
957        assert_eq!(p.parse(0xcd), None);
958        assert_eq!(p.parse(0x00), None); // mac_address
959        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), // terminal[0].rssi
968            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}