Add optional Home Assistant integration for battery percentage tracking
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import logging
|
||||
import threading
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class HaPoller:
|
||||
"""Background daemon thread that periodically polls Home Assistant
|
||||
for battery percentages and updates installed batteries in the DB.
|
||||
|
||||
Lifecycle:
|
||||
poller = HaPoller(ha_client, session_factory, interval_seconds)
|
||||
poller.start() # called once from create_app
|
||||
poller.stop() # not normally needed; daemon thread exits with the process
|
||||
"""
|
||||
|
||||
def __init__(self, ha_client, session_factory, interval: int):
|
||||
self._client = ha_client
|
||||
self._Session = session_factory
|
||||
self._interval = interval
|
||||
self._stop = threading.Event()
|
||||
self._thread = threading.Thread(
|
||||
target=self._run, name="ha-poller", daemon=True
|
||||
)
|
||||
|
||||
def start(self):
|
||||
self._thread.start()
|
||||
logger.info("HA poller started (interval=%ds)", self._interval)
|
||||
|
||||
def stop(self):
|
||||
self._stop.set()
|
||||
|
||||
def _run(self):
|
||||
# Wait first so startup DB activity settles before the first poll
|
||||
while not self._stop.wait(self._interval):
|
||||
self._poll_once()
|
||||
|
||||
def _poll_once(self):
|
||||
from models import Battery, Device # local import avoids circular-import risk
|
||||
|
||||
session = self._Session()
|
||||
try:
|
||||
devices = (
|
||||
session.query(Device)
|
||||
.filter(Device.ha_entity_id.isnot(None))
|
||||
.all()
|
||||
)
|
||||
for device in devices:
|
||||
pct = self._client.get_state(device.ha_entity_id)
|
||||
if pct is not None:
|
||||
for battery in device.batteries:
|
||||
if battery.status == "installed":
|
||||
battery.battery_percentage = pct
|
||||
session.commit()
|
||||
logger.debug("HA poll complete (%d devices checked)", len(devices))
|
||||
except Exception as exc:
|
||||
session.rollback()
|
||||
logger.warning("HA poll failed: %s", exc)
|
||||
finally:
|
||||
session.close()
|
||||
Reference in New Issue
Block a user