[feat](trx-rs): add VDES decoder mode support

Add a new trx-vdes decoder path alongside AIS, wire VDES through the server/frontend decode pipeline, and fix the web map so AIS vessel symbols load correctly and the TRX receiver marker appears when location data arrives.

Co-authored-by: OpenAI Codex <codex@openai.com>
Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
2026-03-03 00:05:16 +01:00
parent 051d07eaab
commit 92423f1e02
25 changed files with 878 additions and 32 deletions
+1
View File
@@ -16,6 +16,7 @@ pub const AUDIO_MSG_CW_DECODE: u8 = 0x04;
pub const AUDIO_MSG_FT8_DECODE: u8 = 0x05;
pub const AUDIO_MSG_WSPR_DECODE: u8 = 0x06;
pub const AUDIO_MSG_AIS_DECODE: u8 = 0x07;
pub const AUDIO_MSG_VDES_DECODE: u8 = 0x08;
/// Maximum payload size (1 MB) to reject bogus frames early.
const MAX_PAYLOAD_SIZE: u32 = 1_048_576;
+33
View File
@@ -12,6 +12,8 @@ use serde::{Deserialize, Serialize};
pub enum DecodedMessage {
#[serde(rename = "ais")]
Ais(AisMessage),
#[serde(rename = "vdes")]
Vdes(VdesMessage),
#[serde(rename = "aprs")]
Aprs(AprsPacket),
#[serde(rename = "cw")]
@@ -53,6 +55,37 @@ pub struct AisMessage {
pub destination: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VdesMessage {
#[serde(skip_serializing_if = "Option::is_none")]
pub ts_ms: Option<i64>,
pub channel: String,
pub message_type: u8,
pub repeat: u8,
pub mmsi: u32,
pub crc_ok: bool,
pub bit_len: usize,
pub raw_bytes: Vec<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lat: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lon: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sog_knots: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cog_deg: Option<f32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub heading_deg: Option<u16>,
#[serde(skip_serializing_if = "Option::is_none")]
pub nav_status: Option<u8>,
#[serde(skip_serializing_if = "Option::is_none")]
pub vessel_name: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub callsign: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub destination: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AprsPacket {
#[serde(skip_serializing_if = "Option::is_none")]
+1
View File
@@ -71,6 +71,7 @@ pub enum RigMode {
WFM,
FM,
AIS,
VDES,
DIG,
PKT,
Other(String),