Skip to content

Commit da0208e

Browse files
authored
fix(mqtt): reconnect after dropped broker connection (#787)
1 parent 11450d7 commit da0208e

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

custom_components/ecoflow_cloud/api/__init__.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import logging
2+
import time
23
from abc import ABC, abstractmethod
34
from typing import Any
45

@@ -31,6 +32,8 @@ def __init__(self):
3132
self.mqtt_info: EcoflowMqttInfo
3233
self.devices: dict[str, Any] = {}
3334
self.mqtt_client: EcoflowMQTTClient
35+
self._mqtt_reconnect_last_attempt = 0.0
36+
self._mqtt_reconnect_count = 0
3437

3538
@abstractmethod
3639
async def login(self):
@@ -133,6 +136,22 @@ def start(self):
133136

134137
self.mqtt_client = EcoflowMQTTClient(self.mqtt_info, self.devices)
135138

139+
def schedule_mqtt_reconnect(self, cooldown_sec: int = 60) -> int | None:
140+
if self.mqtt_client.is_connected():
141+
return None
142+
143+
now = time.monotonic()
144+
if now - self._mqtt_reconnect_last_attempt < cooldown_sec:
145+
return None
146+
147+
self._mqtt_reconnect_last_attempt = now
148+
self._mqtt_reconnect_count += 1
149+
return self._mqtt_reconnect_count
150+
151+
@property
152+
def mqtt_reconnect_count(self) -> int:
153+
return self._mqtt_reconnect_count
154+
136155
def stop(self):
137156
_LOGGER.debug("Stopping MQTT client for %s", self.mqtt_info.client_id)
138157
assert self.mqtt_client is not None

custom_components/ecoflow_cloud/sensor.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
ATTR_DATA_UPDATES,
3939
ATTR_MQTT_CONNECTED,
4040
ATTR_QUOTA_REQUESTS,
41+
ATTR_STATUS_RECONNECTS,
4142
ATTR_STATUS_DATA_LAST_UPDATE,
4243
ATTR_STATUS_LAST_UPDATE,
4344
ATTR_STATUS_SN,
@@ -503,6 +504,7 @@ def __init__(
503504
self._attrs[ATTR_STATUS_SN] = self._device.device_info.sn
504505
self._attrs[ATTR_STATUS_DATA_LAST_UPDATE] = None
505506
self._attrs[ATTR_MQTT_CONNECTED] = None
507+
self._attrs[ATTR_STATUS_RECONNECTS] = 0
506508
if poll_when_silent or scheduled_refresh_sec is not None:
507509
self._attrs[ATTR_QUOTA_REQUESTS] = 0
508510

@@ -512,6 +514,9 @@ def _handle_coordinator_update(self) -> None:
512514
status = self._tracker.status
513515
changed = status != self._prev_status
514516

517+
if self._schedule_mqtt_reconnect():
518+
changed = True
519+
515520
# Active polling when device goes silent
516521
if self._poll_when_silent and status == OnlineStatus.ASSUME_OFFLINE:
517522
if (dt.utcnow() - self._last_poll).total_seconds() >= self._tracker.assume_offline_sec:
@@ -543,6 +548,21 @@ def _handle_coordinator_update(self) -> None:
543548
self._actualize_attributes()
544549
self.schedule_update_ha_state()
545550

551+
def _schedule_mqtt_reconnect(self) -> bool:
552+
reconnect_count = self._client.schedule_mqtt_reconnect()
553+
if reconnect_count is None:
554+
return False
555+
556+
self._attrs[ATTR_STATUS_RECONNECTS] = reconnect_count
557+
self.hass.async_create_background_task(
558+
self._async_reconnect_mqtt(),
559+
f"reconnect ecoflow mqtt {self._device.device_info.sn}",
560+
)
561+
return True
562+
563+
async def _async_reconnect_mqtt(self) -> None:
564+
await self.hass.async_add_executor_job(self._client.mqtt_client.reconnect)
565+
546566
def _format_age(self, timestamp: datetime | None) -> str | None:
547567
if timestamp is None:
548568
return None
@@ -558,6 +578,7 @@ def _actualize_attributes(self):
558578
self._attrs[ATTR_STATUS_UPDATES] = self._tracker._explicit_status_count
559579
self._attrs[ATTR_DATA_UPDATES] = self._tracker._data_received_count
560580
self._attrs[ATTR_MQTT_CONNECTED] = self._client.mqtt_client.is_connected()
581+
self._attrs[ATTR_STATUS_RECONNECTS] = self._client.mqtt_reconnect_count
561582

562583
@property
563584
def extra_state_attributes(self) -> Mapping[str, Any] | None:

0 commit comments

Comments
 (0)