@@ -199,6 +199,7 @@ def initialize(self, gateway_device_id=None, mqtt_host=None, mqtt_port=8883, mqt
199199 self ._last_published_plan = None
200200 self ._pending_plan = None
201201 self ._suffix_to_serial = {} # maps entity suffix (last 6 chars of serial) -> full serial string
202+ self ._command_id = 0 # incrementing counter included in every published command
202203
203204 # Predbat data publish state (price/timeline for device display)
204205 self ._last_predbat_data = None
@@ -1122,11 +1123,14 @@ async def publish_command(self, command, **kwargs):
11221123 command: Command name (set_mode, set_charge_rate, etc.)
11231124 **kwargs: Command-specific fields (mode, power_w, target_soc).
11241125 """
1125- cmd_json = self .build_command (command , ** kwargs )
1126+ self ._command_id += 1
1127+ cmd_json = self .build_command (command , command_id = self ._command_id , ** kwargs )
1128+
1129+ self .log ("Info: GatewayMQTT: publish_command: command={}, payload={}" .format (command , cmd_json ))
11261130
11271131 if self ._mqtt_connected :
11281132 await self ._publish_raw (self .topic_command , cmd_json .encode ("utf-8" ))
1129- self .log (f"Info: GatewayMQTT: Published command: { command } " )
1133+ self .log (f"Info: GatewayMQTT: Published command: { command } payload= { cmd_json } " )
11301134 else :
11311135 self .log (f"Warn: GatewayMQTT: Not connected — cannot publish command: { command } " )
11321136
@@ -1172,6 +1176,7 @@ def _serial_from_entity_id(self, entity_id):
11721176 """Extract the full inverter serial from a gateway entity_id.
11731177
11741178 Entity IDs follow the pattern {domain}.{prefix}_gateway_{suffix}_{attribute}
1179+ e.g. select.predbat_gateway_30g499_charge_slot1_start
11751180 where suffix is the last 6 chars of the inverter serial, lowercased.
11761181 Returns the full serial string, or None if the suffix is not in the map.
11771182 """
@@ -1198,10 +1203,13 @@ async def select_event(self, entity_id, value):
11981203
11991204 self .log ("Info: GatewayMQTT: select_event: entity_id={}, value={}" .format (entity_id , value ))
12001205 serial = self ._serial_from_entity_id (entity_id )
1206+ if serial is None :
1207+ self .log (f"Warn: GatewayMQTT: select_event: cannot resolve serial for entity '{ entity_id } ' — command not sent" )
1208+ return
12011209 # Operating mode selector
12021210 if "_mode_select" in entity_id :
12031211 mode_int = GATEWAY_OPERATING_MODE_VALUES .get (str (value ).strip (), 0 )
1204- await self .publish_command ("set_mode" , mode = mode_int , ** ({ " serial" : serial } if serial else {}) )
1212+ await self .publish_command ("set_mode" , mode = mode_int , serial = serial )
12051213 self .log (f"Info: GatewayMQTT: Operating mode set to { value } ({ mode_int } )" )
12061214 return
12071215
@@ -1220,23 +1228,23 @@ async def select_event(self, entity_id, value):
12201228 # Read current charge slot times to send both start and end
12211229 await self ._update_charge_slot (entity_id , hhmm , serial = serial )
12221230
1223- async def _update_charge_slot (self , entity_id , hhmm , serial = None ):
1231+ async def _update_charge_slot (self , entity_id , hhmm , serial ):
12241232 """Send set_charge_slot command with updated start or end time."""
12251233 # Determine which field changed
12261234 if "_start" in entity_id :
12271235 schedule = {"start" : hhmm }
12281236 else :
12291237 schedule = {"end" : hhmm }
1230- await self .publish_command ("set_charge_slot" , schedule_json = json .dumps (schedule ), ** ({ " serial" : serial } if serial else {}) )
1238+ await self .publish_command ("set_charge_slot" , schedule_json = json .dumps (schedule ), serial = serial )
12311239 self .log (f"Info: GatewayMQTT: Charge slot update: { schedule } " )
12321240
1233- async def _update_discharge_slot (self , entity_id , hhmm , serial = None ):
1241+ async def _update_discharge_slot (self , entity_id , hhmm , serial ):
12341242 """Send set_discharge_slot command with updated start or end time."""
12351243 if "_start" in entity_id :
12361244 schedule = {"start" : hhmm }
12371245 else :
12381246 schedule = {"end" : hhmm }
1239- await self .publish_command ("set_discharge_slot" , schedule_json = json .dumps (schedule ), ** ({ " serial" : serial } if serial else {}) )
1247+ await self .publish_command ("set_discharge_slot" , schedule_json = json .dumps (schedule ), serial = serial )
12401248 self .log (f"Info: GatewayMQTT: Discharge slot update: { schedule } " )
12411249
12421250 async def number_event (self , entity_id , value ):
@@ -1255,15 +1263,17 @@ async def number_event(self, entity_id, value):
12551263 return
12561264
12571265 serial = self ._serial_from_entity_id (entity_id )
1258- serial_kwarg = {"serial" : serial } if serial else {}
1266+ if serial is None :
1267+ self .log (f"Warn: GatewayMQTT: number_event: cannot resolve serial for entity '{ entity_id } ' — command not sent" )
1268+ return
12591269 if "_discharge_rate" in entity_id :
1260- await self .publish_command ("set_discharge_rate" , power_w = val , ** serial_kwarg )
1270+ await self .publish_command ("set_discharge_rate" , power_w = val , serial = serial )
12611271 elif "_charge_rate" in entity_id :
1262- await self .publish_command ("set_charge_rate" , power_w = val , ** serial_kwarg )
1272+ await self .publish_command ("set_charge_rate" , power_w = val , serial = serial )
12631273 elif "_reserve" in entity_id :
1264- await self .publish_command ("set_reserve" , target_soc = val , ** serial_kwarg )
1274+ await self .publish_command ("set_reserve" , target_soc = val , serial = serial )
12651275 elif "_target_soc" in entity_id :
1266- await self .publish_command ("set_target_soc" , target_soc = val , ** serial_kwarg )
1276+ await self .publish_command ("set_target_soc" , target_soc = val , serial = serial )
12671277
12681278 async def switch_event (self , entity_id , service ):
12691279 """Handle switch entity service calls (charge/discharge enable).
@@ -1288,12 +1298,14 @@ async def switch_event(self, entity_id, service):
12881298 return
12891299
12901300 serial = self ._serial_from_entity_id (entity_id )
1291- serial_kwarg = {"serial" : serial } if serial else {}
1301+ if serial is None :
1302+ self .log (f"Warn: GatewayMQTT: switch_event: cannot resolve serial for entity '{ entity_id } ' — command not sent" )
1303+ return
12921304 if "_charge_enabled" in entity_id :
1293- await self .publish_command ("set_charge_enable" , enable = is_on , ** serial_kwarg )
1305+ await self .publish_command ("set_charge_enable" , enable = is_on , serial = serial )
12941306 self .log (f"Info: GatewayMQTT: Charge { 'enabled' if is_on else 'disabled' } " )
12951307 elif "_discharge_enabled" in entity_id :
1296- await self .publish_command ("set_discharge_enable" , enable = is_on , ** serial_kwarg )
1308+ await self .publish_command ("set_discharge_enable" , enable = is_on , serial = serial )
12971309 self .log (f"Info: GatewayMQTT: Discharge { 'enabled' if is_on else 'disabled' } " )
12981310
12991311 async def final (self ):
@@ -1578,7 +1590,7 @@ def build_command(command, **kwargs):
15781590 """
15791591 cmd = {
15801592 "command" : command ,
1581- "command_id" : str (uuid . uuid4 ( )),
1593+ "command_id" : "PBAT" + str (kwargs . get ( "command_id" , 0 )),
15821594 }
15831595
15841596 if "mode" in kwargs :
@@ -1592,6 +1604,6 @@ def build_command(command, **kwargs):
15921604 if "enable" in kwargs :
15931605 cmd ["enable" ] = bool (kwargs ["enable" ])
15941606 if "serial" in kwargs :
1595- cmd ["serial " ] = kwargs ["serial" ]
1607+ cmd ["dongle_serial " ] = kwargs ["serial" ]
15961608
15971609 return json .dumps (cmd )
0 commit comments