Skip to content

Commit

Permalink
feat: add connection monitoring and reconnect logic
Browse files Browse the repository at this point in the history
  • Loading branch information
EuleMitKeule committed Jan 22, 2024
1 parent 9ef6517 commit 077883d
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 16 deletions.
29 changes: 29 additions & 0 deletions custom_components/eq3btsmart/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
ENTITY_NAME_BUSY,
ENTITY_NAME_CONNECTED,
ENTITY_NAME_DST,
ENTITY_NAME_MONITORING,
ENTITY_NAME_WINDOW_OPEN,
)

Expand All @@ -45,6 +46,7 @@ async def async_setup_entry(
entities_to_add += [
BusySensor(eq3_config, thermostat),
ConnectedSensor(eq3_config, thermostat),
MonitoringSensor(eq3_config, thermostat),
]

async_add_entities(entities_to_add)
Expand Down Expand Up @@ -114,6 +116,33 @@ def is_on(self) -> bool:
return self._thermostat._conn.is_connected


class MonitoringSensor(Base):
"""Binary sensor that reports if the thermostat connection monitor is running."""

def __init__(self, eq3_config: Eq3Config, thermostat: Thermostat):
super().__init__(eq3_config, thermostat)

self._thermostat.register_connection_callback(self.schedule_update_ha_state)
self._attr_entity_category = EntityCategory.DIAGNOSTIC
self._attr_name = ENTITY_NAME_MONITORING
self._attr_device_class = BinarySensorDeviceClass.RUNNING

# @property
# def extra_state_attributes(self) -> dict[str, str] | None:
# if (device := self._thermostat._conn._device) is None:
# return None
# if (details := device.details) is None:
# return None
# if "props" not in details:
# return None

# return json.loads(json.dumps(details["props"], default=lambda obj: None))

@property
def is_on(self) -> bool:
return self._thermostat._monitor._run


class BatterySensor(Base):
"""Binary sensor that reports if the thermostat battery is low."""

Expand Down
1 change: 1 addition & 0 deletions custom_components/eq3btsmart/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class Preset(str, Enum):
ENTITY_NAME_AWAY_SWITCH = "Away"
ENTITY_NAME_BOOST_SWITCH = "Boost"
ENTITY_NAME_CONNECTION = "Connection"
ENTITY_NAME_MONITORING = "Monitoring"

ENTITY_ICON_VALVE = "mdi:pipe-valve"
ENTITY_ICON_AWAY_SWITCH = "mdi:lock"
Expand Down
16 changes: 0 additions & 16 deletions custom_components/eq3btsmart/eq3_coordinator.py

This file was deleted.

24 changes: 24 additions & 0 deletions eq3btsmart/eq3_connection_monitor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import asyncio

from bleak import BleakClient


class Eq3ConnectionMonitor:
def __init__(self, client: BleakClient):
self._client = client
self._run = False

async def run(self):
self._run = True

while self._run:
try:
if not self._client.is_connected:
await self._client.connect()
except Exception:
pass

await asyncio.sleep(5)

async def stop(self):
self._run = False
6 changes: 6 additions & 0 deletions eq3btsmart/thermostat.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
WeekDay,
)
from eq3btsmart.eq3_away_time import Eq3AwayTime
from eq3btsmart.eq3_connection_monitor import Eq3ConnectionMonitor
from eq3btsmart.eq3_duration import Eq3Duration
from eq3btsmart.eq3_temperature import Eq3Temperature
from eq3btsmart.eq3_temperature_offset import Eq3TemperatureOffset
Expand Down Expand Up @@ -84,6 +85,7 @@ def __init__(
timeout=REQUEST_TIMEOUT,
)
self._lock = asyncio.Lock()
self._monitor = Eq3ConnectionMonitor(self._conn)

def register_connection_callback(self, on_connect: Callable) -> None:
"""Register a callback function that will be called when a connection is established."""
Expand All @@ -101,9 +103,13 @@ async def async_connect(self) -> None:
await self._conn.connect()
await self._conn.start_notify(PROP_NOTIFY_UUID, self.on_notification)

loop = asyncio.get_running_loop()
loop.create_task(self._monitor.run())

async def async_disconnect(self) -> None:
"""Shutdown the connection to the thermostat."""

await self._monitor.stop()
await self._conn.disconnect()

async def async_get_id(self) -> None:
Expand Down

0 comments on commit 077883d

Please sign in to comment.