from __future__ import annotations import json import logging import time import urllib.request from .config import Config from .events import error_event, status_event from .http import HttpFailure, request_json from .smartthings import SmartThingsClient, TokenManager LOG = logging.getLogger(__name__) class Poller: def __init__(self, config: Config): self.config = config tokens = TokenManager(config.client_id, config.client_secret, config.refresh_token, config.access_token, config.token_file, config.request_timeout_seconds) self.client = SmartThingsClient(config.api_base_url, config.device_id, tokens, config.request_timeout_seconds) def poll_once(self) -> dict: try: event = status_event(self.config, self.client.get_status()) except Exception as error: event = error_event(self.config, error) self.publish(event) return event def publish(self, event: dict) -> None: data = json.dumps(event, ensure_ascii=False, separators=(",", ":")).encode() request = urllib.request.Request(self.config.redpanda_url, data=data, method="POST", headers={"Content-Type": "application/json", "Accept": "application/json"}) try: request_json(request, self.config.redpanda_timeout_seconds) except HttpFailure: LOG.exception("Could not publish event to Redpanda Connect") raise def run(self) -> None: while True: started = time.monotonic() try: event = self.poll_once() LOG.log(logging.WARNING if event["level"] != "info" else logging.INFO, "Poll result: %s", event["status"]) except Exception: LOG.exception("Poll cycle failed") time.sleep(max(0, self.config.interval_seconds - (time.monotonic() - started)))