From d46334570785dfcc00720e6b1002d5d050d8513a Mon Sep 17 00:00:00 2001 From: zewelor Date: Fri, 24 Nov 2017 07:30:42 +0100 Subject: [PATCH] Add basic cron support --- config.yaml.example | 3 ++- gateway.py | 24 +++++++++++++++++++++--- requirements.txt | 2 ++ workers/miscale.py | 6 +++--- workers/thermostat.py | 2 +- workers_manager.py | 19 ++++++++++++++++--- 6 files changed, 45 insertions(+), 11 deletions(-) diff --git a/config.yaml.example b/config.yaml.example index 3909ca0..2b34739 100644 --- a/config.yaml.example +++ b/config.yaml.example @@ -7,4 +7,5 @@ workers: args: devices: bedroom: 00:11:22:33:44:55 - topic_prefix: thermostats \ No newline at end of file + topic_prefix: thermostats + update_interval: 60 diff --git a/gateway.py b/gateway.py index 7ddd864..8edb2bb 100644 --- a/gateway.py +++ b/gateway.py @@ -1,9 +1,27 @@ +from queue import Queue + +from apscheduler.schedulers.background import BackgroundScheduler + from config import settings from mqtt import MqttClient from workers_manager import WorkersManager +queue = Queue() +scheduler = BackgroundScheduler() mqtt = MqttClient(settings['mqtt']) - manager = WorkersManager(settings['workers']) -for worker_name in manager.workers.keys(): - mqtt.publish(manager.update(worker_name)) + +for worker_name, interval in manager.interval_enabled_workers.items(): + queue.put([worker_name]) + scheduler.add_job(lambda x: queue.put([x]), 'interval', seconds=interval, args=[worker_name]) + +scheduler.start() + +while True: + for worker_name in queue.get(block=True): + try: + mqtt.publish(manager.update(worker_name)) + except (KeyboardInterrupt, SystemExit): + raise + except: + print('Some error') diff --git a/requirements.txt b/requirements.txt index fd3e4f3..1d19bdf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,4 @@ paho-mqtt pyyaml +interruptingcow +apscheduler diff --git a/workers/miscale.py b/workers/miscale.py index 75cbad1..94192e3 100644 --- a/workers/miscale.py +++ b/workers/miscale.py @@ -1,8 +1,9 @@ import time +from interruptingcow import timeout from mqtt import MqttMessage -REQUIREMENTS = ['bluepy', 'interruptingcow'] +REQUIREMENTS = ['bluepy'] # Bluepy might need special settings # sudo setcap 'cap_net_raw,cap_net_admin+eip' /usr/local/lib/python3.6/dist-packages/bluepy/bluepy-helper @@ -12,11 +13,10 @@ class MiscaleWorker(): self._mac = mac def status_update(self): - return [MqttMessage(topic='weight/kg', payload= self._get_weight())] + return [MqttMessage(topic='weight/kg', payload=self._get_weight())] def _get_weight(self): from bluepy import btle - from interruptingcow import timeout scan_processor = ScanProcessor(self._mac) scanner = btle.Scanner().withDelegate(scan_processor) diff --git a/workers/thermostat.py b/workers/thermostat.py index a8ae016..fea79c3 100644 --- a/workers/thermostat.py +++ b/workers/thermostat.py @@ -5,7 +5,7 @@ REQUIREMENTS = ['python-eq3bt'] monitoredAttrs = ["low_battery", "valve_state", "target_temperature"] class ThermostatWorker: - def __init__(self, devices=None): + def __init__(self, devices): self._devices = devices def status_update(self): diff --git a/workers_manager.py b/workers_manager.py index 1315fd9..dd7b2a1 100644 --- a/workers_manager.py +++ b/workers_manager.py @@ -1,15 +1,19 @@ import importlib import pip +from interruptingcow import timeout class WorkersManager: def __init__(self, config): self._config = config + self._interval_enabled_workers = {} self._workers = self._register_klasses() def update(self, worker_name): - messages = self.workers[worker_name].status_update() - for message in messages: - message.topic = '/'.join([self._config[worker_name]['topic_prefix'], message.topic]) + messages = [] + with timeout(30): + messages = self.workers[worker_name].status_update() + for message in messages: + message.topic = '/'.join([self._config[worker_name]['topic_prefix'], message.topic]) return messages @@ -17,14 +21,23 @@ class WorkersManager: def workers(self): return self._workers + @property + def interval_enabled_workers(self): + return self._interval_enabled_workers + def _register_klasses(self): arr = {} for worker_klass in self._config.keys(): moduleObj = importlib.import_module("workers.%s" % worker_klass) klass = getattr(moduleObj, "%sWorker" % worker_klass.title()) + if moduleObj.REQUIREMENTS is not None: self._pip_install_helper(moduleObj.REQUIREMENTS) + + if self._config[worker_klass]['update_interval'] is not None: + self._interval_enabled_workers[worker_klass] = self._config[worker_klass]['update_interval'] + arr[worker_klass] = klass(**self._args_for(worker_klass)) return arr