AIS 消息由位向量组成;每条消息中的各个字段都是任意数量的位长,并且它们并不总是在字节边界上对齐。
然后这个位向量被 ASCII 编码,并嵌入到NMEA语句中。
来自http://catb.org/gpsd/AIVDM.html:
数据有效载荷是一个 ASCII 编码的位向量。每个字符代表六位数据。要恢复六位,请从 ASCII 字符值中减去 48;如果结果大于 40,则减去 8。根据 [IEC-PAS],此编码的有效 ASCII 字符以“0”(64)开头,以“w”(87)结尾;但是,不使用中间范围“X”(88)到“_”(95)。
例子
!AIVDM,1,1,,A,D03Ovk1T1N>5N8ffqMhNfp0,0*68
是 NMEA 句子D03Ovk1T1N>5N8ffqMhNfp0
是编码的 AIS 数据010100000000000011011111111110110011000001100100000001011110001110000101011110001000101110101110111001011101110000011110101110111000000000
是解码后的 AIS 数据作为位向量
问题
我把这些列在一起是因为我认为它们可能是相关的……
1. 将 ASCII 解码为位向量
我可以手动完成,通过迭代字符,减去适当的值,并通过做大量的位移工作来构建一个字节数组,等等。这很好,但似乎我应该能够在 nom 中执行此操作,并将其与实际的 AIS 位解析器链接起来,从而消除临时字节数组。
2.读取任意位数
例如,可以从 nom 字节数组中读取 3 位。但是,每次调用bits!
似乎一次消耗一个完整的字节(如果读入 a u8
)。
例如:
named!(take_3_bits<u8>, bits!(take_bits!(u8, 3)));
将 3 位读入u8
. 但如果我运行take_3_bits
两次,我将消耗 16 位流。
我可以结合阅读:
named!(get_field_1_and_2<(u8, u8)>, bits!(pair!(take_bits!(u8, 2), take_bits!(u8, 3))));
调用get_field_1_and_2
会给我一个(u8, u8)
元组,其中第一项包含前 2 位,第二项包含接下来的 3 位,但 nom 在读取后仍将前进一个完整字节。
我可以peek
用来阻止 nom 的读取指针前进,然后手动管理它,但同样,这似乎是不必要的额外工作。