10 个重大版本

0.11.0 2023年11月5日
0.10.0 2023年2月18日
0.9.0 2022年9月17日
0.8.0 2021年11月14日
0.6.0 2020年5月2日

#428 in 解析实现

Download history 16/week @ 2024-03-11 18/week @ 2024-03-25 47/week @ 2024-04-01 30/week @ 2024-04-22 23/week @ 2024-04-29 32/week @ 2024-05-13 48/week @ 2024-05-20 53/week @ 2024-05-27 12/week @ 2024-06-03 4/week @ 2024-06-10 8/week @ 2024-06-17 30/week @ 2024-06-24

每月58次下载

Apache-2.0

135KB
3.5K SLoC

AIS 解析器

这是用 Rust 编写的 AIS 消息解析器的开始。

文档

API 文档可在 https://docs.rs/ais 查找

试用

如果您只想查看一些 AIS NMEA 句子并了解其含义,可以尝试将其作为(非常粗糙的)命令行工具运行。

例如,如果您的 NMEA 源正在将 UDP 数据包发送到端口 4722

nc -u -l 4722 | cargo run

您应该开始看到消息流进来

AidToNavigationReport(AidToNavigationReport { message_type: 21, repeat_indicator: 1, mmsi: 993692016, aid_type: Some(ReferencePoint), name: "6W", accuracy: Unaugmented, longitude: Some(-122.80445), latitude: Some(37.705833), dimension_to_bow: 0, dimension_to_stern: 0, dimension_to_port: 0, dimension_to_starboard: 0, epfd_type: Some(Surveyed), utc_second: 61, off_position: false, regional_reserved: 0, raim: false, virtual_aid: false, assigned_mode: false })
BaseStationReport(BaseStationReport { message_type: 4, repeat_indicator: 0, mmsi: 3669710, year: Some(2020), month: Some(4), day: Some(18), hour: Some(8), minute: Some(46), second: Some(40), fix_quality: DGPS, longitude: Some(-122.42347), latitude: Some(37.96206), epfd_type: None, raim: true, radio_status: Sotdma(SotdmaMessage { sync_state: UtcDirect, slot_timeout: 0, sub_message: SlotOffset(2250) }) })
PositionReport(PositionReport { message_type: 1, repeat_indicator: 0, mmsi: 367625810, navigation_status: Some(UnderWayUsingEngine), rate_of_turn: Some(RateOfTurn { raw: 0 }), speed_over_ground: Some(0.1), position_accuracy: DGPS, longitude: Some(-122.398), latitude: Some(37.80256), course_over_ground: Some(343.8), true_heading: Some(55), timestamp: 41, maneuver_indicator: None, raim: false, radio_status: Sotdma(SotdmaMessage { sync_state: UtcDirect, slot_timeout: 2, sub_message: SlotNumber(1524) }) })
BaseStationReport(BaseStationReport { message_type: 4, repeat_indicator: 0, mmsi: 3669145, year: Some(2020), month: Some(4), day: Some(18), hour: Some(8), minute: Some(46), second: Some(41), fix_quality: DGPS, longitude: Some(-122.46484), latitude: Some(37.794273), epfd_type: None, raim: true, radio_status: Sotdma(SotdmaMessage { sync_state: UtcDirect, slot_timeout: 3, sub_message: ReceivedStations(187) }) })

作为库使用

以下是一个解析单个 NMEA 句子的示例。在这种情况下,它包含一个航行辅助报告

use ais::{AisFragments, AisParser};
use ais::messages::AisMessage;

// The line below is an NMEA sentence, much as you'd see coming out of an AIS decoder.
let line = b"!AIVDM,1,1,,B,E>kb9O9aS@7PUh10dh19@;0Tah2cWrfP:l?M`00003vP100,0*01";

let mut parser = AisParser::new();
if let AisFragments::Complete(sentence) = parser.parse(line, true)? {
   // This sentence is complete, ie unfragmented
   assert_eq!(sentence.num_fragments, 1);
   // The data was transmitted on AIS channel B
   assert_eq!(sentence.channel, Some('B'));

   if let Some(message) = sentence.message {
       match message {
           AisMessage::AidToNavigationReport(report) => {
               assert_eq!(report.mmsi, 993692028);
               assert_eq!(report.name, "SF OAK BAY BR VAIS E");
               // There are a ton more fields available here
           },
           _ => panic!("Unexpected message type"),
       }
   }
}
# Ok::<(), ais::errors::Error>(())

支持的消息类型

目前,只支持少数几种常见类型。它们是

  • 位置报告(类型 1-3)
  • 基站报告(类型 4)
  • 静态和航行相关数据(类型 5)
  • 二进制广播消息(类型 8)
  • UTC/日期响应(类型 11)
  • 询问(类型 15)
  • DGNSS 广播二进制消息(类型 17)
  • 静态 B 类位置报告(类型 18)
  • 扩展 B 类位置报告(类型 19)
  • 数据链路管理消息(类型 20)
  • 航行辅助报告(类型 21)
  • 静态数据报告(类型 24)

希望很快会有更多消息类型!

no_std 支持

此库对 no_std 有实验性支持;将库添加到您的 Cargo.toml 如下所示

ais = { version = "0.9", default-features = false }

一些 AIS 消息具有可变长度的字段;这是通过使用 heapless VecString 类型来实现的,在栈上分配可能的最大数据大小。

如果您可以访问分配器,选择加入 alloc 功能可能会更节省空间,因为观察到的消息大小通常小于可能的最大值。

std 功能是默认的,它与 alloc 版本大致相同;它需要构建二进制 CLI 工具。

依赖关系

~1.5MB
~32K SLoC