| Crates.io | ship162 |
| lib.rs | ship162 |
| version | 0.1.2 |
| created_at | 2025-11-24 22:14:18.14032+00 |
| updated_at | 2026-01-20 22:21:07.443799+00 |
| description | A real-time AIS data decoder |
| homepage | https://github.com/xoolive/ship162 |
| repository | https://github.com/xoolive/ship162 |
| max_upload_size | |
| id | 1948771 |
| size | 187,291 |
ship162 is a complete maritime tracking application that includes the rs162 Rust library for decoding AIS (Automatic Identification System) messages from binary feeds and NMEA sentences using the deku library for clean, declarative binary data parsing.
The library takes its inspiration from the Python pyais library and leverages deku to provide efficient, type-safe AIS message decoding. The major specificity compared to other implementations is the deku-based decoder, which enables clean bit-level parsing with compile-time guarantees.
The directions ambitioned by ship162 include:
The ultimate goal is to create a complete maritime tracking solution that can receive raw radio signals and output structured AIS data, similar to what dump1090 does for aviation ADS-B messages.

rtlsdr: Support for real-time demodulation from RTL-SDR USB dongles (enabled via desperado).mqtt: Support for connecting to MQTT brokers (e.g., Finnish Digitraffic). Disabled by default.The key differentiator of ship162 is its use of deku for declarative binary parsing, providing both performance and correctness guarantees that are difficult to achieve with manual bit manipulation.
The long-term vision for ship162 is to become a complete end-to-end demodulation and decoding application that can:
This will make ship162 the maritime equivalent of rs1090 for aviation tracking.
Run the following Cargo command in your project directory:
# Standard installation
cargo add rs162
# With MQTT support
cargo add rs162 --features mqtt
# With RTL-SDR support
cargo add rs162 --features rtlsdr
Or add the following line to your Cargo.toml:
rs162 = "0.1.0" # check for the latest version
The ship162 application supports TOML configuration files for defining multiple AIS data sources. This makes it easy to configure and manage different input sources without using command-line arguments.
The application searches for configuration files in the following locations (in priority order):
SHIP162_CONFIG environment variable$XDG_CONFIG_HOME/ship162/config.toml~/.config/ship162/config.toml# Example configuration with multiple sources
# RTL-SDR device by index
[[sources]]
rtlsdr = { device = 0 }
gain = 49.6 # Recommended max gain for 162 MHz
bias_tee = true # Enable bias-tee if using powered antenna
# RTL-SDR device by serial number
[[sources]]
rtlsdr = { serial = "00000001" }
gain = 49.6
# RTL-SDR device by manufacturer/product filter
[[sources]]
rtlsdr = { manufacturer = "Realtek", product = "RTL2838UHIDIR" }
gain = 49.6
# SoapySDR device (e.g., PlutoSDR, LimeSDR)
[[sources]]
soapy = "driver=rtlsdr"
gain = 49.6
gain_element = "TUNER" # Optional: specify gain element
bias_tee = false
# PlutoSDR by IP address
[[sources]]
pluto = "192.168.2.1"
gain = 73.0 # Maximum gain for PlutoSDR
# TCP source (e.g., Norwegian Coastal Administration)
[[sources]]
tcp = "153.44.253.27:5631"
# TCP source with SSH tunnel (requires --features ssh)
# [[sources]]
# tcp = { host = "remote-ais-server.example.com", port = 5631, jump = "jumphost" }
# MQTT source (requires --features mqtt)
[[sources]]
mqtt = "mqtt://mqtt.digitraffic.fi"
# I/Q sample file
[[sources]]
iqfile = "/path/to/samples.cf32"
RTL-SDR devices can be selected by:
rtlsdr = { device = 0 }rtlsdr = { serial = "00000001" }rtlsdr = { manufacturer = "Realtek", product = "RTL2838UHIDIR" }Common options:
gain: Gain in dB (recommended: 49.6 for max gain)bias_tee: Enable/disable bias-tee (default: false)SoapySDR sources use a driver string:
soapy = "driver=rtlsdr" for RTL-SDR via SoapySDRsoapy = "driver=plutosdr" for PlutoSDR via SoapySDRsoapy = "driver=lime" for LimeSDRCommon options:
gain: Gain in dBgain_element: Gain element name (default: "TUNER")bias_tee: Enable/disable bias-teePlutoSDR sources require an IP address or URI:
pluto = "192.168.2.1" or pluto = "ip:192.168.2.1"Common options:
gain: Gain in dB (recommended: 73.0 for AIS)TCP sources connect to a remote AIS feed:
tcp = "host:port" - Simple TCP connectiontcp = { host = "hostname", port = 5631 } - Structured formattcp = { host = "hostname", port = 5631, jump = "jumphost" } - SSH tunneled connection (requires --features ssh)SSH tunneling allows secure connections to remote AIS sources through jump hosts. This feature requires building with the ssh feature:
cargo build --release --features rtlsdr,ssh
Configuration:
# TCP source with SSH tunnel
[[sources]]
tcp = { host = "remote-ais-server.example.com", port = 5631, jump = "jumphost.example.com" }
SSH Setup:
SSH tunneling uses standard SSH configuration:
~/.ssh/config - SSH client configuration:
Host jumphost.example.com
User myuser
IdentityFile ~/.ssh/id_ed25519
~/.ssh/known_hosts - Host verification keys (populated automatically on first connection)
~/.ssh/id_* - SSH keys for authentication (generate with ssh-keygen)
The jump parameter refers to a hostname in your ~/.ssh/config or a direct hostname that can be resolved.
MQTT sources connect to an MQTT broker (requires --features mqtt):
mqtt = "mqtt://broker.example.com"No additional configuration options.
I/Q file sources read from a file containing raw I/Q samples:
iqfile = "/path/to/file.cf32"No additional configuration options.
Create a configuration file at ~/.config/ship162/config.toml and run:
cargo run --release --features rtlsdr,soapy
Or specify a custom configuration file location:
SHIP162_CONFIG=/path/to/config.toml cargo run --release
See config.toml.example in the repository for a complete example with documentation.
use rs162::decode::ais::Message;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Single NMEA sentence
let nmea = "!AIVDM,1,1,,B,15M67FC000G?ufbE`FepT@3n00Sa,0*5C";
let message = Message::from_nmea(&[nmea])?;
// Convert to JSON
let json = serde_json::to_string(&message)?;
println!("{}", json);
Ok(())
}
use rs162::decode::ais::Message;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Multi-sentence Type 5 static and voyage data
let sentences = [
"!AIVDM,2,1,1,A,55?MbV02;H;s<HtKR20EHE:0@T4@Dn2222222216L961O5Gf0NSQEp6ClRp8,0*1C",
"!AIVDM,2,2,1,A,88888888880,2*25",
];
let message = Message::from_nmea(&sentences)?;
let json = serde_json::to_string(&message)?;
println!("{}", json);
Ok(())
}
# See examples/nmea_file.rs for a complete file processor
cargo run --example nmea_file
# See examples/nmea_tcp.rs for live AIS data processing
# Connects to Norwegian Coastal Administration's free AIS feed
cargo run --release --example nmea_tcp -- 153.44.253.27:5631 | \
jq -c '.message + .mmsi_info + {timestamp: (.timestamp | strftime("%Y-%m-%dT%H:%M:%SZ"))}'
# See examples/iqfile.rs for processing I/Q sample files
cargo run --release --example iqfile | \
jq -c '.message + .mmsi_info + {timestamp: (.timestamp | strftime("%Y-%m-%dT%H:%M:%SZ"))}'
rtl_tcp# See examples/rtltcp.rs
rtl_tcp -a 127.0.0.1 -p 1234 -f 162M -s 288k -g 49.6
cargo run --release --example rtltcp | \
jq -c '.message + .mmsi_info + {timestamp: (.timestamp | strftime("%Y-%m-%dT%H:%M:%SZ"))}'
[!WARNING]
Please read the following important note for Linux users: https://github.com/ccostes/rtl-sdr-rs#uload-kernel-modules
# See examples/rtlsdr.rs
cargo run --release --example rtlsdr | \
jq -c '.message + .mmsi_info + {timestamp: (.timestamp | strftime("%Y-%m-%dT%H:%M:%SZ"))}'
# See examples/rtlsdr_async.rs
cargo run --release --example rtlsdr_async | \
jq -c '.message + .mmsi_info + {timestamp: (.timestamp | strftime("%Y-%m-%dT%H:%M:%SZ"))}'
The library implements:
Real-time AIS data is freely available from the Norwegian Coastal Administration:
More information: https://www.kystverket.no/en/sea-transport-and-ports/ais/access-to-ais-data/
[!NOTE] You must compile the library or application with
--features mqttto access this source.
Real-time AIS data is available via MQTT from Finnish Digitraffic:
mqtt.digitraffic.fivessels-v2/\<mmsi\>/metadatavessels-v2/\<mmsi\>/locationsvessels-v2/statusMore information: https://www.digitraffic.fi/en/marine-traffic/
Most of the codebase has been generated with the assistance of Claude Sonnet 4, using specifications from:
Contributions are welcome! The project particularly benefits from:
This project is licensed under the MIT License. See the license file for details.