52 lines
1.7 KiB
Python
52 lines
1.7 KiB
Python
from __future__ import annotations
|
|||
|
|
|
||
|
|
import logging
|
||
|
|
import threading
|
||
|
|
import time
|
||
|
|
|
||
|
|
from .data import extract_samples
|
||
|
|
|
||
|
|
LOG = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
|
||
|
|
class Collector:
|
||
|
|
def __init__(self, client, store, module_names: dict[str, str], interval: int = 600):
|
||
|
|
self.client = client
|
||
|
|
self.store = store
|
||
|
|
self.module_names = module_names
|
||
|
|
self.interval = interval
|
||
|
|
self._stop = threading.Event()
|
||
|
|
self._thread: threading.Thread | None = None
|
||
|
|
|
||
|
|
def collect_once(self) -> int:
|
||
|
|
samples = extract_samples(self.client.stations_data(), self.module_names)
|
||
|
|
for name, sample in samples.items():
|
||
|
|
try:
|
||
|
|
self.store.update(name, sample)
|
||
|
|
except Exception:
|
||
|
|
# One stale/duplicate module must not discard the other modules.
|
||
|
|
LOG.exception("Could not update %s RRD", name)
|
||
|
|
LOG.info("Collected %d Netatmo modules", len(samples))
|
||
|
|
return len(samples)
|
||
|
|
|
||
|
|
def start(self) -> None:
|
||
|
|
if self._thread and self._thread.is_alive():
|
||
|
|
return
|
||
|
|
self._thread = threading.Thread(target=self._loop, name="netatmo-collector", daemon=True)
|
||
|
|
self._thread.start()
|
||
|
|
|
||
|
|
def stop(self) -> None:
|
||
|
|
self._stop.set()
|
||
|
|
|
||
|
|
def _loop(self) -> None:
|
||
|
|
# Collect immediately, then align roughly to the configured cadence.
|
||
|
|
while not self._stop.is_set():
|
||
|
|
started = time.monotonic()
|
||
|
|
try:
|
||
|
|
self.collect_once()
|
||
|
|
except Exception:
|
||
|
|
LOG.exception("Netatmo collection failed")
|
||
|
|
remaining = max(1, self.interval - (time.monotonic() - started))
|
||
|
|
self._stop.wait(remaining)
|
||
|
|
|