@@ -2,12 +2,11 @@ use core::fmt;
22use std:: collections:: HashMap ;
33// Read camera config file
44use crate :: detection_mask:: DetectionMask ;
5+ use crate :: set_system_timezone;
56use byteorder:: { LittleEndian , WriteBytesExt } ;
67use chrono:: {
7- DateTime , Duration , FixedOffset , Local , NaiveDate , NaiveDateTime , NaiveTime , Offset , TimeZone ,
8- Utc ,
8+ DateTime , Duration , FixedOffset , Local , NaiveDate , NaiveDateTime , NaiveTime , TimeZone , Utc ,
99} ;
10- use chrono_tz:: Tz ;
1110use log:: { error, info, warn} ;
1211use louvre:: triangulate;
1312use notify:: event:: { AccessKind , AccessMode } ;
@@ -24,9 +23,9 @@ use std::sync::mpsc::{Receiver, Sender, TryRecvError};
2423use std:: { fs, process} ;
2524use sun_times:: sun_times;
2625use toml:: Value ;
27- use toml:: value:: Offset as TomlDateTimeOffset ;
26+ use toml:: value:: Offset ;
2827
29- static TZ_FINDER : LazyLock < tzf_rs:: DefaultFinder > = LazyLock :: new ( tzf_rs:: DefaultFinder :: new) ;
28+ pub static TZ_FINDER : LazyLock < tzf_rs:: DefaultFinder > = LazyLock :: new ( tzf_rs:: DefaultFinder :: new) ;
3029
3130fn default_constant_recorder ( ) -> bool {
3231 false
@@ -289,8 +288,8 @@ where
289288 let time = date_time. time . expect ( "should have time" ) ;
290289 let offset = date_time. offset . expect ( "should have offset" ) ;
291290 let offset_minutes = match offset {
292- TomlDateTimeOffset :: Z => 0 ,
293- TomlDateTimeOffset :: Custom { minutes } => minutes,
291+ Offset :: Z => 0 ,
292+ Offset :: Custom { minutes } => minutes,
294293 } as i32 ;
295294 let fixed_offset = if offset_minutes < 0 {
296295 FixedOffset :: east_opt ( offset_minutes * 60 )
@@ -342,13 +341,12 @@ struct HourMin {
342341 min : u8 ,
343342}
344343
345- fn timezone_offset_seconds ( lat : f32 , lng : f32 ) -> i32 {
346- let tz_from_lat_lng = TZ_FINDER . get_tz_name ( lat as f64 , lng as f64 ) ;
347- let tz = Tz :: from_str ( tz_from_lat_lng)
348- . unwrap_or_else ( |_| panic ! ( "Failed to parse timezone from lat lng {tz_from_lat_lng}" ) ) ;
349- let now_utc = Local :: now ( ) . naive_utc ( ) ;
350- let offset = tz. offset_from_utc_datetime ( & now_utc) ;
351- offset. fix ( ) . local_minus_utc ( )
344+ fn timezone_offset_seconds ( ) -> i32 {
345+ // IMPORTANT: This relies on the system timezone being set correctly to the same locale as the
346+ // devices' GPS coordinates to work out correct absolute start/end recording window times.
347+ let now = Local :: now ( ) ;
348+ let local_tz = now. timezone ( ) ;
349+ local_tz. offset_from_utc_datetime ( & now. naive_utc ( ) ) . local_minus_utc ( )
352350}
353351#[ derive( PartialEq , Clone ) ]
354352pub struct AbsRelTime {
@@ -375,15 +373,14 @@ impl Debug for AbsRelTime {
375373}
376374
377375impl AbsRelTime {
378- pub fn time_offset ( & self , lat : f32 , lng : f32 ) -> ( bool , i32 ) {
376+ pub fn time_offset ( & self ) -> ( bool , i32 ) {
379377 // Absolute or relative time in seconds in the day
380378 if let Some ( abs_time) = & self . absolute_time {
381379 // NOTE: We need to convert this to UTC offsets, since that's what our timestamp is.
382380 let seconds_past_midnight =
383381 ( abs_time. hour as i32 * 60 * 60 ) + ( abs_time. min as i32 * 60 ) ;
384382 //info!("Seconds past midnight local {}", seconds_past_midnight);
385-
386- let tz_offset = timezone_offset_seconds ( lat, lng) ;
383+ let tz_offset = timezone_offset_seconds ( ) ;
387384 // info!(
388385 // "TZ offset {}, seconds past UTC midnight {}",
389386 // tz_offset,
@@ -683,20 +680,22 @@ impl DeviceConfig {
683680 }
684681
685682 pub fn next_recording_window ( & self , now_utc : & NaiveDateTime ) -> ( NaiveDateTime , NaiveDateTime ) {
686- let location =
687- self . location . as_ref ( ) . expect ( "Relative recording windows require a location" ) ;
688- let ( lat, lng) = self . lat_lng ( ) ;
689683 let ( is_absolute_start, mut start_offset) =
690- self . recording_window . start_recording . time_offset ( lat, lng) ;
691- let ( is_absolute_end, mut end_offset) =
692- self . recording_window . stop_recording . time_offset ( lat, lng) ;
684+ self . recording_window . start_recording . time_offset ( ) ;
685+ let ( is_absolute_end, mut end_offset) = self . recording_window . stop_recording . time_offset ( ) ;
693686 if is_absolute_end && end_offset < 0 {
694687 end_offset += 86_400 ;
695688 }
696689 if is_absolute_start && start_offset < 0 {
697690 start_offset += 86_400 ;
698691 }
699692 let ( window_start, window_end) = if !is_absolute_start || !is_absolute_end {
693+ let location =
694+ self . location . as_ref ( ) . expect ( "Relative recording windows require a location" ) ;
695+ let ( lat, lng) = (
696+ location. latitude . expect ( "Relative recording windows require a valid latitude" ) ,
697+ location. longitude . expect ( "Relative recording windows require a valid longitude" ) ,
698+ ) ;
700699 let altitude = location. altitude ;
701700 let yesterday_utc = * now_utc - Duration :: days ( 1 ) ;
702701 let ( _, yesterday_sunset) = sun_times (
@@ -877,8 +876,8 @@ impl DeviceConfig {
877876 buf. write_u8 ( has_loc_accuracy) . unwrap ( ) ;
878877 buf. write_f32 :: < LittleEndian > ( accuracy) . unwrap ( ) ;
879878 let ( abs_rel_start, abs_rel_end) = self . recording_window ( ) ;
880- let ( start_is_abs, start_seconds_offset) = abs_rel_start. time_offset ( latitude , longitude ) ;
881- let ( end_is_abs, end_seconds_offset) = abs_rel_end. time_offset ( latitude , longitude ) ;
879+ let ( start_is_abs, start_seconds_offset) = abs_rel_start. time_offset ( ) ;
880+ let ( end_is_abs, end_seconds_offset) = abs_rel_end. time_offset ( ) ;
882881 buf. write_u8 ( if start_is_abs { 1 } else { 0 } ) . unwrap ( ) ;
883882 buf. write_i32 :: < LittleEndian > ( start_seconds_offset) . unwrap ( ) ;
884883 buf. write_u8 ( if end_is_abs { 1 } else { 0 } ) . unwrap ( ) ;
@@ -917,6 +916,15 @@ pub fn watch_local_config_file_changes(
917916 if config != current_config {
918917 current_config = config;
919918 warn ! ( "Config updated" ) ;
919+
920+ let ( lat, lng) = current_config. lat_lng ( ) ;
921+ if let Err ( e) =
922+ set_system_timezone ( TZ_FINDER . get_tz_name ( lat as f64 , lng as f64 ) )
923+ {
924+ error ! ( "{e}" ) ;
925+ process:: exit ( 1 ) ;
926+ }
927+
920928 let _ = config_tx. send ( current_config. clone ( ) ) ;
921929 }
922930 }
0 commit comments