Skip to content

Commit f1cff22

Browse files
Merge pull request #4087 from springfall2008/fix/gateway_serial
Fix bug with gateway serial not being set correctly
2 parents 2e1a9d7 + aeed2be commit f1cff22

4 files changed

Lines changed: 142 additions & 56 deletions

File tree

.cspell/custom-dictionary-workspace.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ openweathermap
274274
overfitting
275275
overvoltage
276276
ownerapi
277+
pbat
277278
pbgw
278279
pdata
279280
pdetails

apps/predbat/gateway.py

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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)

apps/predbat/predbat.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
import requests
3737
import asyncio
3838

39-
THIS_VERSION = "v8.40.11"
39+
THIS_VERSION = "v8.40.12"
4040

4141
from download import predbat_update_move, predbat_update_download, check_install, resolve_predbat_repository, DEFAULT_PREDBAT_REPOSITORY
4242
from const import MINUTE_WATT

0 commit comments

Comments
 (0)