|
1 | 1 | """sensor.py""" |
2 | 2 |
|
3 | 3 | import logging |
| 4 | +from datetime import datetime |
4 | 5 |
|
5 | 6 | from homeassistant.components.sensor import SensorEntity |
6 | 7 | from homeassistant.components.binary_sensor import BinarySensorEntity |
|
35 | 36 | SOLAR_PANEL_ICON, |
36 | 37 | CACHE_COUNTER_ICON, |
37 | 38 | FROM_GRID_ICON, |
| 39 | + TO_GRID_ICON, |
38 | 40 | CONSUMED_ICON, |
39 | 41 | DOWNLOAD_ICON, |
40 | 42 | INVERTER_MODEL_MAP, |
@@ -235,6 +237,42 @@ async def async_setup_entry(hass, config_entry, add_entities): |
235 | 237 | ] |
236 | 238 | ) |
237 | 239 |
|
| 240 | + # Add lifetime energy export sensors |
| 241 | + sensors.extend( |
| 242 | + [ |
| 243 | + APsystemsECUSensor( |
| 244 | + coordinator, |
| 245 | + ecu, |
| 246 | + "lifetime_energy_export_a", |
| 247 | + label=f"{ecu.ecu.ecu_id} Lifetime Energy Export A", |
| 248 | + unit=UnitOfEnergy.KILO_WATT_HOUR, |
| 249 | + devclass=SensorDeviceClass.ENERGY, |
| 250 | + icon=TO_GRID_ICON, |
| 251 | + stateclass=SensorStateClass.TOTAL_INCREASING, |
| 252 | + ), |
| 253 | + APsystemsECUSensor( |
| 254 | + coordinator, |
| 255 | + ecu, |
| 256 | + "lifetime_energy_export_b", |
| 257 | + label=f"{ecu.ecu.ecu_id} Lifetime Energy Export B", |
| 258 | + unit=UnitOfEnergy.KILO_WATT_HOUR, |
| 259 | + devclass=SensorDeviceClass.ENERGY, |
| 260 | + icon=TO_GRID_ICON, |
| 261 | + stateclass=SensorStateClass.TOTAL_INCREASING, |
| 262 | + ), |
| 263 | + APsystemsECUSensor( |
| 264 | + coordinator, |
| 265 | + ecu, |
| 266 | + "lifetime_energy_export_c", |
| 267 | + label=f"{ecu.ecu.ecu_id} Lifetime Energy Export C", |
| 268 | + unit=UnitOfEnergy.KILO_WATT_HOUR, |
| 269 | + devclass=SensorDeviceClass.ENERGY, |
| 270 | + icon=TO_GRID_ICON, |
| 271 | + stateclass=SensorStateClass.TOTAL_INCREASING, |
| 272 | + ), |
| 273 | + ] |
| 274 | + ) |
| 275 | + |
238 | 276 | # Add inverter binary sensors |
239 | 277 | inverters = coordinator.data.get("inverters", {}) |
240 | 278 | for uid, inv_data in inverters.items(): |
@@ -570,12 +608,17 @@ def __init__( |
570 | 608 | # self._disabled_by = disabled_by |
571 | 609 | self._name = f"ECU {self._label}" |
572 | 610 | self._state = None |
| 611 | + self._last_update_time = None |
| 612 | + self._last_power_value = None |
573 | 613 |
|
574 | 614 | async def async_added_to_hass(self): |
575 | 615 | """Handle entity that needs to be restored.""" |
576 | 616 | await super().async_added_to_hass() |
577 | 617 | last_state = await self.async_get_last_state() |
578 | | - if last_state and self._field == "lifetime_maximum_power": |
| 618 | + if last_state and ( |
| 619 | + self._field == "lifetime_maximum_power" |
| 620 | + or self._field.startswith("lifetime_energy_export") |
| 621 | + ): |
579 | 622 | try: |
580 | 623 | self._state = ( |
581 | 624 | 0 |
@@ -605,6 +648,40 @@ def native_value(self): |
605 | 648 | current_power = self.coordinator.data.get("current_power", 0) or 0 |
606 | 649 | self._state = max(self._state or 0, current_power) |
607 | 650 | return round(self._state) |
| 651 | + elif self._field.startswith("lifetime_energy_export"): |
| 652 | + # Extract the phase (a, b, or c) from the field name |
| 653 | + phase = self._field.split("_")[-1] # Gets 'a', 'b', or 'c' |
| 654 | + grid_field = f"grid_ct_{phase}" |
| 655 | + |
| 656 | + # Get current power and time |
| 657 | + current_power = self.coordinator.data.get(grid_field, 0) or 0 |
| 658 | + current_time = datetime.now() |
| 659 | + |
| 660 | + # Initialize state if None |
| 661 | + if self._state is None: |
| 662 | + self._state = 0.0 |
| 663 | + |
| 664 | + # Calculate energy increment if we have a previous timestamp |
| 665 | + if ( |
| 666 | + self._last_update_time is not None |
| 667 | + and self._last_power_value is not None |
| 668 | + and self._last_power_value < 0 |
| 669 | + ): # Only accumulate when exporting (negative power) |
| 670 | + |
| 671 | + time_delta_hours = ( |
| 672 | + current_time - self._last_update_time |
| 673 | + ).total_seconds() / 3600 |
| 674 | + # Use absolute value of negative power for export energy calculation |
| 675 | + energy_increment_kwh = ( |
| 676 | + abs(self._last_power_value) * time_delta_hours / 1000 |
| 677 | + ) |
| 678 | + self._state += energy_increment_kwh |
| 679 | + |
| 680 | + # Update tracking variables |
| 681 | + self._last_update_time = current_time |
| 682 | + self._last_power_value = current_power |
| 683 | + |
| 684 | + return round(self._state, 3) |
608 | 685 | else: |
609 | 686 | return self.coordinator.data.get(self._field, 0) |
610 | 687 |
|
|
0 commit comments