@@ -104,7 +104,6 @@ def __init__(self, entity_info, hass, entry: MonitorMySolarEntry, bank_name, don
104104 self ._attr_native_unit_of_measurement = entity_info .get ("unit" , None )
105105 self ._attr_device_class = entity_info .get ("class" , None )
106106 self ._manufacturer = entry .data .get ("inverter_brand" )
107- self ._previous_value = self ._attr_native_value # Track the previous value for revert
108107
109108 super ().__init__ (self .coordinator )
110109
@@ -131,43 +130,44 @@ def name(self):
131130 async def async_set_native_value (self , value ):
132131 """Set the number value."""
133132 LOGGER .debug (f"Setting value of number { self .entity_id } to { value } " )
134-
133+
135134 # Check if entity should be available based on conditional settings
136135 availability_info = self .coordinator .get_entity_availability_info (self ._dongle_id , self ._entity_type )
137136 if not availability_info ["available" ] and availability_info ["reason" ]:
138137 raise HomeAssistantError (availability_info ["reason" ])
139-
138+
140139 mqtt_handler = self .coordinator .mqtt_handler
141- if mqtt_handler is not None :
142- # Save the current value before changing
143- self ._previous_value = self ._attr_native_value
144- # Set the new value
145- self ._attr_native_value = value
146- self .throttled_async_write_ha_state ()
140+ if mqtt_handler is None :
141+ raise HomeAssistantError ("MQTT Handler is not initialized" )
147142
148- # Send the update via MQTT
149- success = await mqtt_handler .send_update (
150- self ._dongle_id ,
151- self .entity_info ["unique_id" ],
152- value ,
153- self ,
154- )
155- if not success :
156- self .revert_state ()
157- else :
158- LOGGER .error ("MQTT Handler is not initialized" )
143+ # Save old value in case we need to revert
144+ old_value = self ._attr_native_value
159145
160- def revert_state (self ):
161- """Revert to the previous state."""
162- LOGGER .info (f"Reverting state for { self .entity_id } to { self ._previous_value } " )
163- self ._attr_native_value = self ._previous_value
164- self .hass .loop .call_soon_threadsafe (self .throttled_async_write_ha_state )
146+ # Set the new value optimistically for immediate UI feedback
147+ self ._attr_native_value = value
148+ # Update coordinator's stored value so it doesn't overwrite us
149+ self .coordinator .entities [self .entity_id ] = value
150+ self .throttled_async_write_ha_state ()
151+
152+ # Send the update via MQTT and wait for response
153+ success = await mqtt_handler .send_update (
154+ self ._dongle_id ,
155+ self .entity_info ["unique_id" ],
156+ value ,
157+ self ,
158+ )
159+
160+ # If MQTT update failed, revert both UI and coordinator
161+ if not success :
162+ LOGGER .error (f"Failed to update { self .entity_id } to { value } , reverting to { old_value } " )
163+ self ._attr_native_value = old_value
164+ self .coordinator .entities [self .entity_id ] = old_value
165+ self .throttled_async_write_ha_state ()
166+ raise HomeAssistantError (f"Failed to update { self .entity_id } - no response from inverter" )
165167
166168 @callback
167169 def _handle_coordinator_update (self ) -> None :
168170 """Update sensor with latest data from coordinator."""
169-
170-
171171 if self .entity_id in self .coordinator .entities :
172172 value = self .coordinator .entities [self .entity_id ]
173173 if value is not None :
@@ -203,8 +203,7 @@ def __init__(self, entity_info, hass, entry: MonitorMySolarEntry, dongle_ids):
203203 self ._attr_native_unit_of_measurement = entity_info .get ("unit" , None )
204204 self ._attr_device_class = entity_info .get ("class" , None )
205205 self ._manufacturer = entry .data .get ("inverter_brand" )
206- self ._previous_value = self ._attr_native_value # Track the previous value for revert
207-
206+
208207 # Track source entities that we need to monitor
209208 self ._tracked_entities = []
210209 self ._source_values = {}
@@ -252,19 +251,19 @@ def async_state_changed_listener(event: Event) -> None:
252251
253252 async def _update_combined_state (self ):
254253 """Update the combined state based on source entities.
255-
254+
256255 Takes the average of all current values.
257256 """
258257 # Filter out None values
259258 values = [v for v in self ._source_values .values () if v is not None ]
260-
259+
261260 if not values :
262261 LOGGER .debug (f"No values available for combined number { self ._name } " )
263262 return
264-
263+
265264 # Take the average for the display state
266265 avg_value = sum (values ) / len (values )
267-
266+
268267 if avg_value != self ._attr_native_value :
269268 self ._attr_native_value = avg_value
270269 self .throttled_async_write_ha_state ()
@@ -304,27 +303,38 @@ def device_info(self):
304303 async def async_set_native_value (self , value ):
305304 """Set the value on all dongles."""
306305 mqtt_handler = self .coordinator .mqtt_handler
307- if mqtt_handler is not None :
308- # Save the current value before changing
309- self ._previous_value = self ._attr_native_value
310- # Set the new value
311- self ._attr_native_value = value
306+ if mqtt_handler is None :
307+ raise HomeAssistantError ("MQTT Handler is not initialized" )
308+
309+ # Save old value in case we need to revert
310+ old_value = self ._attr_native_value
311+
312+ # Set the new value optimistically for immediate UI feedback
313+ self ._attr_native_value = value
314+ # Update all source values to prevent them from overwriting us
315+ for entity_id in self ._source_values .keys ():
316+ self ._source_values [entity_id ] = value
317+ self .throttled_async_write_ha_state ()
318+
319+ LOGGER .info (f"Setting Combined Number value for { self .entity_id } to { value } across { len (self ._dongle_ids )} dongles" )
320+ success = await mqtt_handler .send_update_to_multiple_dongles (
321+ self ._dongle_ids , self ._source_entity , value , self
322+ )
323+
324+ # If MQTT update failed, revert and raise error
325+ if not success :
326+ LOGGER .error (f"Failed to update { self .entity_id } to { value } , reverting to { old_value } " )
327+ self ._attr_native_value = old_value
328+ # Revert source values - they'll update from coordinator naturally
329+ for entity_id in self ._source_values .keys ():
330+ state = self .hass .states .get (entity_id )
331+ if state :
332+ try :
333+ self ._source_values [entity_id ] = float (state .state )
334+ except (ValueError , TypeError ):
335+ pass
312336 self .throttled_async_write_ha_state ()
313-
314- LOGGER .info (f"Setting Combined Number value for { self .entity_id } to { value } across { len (self ._dongle_ids )} dongles" )
315- success = await mqtt_handler .send_update_to_multiple_dongles (
316- self ._dongle_ids , self ._source_entity , value , self
317- )
318- if not success :
319- self .revert_state ()
320- else :
321- LOGGER .error ("MQTT Handler is not initialized" )
322-
323- def revert_state (self ):
324- """Revert to the previous state."""
325- LOGGER .info (f"Reverting state for { self .entity_id } to { self ._previous_value } " )
326- self ._attr_native_value = self ._previous_value
327- self .hass .loop .call_soon_threadsafe (self .throttled_async_write_ha_state )
337+ raise HomeAssistantError (f"Failed to update { self .entity_id } - no response from inverter" )
328338
329339 @property
330340 def extra_state_attributes (self ):
0 commit comments