Add xiaomi scale + dynamic requirements support
This commit is contained in:
+3
-5
@@ -4,8 +4,6 @@ from workers_manager import WorkersManager
|
|||||||
|
|
||||||
mqtt = MqttClient(settings['mqtt'])
|
mqtt = MqttClient(settings['mqtt'])
|
||||||
|
|
||||||
workers = WorkersManager(settings['workers'])
|
manager = WorkersManager(settings['workers'])
|
||||||
mqtt.publish(workers.get_updates())
|
for worker_name in manager.workers.keys():
|
||||||
|
mqtt.publish(manager.update(worker_name))
|
||||||
# args = settings['workers']['thermostat']['args']
|
|
||||||
# mqtt.publish(ThermostatWorker(**args).status_update())
|
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
paho-mqtt
|
paho-mqtt
|
||||||
python-eq3bt
|
|
||||||
pyyaml
|
pyyaml
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
import time
|
||||||
|
|
||||||
|
REQUIREMENTS = ['bluepy', 'interruptingcow']
|
||||||
|
|
||||||
|
class MiscaleWorker():
|
||||||
|
def __init__(self, mac):
|
||||||
|
self._mac = mac
|
||||||
|
|
||||||
|
def status_update(self):
|
||||||
|
return [{
|
||||||
|
'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)
|
||||||
|
scanner.scan(5, passive=True)
|
||||||
|
|
||||||
|
with timeout(5):
|
||||||
|
while scan_processor.weight is None:
|
||||||
|
time.sleep(1)
|
||||||
|
return scan_processor.weight
|
||||||
|
|
||||||
|
return -1
|
||||||
|
|
||||||
|
class ScanProcessor():
|
||||||
|
def __init__(self, mac):
|
||||||
|
self._mac = mac
|
||||||
|
self._weight = None
|
||||||
|
|
||||||
|
def handleDiscovery(self, dev, isNewDev, _):
|
||||||
|
if dev.addr == self.mac.lower() and isNewDev:
|
||||||
|
for (sdid, desc, data) in dev.getScanData():
|
||||||
|
if data.startswith('1d18') and sdid == 22:
|
||||||
|
measured = int((data[8:10] + data[6:8]), 16) * 0.01
|
||||||
|
|
||||||
|
self._weight = round(measured / 2, 2)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mac(self):
|
||||||
|
return self._mac
|
||||||
|
|
||||||
|
@property
|
||||||
|
def weight(self):
|
||||||
|
return self._weight
|
||||||
+13
-16
@@ -1,22 +1,23 @@
|
|||||||
from eq3bt import Thermostat, Mode
|
REQUIREMENTS = ['python-eq3bt']
|
||||||
|
|
||||||
haModesMapping = {
|
monitoredAttrs = ["low_battery", "valve_state", "target_temperature"]
|
||||||
|
|
||||||
|
class ThermostatWorker:
|
||||||
|
def __init__(self, devices=None):
|
||||||
|
self._devices = devices
|
||||||
|
|
||||||
|
def status_update(self):
|
||||||
|
from eq3bt import Thermostat, Mode
|
||||||
|
|
||||||
|
haModesMapping = {
|
||||||
Mode.Closed: 'off',
|
Mode.Closed: 'off',
|
||||||
Mode.Open: 'on',
|
Mode.Open: 'on',
|
||||||
Mode.Auto: 'auto',
|
Mode.Auto: 'auto',
|
||||||
Mode.Manual: 'manual',
|
Mode.Manual: 'manual',
|
||||||
Mode.Away: 'away',
|
Mode.Away: 'away',
|
||||||
Mode.Boost: 'boost',
|
Mode.Boost: 'boost',
|
||||||
}
|
}
|
||||||
|
|
||||||
monitoredAttrs = ["low_battery", "valve_state", "target_temperature"]
|
|
||||||
|
|
||||||
class ThermostatWorker:
|
|
||||||
def __init__(self, devices=None, topic_prefix=None):
|
|
||||||
self._devices = devices
|
|
||||||
self._topic_prefix = topic_prefix
|
|
||||||
|
|
||||||
def status_update(self):
|
|
||||||
ret = []
|
ret = []
|
||||||
for name, mac in self.devices.items():
|
for name, mac in self.devices.items():
|
||||||
thermostat = Thermostat(mac)
|
thermostat = Thermostat(mac)
|
||||||
@@ -44,9 +45,5 @@ class ThermostatWorker:
|
|||||||
def devices(self):
|
def devices(self):
|
||||||
return self._devices
|
return self._devices
|
||||||
|
|
||||||
@property
|
|
||||||
def topic_prefix(self):
|
|
||||||
return self._topic_prefix
|
|
||||||
|
|
||||||
def format_topic(self, device, attr):
|
def format_topic(self, device, attr):
|
||||||
return '/'.join([self.topic_prefix, device, attr])
|
return '/'.join([device, attr])
|
||||||
|
|||||||
+21
-8
@@ -1,24 +1,37 @@
|
|||||||
import importlib
|
import importlib
|
||||||
|
import pip
|
||||||
|
|
||||||
class WorkersManager:
|
class WorkersManager:
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self._config = config
|
self._config = config
|
||||||
self._workers = self._register_klasses()
|
self._workers = self._register_klasses()
|
||||||
|
|
||||||
def get_updates(self):
|
def update(self, worker_name):
|
||||||
lazy_map = map(lambda worker: worker.status_update(), self._workers)
|
messages = self.workers[worker_name].status_update()
|
||||||
flat_list = sum(lazy_map, []) # List flatten
|
for message in messages:
|
||||||
return flat_list
|
message['topic'] = '/'.join([self._config[worker_name]['topic_prefix'], message['topic']])
|
||||||
|
|
||||||
|
return messages
|
||||||
|
|
||||||
|
@property
|
||||||
|
def workers(self):
|
||||||
|
return self._workers
|
||||||
|
|
||||||
def _register_klasses(self):
|
def _register_klasses(self):
|
||||||
arr = []
|
arr = {}
|
||||||
|
|
||||||
for worker_klass in self._config.keys():
|
for worker_klass in self._config.keys():
|
||||||
klass = getattr(importlib.import_module("workers.%s" % worker_klass), "%sWorker" % worker_klass.title())
|
moduleObj = importlib.import_module("workers.%s" % worker_klass)
|
||||||
arr.append(klass(**self._args_for(worker_klass)))
|
klass = getattr(moduleObj, "%sWorker" % worker_klass.title())
|
||||||
|
if moduleObj.REQUIREMENTS is not None:
|
||||||
|
self._pip_install_helper(moduleObj.REQUIREMENTS)
|
||||||
|
arr[worker_klass] = klass(**self._args_for(worker_klass))
|
||||||
|
|
||||||
return arr
|
return arr
|
||||||
|
|
||||||
def _args_for(self, klass):
|
def _args_for(self, klass):
|
||||||
return self._config[klass]['args']
|
return self._config[klass]['args']
|
||||||
|
|
||||||
|
def _pip_install_helper(self, package_names):
|
||||||
|
for package in package_names:
|
||||||
|
pip.main(['install','-q', package])
|
||||||
|
|||||||
Reference in New Issue
Block a user