[feat](trx-rs): show server/client build info in HTTP footer
Add compile-time build dates for trx-server and trx-frontend-http, propagate server build metadata through rig state/snapshot, and render both versions + build dates in the HTTP footer. Co-authored-by: OpenAI Codex <codex@openai.com> Signed-off-by: Stanislaw Grams <stanislawgrams@gmail.com>
This commit is contained in:
@@ -410,6 +410,7 @@ mod tests {
|
||||
initialized: true,
|
||||
server_callsign: Some("N0CALL".to_string()),
|
||||
server_version: Some("test".to_string()),
|
||||
server_build_date: Some("2026-01-01".to_string()),
|
||||
server_latitude: None,
|
||||
server_longitude: None,
|
||||
pskreporter_status: Some("Disabled".to_string()),
|
||||
|
||||
@@ -333,6 +333,7 @@ mod tests {
|
||||
initialized: true,
|
||||
server_callsign: Some("N0CALL".to_string()),
|
||||
server_version: Some("test".to_string()),
|
||||
server_build_date: Some("2026-01-01".to_string()),
|
||||
server_latitude: None,
|
||||
server_longitude: None,
|
||||
pskreporter_status: Some("Disabled".to_string()),
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
name = "trx-frontend-http"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
trx-core = { path = "../../../trx-core" }
|
||||
|
||||
@@ -629,10 +629,19 @@ function setDisabled(disabled) {
|
||||
}
|
||||
|
||||
let serverVersion = null;
|
||||
let serverBuildDate = null;
|
||||
let serverCallsign = null;
|
||||
let serverLat = null;
|
||||
let serverLon = null;
|
||||
|
||||
function updateFooterBuildInfo() {
|
||||
const serverEl = document.getElementById("footer-server-build");
|
||||
if (!serverEl) return;
|
||||
const ver = serverVersion || "--";
|
||||
const build = serverBuildDate || "--";
|
||||
serverEl.textContent = `trx-server v${ver} ${build}`;
|
||||
}
|
||||
|
||||
function updateTitle() {
|
||||
let title = rigName || "Rig";
|
||||
if (serverCallsign) title = `${serverCallsign}'s ${title}`;
|
||||
@@ -643,10 +652,12 @@ function render(update) {
|
||||
if (!update) return;
|
||||
if (update.info && update.info.model) rigName = update.info.model;
|
||||
if (update.server_version) serverVersion = update.server_version;
|
||||
if (update.server_build_date) serverBuildDate = update.server_build_date;
|
||||
if (update.server_callsign) serverCallsign = update.server_callsign;
|
||||
if (update.server_latitude != null) serverLat = update.server_latitude;
|
||||
if (update.server_longitude != null) serverLon = update.server_longitude;
|
||||
updateTitle();
|
||||
updateFooterBuildInfo();
|
||||
|
||||
initialized = !!update.initialized;
|
||||
if (!initialized) {
|
||||
|
||||
@@ -266,7 +266,11 @@
|
||||
</table>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<div class="copyright">Built by <a href="https://www.qrzcq.com/call/SP2SJG" target="_blank" rel="noopener">SP2SJG</a> from <a href="https://haxx.space" target="_blank" rel="noopener">haxx.space</a> — <span id="copyright-year"></span></div>
|
||||
<div class="copyright">
|
||||
Built by <a href="https://www.qrzcq.com/call/SP2SJG" target="_blank" rel="noopener">SP2SJG</a> from <a href="https://haxx.space" target="_blank" rel="noopener">haxx.space</a> — <span id="copyright-year"></span>
|
||||
- <span id="footer-server-build">trx-server v-- --</span>
|
||||
- <span id="footer-client-build">trx-client v{ver} {client_build_date}</span>
|
||||
</div>
|
||||
<div class="hint" id="power-hint">Connecting…</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
fn utc_ymd_from_unix_secs(secs: i64) -> (i32, u32, u32) {
|
||||
let days = secs.div_euclid(86_400);
|
||||
let z = days + 719_468;
|
||||
let era = if z >= 0 { z } else { z - 146_096 } / 146_097;
|
||||
let doe = z - era * 146_097;
|
||||
let yoe = (doe - doe / 1_460 + doe / 36_524 - doe / 146_096) / 365;
|
||||
let mut y = yoe + era * 400;
|
||||
let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
|
||||
let mp = (5 * doy + 2) / 153;
|
||||
let d = doy - (153 * mp + 2) / 5 + 1;
|
||||
let m = mp + if mp < 10 { 3 } else { -9 };
|
||||
y += if m <= 2 { 1 } else { 0 };
|
||||
(y as i32, m as u32, d as u32)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let secs = match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||
Ok(d) => d.as_secs() as i64,
|
||||
Err(_) => 0,
|
||||
};
|
||||
let (y, m, d) = utc_ymd_from_unix_secs(secs);
|
||||
println!("cargo:rustc-env=TRX_CLIENT_BUILD_DATE={y:04}-{m:02}-{d:02}");
|
||||
}
|
||||
@@ -625,6 +625,7 @@ async fn wait_for_view(mut rx: watch::Receiver<RigState>) -> Result<RigSnapshot,
|
||||
initialized: state.initialized,
|
||||
server_callsign: state.server_callsign,
|
||||
server_version: state.server_version,
|
||||
server_build_date: state.server_build_date,
|
||||
server_latitude: state.server_latitude,
|
||||
server_longitude: state.server_longitude,
|
||||
pskreporter_status: state.pskreporter_status,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
const PKG_NAME: &str = env!("CARGO_PKG_NAME");
|
||||
const PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||
const CLIENT_BUILD_DATE: &str = env!("TRX_CLIENT_BUILD_DATE");
|
||||
|
||||
const INDEX_HTML: &str = include_str!("../assets/web/index.html");
|
||||
pub const STYLE_CSS: &str = include_str!("../assets/web/style.css");
|
||||
@@ -17,4 +18,5 @@ pub fn index_html() -> String {
|
||||
INDEX_HTML
|
||||
.replace("{pkg}", PKG_NAME)
|
||||
.replace("{ver}", PKG_VERSION)
|
||||
.replace("{client_build_date}", CLIENT_BUILD_DATE)
|
||||
}
|
||||
|
||||
@@ -657,6 +657,7 @@ mod tests {
|
||||
initialized: true,
|
||||
server_callsign: None,
|
||||
server_version: None,
|
||||
server_build_date: None,
|
||||
server_latitude: None,
|
||||
server_longitude: None,
|
||||
pskreporter_status: None,
|
||||
|
||||
@@ -21,6 +21,8 @@ pub struct RigState {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub server_version: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub server_build_date: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub server_latitude: Option<f64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub server_longitude: Option<f64>,
|
||||
@@ -114,6 +116,7 @@ impl RigState {
|
||||
control: RigControl::default(),
|
||||
server_callsign: None,
|
||||
server_version: None,
|
||||
server_build_date: None,
|
||||
server_latitude: None,
|
||||
server_longitude: None,
|
||||
pskreporter_status: None,
|
||||
@@ -135,6 +138,7 @@ impl RigState {
|
||||
pub fn new_with_metadata(
|
||||
callsign: Option<String>,
|
||||
version: Option<String>,
|
||||
build_date: Option<String>,
|
||||
latitude: Option<f64>,
|
||||
longitude: Option<f64>,
|
||||
initial_freq_hz: u64,
|
||||
@@ -143,6 +147,7 @@ impl RigState {
|
||||
let mut state = Self::new_uninitialized();
|
||||
state.server_callsign = callsign;
|
||||
state.server_version = version;
|
||||
state.server_build_date = build_date;
|
||||
state.server_latitude = latitude;
|
||||
state.server_longitude = longitude;
|
||||
state.status.freq = Freq {
|
||||
@@ -170,6 +175,7 @@ impl RigState {
|
||||
},
|
||||
server_callsign: snapshot.server_callsign,
|
||||
server_version: snapshot.server_version,
|
||||
server_build_date: snapshot.server_build_date,
|
||||
server_latitude: snapshot.server_latitude,
|
||||
server_longitude: snapshot.server_longitude,
|
||||
pskreporter_status: snapshot.pskreporter_status,
|
||||
@@ -206,6 +212,7 @@ impl RigState {
|
||||
initialized: self.initialized,
|
||||
server_callsign: self.server_callsign.clone(),
|
||||
server_version: self.server_version.clone(),
|
||||
server_build_date: self.server_build_date.clone(),
|
||||
server_latitude: self.server_latitude,
|
||||
server_longitude: self.server_longitude,
|
||||
pskreporter_status: self.pskreporter_status.clone(),
|
||||
@@ -255,6 +262,8 @@ pub struct RigSnapshot {
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub server_version: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub server_build_date: Option<String>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub server_latitude: Option<f64>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub server_longitude: Option<f64>,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
name = "trx-server"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
tokio = { workspace = true, features = ["full"] }
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
fn utc_ymd_from_unix_secs(secs: i64) -> (i32, u32, u32) {
|
||||
let days = secs.div_euclid(86_400);
|
||||
let z = days + 719_468;
|
||||
let era = if z >= 0 { z } else { z - 146_096 } / 146_097;
|
||||
let doe = z - era * 146_097;
|
||||
let yoe = (doe - doe / 1_460 + doe / 36_524 - doe / 146_096) / 365;
|
||||
let mut y = yoe + era * 400;
|
||||
let doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
|
||||
let mp = (5 * doy + 2) / 153;
|
||||
let d = doy - (153 * mp + 2) / 5 + 1;
|
||||
let m = mp + if mp < 10 { 3 } else { -9 };
|
||||
y += if m <= 2 { 1 } else { 0 };
|
||||
(y as i32, m as u32, d as u32)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let secs = match SystemTime::now().duration_since(UNIX_EPOCH) {
|
||||
Ok(d) => d.as_secs() as i64,
|
||||
Err(_) => 0,
|
||||
};
|
||||
let (y, m, d) = utc_ymd_from_unix_secs(secs);
|
||||
println!("cargo:rustc-env=TRX_SERVER_BUILD_DATE={y:04}-{m:02}-{d:02}");
|
||||
}
|
||||
@@ -224,6 +224,7 @@ fn build_rig_task_config(
|
||||
initial_mode: cfg.rig.initial_mode.clone(),
|
||||
server_callsign: resolved.callsign.clone(),
|
||||
server_version: Some(env!("CARGO_PKG_VERSION").to_string()),
|
||||
server_build_date: Some(env!("TRX_SERVER_BUILD_DATE").to_string()),
|
||||
server_latitude: resolved.latitude,
|
||||
server_longitude: resolved.longitude,
|
||||
pskreporter_status,
|
||||
@@ -302,6 +303,7 @@ async fn main() -> DynResult<()> {
|
||||
let initial_state = RigState::new_with_metadata(
|
||||
resolved.callsign.clone(),
|
||||
Some(env!("CARGO_PKG_VERSION").to_string()),
|
||||
Some(env!("TRX_SERVER_BUILD_DATE").to_string()),
|
||||
resolved.latitude,
|
||||
resolved.longitude,
|
||||
cfg.rig.initial_freq_hz,
|
||||
|
||||
@@ -38,6 +38,7 @@ pub struct RigTaskConfig {
|
||||
pub initial_mode: RigMode,
|
||||
pub server_callsign: Option<String>,
|
||||
pub server_version: Option<String>,
|
||||
pub server_build_date: Option<String>,
|
||||
pub server_latitude: Option<f64>,
|
||||
pub server_longitude: Option<f64>,
|
||||
pub pskreporter_status: Option<String>,
|
||||
@@ -60,6 +61,7 @@ impl Default for RigTaskConfig {
|
||||
initial_mode: RigMode::USB,
|
||||
server_callsign: None,
|
||||
server_version: None,
|
||||
server_build_date: None,
|
||||
server_latitude: None,
|
||||
server_longitude: None,
|
||||
pskreporter_status: None,
|
||||
@@ -102,6 +104,7 @@ pub async fn run_rig_task(
|
||||
let mut state = RigState::new_with_metadata(
|
||||
config.server_callsign.clone(),
|
||||
config.server_version.clone(),
|
||||
config.server_build_date.clone(),
|
||||
config.server_latitude,
|
||||
config.server_longitude,
|
||||
config.initial_freq_hz,
|
||||
|
||||
Reference in New Issue
Block a user