1 """Support for monitoring a Smappee energy sensor."""
3 from __future__
import annotations
5 from dataclasses
import dataclass, field
10 SensorEntityDescription,
18 from .
import SmappeeConfigEntry
19 from .const
import DOMAIN
22 @dataclass(frozen=True, kw_only=True)
24 """Describes Smappee sensor entity."""
29 @dataclass(frozen=True, kw_only=True)
31 """Describes Smappee sensor entity."""
33 local_polling: bool =
False
36 @dataclass(frozen=True, kw_only=True)
38 """Describes Smappee sensor entity."""
40 phase_types: set[str] = field(default_factory=set)
43 TREND_SENSORS: tuple[SmappeePollingSensorEntityDescription, ...] = (
46 name=
"Total consumption - Active power",
47 native_unit_of_measurement=UnitOfPower.WATT,
48 sensor_id=
"total_power",
49 device_class=SensorDeviceClass.POWER,
50 state_class=SensorStateClass.MEASUREMENT,
55 name=
"Always on - Active power",
56 native_unit_of_measurement=UnitOfPower.WATT,
58 device_class=SensorDeviceClass.POWER,
59 state_class=SensorStateClass.MEASUREMENT,
63 name=
"Total consumption - Today",
64 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
65 sensor_id=
"power_today",
66 device_class=SensorDeviceClass.ENERGY,
67 state_class=SensorStateClass.TOTAL_INCREASING,
70 key=
"power_current_hour",
71 name=
"Total consumption - Current hour",
72 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
73 sensor_id=
"power_current_hour",
74 device_class=SensorDeviceClass.ENERGY,
75 state_class=SensorStateClass.TOTAL_INCREASING,
78 key=
"power_last_5_minutes",
79 name=
"Total consumption - Last 5 minutes",
80 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
81 sensor_id=
"power_last_5_minutes",
82 device_class=SensorDeviceClass.ENERGY,
83 state_class=SensorStateClass.TOTAL_INCREASING,
87 name=
"Always on - Today",
88 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
89 sensor_id=
"alwayson_today",
90 device_class=SensorDeviceClass.ENERGY,
91 state_class=SensorStateClass.TOTAL_INCREASING,
94 REACTIVE_SENSORS: tuple[SmappeeSensorEntityDescription, ...] = (
96 key=
"total_reactive_power",
97 name=
"Total consumption - Reactive power",
98 native_unit_of_measurement=UnitOfPower.WATT,
99 sensor_id=
"total_reactive_power",
100 device_class=SensorDeviceClass.POWER,
101 state_class=SensorStateClass.MEASUREMENT,
104 SOLAR_SENSORS: tuple[SmappeePollingSensorEntityDescription, ...] = (
107 name=
"Total production - Active power",
108 native_unit_of_measurement=UnitOfPower.WATT,
109 sensor_id=
"solar_power",
110 device_class=SensorDeviceClass.POWER,
111 state_class=SensorStateClass.MEASUREMENT,
116 name=
"Total production - Today",
117 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
118 sensor_id=
"solar_today",
119 device_class=SensorDeviceClass.ENERGY,
120 state_class=SensorStateClass.TOTAL_INCREASING,
123 key=
"solar_current_hour",
124 name=
"Total production - Current hour",
125 native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
126 sensor_id=
"solar_current_hour",
127 device_class=SensorDeviceClass.ENERGY,
128 state_class=SensorStateClass.TOTAL_INCREASING,
131 VOLTAGE_SENSORS: tuple[SmappeeVoltageSensorEntityDescription, ...] = (
133 key=
"phase_voltages_a",
134 name=
"Phase voltages - A",
135 native_unit_of_measurement=UnitOfElectricPotential.VOLT,
136 sensor_id=
"phase_voltage_a",
137 device_class=SensorDeviceClass.VOLTAGE,
138 state_class=SensorStateClass.MEASUREMENT,
139 phase_types={
"ONE",
"TWO",
"THREE_STAR",
"THREE_DELTA"},
142 key=
"phase_voltages_b",
143 name=
"Phase voltages - B",
144 native_unit_of_measurement=UnitOfElectricPotential.VOLT,
145 sensor_id=
"phase_voltage_b",
146 device_class=SensorDeviceClass.VOLTAGE,
147 state_class=SensorStateClass.MEASUREMENT,
148 phase_types={
"TWO",
"THREE_STAR",
"THREE_DELTA"},
151 key=
"phase_voltages_c",
152 name=
"Phase voltages - C",
153 native_unit_of_measurement=UnitOfElectricPotential.VOLT,
154 sensor_id=
"phase_voltage_c",
155 device_class=SensorDeviceClass.VOLTAGE,
156 state_class=SensorStateClass.MEASUREMENT,
157 phase_types={
"THREE_STAR"},
160 key=
"line_voltages_a",
161 name=
"Line voltages - A",
162 native_unit_of_measurement=UnitOfElectricPotential.VOLT,
163 sensor_id=
"line_voltage_a",
164 device_class=SensorDeviceClass.VOLTAGE,
165 state_class=SensorStateClass.MEASUREMENT,
166 phase_types={
"ONE",
"TWO",
"THREE_STAR",
"THREE_DELTA"},
169 key=
"line_voltages_b",
170 name=
"Line voltages - B",
171 native_unit_of_measurement=UnitOfElectricPotential.VOLT,
172 sensor_id=
"line_voltage_b",
173 device_class=SensorDeviceClass.VOLTAGE,
174 state_class=SensorStateClass.MEASUREMENT,
175 phase_types={
"TWO",
"THREE_STAR",
"THREE_DELTA"},
178 key=
"line_voltages_c",
179 name=
"Line voltages - C",
180 native_unit_of_measurement=UnitOfElectricPotential.VOLT,
181 sensor_id=
"line_voltage_c",
182 device_class=SensorDeviceClass.VOLTAGE,
183 state_class=SensorStateClass.MEASUREMENT,
184 phase_types={
"THREE_STAR",
"THREE_DELTA"},
191 config_entry: SmappeeConfigEntry,
192 async_add_entities: AddEntitiesCallback,
194 """Set up the Smappee sensor."""
195 smappee_base = config_entry.runtime_data
198 for service_location
in smappee_base.smappee.service_locations.values():
204 smappee_base=smappee_base,
205 service_location=service_location,
206 description=description,
208 for description
in TREND_SENSORS
209 if not service_location.local_polling
or description.local_polling
213 if service_location.has_reactive_value:
217 smappee_base=smappee_base,
218 service_location=service_location,
219 description=description,
221 for description
in REACTIVE_SENSORS
226 if service_location.has_solar_production:
230 smappee_base=smappee_base,
231 service_location=service_location,
232 description=description,
234 for description
in SOLAR_SENSORS
235 if not service_location.local_polling
or description.local_polling
243 smappee_base=smappee_base,
244 service_location=service_location,
247 name=measurement.name,
248 native_unit_of_measurement=UnitOfPower.WATT,
249 sensor_id=measurement_id,
250 device_class=SensorDeviceClass.POWER,
251 state_class=SensorStateClass.MEASUREMENT,
254 for measurement_id, measurement
in service_location.measurements.items()
259 if service_location.has_voltage_values:
263 smappee_base=smappee_base,
264 service_location=service_location,
265 description=description,
267 for description
in VOLTAGE_SENSORS
269 service_location.phase_type
in description.phase_types
271 description.key.startswith(
"line_")
272 and service_location.local_polling
282 smappee_base=smappee_base,
283 service_location=service_location,
286 name=channel.get(
"name"),
289 if channel.get(
"type") ==
"water"
290 else "mdi:gas-cylinder"
292 native_unit_of_measurement=channel.get(
"uom"),
293 sensor_id=f
"{sensor_id}-{channel.get('channel')}",
294 state_class=SensorStateClass.MEASUREMENT,
297 for sensor_id, sensor
in service_location.sensors.items()
298 for channel
in sensor.channels
306 smappee_base=smappee_base,
307 service_location=service_location,
310 name=f
"{actuator.name} - energy today",
311 native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
312 sensor_id=actuator_id,
313 device_class=SensorDeviceClass.ENERGY,
314 state_class=SensorStateClass.TOTAL_INCREASING,
317 for actuator_id, actuator
in service_location.actuators.items()
318 if actuator.type ==
"SWITCH" and not service_location.local_polling
326 """Implementation of a Smappee sensor."""
328 entity_description: SmappeeSensorEntityDescription
334 description: SmappeeSensorEntityDescription,
336 """Initialize the Smappee sensor."""
341 identifiers={(DOMAIN, service_location.device_serial_number)},
342 manufacturer=
"Smappee",
343 model=service_location.device_model,
344 name=service_location.service_location_name,
345 sw_version=service_location.firmware_version,
350 """Return the name for this sensor."""
353 if sensor_key
in (
"sensor",
"load",
"switch"):
355 f
"{self._service_location.service_location_name} - "
356 f
"{sensor_key.title()} - {sensor_name}"
359 return f
"{self._service_location.service_location_name} - {sensor_name}"
363 """Return the unique ID for this sensor."""
365 if sensor_key
in (
"load",
"sensor",
"switch"):
367 f
"{self._service_location.device_serial_number}-"
368 f
"{self._service_location.service_location_id}-"
369 f
"{sensor_key}-{self.entity_description.sensor_id}"
373 f
"{self._service_location.device_serial_number}-"
374 f
"{self._service_location.service_location_id}-"
379 """Get the latest data from Smappee and update the state."""
383 if sensor_key ==
"total_power":
385 elif sensor_key ==
"total_reactive_power":
387 elif sensor_key ==
"solar_power":
389 elif sensor_key ==
"alwayson":
397 if phase_voltages
is not None:
398 if sensor_key ==
"phase_voltages_a":
400 elif sensor_key ==
"phase_voltages_b":
402 elif sensor_key ==
"phase_voltages_c":
404 elif sensor_key
in (
"line_voltages_a",
"line_voltages_b",
"line_voltages_c"):
406 if line_voltages
is not None:
407 if sensor_key ==
"line_voltages_a":
409 elif sensor_key ==
"line_voltages_b":
411 elif sensor_key ==
"line_voltages_c":
415 "power_current_hour",
416 "power_last_5_minutes",
418 "solar_current_hour",
421 trend_value = self.
_service_location_service_location.aggregated_values.get(sensor_key)
423 round(trend_value)
if trend_value
is not None else None
425 elif sensor_key ==
"load":
429 elif sensor_key ==
"sensor":
430 sensor_id, channel_id = self.
entity_descriptionentity_description.sensor_id.split(
"-")
432 for channel
in sensor.channels:
433 if channel.get(
"channel") ==
int(channel_id):
435 elif sensor_key ==
"switch":
None __init__(self, smappee_base, service_location, SmappeeSensorEntityDescription description)
None async_setup_entry(HomeAssistant hass, SmappeeConfigEntry config_entry, AddEntitiesCallback async_add_entities)