Betaflight setup wizard
1import betaflight_wizard/msp/msp
2import gleam/bit_array
3import gleam/int
4
5pub fn msp_encode_v1_empty_test() {
6 do_msp_encode_v1_empty(0)
7}
8
9pub fn encode_random_v1_message_test() {
10 let op_code = int.random(256)
11 let input_data_length = 100 + int.random(100)
12 let input_data = fill_input_data(input_data_length, 0, <<>>)
13
14 let encoded = msp.encode_v1_raw(op_code, input_data)
15 let encoded_length = bit_array.byte_size(encoded)
16
17 assert bit_array.slice(encoded, 0, 3) == Ok(<<"$M":utf8, "<":utf8>>)
18 assert bit_array.slice(encoded, 3, 1) == Ok(<<input_data_length:size(8)>>)
19 assert bit_array.slice(encoded, 4, 1) == Ok(<<op_code:size(8)>>)
20 assert bit_array.slice(encoded, 5, input_data_length) == Ok(input_data)
21 assert bit_array.slice(encoded, encoded_length - 1, 1)
22 == Ok(<<
23 msp.calculate_crc_v1(input_data_length, op_code, input_data, 0):size(8),
24 >>)
25}
26
27pub fn msp_encode_v2_empty_test() {
28 do_msp_encode_v2_empty(0)
29}
30
31pub fn encode_random_v2_message_test() {
32 let op_code = int.random(65_536)
33 let flag = int.random(256)
34 let input_data_length = int.random(65_536)
35 let input_data = fill_input_data(input_data_length, 0, <<>>)
36
37 let encoded = msp.encode_v2_raw(command: op_code, flag:, data: input_data)
38 let encoded_length = bit_array.byte_size(encoded)
39
40 // preamble, direction, flag, cmd low, cmd high, size, data, crc
41 // preamble, direction
42 assert bit_array.slice(encoded, 0, 3) == Ok(<<"$X", "<">>)
43 // flag
44 assert bit_array.slice(encoded, 3, 1) == Ok(<<flag>>)
45 // cmd
46 assert bit_array.slice(encoded, 4, 2) == Ok(<<op_code:little-size(16)>>)
47 // size
48 assert bit_array.slice(encoded, 6, 2)
49 == Ok(<<input_data_length:little-size(16)>>)
50 // data
51 assert bit_array.slice(encoded, 8, input_data_length) == Ok(input_data)
52 // crc
53 assert bit_array.slice(encoded, encoded_length - 1, 1)
54 == Ok(<<
55 msp.calculate_crc_v2(
56 size: input_data_length,
57 flag:,
58 cmd: op_code,
59 data: input_data,
60 ),
61 >>)
62}
63
64fn do_msp_encode_v1_empty(cmd: Int) {
65 case cmd {
66 256 -> Nil
67 _ -> {
68 let encoded = msp.encode_v1_raw(cmd, <<>>)
69 // preamble, direction, data size, command, data, crc
70 assert encoded == <<"$M", "<", 0, cmd, cmd>>
71 do_msp_encode_v1_empty(cmd + 1)
72 }
73 }
74}
75
76fn fill_input_data(input_data_length: Int, n: Int, data: BitArray) -> BitArray {
77 case n {
78 n if n >= input_data_length -> data
79 n ->
80 fill_input_data(input_data_length, n + 1, <<data:bits, int.random(256)>>)
81 }
82}
83
84fn do_msp_encode_v2_empty(cmd: Int) {
85 case cmd {
86 // MSPv2 commands are 16bit rather than 8bit
87 65_536 -> Nil
88 _ -> {
89 let encoded = msp.encode_v2_raw(command: cmd, flag: 0, data: <<>>)
90 // preamble, direction, flag, cmd low, cmd high, size, data, crc
91 assert encoded
92 == <<
93 "$X",
94 "<",
95 0,
96 cmd:little-size(16),
97 0:size(16),
98 // skip data
99 msp.calculate_crc_v2(size: 0, cmd: cmd, flag: 0, data: <<>>),
100 >>
101 do_msp_encode_v2_empty(cmd + 1)
102 }
103 }
104}