device_envoy_core/wasm/
clock.rs1use core::cell::Cell;
13use std::rc::Rc;
14
15use embassy_time::{Duration, Timer};
16use time::{OffsetDateTime, Time, UtcOffset};
17
18use crate::clock_sync::{ClockSync, ClockSyncTick, UnixSeconds};
19
20pub struct ClockSyncWasm {
23 offset_minutes: Cell<i32>,
24 time_of_day: Rc<Cell<Option<u32>>>,
25 visible: Rc<Cell<bool>>,
26}
27
28impl ClockSyncWasm {
29 pub fn new() -> Self {
32 Self::new_with_control_state(Rc::new(Cell::new(None)), Rc::new(Cell::new(false)))
33 }
34
35 pub(crate) fn new_with_control_state(
36 time_of_day: Rc<Cell<Option<u32>>>,
37 visible: Rc<Cell<bool>>,
38 ) -> Self {
39 Self {
40 offset_minutes: Cell::new(-(js_sys::Date::new_0().get_timezone_offset() as i32)),
41 time_of_day,
42 visible,
43 }
44 }
45
46 pub fn show(&self) {
49 self.visible.set(true);
50 }
51
52 pub fn control_is_visible(&self) -> bool {
55 self.visible.get()
56 }
57
58 fn browser_local_time(&self) -> OffsetDateTime {
59 let unix_seconds = (js_sys::Date::now() / 1000.0) as i64;
60 let Ok(utc) = OffsetDateTime::from_unix_timestamp(unix_seconds) else {
61 return OffsetDateTime::UNIX_EPOCH;
62 };
63 let Ok(offset) = UtcOffset::from_whole_seconds(self.offset_minutes.get() * 60) else {
64 return utc;
65 };
66 let local = utc.to_offset(offset);
67 let Some(seconds_of_day) = self.time_of_day.get() else {
68 return local;
69 };
70 let hour = (seconds_of_day / 3600) as u8;
71 let minute = ((seconds_of_day % 3600) / 60) as u8;
72 let second = (seconds_of_day % 60) as u8;
73 let Ok(time) = Time::from_hms(hour, minute, second) else {
74 return local;
75 };
76 local.replace_time(time)
77 }
78}
79
80impl Default for ClockSyncWasm {
81 fn default() -> Self {
82 Self::new()
83 }
84}
85
86#[cfg(feature = "wifi")]
87impl ClockSync for ClockSyncWasm {
88 async fn wait_for_tick(&self) -> ClockSyncTick {
89 Timer::after(Duration::from_secs(1)).await;
90 ClockSyncTick {
91 local_time: self.browser_local_time(),
92 since_last_sync: Duration::from_secs(0),
93 }
94 }
95
96 fn now_local(&self) -> OffsetDateTime {
97 self.browser_local_time()
98 }
99
100 fn set_offset_minutes(&self, minutes: i32) {
101 self.offset_minutes.set(minutes);
102 }
103
104 fn offset_minutes(&self) -> i32 {
105 self.offset_minutes.get()
106 }
107
108 fn set_tick_interval(&self, _interval: Option<Duration>) {}
109 fn set_speed(&self, _speed_multiplier: f32) {}
110 fn set_utc_time(&self, _unix_seconds: UnixSeconds) {}
111}
112
113#[cfg(not(feature = "wifi"))]
114impl ClockSync for ClockSyncWasm {
115 fn wait_for_tick(&self) -> impl core::future::Future<Output = ClockSyncTick> {
116 async {
117 Timer::after(Duration::from_secs(1)).await;
118 ClockSyncTick {
119 local_time: self.browser_local_time(),
120 since_last_sync: Duration::from_secs(0),
121 }
122 }
123 }
124
125 fn now_local(&self) -> OffsetDateTime {
126 self.browser_local_time()
127 }
128
129 fn set_offset_minutes(&self, minutes: i32) {
130 self.offset_minutes.set(minutes);
131 }
132
133 fn offset_minutes(&self) -> i32 {
134 self.offset_minutes.get()
135 }
136
137 fn set_tick_interval(&self, _interval: Option<Duration>) {}
138 fn set_speed(&self, _speed_multiplier: f32) {}
139 fn set_utc_time(&self, _unix_seconds: UnixSeconds) {}
140}