bp35c0_j11/
command.rs

1use crate::*;
2
3#[derive(Copy, Clone, Eq, PartialEq, Debug)]
4#[cfg_attr(feature = "defmt", derive(defmt::Format))]
5pub enum Command<'a> {
6    GetStatus,
7    GetUdpPorts,
8    GetIpAddress,
9    GetMacAddress,
10    GetClientMacAddress,
11    GetClientIpAddress,
12    GetNeighborDiscoverySettings,
13    GetOperationMode,
14    GetUartSettings,
15
16    SetOperationMode {
17        mode: OperationMode,
18        han_sleep: bool,
19        channel: Channel,
20        tx_power: TxPower,
21    },
22    SetNeighborDiscoverySettings {
23        enable: bool,
24    },
25    SetUartSettings {
26        flow_control: bool,
27    },
28
29    OpenUdpPort(u16),
30    CloseUdpPort(u16),
31    TransmitData {
32        destination_address: u128,
33        source_port: u16,
34        destination_port: u16,
35        data: &'a [u8],
36    },
37    DoActiveScan {
38        duration: ScanDuration,
39        mask_channels: u32,
40        pairing_id: Option<u64>,
41    },
42
43    GetVersionInformation,
44
45    SetRouteBPanaAuthenticationInformation {
46        id: &'a [u8],
47        password: &'a [u8],
48    },
49
50    StartRouteBOperation,
51    StartRouteBPana,
52    TerminateRouteBPana,
53    TerminateRouteBOperation,
54    RedoRouteBPanaAuthentication,
55}
56
57#[allow(clippy::result_unit_err)] // TODO:
58pub fn serialize_to_bytes<'a>(cmd: &'a Command<'a>, buf: &mut [u8]) -> Result<usize, ()> {
59    let mut total_len = COMMAND_RANGE_DATA.start;
60
61    if buf.len() < total_len {
62        return Err(());
63    }
64
65    buf[COMMAND_RANGE_UNIQUE_CODE].copy_from_slice(&0xd0ea83fc_u32.to_be_bytes());
66
67    match cmd {
68        Command::GetStatus => {
69            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0001_u16.to_be_bytes())
70        }
71
72        Command::GetUdpPorts => {
73            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0007_u16.to_be_bytes())
74        }
75
76        Command::GetIpAddress => {
77            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0009_u16.to_be_bytes())
78        }
79
80        Command::GetMacAddress => {
81            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x000e_u16.to_be_bytes())
82        }
83
84        Command::GetClientMacAddress => {
85            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0011_u16.to_be_bytes())
86        }
87
88        Command::GetClientIpAddress => {
89            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0100_u16.to_be_bytes())
90        }
91
92        Command::GetNeighborDiscoverySettings => {
93            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0102_u16.to_be_bytes())
94        }
95
96        Command::GetOperationMode => {
97            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0107_u16.to_be_bytes())
98        }
99
100        Command::GetUartSettings => {
101            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x010b_u16.to_be_bytes())
102        }
103
104        Command::SetOperationMode {
105            mode,
106            han_sleep,
107            channel,
108            tx_power,
109        } => {
110            let data = [
111                u8::from(*mode),
112                if *han_sleep { 0x01 } else { 0x00 },
113                u8::from(*channel),
114                u8::from(*tx_power),
115            ];
116            total_len += data.len();
117            if buf.len() < total_len {
118                return Err(());
119            }
120            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x005f_u16.to_be_bytes());
121            buf[COMMAND_RANGE_DATA.start..COMMAND_RANGE_DATA.start + data.len()]
122                .copy_from_slice(&data);
123        }
124
125        Command::SetNeighborDiscoverySettings { enable } => {
126            let data = [*enable as _];
127            total_len += data.len();
128            if buf.len() < total_len {
129                return Err(());
130            }
131            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0101_u16.to_be_bytes());
132            buf[COMMAND_RANGE_DATA.start..COMMAND_RANGE_DATA.start + data.len()]
133                .copy_from_slice(&data);
134        }
135
136        Command::SetUartSettings { flow_control } => {
137            let data = [*flow_control as _];
138            total_len += data.len();
139            if buf.len() < total_len {
140                return Err(());
141            }
142            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x010a_u16.to_be_bytes());
143            buf[COMMAND_RANGE_DATA.start..COMMAND_RANGE_DATA.start + data.len()]
144                .copy_from_slice(&data);
145        }
146
147        Command::OpenUdpPort(port) => {
148            let data = port.to_be_bytes();
149            total_len += data.len();
150            if buf.len() < total_len {
151                return Err(());
152            }
153            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0005_u16.to_be_bytes());
154            buf[COMMAND_RANGE_DATA.start..COMMAND_RANGE_DATA.start + data.len()]
155                .copy_from_slice(&data);
156        }
157
158        Command::CloseUdpPort(port) => {
159            let data = port.to_be_bytes();
160            total_len += data.len();
161            if buf.len() < total_len {
162                return Err(());
163            }
164            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0006_u16.to_be_bytes());
165            buf[COMMAND_RANGE_DATA.start..COMMAND_RANGE_DATA.start + data.len()]
166                .copy_from_slice(&data);
167        }
168
169        Command::TransmitData {
170            destination_address,
171            source_port,
172            destination_port,
173            data,
174        } => {
175            if data.len() > 0x4d0 {
176                return Err(());
177            }
178            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0008_u16.to_be_bytes());
179
180            let mut data_len = 0;
181            for s in [
182                destination_address.to_be_bytes().as_slice(),
183                source_port.to_be_bytes().as_slice(),
184                destination_port.to_be_bytes().as_slice(),
185                (data.len() as u16).to_be_bytes().as_slice(),
186                data,
187            ] {
188                let new_data_len = data_len + s.len();
189                if buf.len() < total_len + new_data_len {
190                    return Err(());
191                }
192                buf[total_len + data_len..total_len + new_data_len].copy_from_slice(s);
193                data_len = new_data_len;
194            }
195            total_len += data_len;
196        }
197
198        Command::DoActiveScan {
199            duration,
200            mask_channels,
201            pairing_id: None,
202        } => {
203            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0051_u16.to_be_bytes());
204
205            let mut data_len = 0;
206            for s in [
207                u8::from(*duration).to_be_bytes().as_slice(),
208                mask_channels.to_be_bytes().as_slice(),
209                0x00_u8.to_be_bytes().as_slice(),
210            ] {
211                let new_data_len = data_len + s.len();
212                if buf.len() < total_len + new_data_len {
213                    return Err(());
214                }
215                buf[total_len + data_len..total_len + new_data_len].copy_from_slice(s);
216                data_len = new_data_len;
217            }
218            total_len += data_len;
219        }
220
221        Command::DoActiveScan {
222            duration,
223            mask_channels,
224            pairing_id: Some(pairing_id),
225        } => {
226            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0051_u16.to_be_bytes());
227
228            let mut data_len = 0;
229            for s in [
230                u8::from(*duration).to_be_bytes().as_slice(),
231                mask_channels.to_be_bytes().as_slice(),
232                0x01_u8.to_be_bytes().as_slice(),
233                pairing_id.to_be_bytes().as_slice(),
234            ] {
235                let new_data_len = data_len + s.len();
236                if buf.len() < total_len + new_data_len {
237                    return Err(());
238                }
239                buf[total_len + data_len..total_len + new_data_len].copy_from_slice(s);
240                data_len = new_data_len;
241            }
242            total_len += data_len;
243        }
244
245        Command::GetVersionInformation => {
246            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x006b_u16.to_be_bytes())
247        }
248
249        Command::SetRouteBPanaAuthenticationInformation { id, password } => {
250            if id.len() != 32 || password.len() != 12 {
251                return Err(());
252            }
253
254            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0054_u16.to_be_bytes());
255
256            let mut data_len = 0;
257            for s in [id, password] {
258                let new_data_len = data_len + s.len();
259                if buf.len() < total_len + new_data_len {
260                    return Err(());
261                }
262                buf[total_len + data_len..total_len + new_data_len].copy_from_slice(s);
263                data_len = new_data_len;
264            }
265            total_len += data_len;
266        }
267
268        Command::StartRouteBOperation => {
269            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0053_u16.to_be_bytes())
270        }
271
272        Command::StartRouteBPana => {
273            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0056_u16.to_be_bytes())
274        }
275
276        Command::TerminateRouteBPana => {
277            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0057_u16.to_be_bytes())
278        }
279
280        Command::TerminateRouteBOperation => {
281            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x0058_u16.to_be_bytes())
282        }
283
284        Command::RedoRouteBPanaAuthentication => {
285            buf[COMMAND_RANGE_COMMAND_CODE].copy_from_slice(&0x00d2_u16.to_be_bytes())
286        }
287    }
288
289    let message_len = (total_len - 4 - 2 - 2) as u16;
290    buf[COMMAND_RANGE_MESSAGE_LEN].copy_from_slice(&message_len.to_be_bytes());
291
292    let header_sum = buf[COMMAND_RANGE_UNIQUE_CODE.start..COMMAND_RANGE_HEADER_SUM.start]
293        .iter()
294        .fold(0_u16, |acc, &x| acc + x as u16);
295    buf[COMMAND_RANGE_HEADER_SUM].copy_from_slice(&header_sum.to_be_bytes());
296
297    let data_sum = buf[COMMAND_RANGE_DATA.start..total_len]
298        .iter()
299        .fold(0_u16, |acc, &x| acc + x as u16);
300    buf[COMMAND_RANGE_DATA_SUM].copy_from_slice(&data_sum.to_be_bytes());
301
302    Ok(total_len)
303}
304
305#[cfg(test)]
306mod tests {
307    extern crate std;
308    use crate::command::*;
309
310    #[test]
311    fn test_serialize_to_bytes() {
312        let mut buf = [0; 256];
313
314        assert_eq!(
315            serialize_to_bytes(&Command::GetStatus, &mut buf).map(|len| &buf[..len]),
316            Ok([
317                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
318                0x00_u8, 0x01_u8, // command
319                0x00_u8, 0x04_u8, // length
320                0x03_u8, 0x3e_u8, // header sum
321                0x00_u8, 0x00_u8, // data sum
322            ]
323            .as_slice())
324        );
325
326        assert_eq!(
327            serialize_to_bytes(&Command::GetUdpPorts, &mut buf).map(|len| &buf[..len]),
328            Ok([
329                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
330                0x00_u8, 0x07_u8, // command
331                0x00_u8, 0x04_u8, // length
332                0x03_u8, 0x44_u8, // header sum
333                0x00_u8, 0x00_u8, // data sum
334            ]
335            .as_slice())
336        );
337
338        assert_eq!(
339            serialize_to_bytes(&Command::GetIpAddress, &mut buf).map(|len| &buf[..len]),
340            Ok([
341                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
342                0x00_u8, 0x09_u8, // command
343                0x00_u8, 0x04_u8, // length
344                0x03_u8, 0x46_u8, // header sum
345                0x00_u8, 0x00_u8, // data sum
346            ]
347            .as_slice())
348        );
349
350        assert_eq!(
351            serialize_to_bytes(&Command::GetMacAddress, &mut buf).map(|len| &buf[..len]),
352            Ok([
353                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
354                0x00_u8, 0x0e_u8, // command
355                0x00_u8, 0x04_u8, // length
356                0x03_u8, 0x4b_u8, // header sum
357                0x00_u8, 0x00_u8, // data sum
358            ]
359            .as_slice())
360        );
361
362        assert_eq!(
363            serialize_to_bytes(&Command::GetClientMacAddress, &mut buf).map(|len| &buf[..len]),
364            Ok([
365                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
366                0x00_u8, 0x11_u8, // command
367                0x00_u8, 0x04_u8, // length
368                0x03_u8, 0x4e_u8, // header sum
369                0x00_u8, 0x00_u8, // data sum
370            ]
371            .as_slice())
372        );
373
374        assert_eq!(
375            serialize_to_bytes(&Command::GetClientIpAddress, &mut buf).map(|len| &buf[..len]),
376            Ok([
377                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
378                0x01_u8, 0x00_u8, // command
379                0x00_u8, 0x04_u8, // length
380                0x03_u8, 0x3e_u8, // header sum
381                0x00_u8, 0x00_u8, // data sum
382            ]
383            .as_slice())
384        );
385
386        assert_eq!(
387            serialize_to_bytes(&Command::GetNeighborDiscoverySettings, &mut buf)
388                .map(|len| &buf[..len]),
389            Ok([
390                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
391                0x01_u8, 0x02_u8, // command
392                0x00_u8, 0x04_u8, // length
393                0x03_u8, 0x40_u8, // header sum
394                0x00_u8, 0x00_u8, // data sum
395            ]
396            .as_slice())
397        );
398
399        assert_eq!(
400            serialize_to_bytes(&Command::GetOperationMode, &mut buf).map(|len| &buf[..len]),
401            Ok([
402                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
403                0x01_u8, 0x07_u8, // command
404                0x00_u8, 0x04_u8, // length
405                0x03_u8, 0x45_u8, // header sum
406                0x00_u8, 0x00_u8, // data sum
407            ]
408            .as_slice())
409        );
410
411        assert_eq!(
412            serialize_to_bytes(&Command::GetUartSettings, &mut buf).map(|len| &buf[..len]),
413            Ok([
414                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
415                0x01_u8, 0x0b_u8, // command
416                0x00_u8, 0x04_u8, // length
417                0x03_u8, 0x49_u8, // header sum
418                0x00_u8, 0x00_u8, // data sum
419            ]
420            .as_slice())
421        );
422
423        assert_eq!(
424            serialize_to_bytes(
425                &Command::SetOperationMode {
426                    mode: OperationMode::Dual,
427                    han_sleep: false,
428                    channel: Channel::Ch5F922p9MHz,
429                    tx_power: TxPower::P20mW,
430                },
431                &mut buf,
432            )
433            .map(|len| &buf[..len]),
434            Ok([
435                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
436                0x00_u8, 0x5f_u8, // command
437                0x00_u8, 0x08_u8, // length
438                0x03_u8, 0xa0_u8, // header sum
439                0x00_u8, 0x0a_u8, // data sum
440                0x05_u8, // mode
441                0x00_u8, // han_sleep
442                0x05_u8, // channel
443                0x00_u8, // tx_power
444            ]
445            .as_slice())
446        );
447
448        assert_eq!(
449            serialize_to_bytes(
450                &Command::SetNeighborDiscoverySettings { enable: true },
451                &mut buf
452            )
453            .map(|len| &buf[..len]),
454            Ok([
455                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
456                0x01_u8, 0x01_u8, // command
457                0x00_u8, 0x05_u8, // length
458                0x03_u8, 0x40_u8, // header sum
459                0x00_u8, 0x01_u8, // data sum
460                0x01_u8, // enable
461            ]
462            .as_slice())
463        );
464
465        assert_eq!(
466            serialize_to_bytes(&Command::SetUartSettings { flow_control: true }, &mut buf)
467                .map(|len| &buf[..len]),
468            Ok([
469                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
470                0x01_u8, 0x0A_u8, // command
471                0x00_u8, 0x05_u8, // length
472                0x03_u8, 0x49_u8, // header sum
473                0x00_u8, 0x01_u8, // data sum
474                0x01_u8, // flow control
475            ]
476            .as_slice())
477        );
478
479        assert_eq!(
480            serialize_to_bytes(&Command::OpenUdpPort(0x1234), &mut buf).map(|len| &buf[..len]),
481            Ok([
482                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
483                0x00_u8, 0x05_u8, // command
484                0x00_u8, 0x06_u8, // length
485                0x03_u8, 0x44_u8, // header sum
486                0x00_u8, 0x46_u8, // data sum
487                0x12_u8, 0x34_u8, // port
488            ]
489            .as_slice())
490        );
491
492        assert_eq!(
493            serialize_to_bytes(&Command::CloseUdpPort(0x1234), &mut buf).map(|len| &buf[..len]),
494            Ok([
495                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
496                0x00_u8, 0x06_u8, // command
497                0x00_u8, 0x06_u8, // length
498                0x03_u8, 0x45_u8, // header sum
499                0x00_u8, 0x46_u8, // data sum
500                0x12_u8, 0x34_u8, // port
501            ]
502            .as_slice())
503        );
504
505        assert_eq!(
506            serialize_to_bytes(
507                &Command::TransmitData {
508                    destination_address: 0x123456789abcdef0123456789abcdef0,
509                    source_port: 0xabcd,
510                    destination_port: 0x1234,
511                    data: &[0xde, 0xad, 0xbe, 0xef],
512                },
513                &mut buf
514            )
515            .map(|len| &buf[..len]),
516            Ok([
517                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
518                0x00_u8, 0x08_u8, // command
519                0x00_u8, 0x1e_u8, // length
520                0x03_u8, 0x5f_u8, // header sum
521                0x0d_u8, 0x6a_u8, // data sum
522                0x12_u8, 0x34_u8, 0x56_u8, 0x78_u8, // address
523                0x9a_u8, 0xbc_u8, 0xde_u8, 0xf0_u8, //
524                0x12_u8, 0x34_u8, 0x56_u8, 0x78_u8, //
525                0x9a_u8, 0xbc_u8, 0xde_u8, 0xf0_u8, //
526                0xab_u8, 0xcd_u8, // source port
527                0x12_u8, 0x34_u8, // destination port
528                0x00_u8, 0x04_u8, // length
529                0xde_u8, 0xad_u8, 0xbe_u8, 0xef_u8, // data
530            ]
531            .as_slice())
532        );
533
534        assert_eq!(
535            serialize_to_bytes(
536                &Command::DoActiveScan {
537                    duration: ScanDuration::T38p56ms,
538                    mask_channels: 0x12345678,
539                    pairing_id: None,
540                },
541                &mut buf
542            )
543            .map(|len| &buf[..len]),
544            Ok([
545                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
546                0x00_u8, 0x51_u8, // command
547                0x00_u8, 0x0a_u8, // length
548                0x03_u8, 0x94_u8, // header sum
549                0x01_u8, 0x16_u8, // data sum
550                0x02_u8, // duration
551                0x12_u8, 0x34_u8, 0x56_u8, 0x78_u8, // channel mask
552                0x00_u8, // has pairing id
553            ]
554            .as_slice())
555        );
556
557        assert_eq!(
558            serialize_to_bytes(
559                &Command::DoActiveScan {
560                    duration: ScanDuration::T38p56ms,
561                    mask_channels: 0x12345678,
562                    pairing_id: Some(0x12345678_9abcdef0),
563                },
564                &mut buf
565            )
566            .map(|len| &buf[..len]),
567            Ok([
568                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
569                0x00_u8, 0x51_u8, // command
570                0x00_u8, 0x12_u8, // length
571                0x03_u8, 0x9c_u8, // header sum
572                0x05_u8, 0x4f_u8, // data sum
573                0x02_u8, // duration
574                0x12_u8, 0x34_u8, 0x56_u8, 0x78_u8, // channel mask
575                0x01_u8, // has pairing id
576                0x12_u8, 0x34_u8, 0x56_u8, 0x78_u8, // pairing id
577                0x9a_u8, 0xbc_u8, 0xde_u8, 0xf0_u8, //
578            ]
579            .as_slice())
580        );
581
582        assert_eq!(
583            serialize_to_bytes(&Command::GetVersionInformation, &mut buf).map(|len| &buf[..len]),
584            Ok([
585                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
586                0x00_u8, 0x6b_u8, // command
587                0x00_u8, 0x04_u8, // length
588                0x03_u8, 0xa8_u8, // header sum
589                0x00_u8, 0x00_u8, // data sum
590            ]
591            .as_slice())
592        );
593
594        assert_eq!(
595            serialize_to_bytes(
596                &Command::SetRouteBPanaAuthenticationInformation {
597                    id: b"ABCDEFGHIJKLMNOPQRSTUVWXYZ012345",
598                    password: b"0123456789ab",
599                },
600                &mut buf,
601            )
602            .map(|len| &buf[..len]),
603            Ok([
604                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
605                0x00_u8, 0x54_u8, // command
606                0x00_u8, 0x30_u8, // length
607                0x03_u8, 0xbd_u8, // header sum
608                0x0b_u8, 0xde_u8, // data sum
609                // id
610                b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', //
611                b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', //
612                b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X', //
613                b'Y', b'Z', b'0', b'1', b'2', b'3', b'4', b'5', //
614                // password
615                b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b',
616            ]
617            .as_slice())
618        );
619
620        assert_eq!(
621            serialize_to_bytes(&Command::StartRouteBOperation, &mut buf).map(|len| &buf[..len]),
622            Ok([
623                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
624                0x00_u8, 0x53_u8, // command
625                0x00_u8, 0x04_u8, // length
626                0x03_u8, 0x90_u8, // header sum
627                0x00_u8, 0x00_u8, // data sum
628            ]
629            .as_slice())
630        );
631
632        assert_eq!(
633            serialize_to_bytes(&Command::StartRouteBPana, &mut buf).map(|len| &buf[..len]),
634            Ok([
635                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
636                0x00_u8, 0x56_u8, // command
637                0x00_u8, 0x04_u8, // length
638                0x03_u8, 0x93_u8, // header sum
639                0x00_u8, 0x00_u8, // data sum
640            ]
641            .as_slice())
642        );
643
644        assert_eq!(
645            serialize_to_bytes(&Command::TerminateRouteBPana, &mut buf).map(|len| &buf[..len]),
646            Ok([
647                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
648                0x00_u8, 0x57_u8, // command
649                0x00_u8, 0x04_u8, // length
650                0x03_u8, 0x94_u8, // header sum
651                0x00_u8, 0x00_u8, // data sum
652            ]
653            .as_slice())
654        );
655
656        assert_eq!(
657            serialize_to_bytes(&Command::TerminateRouteBOperation, &mut buf).map(|len| &buf[..len]),
658            Ok([
659                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
660                0x00_u8, 0x58_u8, // command
661                0x00_u8, 0x04_u8, // length
662                0x03_u8, 0x95_u8, // header sum
663                0x00_u8, 0x00_u8, // data sum
664            ]
665            .as_slice())
666        );
667
668        assert_eq!(
669            serialize_to_bytes(&Command::RedoRouteBPanaAuthentication, &mut buf)
670                .map(|len| &buf[..len]),
671            Ok([
672                0xd0_u8, 0xea_u8, 0x83_u8, 0xfc_u8, // unique code
673                0x00_u8, 0xd2_u8, // command
674                0x00_u8, 0x04_u8, // length
675                0x04_u8, 0x0f_u8, // header sum
676                0x00_u8, 0x00_u8, // data sum
677            ]
678            .as_slice())
679        );
680    }
681}