[style](trx-rs): apply rustfmt formatting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -248,13 +248,7 @@ impl VdesDecoder {
|
|||||||
if let Some(ref ll_frame) = viterbi_frame {
|
if let Some(ref ll_frame) = viterbi_frame {
|
||||||
if ll_frame.crc_ok {
|
if ll_frame.crc_ok {
|
||||||
return Some(build_link_layer_message(
|
return Some(build_link_layer_message(
|
||||||
channel,
|
channel, ll_frame, &framed, &mode, rms, link_id, 0.0,
|
||||||
ll_frame,
|
|
||||||
&framed,
|
|
||||||
&mode,
|
|
||||||
rms,
|
|
||||||
link_id,
|
|
||||||
0.0,
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,8 +101,8 @@ fn find_qpp_params(block_size: usize) -> (usize, usize) {
|
|||||||
fn is_valid_qpp(block_size: usize, f1: usize, f2: usize) -> bool {
|
fn is_valid_qpp(block_size: usize, f1: usize, f2: usize) -> bool {
|
||||||
let mut seen = vec![false; block_size];
|
let mut seen = vec![false; block_size];
|
||||||
for i in 0..block_size {
|
for i in 0..block_size {
|
||||||
let idx = ((f1 as u64 * i as u64 + f2 as u64 * (i as u64 * i as u64))
|
let idx = ((f1 as u64 * i as u64 + f2 as u64 * (i as u64 * i as u64)) % block_size as u64)
|
||||||
% block_size as u64) as usize;
|
as usize;
|
||||||
if seen[idx] {
|
if seen[idx] {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,10 @@ fn gcd(mut a: usize, mut b: usize) -> usize {
|
|||||||
///
|
///
|
||||||
/// Input: received LLRs (positive = likely 0, negative = likely 1)
|
/// Input: received LLRs (positive = likely 0, negative = likely 1)
|
||||||
/// Output: (systematic, parity1, parity2) LLR vectors
|
/// Output: (systematic, parity1, parity2) LLR vectors
|
||||||
pub fn depuncture_rate_half(received_llrs: &[Llr], info_len: usize) -> (Vec<Llr>, Vec<Llr>, Vec<Llr>) {
|
pub fn depuncture_rate_half(
|
||||||
|
received_llrs: &[Llr],
|
||||||
|
info_len: usize,
|
||||||
|
) -> (Vec<Llr>, Vec<Llr>, Vec<Llr>) {
|
||||||
let mut systematic = vec![0.0; info_len];
|
let mut systematic = vec![0.0; info_len];
|
||||||
let mut parity1 = vec![0.0; info_len];
|
let mut parity1 = vec![0.0; info_len];
|
||||||
let mut parity2 = vec![0.0; info_len];
|
let mut parity2 = vec![0.0; info_len];
|
||||||
@@ -231,10 +234,7 @@ pub fn turbo_decode_soft(received_llrs: &[Llr], info_len: usize) -> (Vec<u8>, f3
|
|||||||
|
|
||||||
for _iter in 0..TURBO_ITERATIONS {
|
for _iter in 0..TURBO_ITERATIONS {
|
||||||
// --- Decoder 1 (natural order) ---
|
// --- Decoder 1 (natural order) ---
|
||||||
let apriori_1: Vec<Llr> = deinterleaver
|
let apriori_1: Vec<Llr> = deinterleaver.iter().map(|&i| extrinsic_2_to_1[i]).collect();
|
||||||
.iter()
|
|
||||||
.map(|&i| extrinsic_2_to_1[i])
|
|
||||||
.collect();
|
|
||||||
let aposteriori_1 = bcjr_decode(&sys_llr, &par1_llr, &apriori_1);
|
let aposteriori_1 = bcjr_decode(&sys_llr, &par1_llr, &apriori_1);
|
||||||
// Extrinsic = aposteriori - systematic - apriori
|
// Extrinsic = aposteriori - systematic - apriori
|
||||||
for k in 0..info_len {
|
for k in 0..info_len {
|
||||||
@@ -242,10 +242,7 @@ pub fn turbo_decode_soft(received_llrs: &[Llr], info_len: usize) -> (Vec<u8>, f3
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- Decoder 2 (interleaved order) ---
|
// --- Decoder 2 (interleaved order) ---
|
||||||
let apriori_2: Vec<Llr> = interleaver
|
let apriori_2: Vec<Llr> = interleaver.iter().map(|&i| extrinsic_1_to_2[i]).collect();
|
||||||
.iter()
|
|
||||||
.map(|&i| extrinsic_1_to_2[i])
|
|
||||||
.collect();
|
|
||||||
let aposteriori_2 = bcjr_decode(&sys_interleaved, &par2_llr, &apriori_2);
|
let aposteriori_2 = bcjr_decode(&sys_interleaved, &par2_llr, &apriori_2);
|
||||||
for k in 0..info_len {
|
for k in 0..info_len {
|
||||||
extrinsic_2_to_1[k] = aposteriori_2[k] - sys_interleaved[k] - apriori_2[k];
|
extrinsic_2_to_1[k] = aposteriori_2[k] - sys_interleaved[k] - apriori_2[k];
|
||||||
@@ -254,11 +251,11 @@ pub fn turbo_decode_soft(received_llrs: &[Llr], info_len: usize) -> (Vec<u8>, f3
|
|||||||
// Combine for final decision (deinterleave decoder 2 output)
|
// Combine for final decision (deinterleave decoder 2 output)
|
||||||
for k in 0..info_len {
|
for k in 0..info_len {
|
||||||
let deint_apost2 = aposteriori_2[deinterleaver[k]];
|
let deint_apost2 = aposteriori_2[deinterleaver[k]];
|
||||||
final_llr[k] = sys_llr[k] + extrinsic_1_to_2[k] + deint_apost2
|
final_llr[k] =
|
||||||
- sys_llr[k]
|
sys_llr[k] + extrinsic_1_to_2[k] + deint_apost2 - sys_llr[k] - extrinsic_1_to_2[k];
|
||||||
- extrinsic_1_to_2[k];
|
|
||||||
// Simplified: final = systematic + extrinsic from both decoders
|
// Simplified: final = systematic + extrinsic from both decoders
|
||||||
final_llr[k] = sys_llr[k] + apriori_1[k] + (aposteriori_1[k] - sys_llr[k] - apriori_1[k]);
|
final_llr[k] =
|
||||||
|
sys_llr[k] + apriori_1[k] + (aposteriori_1[k] - sys_llr[k] - apriori_1[k]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,7 +345,8 @@ fn bcjr_decode(systematic: &[Llr], parity: &[Llr], apriori: &[Llr]) -> Vec<Llr>
|
|||||||
-par_ext[t] / 2.0
|
-par_ext[t] / 2.0
|
||||||
};
|
};
|
||||||
let branch = sys_metric + par_metric;
|
let branch = sys_metric + par_metric;
|
||||||
alpha[t + 1][next_state] = log_sum_exp(alpha[t + 1][next_state], alpha[t][s] + branch);
|
alpha[t + 1][next_state] =
|
||||||
|
log_sum_exp(alpha[t + 1][next_state], alpha[t][s] + branch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -543,7 +541,12 @@ mod tests {
|
|||||||
let b = 3.0f32;
|
let b = 3.0f32;
|
||||||
let expected = (a.exp() + b.exp()).ln();
|
let expected = (a.exp() + b.exp()).ln();
|
||||||
let result = log_sum_exp(a, b);
|
let result = log_sum_exp(a, b);
|
||||||
assert!((result - expected).abs() < 0.01, "got {}, expected {}", result, expected);
|
assert!(
|
||||||
|
(result - expected).abs() < 0.01,
|
||||||
|
"got {}, expected {}",
|
||||||
|
result,
|
||||||
|
expected
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@@ -524,8 +524,7 @@ async fn send_command(
|
|||||||
// Update the per-rig watch channel first so SSE sessions
|
// Update the per-rig watch channel first so SSE sessions
|
||||||
// subscribed to a specific rig see the change immediately
|
// subscribed to a specific rig see the change immediately
|
||||||
// instead of waiting for the next poll cycle.
|
// instead of waiting for the next poll cycle.
|
||||||
let channel_key = channel_key_override
|
let channel_key = channel_key_override.or_else(|| selected_rig_id(config));
|
||||||
.or_else(|| selected_rig_id(config));
|
|
||||||
if let Some(key) = channel_key {
|
if let Some(key) = channel_key {
|
||||||
if let Ok(map) = config.rig_states.read() {
|
if let Ok(map) = config.rig_states.read() {
|
||||||
if let Some(tx) = map.get(&key) {
|
if let Some(tx) = map.get(&key) {
|
||||||
|
|||||||
@@ -4,15 +4,12 @@
|
|||||||
|
|
||||||
//! Static asset serving endpoints (HTML pages, JS, CSS, favicon, logo).
|
//! Static asset serving endpoints (HTML pages, JS, CSS, favicon, logo).
|
||||||
|
|
||||||
use actix_web::{get, HttpRequest, HttpResponse, Responder};
|
|
||||||
use actix_web::http::header;
|
use actix_web::http::header;
|
||||||
|
use actix_web::{get, HttpRequest, HttpResponse, Responder};
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
|
|
||||||
|
use super::{gz_cache_entry, static_asset_response, GzCacheEntry, FAVICON_BYTES, LOGO_BYTES};
|
||||||
use crate::server::status;
|
use crate::server::status;
|
||||||
use super::{
|
|
||||||
static_asset_response, GzCacheEntry, gz_cache_entry,
|
|
||||||
FAVICON_BYTES, LOGO_BYTES,
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Pre-compressed asset caches
|
// Pre-compressed asset caches
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use actix_web::{delete, get, post, put, web, HttpRequest, HttpResponse};
|
|
||||||
use actix_web::Error;
|
use actix_web::Error;
|
||||||
|
use actix_web::{delete, get, post, put, web, HttpRequest, HttpResponse};
|
||||||
|
|
||||||
use super::{no_cache_response, request_accepts_html, require_control};
|
use super::{no_cache_response, request_accepts_html, require_control};
|
||||||
use crate::server::status;
|
use crate::server::status;
|
||||||
|
|||||||
@@ -6,9 +6,9 @@
|
|||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use actix_web::{get, post, web, HttpResponse, Responder};
|
|
||||||
use actix_web::Error;
|
|
||||||
use actix_web::http::header;
|
use actix_web::http::header;
|
||||||
|
use actix_web::Error;
|
||||||
|
use actix_web::{get, post, web, HttpResponse, Responder};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures_util::stream::{select, StreamExt};
|
use futures_util::stream::{select, StreamExt};
|
||||||
use tokio::sync::{broadcast, mpsc, watch};
|
use tokio::sync::{broadcast, mpsc, watch};
|
||||||
|
|||||||
@@ -902,7 +902,9 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let req = actix_test::TestRequest::post().uri("/set_freq").to_request();
|
let req = actix_test::TestRequest::post()
|
||||||
|
.uri("/set_freq")
|
||||||
|
.to_request();
|
||||||
let resp = actix_test::call_service(&app, req).await;
|
let resp = actix_test::call_service(&app, req).await;
|
||||||
assert_eq!(resp.status(), 400);
|
assert_eq!(resp.status(), 400);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use actix_web::{get, web, HttpResponse};
|
|
||||||
use actix_web::Error;
|
|
||||||
use actix_web::http::header;
|
use actix_web::http::header;
|
||||||
|
use actix_web::Error;
|
||||||
|
use actix_web::{get, web, HttpResponse};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures_util::stream::{select, StreamExt};
|
use futures_util::stream::{select, StreamExt};
|
||||||
use tokio::sync::{broadcast, watch};
|
use tokio::sync::{broadcast, watch};
|
||||||
@@ -23,8 +23,8 @@ use trx_frontend::FrontendRuntimeContext;
|
|||||||
use crate::server::vchan::ClientChannelManager;
|
use crate::server::vchan::ClientChannelManager;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
base64_encode, frontend_meta_from_context, wait_for_view,
|
base64_encode, frontend_meta_from_context, wait_for_view, RemoteQuery, SessionRigManager,
|
||||||
RemoteQuery, SessionRigManager, SnapshotWithMeta,
|
SnapshotWithMeta,
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use actix_web::{delete, get, post, put, web, HttpResponse, Responder};
|
|
||||||
use actix_web::Error;
|
use actix_web::Error;
|
||||||
|
use actix_web::{delete, get, post, put, web, HttpResponse, Responder};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
|||||||
@@ -563,9 +563,7 @@ fn evaluate_bookmark(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
if !enabled {
|
if !enabled {
|
||||||
return ChannelAction::Skip {
|
return ChannelAction::Skip { reason: "disabled" };
|
||||||
reason: "disabled",
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
if !users_connected {
|
if !users_connected {
|
||||||
return ChannelAction::Skip {
|
return ChannelAction::Skip {
|
||||||
@@ -718,8 +716,15 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn skip_no_supported_decoders() {
|
fn skip_no_supported_decoders() {
|
||||||
let action = evaluate_bookmark(
|
let action = evaluate_bookmark(
|
||||||
true, true, true, false, &empty_scheduled(), "bm1", false,
|
true,
|
||||||
Some((14_074_000, 96_000)), 14_074_000,
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
&empty_scheduled(),
|
||||||
|
"bm1",
|
||||||
|
false,
|
||||||
|
Some((14_074_000, 96_000)),
|
||||||
|
14_074_000,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
action,
|
action,
|
||||||
@@ -732,8 +737,15 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn skip_disabled() {
|
fn skip_disabled() {
|
||||||
let action = evaluate_bookmark(
|
let action = evaluate_bookmark(
|
||||||
false, false, true, false, &empty_scheduled(), "bm1", false,
|
false,
|
||||||
Some((14_074_000, 96_000)), 14_074_000,
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
&empty_scheduled(),
|
||||||
|
"bm1",
|
||||||
|
false,
|
||||||
|
Some((14_074_000, 96_000)),
|
||||||
|
14_074_000,
|
||||||
);
|
);
|
||||||
assert_eq!(action, ChannelAction::Skip { reason: "disabled" });
|
assert_eq!(action, ChannelAction::Skip { reason: "disabled" });
|
||||||
}
|
}
|
||||||
@@ -741,8 +753,15 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn skip_waiting_for_user() {
|
fn skip_waiting_for_user() {
|
||||||
let action = evaluate_bookmark(
|
let action = evaluate_bookmark(
|
||||||
false, true, false, false, &empty_scheduled(), "bm1", false,
|
false,
|
||||||
Some((14_074_000, 96_000)), 14_074_000,
|
true,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
&empty_scheduled(),
|
||||||
|
"bm1",
|
||||||
|
false,
|
||||||
|
Some((14_074_000, 96_000)),
|
||||||
|
14_074_000,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
action,
|
action,
|
||||||
@@ -755,8 +774,15 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn skip_scheduler_has_control() {
|
fn skip_scheduler_has_control() {
|
||||||
let action = evaluate_bookmark(
|
let action = evaluate_bookmark(
|
||||||
false, true, true, true, &empty_scheduled(), "bm1", false,
|
false,
|
||||||
Some((14_074_000, 96_000)), 14_074_000,
|
true,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
&empty_scheduled(),
|
||||||
|
"bm1",
|
||||||
|
false,
|
||||||
|
Some((14_074_000, 96_000)),
|
||||||
|
14_074_000,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
action,
|
action,
|
||||||
@@ -771,8 +797,15 @@ mod tests {
|
|||||||
let mut scheduled = HashSet::new();
|
let mut scheduled = HashSet::new();
|
||||||
scheduled.insert("bm1".to_string());
|
scheduled.insert("bm1".to_string());
|
||||||
let action = evaluate_bookmark(
|
let action = evaluate_bookmark(
|
||||||
false, true, true, false, &scheduled, "bm1", false,
|
false,
|
||||||
Some((14_074_000, 96_000)), 14_074_000,
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
&scheduled,
|
||||||
|
"bm1",
|
||||||
|
false,
|
||||||
|
Some((14_074_000, 96_000)),
|
||||||
|
14_074_000,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
action,
|
action,
|
||||||
@@ -785,8 +818,15 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn skip_handled_by_virtual_channel() {
|
fn skip_handled_by_virtual_channel() {
|
||||||
let action = evaluate_bookmark(
|
let action = evaluate_bookmark(
|
||||||
false, true, true, false, &empty_scheduled(), "bm1", true,
|
false,
|
||||||
Some((14_074_000, 96_000)), 14_074_000,
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
&empty_scheduled(),
|
||||||
|
"bm1",
|
||||||
|
true,
|
||||||
|
Some((14_074_000, 96_000)),
|
||||||
|
14_074_000,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
action,
|
action,
|
||||||
@@ -799,8 +839,15 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn skip_waiting_for_spectrum() {
|
fn skip_waiting_for_spectrum() {
|
||||||
let action = evaluate_bookmark(
|
let action = evaluate_bookmark(
|
||||||
false, true, true, false, &empty_scheduled(), "bm1", false,
|
false,
|
||||||
None, 14_074_000,
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
&empty_scheduled(),
|
||||||
|
"bm1",
|
||||||
|
false,
|
||||||
|
None,
|
||||||
|
14_074_000,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
action,
|
action,
|
||||||
@@ -813,7 +860,13 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn skip_out_of_span() {
|
fn skip_out_of_span() {
|
||||||
let action = evaluate_bookmark(
|
let action = evaluate_bookmark(
|
||||||
false, true, true, false, &empty_scheduled(), "bm1", false,
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
&empty_scheduled(),
|
||||||
|
"bm1",
|
||||||
|
false,
|
||||||
Some((14_074_000, 96_000)), // center 14.074 MHz, half span 96 kHz
|
Some((14_074_000, 96_000)), // center 14.074 MHz, half span 96 kHz
|
||||||
7_074_000, // way outside the span
|
7_074_000, // way outside the span
|
||||||
);
|
);
|
||||||
@@ -828,7 +881,13 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn active_at_edge_of_span() {
|
fn active_at_edge_of_span() {
|
||||||
let action = evaluate_bookmark(
|
let action = evaluate_bookmark(
|
||||||
false, true, true, false, &empty_scheduled(), "bm1", false,
|
false,
|
||||||
|
true,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
&empty_scheduled(),
|
||||||
|
"bm1",
|
||||||
|
false,
|
||||||
Some((14_074_000, 96_000)),
|
Some((14_074_000, 96_000)),
|
||||||
14_074_000 + 96_000, // exactly at the edge
|
14_074_000 + 96_000, // exactly at the edge
|
||||||
);
|
);
|
||||||
@@ -839,8 +898,15 @@ mod tests {
|
|||||||
fn priority_no_decoders_over_disabled() {
|
fn priority_no_decoders_over_disabled() {
|
||||||
// Even if disabled, "no_supported_decoders" should take precedence
|
// Even if disabled, "no_supported_decoders" should take precedence
|
||||||
let action = evaluate_bookmark(
|
let action = evaluate_bookmark(
|
||||||
true, false, true, false, &empty_scheduled(), "bm1", false,
|
true,
|
||||||
Some((14_074_000, 96_000)), 14_074_000,
|
false,
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
&empty_scheduled(),
|
||||||
|
"bm1",
|
||||||
|
false,
|
||||||
|
Some((14_074_000, 96_000)),
|
||||||
|
14_074_000,
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
action,
|
action,
|
||||||
|
|||||||
@@ -1242,7 +1242,10 @@ async fn run_aprs_decoder_inner(
|
|||||||
histories: Arc<DecoderHistories>,
|
histories: Arc<DecoderHistories>,
|
||||||
is_hf: bool,
|
is_hf: bool,
|
||||||
) {
|
) {
|
||||||
info!("{} decoder started ({}Hz, {} ch)", label, sample_rate, channels);
|
info!(
|
||||||
|
"{} decoder started ({}Hz, {} ch)",
|
||||||
|
label, sample_rate, channels
|
||||||
|
);
|
||||||
|
|
||||||
let mut decoder = if is_hf {
|
let mut decoder = if is_hf {
|
||||||
AprsDecoder::new_hf(sample_rate)
|
AprsDecoder::new_hf(sample_rate)
|
||||||
@@ -1266,7 +1269,11 @@ async fn run_aprs_decoder_inner(
|
|||||||
state.reset_seqs.aprs_decode_reset_seq
|
state.reset_seqs.aprs_decode_reset_seq
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let span_name = if is_hf { "hf_aprs_decode" } else { "aprs_decode" };
|
let span_name = if is_hf {
|
||||||
|
"hf_aprs_decode"
|
||||||
|
} else {
|
||||||
|
"aprs_decode"
|
||||||
|
};
|
||||||
|
|
||||||
let mut active = mode_match(&state_rx.borrow());
|
let mut active = mode_match(&state_rx.borrow());
|
||||||
|
|
||||||
@@ -1849,7 +1856,10 @@ async fn run_ftx_decoder_inner(
|
|||||||
histories: Arc<DecoderHistories>,
|
histories: Arc<DecoderHistories>,
|
||||||
is_ft4: bool,
|
is_ft4: bool,
|
||||||
) {
|
) {
|
||||||
info!("{} decoder started ({}Hz, {} ch)", label, sample_rate, channels);
|
info!(
|
||||||
|
"{} decoder started ({}Hz, {} ch)",
|
||||||
|
label, sample_rate, channels
|
||||||
|
);
|
||||||
|
|
||||||
let mut decoder = {
|
let mut decoder = {
|
||||||
let result = if is_ft4 {
|
let result = if is_ft4 {
|
||||||
|
|||||||
@@ -911,10 +911,8 @@ mod tests {
|
|||||||
#[ignore = "requires TCP bind permissions"]
|
#[ignore = "requires TCP bind permissions"]
|
||||||
async fn multi_rig_state_isolation() {
|
async fn multi_rig_state_isolation() {
|
||||||
// Two rigs with different frequencies and modes.
|
// Two rigs with different frequencies and modes.
|
||||||
let state_hf =
|
let state_hf = sample_state_custom("HF-Dummy", 14_200_000, trx_core::RigMode::USB);
|
||||||
sample_state_custom("HF-Dummy", 14_200_000, trx_core::RigMode::USB);
|
let state_vhf = sample_state_custom("VHF-Dummy", 145_500_000, trx_core::RigMode::FM);
|
||||||
let state_vhf =
|
|
||||||
sample_state_custom("VHF-Dummy", 145_500_000, trx_core::RigMode::FM);
|
|
||||||
|
|
||||||
let (rigs, default_id, _rx_a, _rx_b) = make_two_rigs(state_hf, state_vhf);
|
let (rigs, default_id, _rx_a, _rx_b) = make_two_rigs(state_hf, state_vhf);
|
||||||
let addr = loopback_addr();
|
let addr = loopback_addr();
|
||||||
@@ -978,10 +976,8 @@ mod tests {
|
|||||||
#[ignore = "requires TCP bind permissions"]
|
#[ignore = "requires TCP bind permissions"]
|
||||||
async fn multi_rig_default_fallback() {
|
async fn multi_rig_default_fallback() {
|
||||||
// When rig_id is omitted, the default rig (rig_hf) should be used.
|
// When rig_id is omitted, the default rig (rig_hf) should be used.
|
||||||
let state_hf =
|
let state_hf = sample_state_custom("HF-Dummy", 14_200_000, trx_core::RigMode::USB);
|
||||||
sample_state_custom("HF-Dummy", 14_200_000, trx_core::RigMode::USB);
|
let state_vhf = sample_state_custom("VHF-Dummy", 145_500_000, trx_core::RigMode::FM);
|
||||||
let state_vhf =
|
|
||||||
sample_state_custom("VHF-Dummy", 145_500_000, trx_core::RigMode::FM);
|
|
||||||
|
|
||||||
let (rigs, default_id, _rx_a, _rx_b) = make_two_rigs(state_hf, state_vhf);
|
let (rigs, default_id, _rx_a, _rx_b) = make_two_rigs(state_hf, state_vhf);
|
||||||
let addr = loopback_addr();
|
let addr = loopback_addr();
|
||||||
@@ -1004,12 +1000,7 @@ mod tests {
|
|||||||
let mut reader = BufReader::new(read_half);
|
let mut reader = BufReader::new(read_half);
|
||||||
|
|
||||||
// No rig_id — should resolve to default (rig_hf).
|
// No rig_id — should resolve to default (rig_hf).
|
||||||
let resp = send_and_recv(
|
let resp = send_and_recv(&mut writer, &mut reader, br#"{"cmd":"get_state"}"#).await;
|
||||||
&mut writer,
|
|
||||||
&mut reader,
|
|
||||||
br#"{"cmd":"get_state"}"#,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
assert!(resp.success, "default get_state should succeed");
|
assert!(resp.success, "default get_state should succeed");
|
||||||
assert_eq!(resp.rig_id.as_deref(), Some("rig_hf"));
|
assert_eq!(resp.rig_id.as_deref(), Some("rig_hf"));
|
||||||
let snap = resp.state.expect("default snapshot");
|
let snap = resp.state.expect("default snapshot");
|
||||||
@@ -1023,10 +1014,8 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[ignore = "requires TCP bind permissions"]
|
#[ignore = "requires TCP bind permissions"]
|
||||||
async fn multi_rig_get_rigs_returns_all() {
|
async fn multi_rig_get_rigs_returns_all() {
|
||||||
let state_hf =
|
let state_hf = sample_state_custom("HF-Dummy", 14_200_000, trx_core::RigMode::USB);
|
||||||
sample_state_custom("HF-Dummy", 14_200_000, trx_core::RigMode::USB);
|
let state_vhf = sample_state_custom("VHF-Dummy", 145_500_000, trx_core::RigMode::FM);
|
||||||
let state_vhf =
|
|
||||||
sample_state_custom("VHF-Dummy", 145_500_000, trx_core::RigMode::FM);
|
|
||||||
|
|
||||||
let (rigs, default_id, _rx_a, _rx_b) = make_two_rigs(state_hf, state_vhf);
|
let (rigs, default_id, _rx_a, _rx_b) = make_two_rigs(state_hf, state_vhf);
|
||||||
let addr = loopback_addr();
|
let addr = loopback_addr();
|
||||||
@@ -1048,12 +1037,7 @@ mod tests {
|
|||||||
let (read_half, mut writer) = stream.into_split();
|
let (read_half, mut writer) = stream.into_split();
|
||||||
let mut reader = BufReader::new(read_half);
|
let mut reader = BufReader::new(read_half);
|
||||||
|
|
||||||
let resp = send_and_recv(
|
let resp = send_and_recv(&mut writer, &mut reader, br#"{"cmd":"get_rigs"}"#).await;
|
||||||
&mut writer,
|
|
||||||
&mut reader,
|
|
||||||
br#"{"cmd":"get_rigs"}"#,
|
|
||||||
)
|
|
||||||
.await;
|
|
||||||
assert!(resp.success, "get_rigs should succeed");
|
assert!(resp.success, "get_rigs should succeed");
|
||||||
let entries = resp.rigs.expect("rigs list");
|
let entries = resp.rigs.expect("rigs list");
|
||||||
assert_eq!(entries.len(), 2, "should return both rigs");
|
assert_eq!(entries.len(), 2, "should return both rigs");
|
||||||
@@ -1090,13 +1074,10 @@ mod tests {
|
|||||||
async fn multi_rig_command_routing() {
|
async fn multi_rig_command_routing() {
|
||||||
// Verify that a set_freq command targeting rig_vhf is delivered to the
|
// Verify that a set_freq command targeting rig_vhf is delivered to the
|
||||||
// VHF rig's mpsc channel and not to the HF rig's channel.
|
// VHF rig's mpsc channel and not to the HF rig's channel.
|
||||||
let state_hf =
|
let state_hf = sample_state_custom("HF-Dummy", 14_200_000, trx_core::RigMode::USB);
|
||||||
sample_state_custom("HF-Dummy", 14_200_000, trx_core::RigMode::USB);
|
let state_vhf = sample_state_custom("VHF-Dummy", 145_500_000, trx_core::RigMode::FM);
|
||||||
let state_vhf =
|
|
||||||
sample_state_custom("VHF-Dummy", 145_500_000, trx_core::RigMode::FM);
|
|
||||||
|
|
||||||
let (rigs, default_id, mut rx_hf, mut rx_vhf) =
|
let (rigs, default_id, mut rx_hf, mut rx_vhf) = make_two_rigs(state_hf, state_vhf);
|
||||||
make_two_rigs(state_hf, state_vhf);
|
|
||||||
let addr = loopback_addr();
|
let addr = loopback_addr();
|
||||||
let (shutdown_tx, shutdown_rx) = watch::channel(false);
|
let (shutdown_tx, shutdown_rx) = watch::channel(false);
|
||||||
|
|
||||||
@@ -1125,10 +1106,7 @@ mod tests {
|
|||||||
writer.flush().await.expect("flush");
|
writer.flush().await.expect("flush");
|
||||||
|
|
||||||
// The VHF channel should receive the command.
|
// The VHF channel should receive the command.
|
||||||
let req = tokio::time::timeout(
|
let req = tokio::time::timeout(std::time::Duration::from_secs(2), rx_vhf.recv())
|
||||||
std::time::Duration::from_secs(2),
|
|
||||||
rx_vhf.recv(),
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
.expect("timeout waiting for VHF command")
|
.expect("timeout waiting for VHF command")
|
||||||
.expect("VHF channel closed");
|
.expect("VHF channel closed");
|
||||||
@@ -1153,13 +1131,10 @@ mod tests {
|
|||||||
#[ignore = "requires TCP bind permissions"]
|
#[ignore = "requires TCP bind permissions"]
|
||||||
async fn multi_rig_command_routing_to_default() {
|
async fn multi_rig_command_routing_to_default() {
|
||||||
// When rig_id is omitted, commands should go to the default rig (HF).
|
// When rig_id is omitted, commands should go to the default rig (HF).
|
||||||
let state_hf =
|
let state_hf = sample_state_custom("HF-Dummy", 14_200_000, trx_core::RigMode::USB);
|
||||||
sample_state_custom("HF-Dummy", 14_200_000, trx_core::RigMode::USB);
|
let state_vhf = sample_state_custom("VHF-Dummy", 145_500_000, trx_core::RigMode::FM);
|
||||||
let state_vhf =
|
|
||||||
sample_state_custom("VHF-Dummy", 145_500_000, trx_core::RigMode::FM);
|
|
||||||
|
|
||||||
let (rigs, default_id, mut rx_hf, mut rx_vhf) =
|
let (rigs, default_id, mut rx_hf, mut rx_vhf) = make_two_rigs(state_hf, state_vhf);
|
||||||
make_two_rigs(state_hf, state_vhf);
|
|
||||||
let addr = loopback_addr();
|
let addr = loopback_addr();
|
||||||
let (shutdown_tx, shutdown_rx) = watch::channel(false);
|
let (shutdown_tx, shutdown_rx) = watch::channel(false);
|
||||||
|
|
||||||
@@ -1187,10 +1162,7 @@ mod tests {
|
|||||||
writer.flush().await.expect("flush");
|
writer.flush().await.expect("flush");
|
||||||
|
|
||||||
// The HF channel should receive the command.
|
// The HF channel should receive the command.
|
||||||
let req = tokio::time::timeout(
|
let req = tokio::time::timeout(std::time::Duration::from_secs(2), rx_hf.recv())
|
||||||
std::time::Duration::from_secs(2),
|
|
||||||
rx_hf.recv(),
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
.expect("timeout waiting for HF command")
|
.expect("timeout waiting for HF command")
|
||||||
.expect("HF channel closed");
|
.expect("HF channel closed");
|
||||||
|
|||||||
Reference in New Issue
Block a user