diff --git a/src/trx-client/src/remote_client.rs b/src/trx-client/src/remote_client.rs
index aaf3312..b0a8edc 100644
--- a/src/trx-client/src/remote_client.rs
+++ b/src/trx-client/src/remote_client.rs
@@ -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()),
diff --git a/src/trx-client/trx-frontend/trx-frontend-http-json/src/server.rs b/src/trx-client/trx-frontend/trx-frontend-http-json/src/server.rs
index 68f5ed8..b505268 100644
--- a/src/trx-client/trx-frontend/trx-frontend-http-json/src/server.rs
+++ b/src/trx-client/trx-frontend/trx-frontend-http-json/src/server.rs
@@ -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()),
diff --git a/src/trx-client/trx-frontend/trx-frontend-http/Cargo.toml b/src/trx-client/trx-frontend/trx-frontend-http/Cargo.toml
index 75bc19a..1f7cacb 100644
--- a/src/trx-client/trx-frontend/trx-frontend-http/Cargo.toml
+++ b/src/trx-client/trx-frontend/trx-frontend-http/Cargo.toml
@@ -6,6 +6,7 @@
name = "trx-frontend-http"
version = "0.1.0"
edition = "2021"
+build = "build.rs"
[dependencies]
trx-core = { path = "../../../trx-core" }
diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js
index 4e9278a..a2c7d53 100644
--- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js
+++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js
@@ -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) {
diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html
index b936703..134dcc0 100644
--- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html
+++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html
@@ -266,7 +266,11 @@
diff --git a/src/trx-client/trx-frontend/trx-frontend-http/build.rs b/src/trx-client/trx-frontend/trx-frontend-http/build.rs
new file mode 100644
index 0000000..882c673
--- /dev/null
+++ b/src/trx-client/trx-frontend/trx-frontend-http/build.rs
@@ -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}");
+}
diff --git a/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs b/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs
index c489fea..818c607 100644
--- a/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs
+++ b/src/trx-client/trx-frontend/trx-frontend-http/src/api.rs
@@ -625,6 +625,7 @@ async fn wait_for_view(mut rx: watch::Receiver) -> Result String {
INDEX_HTML
.replace("{pkg}", PKG_NAME)
.replace("{ver}", PKG_VERSION)
+ .replace("{client_build_date}", CLIENT_BUILD_DATE)
}
diff --git a/src/trx-client/trx-frontend/trx-frontend-rigctl/src/server.rs b/src/trx-client/trx-frontend/trx-frontend-rigctl/src/server.rs
index 3d8af41..b1e6a00 100644
--- a/src/trx-client/trx-frontend/trx-frontend-rigctl/src/server.rs
+++ b/src/trx-client/trx-frontend/trx-frontend-rigctl/src/server.rs
@@ -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,
diff --git a/src/trx-core/src/rig/state.rs b/src/trx-core/src/rig/state.rs
index 6422235..709f26f 100644
--- a/src/trx-core/src/rig/state.rs
+++ b/src/trx-core/src/rig/state.rs
@@ -21,6 +21,8 @@ pub struct RigState {
#[serde(default, skip_serializing_if = "Option::is_none")]
pub server_version: Option,
#[serde(default, skip_serializing_if = "Option::is_none")]
+ pub server_build_date: Option,
+ #[serde(default, skip_serializing_if = "Option::is_none")]
pub server_latitude: Option,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub server_longitude: Option,
@@ -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,
version: Option,
+ build_date: Option,
latitude: Option,
longitude: Option,
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,
#[serde(default, skip_serializing_if = "Option::is_none")]
+ pub server_build_date: Option,
+ #[serde(default, skip_serializing_if = "Option::is_none")]
pub server_latitude: Option,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub server_longitude: Option,
diff --git a/src/trx-server/Cargo.toml b/src/trx-server/Cargo.toml
index 39a694a..82878e3 100644
--- a/src/trx-server/Cargo.toml
+++ b/src/trx-server/Cargo.toml
@@ -6,6 +6,7 @@
name = "trx-server"
version = "0.1.0"
edition = "2021"
+build = "build.rs"
[dependencies]
tokio = { workspace = true, features = ["full"] }
diff --git a/src/trx-server/build.rs b/src/trx-server/build.rs
new file mode 100644
index 0000000..00f46e0
--- /dev/null
+++ b/src/trx-server/build.rs
@@ -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}");
+}
diff --git a/src/trx-server/src/main.rs b/src/trx-server/src/main.rs
index c256bab..bef86f2 100644
--- a/src/trx-server/src/main.rs
+++ b/src/trx-server/src/main.rs
@@ -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,
diff --git a/src/trx-server/src/rig_task.rs b/src/trx-server/src/rig_task.rs
index 686cc6c..7b92e05 100644
--- a/src/trx-server/src/rig_task.rs
+++ b/src/trx-server/src/rig_task.rs
@@ -38,6 +38,7 @@ pub struct RigTaskConfig {
pub initial_mode: RigMode,
pub server_callsign: Option,
pub server_version: Option,
+ pub server_build_date: Option,
pub server_latitude: Option,
pub server_longitude: Option,
pub pskreporter_status: Option,
@@ -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,