@@ -118,7 +118,49 @@ async def async_update_data():
118118 entities .append (build_sensor_entity (sensor_dict , coordinator ))
119119
120120
121- entities .append (CumulativeEnergySensor (hass , coordinator , "Inverter Power DC Total (Huawei)" , interval ))
121+ # Create cumulative energy sensor with smart fallback for different inverter types
122+
123+ source_sensor = None
124+ available_sensor_names = [s .get ("name" , "" ) for s in coordinator .data ]
125+
126+ # Priority 1: Try Huawei-specific sensor first
127+ if "Inverter: Power DC Total (Huawei)" in available_sensor_names :
128+ source_sensor = "Inverter: Power DC Total (Huawei)"
129+ _LOGGER .info ("[Enpal] Using Huawei-specific DC power sensor: %s" , source_sensor )
130+
131+ # Priority 2: Try other manufacturer-specific sensors (SMA, Fronius, etc.)
132+ # Look for pattern: "Inverter: Power DC Total (<Manufacturer>)"
133+ if not source_sensor :
134+ for name in available_sensor_names :
135+ name_id = make_id (name )
136+ # Match manufacturer-specific format but exclude Calculated
137+ if (name_id .startswith ("inverter_power_dc_total_" ) and
138+ name_id != "inverter_power_dc_total_calculated" and
139+ name_id != "inverter_power_dc_total" ):
140+ source_sensor = name
141+ _LOGGER .info ("[Enpal] Found manufacturer-specific DC power sensor: %s" , name )
142+ break
143+
144+ # Priority 3: Try generic "Inverter: Power DC Total"
145+ if not source_sensor and "Inverter: Power DC Total" in available_sensor_names :
146+ source_sensor = "Inverter: Power DC Total"
147+ _LOGGER .info ("[Enpal] Using generic DC power sensor: %s" , source_sensor )
148+
149+ # Priority 4: Last resort - use calculated sensor
150+ if not source_sensor and "Inverter: Power DC Total Calculated" in available_sensor_names :
151+ source_sensor = "Inverter: Power DC Total Calculated"
152+ _LOGGER .warning ("[Enpal] Using calculated DC power sensor (least accurate): %s" , source_sensor )
153+
154+ # Final fallback: If nothing found, use Huawei as default (will trigger warning)
155+ if not source_sensor :
156+ source_sensor = "Inverter: Power DC Total (Huawei)"
157+ _LOGGER .warning (
158+ "[Enpal] No DC power sensor found. Available power sensors: %s. Using fallback: %s" ,
159+ ", " .join ([make_id (n ) for n in available_sensor_names if "power" in make_id (n ).lower ()]),
160+ source_sensor
161+ )
162+
163+ entities .append (CumulativeEnergySensor (hass , coordinator , [source_sensor ], interval ))
122164 entities .append (DailyResetFromEntitySensor (hass , "sensor.inverter_energy_produced_total_dc" ))
123165
124166 if entry .options .get ("use_wallbox_addon" , False ):
@@ -165,7 +207,7 @@ async def async_wallbox_update():
165207
166208
167209class CumulativeEnergySensor (SensorEntity , RestoreEntity ):
168- def __init__ (self , hass : HomeAssistant , coordinator : DataUpdateCoordinator , sensor_name : str , interval_seconds : int ):
210+ def __init__ (self , hass : HomeAssistant , coordinator : DataUpdateCoordinator , sensor_names : list [ str ] , interval_seconds : int ):
169211 self .hass = hass
170212 self ._attr_name = str ("Inverter: Energy produced total (DC)" )
171213 self ._attr_unique_id = str ("cumulative_energy_produced_dc_kwh" )
@@ -174,7 +216,8 @@ def __init__(self, hass: HomeAssistant, coordinator: DataUpdateCoordinator, sens
174216 self ._attr_native_unit_of_measurement = "kWh"
175217 self ._attr_icon = "mdi:solar-power"
176218 self ._coordinator = coordinator
177- self ._source_uid = make_id (sensor_name )
219+ self ._source_candidates = [make_id (name ) for name in sensor_names ]
220+ self ._active_source_uid = None # Will be determined from available sensors
178221 self ._interval_hours = interval_seconds / 3600
179222 self ._state = self .hass .data [DOMAIN ]["cumulative_energy_state" ]
180223 self ._value = None
@@ -187,7 +230,8 @@ def native_value(self) -> StateType:
187230 @property
188231 def extra_state_attributes (self ) -> dict :
189232 return {
190- "last_updated" : self ._last_updated
233+ "last_updated" : self ._last_updated ,
234+ "source_sensor" : self ._active_source_uid if self ._active_source_uid else "Not determined"
191235 }
192236
193237 async def async_added_to_hass (self ):
@@ -204,17 +248,34 @@ async def async_added_to_hass(self):
204248 self ._coordinator .async_add_listener (self ._handle_coordinator_update )
205249
206250 def _handle_coordinator_update (self ):
251+ # If we haven't determined the active source yet, find the first available one
252+ if self ._active_source_uid is None :
253+ available_sensors = {make_id (s ["name" ]) for s in self ._coordinator .data }
254+ for candidate in self ._source_candidates :
255+ if candidate in available_sensors :
256+ self ._active_source_uid = candidate
257+ _LOGGER .info ("[Enpal] Using DC power sensor: %s" , candidate )
258+ break
259+
260+ if self ._active_source_uid is None :
261+ _LOGGER .warning (
262+ "[Enpal] No suitable DC power sensor found. Tried: %s" ,
263+ ", " .join (self ._source_candidates )
264+ )
265+ self .async_write_ha_state ()
266+ return
267+
268+ # Now process the update with the active source
207269 for sensor in self ._coordinator .data :
208- _LOGGER .debug ("[Enpal] Checking Sensor: %s (%s)" , sensor ["name" ], make_id (sensor ["name" ]))
209- if make_id (sensor ["name" ]) == self ._source_uid :
270+ if make_id (sensor ["name" ]) == self ._active_source_uid :
210271 try :
211272 power_watt = float (sensor ["value" ])
212273 energy_kwh = power_watt * self ._interval_hours / 1000
213274 if self ._value is None :
214275 self ._value = 0.0
215276 self ._value += energy_kwh
216277 self ._last_updated = datetime .now ().isoformat ()
217- _LOGGER .debug ("[Enpal] +%.5f kWh -> Total: %.3f" , energy_kwh , self ._state [ "value" ] )
278+ _LOGGER .debug ("[Enpal] +%.5f kWh -> Total: %.3f kWh " , energy_kwh , self ._value )
218279 except Exception as e :
219280 _LOGGER .warning ("[Enpal] Error in energy calculation: %s" , e )
220281 break
0 commit comments