diff --git a/Cargo.lock b/Cargo.lock index 685b1446..b8feb3a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2099,6 +2099,7 @@ dependencies = [ "serde", "serde_json", "tikv-jemallocator", + "time", "tokio", "tokio-stream", "tokio-util", diff --git a/Cargo.toml b/Cargo.toml index 8b582b71..30ba266d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,7 @@ serde = { version = "1.0.228", features = ["derive"] } serde_json = "1.0.149" tokio = { version = "1.50.0", features = ["rt-multi-thread", "macros", "io-util", "tracing", "signal"] } tokio-stream = "0.1.18" +time = { version = "0.3", features = ["local-offset"] } tokio-util = { version = "0.7.18", features = ["full", "tracing"] } toml = "1.0.7" uuid = { version = "1.22.0", features = ["v4"] } diff --git a/README.md b/README.md index c6dafef6..b2c3937d 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ merged, plus additional improvements: - Low-latency RTSP mode with frame draining, live-mode AppSrc, and reduced buffers - Docker images published to GHCR instead of Docker Hub - Updated dependencies and Debian Trixie base image +- Use local timezone when using `update_time` to set camera time **Inherited features from upstream:** diff --git a/docs/configuration.md b/docs/configuration.md index 4e66b2a7..d86ae90a 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -55,7 +55,7 @@ enable_low_latency = false # reduce stream delay (default: false) # Diagnostics debug = false # dump raw XML from camera print_format = "None" # "None", "Human", or "Xml" for status messages -update_time = false # force camera clock sync on connect +update_time = false # force camera clock sync on connect (uses local wall-clock time) # NVR channel (for multi-camera NVRs) channel_id = 0 # 0-indexed camera on NVR diff --git a/src/common/camthread.rs b/src/common/camthread.rs index 6254ab9c..2cd2e424 100644 --- a/src/common/camthread.rs +++ b/src/common/camthread.rs @@ -194,7 +194,11 @@ impl Drop for NeoCamThread { } } -async fn update_camera_time(camera: &BcCamera, name: &str, update_time: bool) -> AnyResult<()> { +async fn update_camera_time( + camera: &BcCamera, + name: &str, + update_time: bool, +) -> AnyResult<()> { let cam_time = camera.get_time().await?; let mut update = false; if let Some(time) = cam_time { @@ -207,11 +211,21 @@ async fn update_camera_time(camera: &BcCamera, name: &str, update_time: bool) -> log::warn!("{}: Camera has no time set, Updating", name); } if update { - use std::time::SystemTime; - let new_time = SystemTime::now(); - - log::info!("{}: Setting time to {:?}", name, new_time); - match camera.set_time(new_time.into()).await { + use time::{OffsetDateTime, UtcOffset}; + + let utc_now = OffsetDateTime::now_utc(); + let offset = UtcOffset::local_offset_at(utc_now).unwrap_or(UtcOffset::UTC); + let local = utc_now.to_offset(offset); + log::info!( + "{}: Setting camera time to local time: {} {}", + name, + local, + offset + ); + // Strip the offset so the camera stores wall-clock local time as-is + let new_time = local.replace_offset(UtcOffset::UTC); + + match camera.set_time(new_time).await { Ok(_) => { let cam_time = camera.get_time().await?; if let Some(time) = cam_time {