std_rs/device_support/
time_of_day.rs1use std::time::{SystemTime, UNIX_EPOCH};
2
3use epics_base_rs::error::CaResult;
4use epics_base_rs::server::device_support::{DeviceReadOutcome, DeviceSupport};
5use epics_base_rs::server::record::Record;
6use epics_base_rs::types::EpicsValue;
7
8use chrono::Local;
9
10const EPICS_EPOCH_OFFSET: u64 = 631152000;
12
13pub struct TimeOfDayStringDeviceSupport;
22
23impl Default for TimeOfDayStringDeviceSupport {
24 fn default() -> Self {
25 Self::new()
26 }
27}
28
29impl TimeOfDayStringDeviceSupport {
30 pub fn new() -> Self {
31 Self
32 }
33}
34
35impl DeviceSupport for TimeOfDayStringDeviceSupport {
36 fn dtyp(&self) -> &str {
37 "Time of Day"
38 }
39
40 fn read(&mut self, record: &mut dyn Record) -> CaResult<DeviceReadOutcome> {
41 let now = Local::now();
42
43 let phas = record
46 .get_field("PHAS")
47 .and_then(|v| match v {
48 EpicsValue::Short(s) => Some(s),
49 _ => None,
50 })
51 .unwrap_or(0);
52
53 let formatted = if phas != 0 {
54 now.format("%m/%d/%y %H:%M:%S").to_string()
55 } else {
56 now.format("%b %d, %Y %H:%M:%S").to_string()
57 };
58
59 record.put_field("VAL", EpicsValue::String(formatted))?;
60 Ok(DeviceReadOutcome::ok())
61 }
62
63 fn write(&mut self, _record: &mut dyn Record) -> CaResult<()> {
64 Ok(())
65 }
66}
67
68pub struct SecPastEpochDeviceSupport;
75
76impl Default for SecPastEpochDeviceSupport {
77 fn default() -> Self {
78 Self::new()
79 }
80}
81
82impl SecPastEpochDeviceSupport {
83 pub fn new() -> Self {
84 Self
85 }
86}
87
88impl DeviceSupport for SecPastEpochDeviceSupport {
89 fn dtyp(&self) -> &str {
90 "Sec Past Epoch"
91 }
92
93 fn read(&mut self, record: &mut dyn Record) -> CaResult<DeviceReadOutcome> {
94 let now = SystemTime::now()
95 .duration_since(UNIX_EPOCH)
96 .unwrap_or_default();
97
98 let sec_past_epoch = now.as_secs().saturating_sub(EPICS_EPOCH_OFFSET);
99
100 let phas = record
101 .get_field("PHAS")
102 .and_then(|v| match v {
103 EpicsValue::Short(s) => Some(s),
104 _ => None,
105 })
106 .unwrap_or(0);
107
108 let val = if phas != 0 {
109 sec_past_epoch as f64 + (now.subsec_nanos() as f64 / 1e9)
110 } else {
111 sec_past_epoch as f64
112 };
113
114 record.put_field("VAL", EpicsValue::Double(val))?;
115 Ok(DeviceReadOutcome::ok())
116 }
117
118 fn write(&mut self, _record: &mut dyn Record) -> CaResult<()> {
119 Ok(())
120 }
121}