1use crate::{Entity, EntityCommonConfig, EntityConfig, NumericSensorState, constants};
2
3#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
4pub enum StateClass {
5 #[default]
6 Measurement,
7 Total,
8 TotalIncreasing,
9}
10
11impl StateClass {
12 pub fn as_str(&self) -> &'static str {
13 match self {
14 StateClass::Measurement => constants::HA_STATE_CLASS_MEASUREMENT,
15 StateClass::Total => constants::HA_STATE_CLASS_TOTAL,
16 StateClass::TotalIncreasing => constants::HA_STATE_CLASS_TOTAL_INCREASING,
17 }
18 }
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
22pub enum SensorClass {
23 #[default]
24 Generic,
25 ApparentPower,
26 Aqi,
27 AtmosphericPressure,
28 Battery,
29 CarbonDioxide,
30 CarbonMonoxide,
31 Current,
32 DataRate,
33 DataSize,
34 Date,
35 Distance,
36 Duration,
37 Energy,
38 EnergyStorage,
39 Enum,
40 Frequency,
41 Gas,
42 Humidity,
43 Illuminance,
44 Irradiance,
45 Moisture,
46 Monetary,
47 NitrogenDioxide,
48 NitrogenMonoxide,
49 NitrousOxide,
50 Ozone,
51 Ph,
52 Pm1,
53 Pm25,
54 Pm10,
55 PowerFactor,
56 Power,
57 Precipitation,
58 PrecipitationIntensity,
59 Pressure,
60 ReactivePower,
61 SignalStrength,
62 SoundPressure,
63 Speed,
64 SulphurDioxide,
65 Temperature,
66 Timestamp,
67 VolatileOrganicCompounds,
68 VolatileOrganicCompoundsParts,
69 Voltage,
70 Volume,
71 VolumeFlowRate,
72 VolumeStorage,
73 Water,
74 Weight,
75 WindSpeed,
76 Other(&'static str),
77}
78
79impl SensorClass {
80 pub fn as_str(&self) -> Option<&'static str> {
81 match self {
82 SensorClass::Generic => None,
83 SensorClass::Other(s) => Some(s),
84 SensorClass::ApparentPower => Some(constants::HA_DEVICE_CLASS_SENSOR_APPARENT_POWER),
85 SensorClass::Aqi => Some(constants::HA_DEVICE_CLASS_SENSOR_AQI),
86 SensorClass::AtmosphericPressure => {
87 Some(constants::HA_DEVICE_CLASS_SENSOR_ATMOSPHERIC_PRESSURE)
88 }
89 SensorClass::Battery => Some(constants::HA_DEVICE_CLASS_SENSOR_BATTERY),
90 SensorClass::CarbonDioxide => Some(constants::HA_DEVICE_CLASS_SENSOR_CARBON_DIOXIDE),
91 SensorClass::CarbonMonoxide => Some(constants::HA_DEVICE_CLASS_SENSOR_CARBON_MONOXIDE),
92 SensorClass::Current => Some(constants::HA_DEVICE_CLASS_SENSOR_CURRENT),
93 SensorClass::DataRate => Some(constants::HA_DEVICE_CLASS_SENSOR_DATA_RATE),
94 SensorClass::DataSize => Some(constants::HA_DEVICE_CLASS_SENSOR_DATA_SIZE),
95 SensorClass::Date => Some(constants::HA_DEVICE_CLASS_SENSOR_DATE),
96 SensorClass::Distance => Some(constants::HA_DEVICE_CLASS_SENSOR_DISTANCE),
97 SensorClass::Duration => Some(constants::HA_DEVICE_CLASS_SENSOR_DURATION),
98 SensorClass::Energy => Some(constants::HA_DEVICE_CLASS_SENSOR_ENERGY),
99 SensorClass::EnergyStorage => Some(constants::HA_DEVICE_CLASS_SENSOR_ENERGY_STORAGE),
100 SensorClass::Enum => Some(constants::HA_DEVICE_CLASS_SENSOR_ENUM),
101 SensorClass::Frequency => Some(constants::HA_DEVICE_CLASS_SENSOR_FREQUENCY),
102 SensorClass::Gas => Some(constants::HA_DEVICE_CLASS_SENSOR_GAS),
103 SensorClass::Humidity => Some(constants::HA_DEVICE_CLASS_SENSOR_HUMIDITY),
104 SensorClass::Illuminance => Some(constants::HA_DEVICE_CLASS_SENSOR_ILLUMINANCE),
105 SensorClass::Irradiance => Some(constants::HA_DEVICE_CLASS_SENSOR_IRRADIANCE),
106 SensorClass::Moisture => Some(constants::HA_DEVICE_CLASS_SENSOR_MOISTURE),
107 SensorClass::Monetary => Some(constants::HA_DEVICE_CLASS_SENSOR_MONETARY),
108 SensorClass::NitrogenDioxide => {
109 Some(constants::HA_DEVICE_CLASS_SENSOR_NITROGEN_DIOXIDE)
110 }
111 SensorClass::NitrogenMonoxide => {
112 Some(constants::HA_DEVICE_CLASS_SENSOR_NITROGEN_MONOXIDE)
113 }
114 SensorClass::NitrousOxide => Some(constants::HA_DEVICE_CLASS_SENSOR_NITROUS_OXIDE),
115 SensorClass::Ozone => Some(constants::HA_DEVICE_CLASS_SENSOR_OZONE),
116 SensorClass::Ph => Some(constants::HA_DEVICE_CLASS_SENSOR_PH),
117 SensorClass::Pm1 => Some(constants::HA_DEVICE_CLASS_SENSOR_PM1),
118 SensorClass::Pm25 => Some(constants::HA_DEVICE_CLASS_SENSOR_PM25),
119 SensorClass::Pm10 => Some(constants::HA_DEVICE_CLASS_SENSOR_PM10),
120 SensorClass::PowerFactor => Some(constants::HA_DEVICE_CLASS_SENSOR_POWER_FACTOR),
121 SensorClass::Power => Some(constants::HA_DEVICE_CLASS_SENSOR_POWER),
122 SensorClass::Precipitation => Some(constants::HA_DEVICE_CLASS_SENSOR_PRECIPITATION),
123 SensorClass::PrecipitationIntensity => {
124 Some(constants::HA_DEVICE_CLASS_SENSOR_PRECIPITATION_INTENSITY)
125 }
126 SensorClass::Pressure => Some(constants::HA_DEVICE_CLASS_SENSOR_PRESSURE),
127 SensorClass::ReactivePower => Some(constants::HA_DEVICE_CLASS_SENSOR_REACTIVE_POWER),
128 SensorClass::SignalStrength => Some(constants::HA_DEVICE_CLASS_SENSOR_SIGNAL_STRENGTH),
129 SensorClass::SoundPressure => Some(constants::HA_DEVICE_CLASS_SENSOR_SOUND_PRESSURE),
130 SensorClass::Speed => Some(constants::HA_DEVICE_CLASS_SENSOR_SPEED),
131 SensorClass::SulphurDioxide => Some(constants::HA_DEVICE_CLASS_SENSOR_SULPHUR_DIOXIDE),
132 SensorClass::Temperature => Some(constants::HA_DEVICE_CLASS_SENSOR_TEMPERATURE),
133 SensorClass::Timestamp => Some(constants::HA_DEVICE_CLASS_SENSOR_TIMESTAMP),
134 SensorClass::VolatileOrganicCompounds => {
135 Some(constants::HA_DEVICE_CLASS_SENSOR_VOLATILE_ORGANIC_COMPOUNDS)
136 }
137 SensorClass::VolatileOrganicCompoundsParts => {
138 Some(constants::HA_DEVICE_CLASS_SENSOR_VOLATILE_ORGANIC_COMPOUNDS_PARTS)
139 }
140 SensorClass::Voltage => Some(constants::HA_DEVICE_CLASS_SENSOR_VOLTAGE),
141 SensorClass::Volume => Some(constants::HA_DEVICE_CLASS_SENSOR_VOLUME),
142 SensorClass::VolumeFlowRate => Some(constants::HA_DEVICE_CLASS_SENSOR_VOLUME_FLOW_RATE),
143 SensorClass::VolumeStorage => Some(constants::HA_DEVICE_CLASS_SENSOR_VOLUME_STORAGE),
144 SensorClass::Water => Some(constants::HA_DEVICE_CLASS_SENSOR_WATER),
145 SensorClass::Weight => Some(constants::HA_DEVICE_CLASS_SENSOR_WEIGHT),
146 SensorClass::WindSpeed => Some(constants::HA_DEVICE_CLASS_SENSOR_WIND_SPEED),
147 }
148 }
149}
150
151#[derive(Debug, Default)]
152pub struct SensorConfig {
153 pub common: EntityCommonConfig,
154 pub class: SensorClass,
155 pub state_class: StateClass,
156 pub unit: Option<&'static str>,
157 pub suggested_display_precision: Option<u8>,
158}
159
160impl SensorConfig {
161 pub(crate) fn populate(&self, config: &mut EntityConfig) {
162 self.common.populate(config);
163 config.domain = constants::HA_DOMAIN_SENSOR;
164 config.device_class = self.class.as_str();
165 config.state_class = Some(self.state_class.as_str());
166 config.measurement_unit = self.unit;
167 config.suggested_display_precision = self.suggested_display_precision;
168 }
169}
170
171pub struct Sensor<'a>(Entity<'a>);
172
173impl<'a> Sensor<'a> {
174 pub(crate) fn new(entity: Entity<'a>) -> Self {
175 Self(entity)
176 }
177
178 pub fn publish(&mut self, value: f32) {
179 let publish = self.0.with_data(|data| {
180 let storage = data.storage.as_numeric_sensor_mut();
181 let prev_state = storage.state.replace(NumericSensorState {
182 value,
183 timestamp: embassy_time::Instant::now(),
184 });
185 match prev_state {
186 Some(state) => state.value != value,
187 None => true,
188 }
189 });
190 if publish {
191 self.0.queue_publish();
192 }
193 }
194}