[feat](trx-rs): add FT2 decoder support (wired to FT4)
Mirrors the FT4 implementation across the full stack. The trx-ft8 crate wires Ft8Decoder::new_ft2() to FTX_PROTOCOL_FT4 as a placeholder pending a dedicated FT2 implementation. Changes: - trx-ft8: Ft8Decoder::new_ft2() delegates to with_protocol(Ft4) - trx-core: DecodedMessage::Ft2, AUDIO_MSG_FT2_DECODE (0x15), ft2_decode_enabled/ft2_decode_reset_seq state, SetFt2DecodeEnabled/ ResetFt2Decoder commands, protocol mapping - trx-server: DecoderHistories::ft2, run_ft2_decoder (7.5s slots), run_background_ft2_decoder, history push/replay, decoder task spawn - trx-frontend-http: ft2_history in FrontendRuntimeContext, toggle/clear endpoints, /ft2.js route, bookmark/scheduler/background decode support, DecodeHistoryPayload ft2 field - web: ft2.js plugin (3.75s period timer), FT2 subtab in index.html, FT2 map source (distinct hue), app.js dispatch, decode-history-worker HISTORY_GROUP_KEYS, bookmarks read/write/apply Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
This commit is contained in:
@@ -64,6 +64,8 @@ pub const AUDIO_MSG_VCHAN_DESTROYED: u8 = 0x12;
|
||||
pub const AUDIO_MSG_VCHAN_BW: u8 = 0x13;
|
||||
/// Server → client: FT4 decoded message (JSON `DecodedMessage::Ft4`).
|
||||
pub const AUDIO_MSG_FT4_DECODE: u8 = 0x14;
|
||||
/// Server → client: FT2 decoded message (JSON `DecodedMessage::Ft2`).
|
||||
pub const AUDIO_MSG_FT2_DECODE: u8 = 0x15;
|
||||
|
||||
/// Maximum payload size for normal messages (1 MB).
|
||||
const MAX_PAYLOAD_SIZE: u32 = 1_048_576;
|
||||
|
||||
@@ -24,6 +24,8 @@ pub enum DecodedMessage {
|
||||
Ft8(Ft8Message),
|
||||
#[serde(rename = "ft4")]
|
||||
Ft4(Ft8Message),
|
||||
#[serde(rename = "ft2")]
|
||||
Ft2(Ft8Message),
|
||||
#[serde(rename = "wspr")]
|
||||
Wspr(WsprMessage),
|
||||
}
|
||||
|
||||
@@ -29,12 +29,14 @@ pub enum RigCommand {
|
||||
SetCwToneHz(u32),
|
||||
SetFt8DecodeEnabled(bool),
|
||||
SetFt4DecodeEnabled(bool),
|
||||
SetFt2DecodeEnabled(bool),
|
||||
SetWsprDecodeEnabled(bool),
|
||||
ResetAprsDecoder,
|
||||
ResetHfAprsDecoder,
|
||||
ResetCwDecoder,
|
||||
ResetFt8Decoder,
|
||||
ResetFt4Decoder,
|
||||
ResetFt2Decoder,
|
||||
ResetWsprDecoder,
|
||||
SetBandwidth(u32),
|
||||
SetFirTaps(u32),
|
||||
|
||||
@@ -510,6 +510,7 @@ pub fn command_from_rig_command(cmd: RigCommand) -> Box<dyn RigCommandHandler> {
|
||||
| RigCommand::SetCwToneHz(_)
|
||||
| RigCommand::SetFt8DecodeEnabled(_)
|
||||
| RigCommand::SetFt4DecodeEnabled(_)
|
||||
| RigCommand::SetFt2DecodeEnabled(_)
|
||||
| RigCommand::SetWsprDecodeEnabled(_)
|
||||
| RigCommand::SetHfAprsDecodeEnabled(_)
|
||||
| RigCommand::ResetHfAprsDecoder
|
||||
@@ -517,6 +518,7 @@ pub fn command_from_rig_command(cmd: RigCommand) -> Box<dyn RigCommandHandler> {
|
||||
| RigCommand::ResetCwDecoder
|
||||
| RigCommand::ResetFt8Decoder
|
||||
| RigCommand::ResetFt4Decoder
|
||||
| RigCommand::ResetFt2Decoder
|
||||
| RigCommand::ResetWsprDecoder
|
||||
| RigCommand::SetBandwidth(_)
|
||||
| RigCommand::SetFirTaps(_)
|
||||
|
||||
@@ -40,6 +40,8 @@ pub struct RigState {
|
||||
#[serde(default)]
|
||||
pub ft4_decode_enabled: bool,
|
||||
#[serde(default)]
|
||||
pub ft2_decode_enabled: bool,
|
||||
#[serde(default)]
|
||||
pub wspr_decode_enabled: bool,
|
||||
#[serde(default)]
|
||||
pub cw_auto: bool,
|
||||
@@ -70,6 +72,8 @@ pub struct RigState {
|
||||
#[serde(default, skip_serializing)]
|
||||
pub ft4_decode_reset_seq: u64,
|
||||
#[serde(default, skip_serializing)]
|
||||
pub ft2_decode_reset_seq: u64,
|
||||
#[serde(default, skip_serializing)]
|
||||
pub wspr_decode_reset_seq: u64,
|
||||
}
|
||||
|
||||
@@ -148,6 +152,7 @@ impl RigState {
|
||||
cw_decode_enabled: true,
|
||||
ft8_decode_enabled: false,
|
||||
ft4_decode_enabled: false,
|
||||
ft2_decode_enabled: false,
|
||||
wspr_decode_enabled: false,
|
||||
cw_auto: true,
|
||||
cw_wpm: 15,
|
||||
@@ -160,6 +165,7 @@ impl RigState {
|
||||
cw_decode_reset_seq: 0,
|
||||
ft8_decode_reset_seq: 0,
|
||||
ft4_decode_reset_seq: 0,
|
||||
ft2_decode_reset_seq: 0,
|
||||
wspr_decode_reset_seq: 0,
|
||||
}
|
||||
}
|
||||
@@ -217,6 +223,7 @@ impl RigState {
|
||||
cw_tone_hz: snapshot.cw_tone_hz,
|
||||
ft8_decode_enabled: snapshot.ft8_decode_enabled,
|
||||
ft4_decode_enabled: snapshot.ft4_decode_enabled,
|
||||
ft2_decode_enabled: snapshot.ft2_decode_enabled,
|
||||
wspr_decode_enabled: snapshot.wspr_decode_enabled,
|
||||
filter: snapshot.filter,
|
||||
spectrum: None, // spectrum flows through /api/spectrum, not persistent state
|
||||
@@ -226,6 +233,7 @@ impl RigState {
|
||||
cw_decode_reset_seq: 0,
|
||||
ft8_decode_reset_seq: 0,
|
||||
ft4_decode_reset_seq: 0,
|
||||
ft2_decode_reset_seq: 0,
|
||||
wspr_decode_reset_seq: 0,
|
||||
}
|
||||
}
|
||||
@@ -261,6 +269,7 @@ impl RigState {
|
||||
cw_tone_hz: self.cw_tone_hz,
|
||||
ft8_decode_enabled: self.ft8_decode_enabled,
|
||||
ft4_decode_enabled: self.ft4_decode_enabled,
|
||||
ft2_decode_enabled: self.ft2_decode_enabled,
|
||||
wspr_decode_enabled: self.wspr_decode_enabled,
|
||||
filter: self.filter.clone(),
|
||||
spectrum: self.spectrum.clone(),
|
||||
@@ -427,6 +436,8 @@ pub struct RigSnapshot {
|
||||
#[serde(default)]
|
||||
pub ft4_decode_enabled: bool,
|
||||
#[serde(default)]
|
||||
pub ft2_decode_enabled: bool,
|
||||
#[serde(default)]
|
||||
pub wspr_decode_enabled: bool,
|
||||
#[serde(default)]
|
||||
pub cw_auto: bool,
|
||||
|
||||
Reference in New Issue
Block a user