lm_sensors/
value.rs

1//! Values of sensors or actuators.
2
3#[cfg(test)]
4mod tests;
5
6use core::ffi::{c_int, c_uint};
7use core::fmt;
8use std::io;
9
10use sensors_sys::sensors_subfeature_type::{
11    SENSORS_SUBFEATURE_BEEP_ENABLE, SENSORS_SUBFEATURE_CURR_ALARM, SENSORS_SUBFEATURE_CURR_AVERAGE,
12    SENSORS_SUBFEATURE_CURR_BEEP, SENSORS_SUBFEATURE_CURR_CRIT, SENSORS_SUBFEATURE_CURR_CRIT_ALARM,
13    SENSORS_SUBFEATURE_CURR_HIGHEST, SENSORS_SUBFEATURE_CURR_INPUT, SENSORS_SUBFEATURE_CURR_LCRIT,
14    SENSORS_SUBFEATURE_CURR_LCRIT_ALARM, SENSORS_SUBFEATURE_CURR_LOWEST,
15    SENSORS_SUBFEATURE_CURR_MAX, SENSORS_SUBFEATURE_CURR_MAX_ALARM, SENSORS_SUBFEATURE_CURR_MIN,
16    SENSORS_SUBFEATURE_CURR_MIN_ALARM, SENSORS_SUBFEATURE_ENERGY_INPUT,
17    SENSORS_SUBFEATURE_FAN_ALARM, SENSORS_SUBFEATURE_FAN_BEEP, SENSORS_SUBFEATURE_FAN_DIV,
18    SENSORS_SUBFEATURE_FAN_FAULT, SENSORS_SUBFEATURE_FAN_INPUT, SENSORS_SUBFEATURE_FAN_MAX,
19    SENSORS_SUBFEATURE_FAN_MAX_ALARM, SENSORS_SUBFEATURE_FAN_MIN, SENSORS_SUBFEATURE_FAN_MIN_ALARM,
20    SENSORS_SUBFEATURE_FAN_PULSES, SENSORS_SUBFEATURE_HUMIDITY_INPUT, SENSORS_SUBFEATURE_IN_ALARM,
21    SENSORS_SUBFEATURE_IN_AVERAGE, SENSORS_SUBFEATURE_IN_BEEP, SENSORS_SUBFEATURE_IN_CRIT,
22    SENSORS_SUBFEATURE_IN_CRIT_ALARM, SENSORS_SUBFEATURE_IN_HIGHEST, SENSORS_SUBFEATURE_IN_INPUT,
23    SENSORS_SUBFEATURE_IN_LCRIT, SENSORS_SUBFEATURE_IN_LCRIT_ALARM, SENSORS_SUBFEATURE_IN_LOWEST,
24    SENSORS_SUBFEATURE_IN_MAX, SENSORS_SUBFEATURE_IN_MAX_ALARM, SENSORS_SUBFEATURE_IN_MIN,
25    SENSORS_SUBFEATURE_IN_MIN_ALARM, SENSORS_SUBFEATURE_INTRUSION_ALARM,
26    SENSORS_SUBFEATURE_INTRUSION_BEEP, SENSORS_SUBFEATURE_POWER_ALARM,
27    SENSORS_SUBFEATURE_POWER_AVERAGE, SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST,
28    SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL, SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST,
29    SENSORS_SUBFEATURE_POWER_CAP, SENSORS_SUBFEATURE_POWER_CAP_ALARM,
30    SENSORS_SUBFEATURE_POWER_CAP_HYST, SENSORS_SUBFEATURE_POWER_CRIT,
31    SENSORS_SUBFEATURE_POWER_CRIT_ALARM, SENSORS_SUBFEATURE_POWER_INPUT,
32    SENSORS_SUBFEATURE_POWER_INPUT_HIGHEST, SENSORS_SUBFEATURE_POWER_INPUT_LOWEST,
33    SENSORS_SUBFEATURE_POWER_LCRIT, SENSORS_SUBFEATURE_POWER_LCRIT_ALARM,
34    SENSORS_SUBFEATURE_POWER_MAX, SENSORS_SUBFEATURE_POWER_MAX_ALARM, SENSORS_SUBFEATURE_POWER_MIN,
35    SENSORS_SUBFEATURE_POWER_MIN_ALARM, SENSORS_SUBFEATURE_TEMP_ALARM,
36    SENSORS_SUBFEATURE_TEMP_BEEP, SENSORS_SUBFEATURE_TEMP_CRIT, SENSORS_SUBFEATURE_TEMP_CRIT_ALARM,
37    SENSORS_SUBFEATURE_TEMP_CRIT_HYST, SENSORS_SUBFEATURE_TEMP_EMERGENCY,
38    SENSORS_SUBFEATURE_TEMP_EMERGENCY_ALARM, SENSORS_SUBFEATURE_TEMP_EMERGENCY_HYST,
39    SENSORS_SUBFEATURE_TEMP_FAULT, SENSORS_SUBFEATURE_TEMP_HIGHEST, SENSORS_SUBFEATURE_TEMP_INPUT,
40    SENSORS_SUBFEATURE_TEMP_LCRIT, SENSORS_SUBFEATURE_TEMP_LCRIT_ALARM,
41    SENSORS_SUBFEATURE_TEMP_LCRIT_HYST, SENSORS_SUBFEATURE_TEMP_LOWEST,
42    SENSORS_SUBFEATURE_TEMP_MAX, SENSORS_SUBFEATURE_TEMP_MAX_ALARM,
43    SENSORS_SUBFEATURE_TEMP_MAX_HYST, SENSORS_SUBFEATURE_TEMP_MIN,
44    SENSORS_SUBFEATURE_TEMP_MIN_ALARM, SENSORS_SUBFEATURE_TEMP_MIN_HYST,
45    SENSORS_SUBFEATURE_TEMP_OFFSET, SENSORS_SUBFEATURE_TEMP_TYPE, SENSORS_SUBFEATURE_UNKNOWN,
46    SENSORS_SUBFEATURE_VID,
47};
48
49use crate::errors::{Error, Result};
50
51/// Value reported by a sensor or set for an actuator,
52/// controlled by a [`SubFeatureRef`] instance.
53#[allow(missing_docs)]
54#[derive(Debug, Copy, Clone, PartialEq)]
55#[non_exhaustive]
56pub enum Value {
57    VoltageInput(f64),
58    VoltageMinimum(f64),
59    VoltageMaximum(f64),
60    VoltageLCritical(f64),
61    VoltageCritical(f64),
62    VoltageAverage(f64),
63    VoltageLowest(f64),
64    VoltageHighest(f64),
65    VoltageAlarm(bool),
66    VoltageMinimumAlarm(bool),
67    VoltageMaximumAlarm(bool),
68    VoltageBeep(bool),
69    VoltageLCriticalAlarm(bool),
70    VoltageCriticalAlarm(bool),
71
72    FanInput(f64),
73    FanMinimum(f64),
74    FanMaximum(f64),
75    FanAlarm(bool),
76    FanFault(bool),
77    FanDivisor(f64),
78    FanBeep(bool),
79    FanPulses(f64),
80    FanMinimumAlarm(bool),
81    FanMaximumAlarm(bool),
82
83    TemperatureInput(f64),
84    TemperatureMaximum(f64),
85    TemperatureMaximumHysteresis(f64),
86    TemperatureMinimum(f64),
87    TemperatureCritical(f64),
88    TemperatureCriticalHysteresis(f64),
89    TemperatureLCritical(f64),
90    TemperatureEmergency(f64),
91    TemperatureEmergencyHysteresis(f64),
92    TemperatureLowest(f64),
93    TemperatureHighest(f64),
94    TemperatureMinimumHysteresis(f64),
95    TemperatureLCriticalHysteresis(f64),
96    TemperatureAlarm(bool),
97    TemperatureMaximumAlarm(bool),
98    TemperatureMinimumAlarm(bool),
99    TemperatureCriticalAlarm(bool),
100    TemperatureFault(bool),
101    TemperatureType(TemperatureSensorKind),
102    TemperatureOffset(f64),
103    TemperatureBeep(bool),
104    TemperatureEmergencyAlarm(bool),
105    TemperatureLCriticalAlarm(bool),
106
107    PowerAverage(f64),
108    PowerAverageHighest(f64),
109    PowerAverageLowest(f64),
110    PowerInput(f64),
111    PowerInputHighest(f64),
112    PowerInputLowest(f64),
113    PowerCap(f64),
114    PowerCapHysteresis(f64),
115    PowerMaximum(f64),
116    PowerCritical(f64),
117    PowerMinimum(f64),
118    PowerLCritical(f64),
119    PowerAverageInterval(f64),
120    PowerAlarm(bool),
121    PowerCapAlarm(bool),
122    PowerMaximumAlarm(bool),
123    PowerCriticalAlarm(bool),
124    PowerMinimumAlarm(bool),
125    PowerLCriticalAlarm(bool),
126
127    EnergyInput(f64),
128
129    CurrentInput(f64),
130    CurrentMinimum(f64),
131    CurrentMaximum(f64),
132    CurrentLCritical(f64),
133    CurrentCritical(f64),
134    CurrentAverage(f64),
135    CurrentLowest(f64),
136    CurrentHighest(f64),
137    CurrentAlarm(bool),
138    CurrentMinimumAlarm(bool),
139    CurrentMaximumAlarm(bool),
140    CurrentBeep(bool),
141    CurrentLCriticalAlarm(bool),
142    CurrentCriticalAlarm(bool),
143
144    HumidityInput(f64),
145
146    VoltageID(f64),
147
148    IntrusionAlarm(bool),
149    IntrusionBeep(bool),
150
151    BeepEnable(bool),
152
153    Unknown { kind: Kind, value: f64 },
154}
155
156impl Value {
157    /// Return an instance of the given type and value.
158    ///
159    /// The valid range for the value depends on the kind.
160    #[must_use]
161    pub fn new(kind: Kind, value: f64) -> Option<Self> {
162        let result = match kind {
163            Kind::VoltageInput => Self::VoltageInput(value),
164            Kind::VoltageMinimum => Self::VoltageMinimum(value),
165            Kind::VoltageMaximum => Self::VoltageMaximum(value),
166            Kind::VoltageLCritical => Self::VoltageLCritical(value),
167            Kind::VoltageCritical => Self::VoltageCritical(value),
168            Kind::VoltageAverage => Self::VoltageAverage(value),
169            Kind::VoltageLowest => Self::VoltageLowest(value),
170            Kind::VoltageHighest => Self::VoltageHighest(value),
171            Kind::VoltageAlarm => Self::VoltageAlarm(value != 0.0_f64),
172            Kind::VoltageMinimumAlarm => Self::VoltageMinimumAlarm(value != 0.0_f64),
173            Kind::VoltageMaximumAlarm => Self::VoltageMaximumAlarm(value != 0.0_f64),
174            Kind::VoltageBeep => Self::VoltageBeep(value != 0.0_f64),
175            Kind::VoltageLCriticalAlarm => Self::VoltageLCriticalAlarm(value != 0.0_f64),
176            Kind::VoltageCriticalAlarm => Self::VoltageCriticalAlarm(value != 0.0_f64),
177
178            Kind::FanInput => Self::FanInput(value),
179            Kind::FanMinimum => Self::FanMinimum(value),
180            Kind::FanMaximum => Self::FanMaximum(value),
181            Kind::FanAlarm => Self::FanAlarm(value != 0.0_f64),
182            Kind::FanFault => Self::FanFault(value != 0.0_f64),
183            Kind::FanDivisor => Self::FanDivisor(value),
184            Kind::FanBeep => Self::FanBeep(value != 0.0_f64),
185            Kind::FanPulses => Self::FanPulses(value),
186            Kind::FanMinimumAlarm => Self::FanMinimumAlarm(value != 0.0_f64),
187            Kind::FanMaximumAlarm => Self::FanMaximumAlarm(value != 0.0_f64),
188
189            Kind::TemperatureInput => Self::TemperatureInput(value),
190            Kind::TemperatureMaximum => Self::TemperatureMaximum(value),
191            Kind::TemperatureMaximumHysteresis => Self::TemperatureMaximumHysteresis(value),
192            Kind::TemperatureMinimum => Self::TemperatureMinimum(value),
193            Kind::TemperatureCritical => Self::TemperatureCritical(value),
194            Kind::TemperatureCriticalHysteresis => Self::TemperatureCriticalHysteresis(value),
195            Kind::TemperatureLCritical => Self::TemperatureLCritical(value),
196            Kind::TemperatureEmergency => Self::TemperatureEmergency(value),
197            Kind::TemperatureEmergencyHysteresis => Self::TemperatureEmergencyHysteresis(value),
198            Kind::TemperatureLowest => Self::TemperatureLowest(value),
199            Kind::TemperatureHighest => Self::TemperatureHighest(value),
200            Kind::TemperatureMinimumHysteresis => Self::TemperatureMinimumHysteresis(value),
201            Kind::TemperatureLCriticalHysteresis => Self::TemperatureLCriticalHysteresis(value),
202            Kind::TemperatureAlarm => Self::TemperatureAlarm(value != 0.0_f64),
203            Kind::TemperatureMaximumAlarm => Self::TemperatureMaximumAlarm(value != 0.0_f64),
204            Kind::TemperatureMinimumAlarm => Self::TemperatureMinimumAlarm(value != 0.0_f64),
205            Kind::TemperatureCriticalAlarm => Self::TemperatureCriticalAlarm(value != 0.0_f64),
206            Kind::TemperatureFault => Self::TemperatureFault(value != 0.0_f64),
207            Kind::TemperatureType => {
208                let value = TemperatureSensorKind::from_raw(value)?;
209                Self::TemperatureType(value)
210            }
211            Kind::TemperatureOffset => Self::TemperatureOffset(value),
212            Kind::TemperatureBeep => Self::TemperatureBeep(value != 0.0_f64),
213            Kind::TemperatureEmergencyAlarm => Self::TemperatureEmergencyAlarm(value != 0.0_f64),
214            Kind::TemperatureLCriticalAlarm => Self::TemperatureLCriticalAlarm(value != 0.0_f64),
215
216            Kind::PowerAverage => Self::PowerAverage(value),
217            Kind::PowerAverageHighest => Self::PowerAverageHighest(value),
218            Kind::PowerAverageLowest => Self::PowerAverageLowest(value),
219            Kind::PowerInput => Self::PowerInput(value),
220            Kind::PowerInputHighest => Self::PowerInputHighest(value),
221            Kind::PowerInputLowest => Self::PowerInputLowest(value),
222            Kind::PowerCap => Self::PowerCap(value),
223            Kind::PowerCapHysteresis => Self::PowerCapHysteresis(value),
224            Kind::PowerMaximum => Self::PowerMaximum(value),
225            Kind::PowerCritical => Self::PowerCritical(value),
226            Kind::PowerMinimum => Self::PowerMinimum(value),
227            Kind::PowerLCritical => Self::PowerLCritical(value),
228            Kind::PowerAverageInterval => Self::PowerAverageInterval(value),
229            Kind::PowerAlarm => Self::PowerAlarm(value != 0.0_f64),
230            Kind::PowerCapAlarm => Self::PowerCapAlarm(value != 0.0_f64),
231            Kind::PowerMaximumAlarm => Self::PowerMaximumAlarm(value != 0.0_f64),
232            Kind::PowerCriticalAlarm => Self::PowerCriticalAlarm(value != 0.0_f64),
233            Kind::PowerMinimumAlarm => Self::PowerMinimumAlarm(value != 0.0_f64),
234            Kind::PowerLCriticalAlarm => Self::PowerLCriticalAlarm(value != 0.0_f64),
235
236            Kind::EnergyInput => Self::EnergyInput(value),
237
238            Kind::CurrentInput => Self::CurrentInput(value),
239            Kind::CurrentMinimum => Self::CurrentMinimum(value),
240            Kind::CurrentMaximum => Self::CurrentMaximum(value),
241            Kind::CurrentLCritical => Self::CurrentLCritical(value),
242            Kind::CurrentCritical => Self::CurrentCritical(value),
243            Kind::CurrentAverage => Self::CurrentAverage(value),
244            Kind::CurrentLowest => Self::CurrentLowest(value),
245            Kind::CurrentHighest => Self::CurrentHighest(value),
246            Kind::CurrentAlarm => Self::CurrentAlarm(value != 0.0_f64),
247            Kind::CurrentMinimumAlarm => Self::CurrentMinimumAlarm(value != 0.0_f64),
248            Kind::CurrentMaximumAlarm => Self::CurrentMaximumAlarm(value != 0.0_f64),
249            Kind::CurrentBeep => Self::CurrentBeep(value != 0.0_f64),
250            Kind::CurrentLCriticalAlarm => Self::CurrentLCriticalAlarm(value != 0.0_f64),
251            Kind::CurrentCriticalAlarm => Self::CurrentCriticalAlarm(value != 0.0_f64),
252
253            Kind::HumidityInput => Self::HumidityInput(value),
254
255            Kind::VoltageID => Self::VoltageID(value),
256
257            Kind::IntrusionAlarm => Self::IntrusionAlarm(value != 0.0_f64),
258            Kind::IntrusionBeep => Self::IntrusionBeep(value != 0.0_f64),
259
260            Kind::BeepEnable => Self::BeepEnable(value != 0.0_f64),
261
262            Kind::Unknown => Self::Unknown { kind, value },
263        };
264        Some(result)
265    }
266
267    /// Return an instance of the given type and boolean value.
268    #[must_use]
269    pub fn new_bool(kind: Kind, value: bool) -> Option<Self> {
270        Self::new(kind, if value { 1.0 } else { 0.0 })
271    }
272
273    /// Return an instance of the given type and temperature sensor type.
274    #[must_use]
275    pub fn new_temperature_sensor_kind(kind: Kind, value: TemperatureSensorKind) -> Option<Self> {
276        match kind {
277            Kind::TemperatureType => Some(Self::TemperatureType(value)),
278
279            Kind::VoltageInput
280            | Kind::VoltageMinimum
281            | Kind::VoltageMaximum
282            | Kind::VoltageLCritical
283            | Kind::VoltageCritical
284            | Kind::VoltageAverage
285            | Kind::VoltageLowest
286            | Kind::VoltageHighest
287            | Kind::VoltageAlarm
288            | Kind::VoltageMinimumAlarm
289            | Kind::VoltageMaximumAlarm
290            | Kind::VoltageBeep
291            | Kind::VoltageLCriticalAlarm
292            | Kind::VoltageCriticalAlarm
293            | Kind::FanInput
294            | Kind::FanMinimum
295            | Kind::FanMaximum
296            | Kind::FanAlarm
297            | Kind::FanFault
298            | Kind::FanDivisor
299            | Kind::FanBeep
300            | Kind::FanPulses
301            | Kind::FanMinimumAlarm
302            | Kind::FanMaximumAlarm
303            | Kind::TemperatureInput
304            | Kind::TemperatureMaximum
305            | Kind::TemperatureMaximumHysteresis
306            | Kind::TemperatureMinimum
307            | Kind::TemperatureCritical
308            | Kind::TemperatureCriticalHysteresis
309            | Kind::TemperatureLCritical
310            | Kind::TemperatureEmergency
311            | Kind::TemperatureEmergencyHysteresis
312            | Kind::TemperatureLowest
313            | Kind::TemperatureHighest
314            | Kind::TemperatureMinimumHysteresis
315            | Kind::TemperatureLCriticalHysteresis
316            | Kind::TemperatureAlarm
317            | Kind::TemperatureMaximumAlarm
318            | Kind::TemperatureMinimumAlarm
319            | Kind::TemperatureCriticalAlarm
320            | Kind::TemperatureFault
321            | Kind::TemperatureOffset
322            | Kind::TemperatureBeep
323            | Kind::TemperatureEmergencyAlarm
324            | Kind::TemperatureLCriticalAlarm
325            | Kind::PowerAverage
326            | Kind::PowerAverageHighest
327            | Kind::PowerAverageLowest
328            | Kind::PowerInput
329            | Kind::PowerInputHighest
330            | Kind::PowerInputLowest
331            | Kind::PowerCap
332            | Kind::PowerCapHysteresis
333            | Kind::PowerMaximum
334            | Kind::PowerCritical
335            | Kind::PowerMinimum
336            | Kind::PowerLCritical
337            | Kind::PowerAverageInterval
338            | Kind::PowerAlarm
339            | Kind::PowerCapAlarm
340            | Kind::PowerMaximumAlarm
341            | Kind::PowerCriticalAlarm
342            | Kind::PowerMinimumAlarm
343            | Kind::PowerLCriticalAlarm
344            | Kind::EnergyInput
345            | Kind::CurrentInput
346            | Kind::CurrentMinimum
347            | Kind::CurrentMaximum
348            | Kind::CurrentLCritical
349            | Kind::CurrentCritical
350            | Kind::CurrentAverage
351            | Kind::CurrentLowest
352            | Kind::CurrentHighest
353            | Kind::CurrentAlarm
354            | Kind::CurrentMinimumAlarm
355            | Kind::CurrentMaximumAlarm
356            | Kind::CurrentBeep
357            | Kind::CurrentLCriticalAlarm
358            | Kind::CurrentCriticalAlarm
359            | Kind::HumidityInput
360            | Kind::VoltageID
361            | Kind::IntrusionAlarm
362            | Kind::IntrusionBeep
363            | Kind::BeepEnable
364            | Kind::Unknown => None,
365        }
366    }
367
368    /// Return an instance of the given raw type and raw value.
369    ///
370    /// The raw type is one of `SENSORS_SUBFEATURE_*` values,
371    /// *e.g.,* [`SENSORS_SUBFEATURE_TEMP_INPUT`].
372    /// The valid range for the raw value depends on the raw kind.
373    #[must_use]
374    pub fn from_raw(kind: c_uint, value: f64) -> Option<Self> {
375        Kind::from_raw(kind).and_then(|kind| Self::new(kind, value))
376    }
377
378    /// Return the type of this instance.
379    #[must_use]
380    pub fn kind(&self) -> Kind {
381        match *self {
382            Self::VoltageInput(_) => Kind::VoltageInput,
383            Self::VoltageMinimum(_) => Kind::VoltageMinimum,
384            Self::VoltageMaximum(_) => Kind::VoltageMaximum,
385            Self::VoltageLCritical(_) => Kind::VoltageLCritical,
386            Self::VoltageCritical(_) => Kind::VoltageCritical,
387            Self::VoltageAverage(_) => Kind::VoltageAverage,
388            Self::VoltageLowest(_) => Kind::VoltageLowest,
389            Self::VoltageHighest(_) => Kind::VoltageHighest,
390            Self::VoltageAlarm(_) => Kind::VoltageAlarm,
391            Self::VoltageMinimumAlarm(_) => Kind::VoltageMinimumAlarm,
392            Self::VoltageMaximumAlarm(_) => Kind::VoltageMaximumAlarm,
393            Self::VoltageBeep(_) => Kind::VoltageBeep,
394            Self::VoltageLCriticalAlarm(_) => Kind::VoltageLCriticalAlarm,
395            Self::VoltageCriticalAlarm(_) => Kind::VoltageCriticalAlarm,
396
397            Self::FanInput(_) => Kind::FanInput,
398            Self::FanMinimum(_) => Kind::FanMinimum,
399            Self::FanMaximum(_) => Kind::FanMaximum,
400            Self::FanAlarm(_) => Kind::FanAlarm,
401            Self::FanFault(_) => Kind::FanFault,
402            Self::FanDivisor(_) => Kind::FanDivisor,
403            Self::FanBeep(_) => Kind::FanBeep,
404            Self::FanPulses(_) => Kind::FanPulses,
405            Self::FanMinimumAlarm(_) => Kind::FanMinimumAlarm,
406            Self::FanMaximumAlarm(_) => Kind::FanMaximumAlarm,
407
408            Self::TemperatureInput(_) => Kind::TemperatureInput,
409            Self::TemperatureMaximum(_) => Kind::TemperatureMaximum,
410            Self::TemperatureMaximumHysteresis(_) => Kind::TemperatureMaximumHysteresis,
411            Self::TemperatureMinimum(_) => Kind::TemperatureMinimum,
412            Self::TemperatureCritical(_) => Kind::TemperatureCritical,
413            Self::TemperatureCriticalHysteresis(_) => Kind::TemperatureCriticalHysteresis,
414            Self::TemperatureLCritical(_) => Kind::TemperatureLCritical,
415            Self::TemperatureEmergency(_) => Kind::TemperatureEmergency,
416            Self::TemperatureEmergencyHysteresis(_) => Kind::TemperatureEmergencyHysteresis,
417            Self::TemperatureLowest(_) => Kind::TemperatureLowest,
418            Self::TemperatureHighest(_) => Kind::TemperatureHighest,
419            Self::TemperatureMinimumHysteresis(_) => Kind::TemperatureMinimumHysteresis,
420            Self::TemperatureLCriticalHysteresis(_) => Kind::TemperatureLCriticalHysteresis,
421            Self::TemperatureAlarm(_) => Kind::TemperatureAlarm,
422            Self::TemperatureMaximumAlarm(_) => Kind::TemperatureMaximumAlarm,
423            Self::TemperatureMinimumAlarm(_) => Kind::TemperatureMinimumAlarm,
424            Self::TemperatureCriticalAlarm(_) => Kind::TemperatureCriticalAlarm,
425            Self::TemperatureFault(_) => Kind::TemperatureFault,
426            Self::TemperatureType(_) => Kind::TemperatureType,
427            Self::TemperatureOffset(_) => Kind::TemperatureOffset,
428            Self::TemperatureBeep(_) => Kind::TemperatureBeep,
429            Self::TemperatureEmergencyAlarm(_) => Kind::TemperatureEmergencyAlarm,
430            Self::TemperatureLCriticalAlarm(_) => Kind::TemperatureLCriticalAlarm,
431
432            Self::PowerAverage(_) => Kind::PowerAverage,
433            Self::PowerAverageHighest(_) => Kind::PowerAverageHighest,
434            Self::PowerAverageLowest(_) => Kind::PowerAverageLowest,
435            Self::PowerInput(_) => Kind::PowerInput,
436            Self::PowerInputHighest(_) => Kind::PowerInputHighest,
437            Self::PowerInputLowest(_) => Kind::PowerInputLowest,
438            Self::PowerCap(_) => Kind::PowerCap,
439            Self::PowerCapHysteresis(_) => Kind::PowerCapHysteresis,
440            Self::PowerMaximum(_) => Kind::PowerMaximum,
441            Self::PowerCritical(_) => Kind::PowerCritical,
442            Self::PowerMinimum(_) => Kind::PowerMinimum,
443            Self::PowerLCritical(_) => Kind::PowerLCritical,
444            Self::PowerAverageInterval(_) => Kind::PowerAverageInterval,
445            Self::PowerAlarm(_) => Kind::PowerAlarm,
446            Self::PowerCapAlarm(_) => Kind::PowerCapAlarm,
447            Self::PowerMaximumAlarm(_) => Kind::PowerMaximumAlarm,
448            Self::PowerCriticalAlarm(_) => Kind::PowerCriticalAlarm,
449            Self::PowerMinimumAlarm(_) => Kind::PowerMinimumAlarm,
450            Self::PowerLCriticalAlarm(_) => Kind::PowerLCriticalAlarm,
451
452            Self::EnergyInput(_) => Kind::EnergyInput,
453
454            Self::CurrentInput(_) => Kind::CurrentInput,
455            Self::CurrentMinimum(_) => Kind::CurrentMinimum,
456            Self::CurrentMaximum(_) => Kind::CurrentMaximum,
457            Self::CurrentLCritical(_) => Kind::CurrentLCritical,
458            Self::CurrentCritical(_) => Kind::CurrentCritical,
459            Self::CurrentAverage(_) => Kind::CurrentAverage,
460            Self::CurrentLowest(_) => Kind::CurrentLowest,
461            Self::CurrentHighest(_) => Kind::CurrentHighest,
462            Self::CurrentAlarm(_) => Kind::CurrentAlarm,
463            Self::CurrentMinimumAlarm(_) => Kind::CurrentMinimumAlarm,
464            Self::CurrentMaximumAlarm(_) => Kind::CurrentMaximumAlarm,
465            Self::CurrentBeep(_) => Kind::CurrentBeep,
466            Self::CurrentLCriticalAlarm(_) => Kind::CurrentLCriticalAlarm,
467            Self::CurrentCriticalAlarm(_) => Kind::CurrentCriticalAlarm,
468
469            Self::HumidityInput(_) => Kind::HumidityInput,
470
471            Self::VoltageID(_) => Kind::VoltageID,
472
473            Self::IntrusionAlarm(_) => Kind::IntrusionAlarm,
474            Self::IntrusionBeep(_) => Kind::IntrusionBeep,
475
476            Self::BeepEnable(_) => Kind::BeepEnable,
477
478            Self::Unknown { .. } => Kind::Unknown,
479        }
480    }
481
482    /// Return the raw value of this instance.
483    #[must_use]
484    pub fn raw_value(&self) -> f64 {
485        match *self {
486            // Voltage
487            Self::VoltageInput(value)
488            | Self::VoltageMinimum(value)
489            | Self::VoltageMaximum(value)
490            | Self::VoltageLCritical(value)
491            | Self::VoltageCritical(value)
492            | Self::VoltageAverage(value)
493            | Self::VoltageLowest(value)
494            | Self::VoltageHighest(value)
495            // Fan
496            | Self::FanInput(value)
497            | Self::FanMinimum(value)
498            | Self::FanMaximum(value)
499            | Self::FanDivisor(value)
500            | Self::FanPulses(value)
501            // Temperature
502            | Self::TemperatureInput(value)
503            | Self::TemperatureMaximum(value)
504            | Self::TemperatureMaximumHysteresis(value)
505            | Self::TemperatureMinimum(value)
506            | Self::TemperatureCritical(value)
507            | Self::TemperatureCriticalHysteresis(value)
508            | Self::TemperatureLCritical(value)
509            | Self::TemperatureEmergency(value)
510            | Self::TemperatureEmergencyHysteresis(value)
511            | Self::TemperatureLowest(value)
512            | Self::TemperatureHighest(value)
513            | Self::TemperatureMinimumHysteresis(value)
514            | Self::TemperatureLCriticalHysteresis(value)
515            | Self::TemperatureOffset(value)
516            // Power
517            | Self::PowerAverage(value)
518            | Self::PowerAverageHighest(value)
519            | Self::PowerAverageLowest(value)
520            | Self::PowerInput(value)
521            | Self::PowerInputHighest(value)
522            | Self::PowerInputLowest(value)
523            | Self::PowerCap(value)
524            | Self::PowerCapHysteresis(value)
525            | Self::PowerMaximum(value)
526            | Self::PowerCritical(value)
527            | Self::PowerMinimum(value)
528            | Self::PowerLCritical(value)
529            | Self::PowerAverageInterval(value)
530            // Energy
531            | Self::EnergyInput(value)
532            // Current
533            | Self::CurrentInput(value)
534            | Self::CurrentMinimum(value)
535            | Self::CurrentMaximum(value)
536            | Self::CurrentLCritical(value)
537            | Self::CurrentCritical(value)
538            | Self::CurrentAverage(value)
539            | Self::CurrentLowest(value)
540            | Self::CurrentHighest(value)
541            // Humidity
542            | Self::HumidityInput(value)
543            // VoltageID
544            | Self::VoltageID(value)
545            // Unknown
546            | Self::Unknown { value, .. }
547            => value,
548
549            // Voltage
550            Self::VoltageAlarm(value)
551            | Self::VoltageMinimumAlarm(value)
552            | Self::VoltageMaximumAlarm(value)
553            | Self::VoltageBeep(value)
554            | Self::VoltageLCriticalAlarm(value)
555            | Self::VoltageCriticalAlarm(value)
556            // Fan
557            | Self::FanAlarm(value)
558            | Self::FanFault(value)
559            | Self::FanBeep(value)
560            | Self::FanMinimumAlarm(value)
561            | Self::FanMaximumAlarm(value)
562            // Temperature
563            | Self::TemperatureAlarm(value)
564            | Self::TemperatureMaximumAlarm(value)
565            | Self::TemperatureMinimumAlarm(value)
566            | Self::TemperatureCriticalAlarm(value)
567            | Self::TemperatureFault(value)
568            | Self::TemperatureBeep(value)
569            | Self::TemperatureEmergencyAlarm(value)
570            | Self::TemperatureLCriticalAlarm(value)
571            // Power
572            | Self::PowerAlarm(value)
573            | Self::PowerCapAlarm(value)
574            | Self::PowerMaximumAlarm(value)
575            | Self::PowerCriticalAlarm(value)
576            | Self::PowerMinimumAlarm(value)
577            | Self::PowerLCriticalAlarm(value)
578            // Current
579            | Self::CurrentAlarm(value)
580            | Self::CurrentMinimumAlarm(value)
581            | Self::CurrentMaximumAlarm(value)
582            | Self::CurrentBeep(value)
583            | Self::CurrentLCriticalAlarm(value)
584            | Self::CurrentCriticalAlarm(value)
585            // Intrusion
586            | Self::IntrusionAlarm(value)
587            | Self::IntrusionBeep(value)
588            // Beep
589            | Self::BeepEnable(value) => {
590                if value {
591                    1.0_f64
592                } else {
593                    0.0_f64
594                }
595            }
596
597            Self::TemperatureType(value) => f64::from(value.as_raw()),
598        }
599    }
600
601    /// Set the raw value of this instance.
602    pub fn set_raw_value(&mut self, new_value: f64) -> Result<f64> {
603        match self {
604            // Voltage
605            Self::VoltageInput(value)
606            | Self::VoltageMinimum(value)
607            | Self::VoltageMaximum(value)
608            | Self::VoltageLCritical(value)
609            | Self::VoltageCritical(value)
610            | Self::VoltageAverage(value)
611            | Self::VoltageLowest(value)
612            | Self::VoltageHighest(value)
613            // Fan
614            | Self::FanInput(value)
615            | Self::FanMinimum(value)
616            | Self::FanMaximum(value)
617            | Self::FanDivisor(value)
618            | Self::FanPulses(value)
619            // Temperature
620            | Self::TemperatureInput(value)
621            | Self::TemperatureMaximum(value)
622            | Self::TemperatureMaximumHysteresis(value)
623            | Self::TemperatureMinimum(value)
624            | Self::TemperatureCritical(value)
625            | Self::TemperatureCriticalHysteresis(value)
626            | Self::TemperatureLCritical(value)
627            | Self::TemperatureEmergency(value)
628            | Self::TemperatureEmergencyHysteresis(value)
629            | Self::TemperatureLowest(value)
630            | Self::TemperatureHighest(value)
631            | Self::TemperatureMinimumHysteresis(value)
632            | Self::TemperatureLCriticalHysteresis(value)
633            | Self::TemperatureOffset(value)
634            // Power
635            | Self::PowerAverage(value)
636            | Self::PowerAverageHighest(value)
637            | Self::PowerAverageLowest(value)
638            | Self::PowerInput(value)
639            | Self::PowerInputHighest(value)
640            | Self::PowerInputLowest(value)
641            | Self::PowerCap(value)
642            | Self::PowerCapHysteresis(value)
643            | Self::PowerMaximum(value)
644            | Self::PowerCritical(value)
645            | Self::PowerMinimum(value)
646            | Self::PowerLCritical(value)
647            | Self::PowerAverageInterval(value)
648            // Energy
649            | Self::EnergyInput(value)
650            // Current
651            | Self::CurrentInput(value)
652            | Self::CurrentMinimum(value)
653            | Self::CurrentMaximum(value)
654            | Self::CurrentLCritical(value)
655            | Self::CurrentCritical(value)
656            | Self::CurrentAverage(value)
657            | Self::CurrentLowest(value)
658            | Self::CurrentHighest(value)
659            // Humidity
660            | Self::HumidityInput(value)
661            // VoltageID
662            | Self::VoltageID(value)
663            // Unknown
664            | Self::Unknown { value, .. } => {
665                let result = *value;
666                *value = new_value;
667                Ok(result)
668            }
669
670            // Voltage
671            Self::VoltageAlarm(value)
672            | Self::VoltageMinimumAlarm(value)
673            | Self::VoltageMaximumAlarm(value)
674            | Self::VoltageBeep(value)
675            | Self::VoltageLCriticalAlarm(value)
676            | Self::VoltageCriticalAlarm(value)
677            // Fan
678            | Self::FanAlarm(value)
679            | Self::FanFault(value)
680            | Self::FanBeep(value)
681            | Self::FanMinimumAlarm(value)
682            | Self::FanMaximumAlarm(value)
683            // Temperature
684            | Self::TemperatureAlarm(value)
685            | Self::TemperatureMaximumAlarm(value)
686            | Self::TemperatureMinimumAlarm(value)
687            | Self::TemperatureCriticalAlarm(value)
688            | Self::TemperatureFault(value)
689            | Self::TemperatureBeep(value)
690            | Self::TemperatureEmergencyAlarm(value)
691            | Self::TemperatureLCriticalAlarm(value)
692            // Power
693            | Self::PowerAlarm(value)
694            | Self::PowerCapAlarm(value)
695            | Self::PowerMaximumAlarm(value)
696            | Self::PowerCriticalAlarm(value)
697            | Self::PowerMinimumAlarm(value)
698            | Self::PowerLCriticalAlarm(value)
699            // Current
700            | Self::CurrentAlarm(value)
701            | Self::CurrentMinimumAlarm(value)
702            | Self::CurrentMaximumAlarm(value)
703            | Self::CurrentBeep(value)
704            | Self::CurrentLCriticalAlarm(value)
705            | Self::CurrentCriticalAlarm(value)
706            // Intrusion
707            | Self::IntrusionAlarm(value)
708            | Self::IntrusionBeep(value)
709            // Beep
710            | Self::BeepEnable(value) => {
711                let result: f64 = if *value { 1.0 } else { 0.0 };
712                *value = new_value != 0.0_f64;
713                Ok(result)
714            },
715
716            Self::TemperatureType(value) => {
717                let new_value = TemperatureSensorKind::from_raw(new_value)
718                    .ok_or_else(|| Error::from_io("TemperatureSensorKind::new", io::ErrorKind::InvalidData.into()))?;
719
720                let result = f64::from(value.as_raw());
721                *value = new_value;
722                Ok(result)
723            },
724        }
725    }
726
727    /// Return the measurement unit of this instance.
728    #[must_use]
729    pub fn unit(&self) -> Unit {
730        self.kind().unit()
731    }
732}
733
734impl fmt::Display for Value {
735    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
736        match *self {
737            Self::VoltageAlarm(value)
738            | Self::VoltageMinimumAlarm(value)
739            | Self::VoltageMaximumAlarm(value)
740            | Self::VoltageLCriticalAlarm(value)
741            | Self::VoltageCriticalAlarm(value)
742            | Self::FanAlarm(value)
743            | Self::FanMinimumAlarm(value)
744            | Self::FanMaximumAlarm(value)
745            | Self::TemperatureAlarm(value)
746            | Self::TemperatureMaximumAlarm(value)
747            | Self::TemperatureMinimumAlarm(value)
748            | Self::TemperatureCriticalAlarm(value)
749            | Self::TemperatureEmergencyAlarm(value)
750            | Self::TemperatureLCriticalAlarm(value)
751            | Self::PowerAlarm(value)
752            | Self::PowerCapAlarm(value)
753            | Self::PowerMaximumAlarm(value)
754            | Self::PowerCriticalAlarm(value)
755            | Self::PowerMinimumAlarm(value)
756            | Self::PowerLCriticalAlarm(value)
757            | Self::CurrentAlarm(value)
758            | Self::CurrentMinimumAlarm(value)
759            | Self::CurrentMaximumAlarm(value)
760            | Self::CurrentLCriticalAlarm(value)
761            | Self::CurrentCriticalAlarm(value)
762            | Self::IntrusionAlarm(value) => {
763                if value {
764                    write!(f, "ALARM")
765                } else {
766                    Ok(())
767                }
768            }
769
770            Self::VoltageBeep(value)
771            | Self::FanBeep(value)
772            | Self::TemperatureBeep(value)
773            | Self::CurrentBeep(value)
774            | Self::IntrusionBeep(value)
775            | Self::BeepEnable(value) => {
776                if value {
777                    write!(f, "BEEP")
778                } else {
779                    Ok(())
780                }
781            }
782
783            Self::FanFault(value) | Self::TemperatureFault(value) => {
784                if value {
785                    write!(f, "FAULT")
786                } else {
787                    Ok(())
788                }
789            }
790
791            Self::FanDivisor(value) | Self::FanPulses(value) | Self::TemperatureOffset(value) => {
792                write!(f, "{value}")
793            }
794
795            Self::TemperatureType(value) => write!(f, "{value}"),
796
797            Self::VoltageInput(value)
798            | Self::VoltageMinimum(value)
799            | Self::VoltageMaximum(value)
800            | Self::VoltageLCritical(value)
801            | Self::VoltageCritical(value)
802            | Self::VoltageAverage(value)
803            | Self::VoltageLowest(value)
804            | Self::VoltageHighest(value)
805            | Self::VoltageID(value) => write!(f, "{} {}", value, Unit::Volt),
806
807            Self::FanInput(value) | Self::FanMinimum(value) | Self::FanMaximum(value) => {
808                write!(f, "{} {}", value, Unit::RotationPerMinute)
809            }
810
811            Self::TemperatureInput(value)
812            | Self::TemperatureMaximum(value)
813            | Self::TemperatureMaximumHysteresis(value)
814            | Self::TemperatureMinimum(value)
815            | Self::TemperatureCritical(value)
816            | Self::TemperatureCriticalHysteresis(value)
817            | Self::TemperatureLCritical(value)
818            | Self::TemperatureEmergency(value)
819            | Self::TemperatureEmergencyHysteresis(value)
820            | Self::TemperatureLowest(value)
821            | Self::TemperatureHighest(value)
822            | Self::TemperatureMinimumHysteresis(value)
823            | Self::TemperatureLCriticalHysteresis(value) => {
824                write!(f, "{} {}", value, Unit::Celcius)
825            }
826
827            Self::PowerAverage(value)
828            | Self::PowerAverageHighest(value)
829            | Self::PowerAverageLowest(value)
830            | Self::PowerInput(value)
831            | Self::PowerInputHighest(value)
832            | Self::PowerInputLowest(value)
833            | Self::PowerCap(value)
834            | Self::PowerCapHysteresis(value)
835            | Self::PowerMaximum(value)
836            | Self::PowerCritical(value)
837            | Self::PowerMinimum(value)
838            | Self::PowerLCritical(value) => write!(f, "{} {}", value, Unit::Watt),
839
840            Self::PowerAverageInterval(value) => write!(f, "{} {}", value, Unit::Second),
841
842            Self::EnergyInput(value) => write!(f, "{} {}", value, Unit::Joule),
843
844            Self::CurrentInput(value)
845            | Self::CurrentMinimum(value)
846            | Self::CurrentMaximum(value)
847            | Self::CurrentLCritical(value)
848            | Self::CurrentCritical(value)
849            | Self::CurrentAverage(value)
850            | Self::CurrentLowest(value)
851            | Self::CurrentHighest(value) => write!(f, "{} {}", value, Unit::Amp),
852
853            Self::HumidityInput(value) => write!(f, "{} {}", value, Unit::Percentage),
854
855            Self::Unknown { .. } => write!(f, "\u{fffd}"),
856        }
857    }
858}
859
860/// Type of the value of a sensor or actuator.
861#[allow(missing_docs)] // Enum variant names are self-explanatory.
862#[repr(u32)]
863#[non_exhaustive]
864#[derive(
865    Debug,
866    Clone,
867    Copy,
868    PartialEq,
869    Eq,
870    PartialOrd,
871    Ord,
872    num_enum::TryFromPrimitive,
873    num_enum::IntoPrimitive,
874)]
875pub enum Kind {
876    VoltageInput = SENSORS_SUBFEATURE_IN_INPUT,
877    VoltageMinimum = SENSORS_SUBFEATURE_IN_MIN,
878    VoltageMaximum = SENSORS_SUBFEATURE_IN_MAX,
879    VoltageLCritical = SENSORS_SUBFEATURE_IN_LCRIT,
880    VoltageCritical = SENSORS_SUBFEATURE_IN_CRIT,
881    VoltageAverage = SENSORS_SUBFEATURE_IN_AVERAGE,
882    VoltageLowest = SENSORS_SUBFEATURE_IN_LOWEST,
883    VoltageHighest = SENSORS_SUBFEATURE_IN_HIGHEST,
884    VoltageAlarm = SENSORS_SUBFEATURE_IN_ALARM,
885    VoltageMinimumAlarm = SENSORS_SUBFEATURE_IN_MIN_ALARM,
886    VoltageMaximumAlarm = SENSORS_SUBFEATURE_IN_MAX_ALARM,
887    VoltageBeep = SENSORS_SUBFEATURE_IN_BEEP,
888    VoltageLCriticalAlarm = SENSORS_SUBFEATURE_IN_LCRIT_ALARM,
889    VoltageCriticalAlarm = SENSORS_SUBFEATURE_IN_CRIT_ALARM,
890
891    FanInput = SENSORS_SUBFEATURE_FAN_INPUT,
892    FanMinimum = SENSORS_SUBFEATURE_FAN_MIN,
893    FanMaximum = SENSORS_SUBFEATURE_FAN_MAX,
894    FanAlarm = SENSORS_SUBFEATURE_FAN_ALARM,
895    FanFault = SENSORS_SUBFEATURE_FAN_FAULT,
896    FanDivisor = SENSORS_SUBFEATURE_FAN_DIV,
897    FanBeep = SENSORS_SUBFEATURE_FAN_BEEP,
898    FanPulses = SENSORS_SUBFEATURE_FAN_PULSES,
899    FanMinimumAlarm = SENSORS_SUBFEATURE_FAN_MIN_ALARM,
900    FanMaximumAlarm = SENSORS_SUBFEATURE_FAN_MAX_ALARM,
901
902    TemperatureInput = SENSORS_SUBFEATURE_TEMP_INPUT,
903    TemperatureMaximum = SENSORS_SUBFEATURE_TEMP_MAX,
904    TemperatureMaximumHysteresis = SENSORS_SUBFEATURE_TEMP_MAX_HYST,
905    TemperatureMinimum = SENSORS_SUBFEATURE_TEMP_MIN,
906    TemperatureCritical = SENSORS_SUBFEATURE_TEMP_CRIT,
907    TemperatureCriticalHysteresis = SENSORS_SUBFEATURE_TEMP_CRIT_HYST,
908    TemperatureLCritical = SENSORS_SUBFEATURE_TEMP_LCRIT,
909    TemperatureEmergency = SENSORS_SUBFEATURE_TEMP_EMERGENCY,
910    TemperatureEmergencyHysteresis = SENSORS_SUBFEATURE_TEMP_EMERGENCY_HYST,
911    TemperatureLowest = SENSORS_SUBFEATURE_TEMP_LOWEST,
912    TemperatureHighest = SENSORS_SUBFEATURE_TEMP_HIGHEST,
913    TemperatureMinimumHysteresis = SENSORS_SUBFEATURE_TEMP_MIN_HYST,
914    TemperatureLCriticalHysteresis = SENSORS_SUBFEATURE_TEMP_LCRIT_HYST,
915    TemperatureAlarm = SENSORS_SUBFEATURE_TEMP_ALARM,
916    TemperatureMaximumAlarm = SENSORS_SUBFEATURE_TEMP_MAX_ALARM,
917    TemperatureMinimumAlarm = SENSORS_SUBFEATURE_TEMP_MIN_ALARM,
918    TemperatureCriticalAlarm = SENSORS_SUBFEATURE_TEMP_CRIT_ALARM,
919    TemperatureFault = SENSORS_SUBFEATURE_TEMP_FAULT,
920    TemperatureType = SENSORS_SUBFEATURE_TEMP_TYPE,
921    TemperatureOffset = SENSORS_SUBFEATURE_TEMP_OFFSET,
922    TemperatureBeep = SENSORS_SUBFEATURE_TEMP_BEEP,
923    TemperatureEmergencyAlarm = SENSORS_SUBFEATURE_TEMP_EMERGENCY_ALARM,
924    TemperatureLCriticalAlarm = SENSORS_SUBFEATURE_TEMP_LCRIT_ALARM,
925
926    PowerAverage = SENSORS_SUBFEATURE_POWER_AVERAGE,
927    PowerAverageHighest = SENSORS_SUBFEATURE_POWER_AVERAGE_HIGHEST,
928    PowerAverageLowest = SENSORS_SUBFEATURE_POWER_AVERAGE_LOWEST,
929    PowerInput = SENSORS_SUBFEATURE_POWER_INPUT,
930    PowerInputHighest = SENSORS_SUBFEATURE_POWER_INPUT_HIGHEST,
931    PowerInputLowest = SENSORS_SUBFEATURE_POWER_INPUT_LOWEST,
932    PowerCap = SENSORS_SUBFEATURE_POWER_CAP,
933    PowerCapHysteresis = SENSORS_SUBFEATURE_POWER_CAP_HYST,
934    PowerMaximum = SENSORS_SUBFEATURE_POWER_MAX,
935    PowerCritical = SENSORS_SUBFEATURE_POWER_CRIT,
936    PowerMinimum = SENSORS_SUBFEATURE_POWER_MIN,
937    PowerLCritical = SENSORS_SUBFEATURE_POWER_LCRIT,
938    PowerAverageInterval = SENSORS_SUBFEATURE_POWER_AVERAGE_INTERVAL,
939    PowerAlarm = SENSORS_SUBFEATURE_POWER_ALARM,
940    PowerCapAlarm = SENSORS_SUBFEATURE_POWER_CAP_ALARM,
941    PowerMaximumAlarm = SENSORS_SUBFEATURE_POWER_MAX_ALARM,
942    PowerCriticalAlarm = SENSORS_SUBFEATURE_POWER_CRIT_ALARM,
943    PowerMinimumAlarm = SENSORS_SUBFEATURE_POWER_MIN_ALARM,
944    PowerLCriticalAlarm = SENSORS_SUBFEATURE_POWER_LCRIT_ALARM,
945
946    EnergyInput = SENSORS_SUBFEATURE_ENERGY_INPUT,
947
948    CurrentInput = SENSORS_SUBFEATURE_CURR_INPUT,
949    CurrentMinimum = SENSORS_SUBFEATURE_CURR_MIN,
950    CurrentMaximum = SENSORS_SUBFEATURE_CURR_MAX,
951    CurrentLCritical = SENSORS_SUBFEATURE_CURR_LCRIT,
952    CurrentCritical = SENSORS_SUBFEATURE_CURR_CRIT,
953    CurrentAverage = SENSORS_SUBFEATURE_CURR_AVERAGE,
954    CurrentLowest = SENSORS_SUBFEATURE_CURR_LOWEST,
955    CurrentHighest = SENSORS_SUBFEATURE_CURR_HIGHEST,
956    CurrentAlarm = SENSORS_SUBFEATURE_CURR_ALARM,
957    CurrentMinimumAlarm = SENSORS_SUBFEATURE_CURR_MIN_ALARM,
958    CurrentMaximumAlarm = SENSORS_SUBFEATURE_CURR_MAX_ALARM,
959    CurrentBeep = SENSORS_SUBFEATURE_CURR_BEEP,
960    CurrentLCriticalAlarm = SENSORS_SUBFEATURE_CURR_LCRIT_ALARM,
961    CurrentCriticalAlarm = SENSORS_SUBFEATURE_CURR_CRIT_ALARM,
962
963    HumidityInput = SENSORS_SUBFEATURE_HUMIDITY_INPUT,
964
965    VoltageID = SENSORS_SUBFEATURE_VID,
966
967    IntrusionAlarm = SENSORS_SUBFEATURE_INTRUSION_ALARM,
968    IntrusionBeep = SENSORS_SUBFEATURE_INTRUSION_BEEP,
969
970    BeepEnable = SENSORS_SUBFEATURE_BEEP_ENABLE,
971
972    Unknown = SENSORS_SUBFEATURE_UNKNOWN,
973}
974
975impl Kind {
976    /// Return an instance from one of the `SENSORS_SUBFEATURE_*` values,
977    /// *e.g.,* [`SENSORS_SUBFEATURE_TEMP_INPUT`].
978    #[must_use]
979    pub fn from_raw(kind: c_uint) -> Option<Self> {
980        Self::try_from(kind).ok()
981    }
982
983    /// Return one of the `SENSORS_SUBFEATURE_*` values
984    /// (*e.g.,* [`SENSORS_SUBFEATURE_TEMP_INPUT`]) equivalent to this instance.
985    #[must_use]
986    pub fn as_raw(self) -> c_uint {
987        self.into()
988    }
989
990    /// Return the measurement unit of this instance.
991    #[must_use]
992    pub fn unit(self) -> Unit {
993        match self {
994            // Voltage
995            Self::VoltageAlarm
996            | Self::VoltageMinimumAlarm
997            | Self::VoltageMaximumAlarm
998            | Self::VoltageLCriticalAlarm
999            | Self::VoltageCriticalAlarm
1000            | Self::VoltageBeep
1001            // Fan
1002            | Self::FanAlarm
1003            | Self::FanMinimumAlarm
1004            | Self::FanMaximumAlarm
1005            | Self::FanBeep
1006            | Self::FanFault
1007            | Self::FanDivisor
1008            | Self::FanPulses
1009            // Temperature
1010            | Self::TemperatureAlarm
1011            | Self::TemperatureMaximumAlarm
1012            | Self::TemperatureMinimumAlarm
1013            | Self::TemperatureCriticalAlarm
1014            | Self::TemperatureEmergencyAlarm
1015            | Self::TemperatureLCriticalAlarm
1016            | Self::TemperatureBeep
1017            | Self::TemperatureFault
1018            | Self::TemperatureOffset
1019            | Self::TemperatureType
1020            // Power
1021            | Self::PowerAlarm
1022            | Self::PowerCapAlarm
1023            | Self::PowerMaximumAlarm
1024            | Self::PowerCriticalAlarm
1025            | Self::PowerMinimumAlarm
1026            | Self::PowerLCriticalAlarm
1027            // Current
1028            | Self::CurrentAlarm
1029            | Self::CurrentMinimumAlarm
1030            | Self::CurrentMaximumAlarm
1031            | Self::CurrentLCriticalAlarm
1032            | Self::CurrentCriticalAlarm
1033            | Self::CurrentBeep
1034            // Intrusion
1035            | Self::IntrusionAlarm
1036            | Self::IntrusionBeep
1037            // Beep
1038            | Self::BeepEnable
1039            // Unknown
1040            | Self::Unknown => Unit::None,
1041
1042            Self::VoltageInput
1043            | Self::VoltageMinimum
1044            | Self::VoltageMaximum
1045            | Self::VoltageLCritical
1046            | Self::VoltageCritical
1047            | Self::VoltageAverage
1048            | Self::VoltageLowest
1049            | Self::VoltageHighest
1050            | Self::VoltageID => Unit::Volt,
1051
1052            Self::FanInput
1053            | Self::FanMinimum
1054            | Self::FanMaximum => Unit::RotationPerMinute,
1055
1056            Self::TemperatureInput
1057            | Self::TemperatureMaximum
1058            | Self::TemperatureMinimum
1059            | Self::TemperatureMaximumHysteresis
1060            | Self::TemperatureCritical
1061            | Self::TemperatureCriticalHysteresis
1062            | Self::TemperatureLCritical
1063            | Self::TemperatureEmergency
1064            | Self::TemperatureEmergencyHysteresis
1065            | Self::TemperatureLowest
1066            | Self::TemperatureHighest
1067            | Self::TemperatureMinimumHysteresis
1068            | Self::TemperatureLCriticalHysteresis => Unit::Celcius,
1069
1070            Self::PowerAverage
1071            | Self::PowerAverageHighest
1072            | Self::PowerAverageLowest
1073            | Self::PowerInput
1074            | Self::PowerInputHighest
1075            | Self::PowerInputLowest
1076            | Self::PowerCap
1077            | Self::PowerCapHysteresis
1078            | Self::PowerMaximum
1079            | Self::PowerCritical
1080            | Self::PowerMinimum
1081            | Self::PowerLCritical => Unit::Watt,
1082
1083            Self::PowerAverageInterval => Unit::Second,
1084
1085            Self::EnergyInput => Unit::Joule,
1086
1087            Self::CurrentInput
1088            | Self::CurrentMinimum
1089            | Self::CurrentMaximum
1090            | Self::CurrentLCritical
1091            | Self::CurrentCritical
1092            | Self::CurrentAverage
1093            | Self::CurrentLowest
1094            | Self::CurrentHighest => Unit::Amp,
1095
1096            Self::HumidityInput => Unit::Percentage,
1097        }
1098    }
1099}
1100
1101impl Default for Kind {
1102    fn default() -> Self {
1103        Self::Unknown
1104    }
1105}
1106
1107impl fmt::Display for Kind {
1108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1109        let name = match *self {
1110            Self::VoltageInput => "VoltageInput",
1111            Self::VoltageMinimum => "VoltageMinimum",
1112            Self::VoltageMaximum => "VoltageMaximum",
1113            Self::VoltageLCritical => "VoltageLCritical",
1114            Self::VoltageCritical => "VoltageCritical",
1115            Self::VoltageAverage => "VoltageAverage",
1116            Self::VoltageLowest => "VoltageLowest",
1117            Self::VoltageHighest => "VoltageHighest",
1118            Self::VoltageAlarm => "VoltageAlarm",
1119            Self::VoltageMinimumAlarm => "VoltageMinimumAlarm",
1120            Self::VoltageMaximumAlarm => "VoltageMaximumAlarm",
1121            Self::VoltageBeep => "VoltageBeep",
1122            Self::VoltageLCriticalAlarm => "VoltageLCriticalAlarm",
1123            Self::VoltageCriticalAlarm => "VoltageCriticalAlarm",
1124            Self::FanInput => "FanInput",
1125            Self::FanMinimum => "FanMinimum",
1126            Self::FanMaximum => "FanMaximum",
1127            Self::FanAlarm => "FanAlarm",
1128            Self::FanFault => "FanFault",
1129            Self::FanDivisor => "FanDivisor",
1130            Self::FanBeep => "FanBeep",
1131            Self::FanPulses => "FanPulses",
1132            Self::FanMinimumAlarm => "FanMinimumAlarm",
1133            Self::FanMaximumAlarm => "FanMaximumAlarm",
1134            Self::TemperatureInput => "TemperatureInput",
1135            Self::TemperatureMaximum => "TemperatureMaximum",
1136            Self::TemperatureMaximumHysteresis => "TemperatureMaximumHysteresis",
1137            Self::TemperatureMinimum => "TemperatureMinimum",
1138            Self::TemperatureCritical => "TemperatureCritical",
1139            Self::TemperatureCriticalHysteresis => "TemperatureCriticalHysteresis",
1140            Self::TemperatureLCritical => "TemperatureLCritical",
1141            Self::TemperatureEmergency => "TemperatureEmergency",
1142            Self::TemperatureEmergencyHysteresis => "TemperatureEmergencyHysteresis",
1143            Self::TemperatureLowest => "TemperatureLowest",
1144            Self::TemperatureHighest => "TemperatureHighest",
1145            Self::TemperatureMinimumHysteresis => "TemperatureMinimumHysteresis",
1146            Self::TemperatureLCriticalHysteresis => "TemperatureLCriticalHysteresis",
1147            Self::TemperatureAlarm => "TemperatureAlarm",
1148            Self::TemperatureMaximumAlarm => "TemperatureMaximumAlarm",
1149            Self::TemperatureMinimumAlarm => "TemperatureMinimumAlarm",
1150            Self::TemperatureCriticalAlarm => "TemperatureCriticalAlarm",
1151            Self::TemperatureFault => "TemperatureFault",
1152            Self::TemperatureType => "TemperatureType",
1153            Self::TemperatureOffset => "TemperatureOffset",
1154            Self::TemperatureBeep => "TemperatureBeep",
1155            Self::TemperatureEmergencyAlarm => "TemperatureEmergencyAlarm",
1156            Self::TemperatureLCriticalAlarm => "TemperatureLCriticalAlarm",
1157            Self::PowerAverage => "PowerAverage",
1158            Self::PowerAverageHighest => "PowerAverageHighest",
1159            Self::PowerAverageLowest => "PowerAverageLowest",
1160            Self::PowerInput => "PowerInput",
1161            Self::PowerInputHighest => "PowerInputHighest",
1162            Self::PowerInputLowest => "PowerInputLowest",
1163            Self::PowerCap => "PowerCap",
1164            Self::PowerCapHysteresis => "PowerCapHysteresis",
1165            Self::PowerMaximum => "PowerMaximum",
1166            Self::PowerCritical => "PowerCritical",
1167            Self::PowerMinimum => "PowerMinimum",
1168            Self::PowerLCritical => "PowerLCritical",
1169            Self::PowerAverageInterval => "PowerAverageInterval",
1170            Self::PowerAlarm => "PowerAlarm",
1171            Self::PowerCapAlarm => "PowerCapAlarm",
1172            Self::PowerMaximumAlarm => "PowerMaximumAlarm",
1173            Self::PowerCriticalAlarm => "PowerCriticalAlarm",
1174            Self::PowerMinimumAlarm => "PowerMinimumAlarm",
1175            Self::PowerLCriticalAlarm => "PowerLCriticalAlarm",
1176            Self::EnergyInput => "EnergyInput",
1177            Self::CurrentInput => "CurrentInput",
1178            Self::CurrentMinimum => "CurrentMinimum",
1179            Self::CurrentMaximum => "CurrentMaximum",
1180            Self::CurrentLCritical => "CurrentLCritical",
1181            Self::CurrentCritical => "CurrentCritical",
1182            Self::CurrentAverage => "CurrentAverage",
1183            Self::CurrentLowest => "CurrentLowest",
1184            Self::CurrentHighest => "CurrentHighest",
1185            Self::CurrentAlarm => "CurrentAlarm",
1186            Self::CurrentMinimumAlarm => "CurrentMinimumAlarm",
1187            Self::CurrentMaximumAlarm => "CurrentMaximumAlarm",
1188            Self::CurrentBeep => "CurrentBeep",
1189            Self::CurrentLCriticalAlarm => "CurrentLCriticalAlarm",
1190            Self::CurrentCriticalAlarm => "CurrentCriticalAlarm",
1191            Self::HumidityInput => "HumidityInput",
1192            Self::VoltageID => "VoltageID",
1193            Self::IntrusionAlarm => "IntrusionAlarm",
1194            Self::IntrusionBeep => "IntrusionBeep",
1195            Self::BeepEnable => "BeepEnable",
1196            Self::Unknown => "Unknown",
1197        };
1198        write!(f, "{name}")
1199    }
1200}
1201
1202/// Unit of a value of a sensor or actuator.
1203#[allow(missing_docs)] // Enum variant names are self-explanatory.
1204#[non_exhaustive]
1205#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
1206pub enum Unit {
1207    None,
1208    Volt,
1209    Amp,
1210    Watt,
1211    Joule,
1212    Celcius,
1213    Second,
1214    RotationPerMinute,
1215    Percentage,
1216}
1217
1218impl Default for Unit {
1219    fn default() -> Self {
1220        Self::None
1221    }
1222}
1223
1224impl fmt::Display for Unit {
1225    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1226        match *self {
1227            Unit::None => Ok(()),
1228            Unit::Volt => write!(f, "V"),
1229            Unit::Amp => write!(f, "A"),
1230            Unit::Watt => write!(f, "W"),
1231            Unit::Joule => write!(f, "J"),
1232            Unit::Celcius => write!(f, "C"),
1233            Unit::Second => write!(f, "s"),
1234            Unit::RotationPerMinute => write!(f, "RPM"),
1235            Unit::Percentage => write!(f, "%"),
1236        }
1237    }
1238}
1239
1240/// Type of a temperature sensor.
1241#[allow(missing_docs)] // Enum variant names are self-explanatory.
1242#[non_exhaustive]
1243#[repr(i32)]
1244#[derive(
1245    Debug,
1246    Copy,
1247    Clone,
1248    PartialEq,
1249    Eq,
1250    PartialOrd,
1251    Ord,
1252    num_enum::TryFromPrimitive,
1253    num_enum::IntoPrimitive,
1254)]
1255pub enum TemperatureSensorKind {
1256    Disabled = 0_i32,
1257    CPUDiode = 1_i32,
1258    Transistor = 2_i32,
1259    ThermalDiode = 3_i32,
1260    Thermistor = 4_i32,
1261    AMDAMDSI = 5_i32,
1262    IntelPECI = 6_i32,
1263}
1264
1265impl TemperatureSensorKind {
1266    /// Return an instance given a raw value, if it is valid.
1267    #[must_use]
1268    pub fn from_raw(value: f64) -> Option<Self> {
1269        if value.is_nan() {
1270            return None;
1271        } else if value.is_infinite() {
1272            return value.is_sign_positive().then_some(Self::Thermistor);
1273        }
1274
1275        // Safety: `value` is finite.
1276        match unsafe { value.round().to_int_unchecked() } {
1277            ..0 => None,
1278            int_value @ 0..=1000 =>
1279            {
1280                #[allow(clippy::as_conversions)]
1281                Self::try_from(int_value as c_int).ok()
1282            }
1283            1001.. => Some(Self::Thermistor),
1284        }
1285    }
1286
1287    /// Return the raw value equivalent to this instance.
1288    #[must_use]
1289    pub fn as_raw(self) -> c_int {
1290        self.into()
1291    }
1292}
1293
1294impl Default for TemperatureSensorKind {
1295    fn default() -> Self {
1296        Self::Disabled
1297    }
1298}
1299
1300impl fmt::Display for TemperatureSensorKind {
1301    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1302        match *self {
1303            Self::Disabled => write!(f, "Disabled"),
1304            Self::CPUDiode => write!(f, "CPU diode"),
1305            Self::Transistor => write!(f, "Transistor"),
1306            Self::ThermalDiode => write!(f, "Thermal diode"),
1307            Self::Thermistor => write!(f, "Thermistor"),
1308            Self::AMDAMDSI => write!(f, "AMD AMDSI"),
1309            Self::IntelPECI => write!(f, "Intel PECI"),
1310        }
1311    }
1312}