Skip to content

Commit d73e84e

Browse files
committed
#292: Refactor publish HA discovery on HA reconnection to enable future supporto for global commands
1 parent 881939b commit d73e84e

File tree

7 files changed

+38
-22
lines changed

7 files changed

+38
-22
lines changed

configuration/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,7 @@ def is_mqtt_enabled(self) -> bool:
5757
@property
5858
def username_is_email(self):
5959
return '@' in self.saic_user
60+
61+
@property
62+
def ha_lwt_topic(self) -> str:
63+
return f'{self.ha_discovery_prefix}/status'

handlers/vehicle.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ def __init__(
4747
True
4848
)
4949
self.vehicle_state = vehicle_state
50-
self.ha_discovery = HomeAssistantDiscovery(vehicle_state, vin_info, config)
50+
if self.configuration.ha_discovery_enabled:
51+
self.__ha_discovery = HomeAssistantDiscovery(vehicle_state, vin_info, config)
52+
else:
53+
self.__ha_discovery = None
5154

5255
self.__setup_abrp(config, vin_info)
5356
self.__setup_osmand(config, vin_info)
@@ -114,8 +117,7 @@ async def handle_vehicle(self) -> None:
114117
exc_info=e
115118
)
116119
finally:
117-
if self.configuration.ha_discovery_enabled:
118-
self.ha_discovery.publish_ha_discovery_messages()
120+
self.publish_ha_discovery_messages(force=False)
119121
else:
120122
# car not active, wait a second
121123
await asyncio.sleep(1.0)
@@ -176,9 +178,10 @@ async def __refresh_abrp(self, charge_status, vehicle_status):
176178
else:
177179
LOG.info(f'ABRP not refreshed, reason {abrp_response}')
178180

179-
async def publish_ha_discovery_messages(self, force=False):
180-
LOG.info(f'Sending HA discovery messages for {self.vin_info.vin} (Force: {force})')
181-
self.ha_discovery.publish_ha_discovery_messages(force)
181+
def publish_ha_discovery_messages(self, *, force=False):
182+
if self.__ha_discovery is not None:
183+
LOG.info(f'Sending HA discovery messages for {self.vin_info.vin} (Force: {force})')
184+
self.__ha_discovery.publish_ha_discovery_messages(force=force)
182185

183186
async def update_vehicle_status(self) -> VehicleStatusResp:
184187
LOG.info('Updating vehicle status')

integrations/home_assistant/discovery.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,15 @@ def __init__(self, vehicle_state: VehicleState, vin_info: VinInfo, configuration
9696
)
9797
self.published = False
9898

99-
def publish_ha_discovery_messages(self, force=False):
100-
if self.published and not force:
101-
LOG.debug("Skipping Home Assistant discovery messages as it was already published")
102-
return
103-
99+
def publish_ha_discovery_messages(self, *, force: bool = False):
104100
if not self.__vehicle_state.is_complete():
105-
LOG.debug("Skipping Home Assistant discovery messages as vehicle state is not yet complete")
101+
LOG.warning("Skipping Home Assistant discovery messages as vehicle state is not yet complete")
106102
return
107103

104+
if self.published and not force:
105+
LOG.debug("Skipping Home Assistant discovery messages as it was already published")
106+
return
107+
108108
self.__publish_ha_discovery_messages_real()
109109
self.published = True
110110

mqtt_gateway.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,15 @@ async def on_charging_detected(self, vin: str) -> None:
179179
LOG.debug(f'Charging detected for unknown vin {vin}')
180180

181181
@override
182-
async def on_homeassistant_got_online_received(self) -> None:
183-
# we only receive this if we subscribed to this topic => resend
184-
for (key, vh) in self.vehicle_handlers.items():
185-
LOG.debug(f'Send HomeAssistant discovery for car {key}')
186-
vh.publish_ha_discovery_messages(True)
182+
async def on_mqtt_global_command_received(self, *, topic: str, payload: str):
183+
match topic:
184+
case self.configuration.ha_lwt_topic:
185+
if payload == 'online':
186+
for (vin, vh) in self.vehicle_handlers.items():
187+
LOG.debug(f'Send HomeAssistant discovery for car {vin}')
188+
vh.publish_ha_discovery_messages(force=True)
189+
case _:
190+
LOG.warning(f'Received unknown global command {topic}: {payload}')
187191

188192
def __on_publish_raw_value(self, key: str, raw: str):
189193
self.publisher.publish_str(key, raw)

publisher/core.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88

99
INVALID_MQTT_CHARS = re.compile(r'[+#*$>]')
1010

11+
1112
class MqttCommandListener(ABC):
1213
async def on_mqtt_command_received(self, *, vin: str, topic: str, payload: str) -> None:
1314
raise NotImplementedError("Should have implemented this")
1415

1516
async def on_charging_detected(self, vin: str) -> None:
1617
raise NotImplementedError("Should have implemented this")
1718

18-
async def on_homeassistant_got_online_received(self) -> None:
19+
async def on_mqtt_global_command_received(self, *, topic: str, payload: str):
1920
raise NotImplementedError("Should have implemented this")
2021

2122

publisher/mqtt_publisher.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def __on_connect(self, _client, _flags, rc, _properties) -> None:
8585
self.client.subscribe(charging_station.connected_topic)
8686
if self.configuration.ha_discovery_enabled:
8787
# enable dynamic discovery pushing in case ha reconnects
88-
self.client.subscibe(f'{self.configuration.ha_discovery_prefix}/status')
88+
self.client.subscribe(self.configuration.ha_lwt_topic)
8989
self.keepalive()
9090
else:
9191
if rc == gmqtt.constants.CONNACK_REFUSED_BAD_USERNAME_PASSWORD:
@@ -123,9 +123,9 @@ async def __on_message_real(self, *, topic: str, payload: str) -> None:
123123
LOG.debug(f'Vehicle with vin {vin} is connected to its charging station')
124124
else:
125125
LOG.debug(f'Vehicle with vin {vin} is disconnected from its charging station')
126-
elif topic == f'{self.configuration.ha_discovery_prefix}/status' and payload == "online":
127-
LOG.debug('HomeAssistant restarted. Send discovery payload')
128-
self.command_listener.on_homeassistant_got_online_received()
126+
elif topic == self.configuration.ha_lwt_topic:
127+
if self.command_listener is not None:
128+
await self.command_listener.on_mqtt_global_command_received(topic=topic, payload=payload)
129129
else:
130130
vin = self.get_vin_from_topic(topic)
131131
if self.command_listener is not None:

tests/test_mqtt_publisher.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@
1414

1515

1616
class TestMqttPublisher(unittest.IsolatedAsyncioTestCase, MqttCommandListener):
17+
@override
18+
async def on_mqtt_global_command_received(self, *, topic: str, payload: str):
19+
pass
20+
1721
@override
1822
async def on_mqtt_command_received(self, *, vin: str, topic: str, payload: str) -> None:
1923
self.received_vin = vin

0 commit comments

Comments
 (0)