support for xiaomi aqara thermometer and few other fixes (#18)
* import pip._internal.main to work with pip version > 10 * make auth optional and add support for an optional port * add worker for xiaomi aqara thermometer * add support for optional global publishing topic_prefix * Update config.yaml.example
This commit is contained in:
@@ -1,2 +1,3 @@
|
||||
config.yaml
|
||||
__pycache__/
|
||||
.idea/
|
||||
|
||||
@@ -20,6 +20,7 @@ See [Wiki](https://github.com/zewelor/bt-mqtt-gateway/wiki) for more information
|
||||
* [Linak Desk](https://www.linak.com/business-areas/desks/office-desks/) via [linak_bt_desk](https://github.com/zewelor/linak_bt_desk)
|
||||
* [MySensors](https://www.mysensors.org/)
|
||||
* [Xiaomi Mi Flora plant sensor](https://xiaomi-mi.com/sockets-and-sensors/xiaomi-huahuacaocao-flower-care-smart-monitor/) via [miflora](https://github.com/open-homeautomation/miflora)
|
||||
* Xiaomi Aqara thermometer via [mithermometer](https://github.com/hobbypunk90/mithermometer)
|
||||
|
||||
## Getting Started
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
mqtt:
|
||||
host: 192.168.1.1
|
||||
port: 1883
|
||||
username: user
|
||||
password: password
|
||||
topic_prefix: hostname
|
||||
|
||||
manager:
|
||||
topic_subscription:
|
||||
@@ -38,3 +40,9 @@ manager:
|
||||
topic_prefix: miflora
|
||||
update_interval: 300
|
||||
|
||||
mithermometer:
|
||||
args:
|
||||
devices:
|
||||
living_room: 00:11:22:33:44:55
|
||||
topic_prefix: mithermometer
|
||||
update_interval: 300
|
||||
|
||||
@@ -6,34 +6,53 @@ class MqttClient:
|
||||
def __init__(self, config):
|
||||
self._config = config
|
||||
self._mqttc = mqtt.Client(client_id='bt-mqtt-gateway', clean_session=False)
|
||||
|
||||
if self.username is not None and self.password is not None:
|
||||
self._auth = {'username': self.username, 'password': self.password}
|
||||
else:
|
||||
self._auth = None
|
||||
|
||||
def publish(self, messages):
|
||||
if messages is None:
|
||||
if messages is None or len(messages) == 0:
|
||||
return
|
||||
|
||||
|
||||
if self.topic_prefix is not None:
|
||||
for m in messages:
|
||||
m.topic = "{}/{}".format(self.topic_prefix, m.topic)
|
||||
|
||||
publish.multiple(list(map(lambda m: m.as_dict, messages)),
|
||||
hostname=self.hostname,
|
||||
auth={'username': self.username, 'password': self.password})
|
||||
port=self.port,
|
||||
auth=self._auth)
|
||||
|
||||
@property
|
||||
def hostname(self):
|
||||
return self._config['host']
|
||||
|
||||
@property
|
||||
def port(self):
|
||||
return self._config['port'] if 'port' in self._config else 1883
|
||||
|
||||
@property
|
||||
def username(self):
|
||||
return self._config['username']
|
||||
return self._config['username'] if 'username' in self._config else None
|
||||
|
||||
@property
|
||||
def password(self):
|
||||
return self._config['password']
|
||||
return self._config['password'] if 'password' in self._config else None
|
||||
|
||||
@property
|
||||
def topic_prefix(self):
|
||||
return self._config['topic_prefix'] if 'topic_prefix' in self._config else None
|
||||
|
||||
@property
|
||||
def mqttc(self):
|
||||
return self._mqttc
|
||||
|
||||
def callbacks_subscription(self, callbacks):
|
||||
self.mqttc.username_pw_set(self.username, self.password)
|
||||
self.mqttc.connect(self.hostname)
|
||||
if self.username is not None and self.password is not None:
|
||||
self.mqttc.username_pw_set(self.username, self.password)
|
||||
self.mqttc.connect(self.hostname, port=self.port)
|
||||
|
||||
for topic, callback in callbacks:
|
||||
self.mqttc.message_callback_add(topic, callback)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
from interruptingcow import timeout
|
||||
from mqtt import MqttMessage
|
||||
from workers.base import BaseWorker
|
||||
|
||||
REQUIREMENTS = ['mithermometer']
|
||||
|
||||
monitoredAttrs = ["temperature", "humidity", "battery"]
|
||||
|
||||
class MithermometerWorker(BaseWorker):
|
||||
def _setup(self):
|
||||
from mithermometer.mithermometer_poller import MiThermometerPoller
|
||||
from btlewrap.bluepy import BluepyBackend
|
||||
|
||||
|
||||
for name, mac in self.devices.items():
|
||||
self.devices[name] = MiThermometerPoller(mac, BluepyBackend)
|
||||
|
||||
def status_update(self):
|
||||
ret = []
|
||||
for name, poller in self.devices.items():
|
||||
try:
|
||||
ret += self.update_device_state(name, poller)
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
return ret
|
||||
|
||||
@timeout(8.0)
|
||||
|
||||
def update_device_state(self, name, poller):
|
||||
|
||||
ret = []
|
||||
for attr in monitoredAttrs:
|
||||
|
||||
ret.append(MqttMessage(topic=self.format_topic(name, attr), payload=poller.parameter_value(attr)))
|
||||
|
||||
return ret
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import importlib
|
||||
import threading
|
||||
|
||||
import pip
|
||||
from pip._internal import main as pip_main
|
||||
from apscheduler.schedulers.background import BackgroundScheduler
|
||||
from interruptingcow import timeout
|
||||
from functools import partial
|
||||
@@ -95,7 +95,7 @@ class WorkersManager:
|
||||
@staticmethod
|
||||
def _pip_install_helper(package_names):
|
||||
for package in package_names:
|
||||
pip.main(['install', '-q', package])
|
||||
pip_main(['install', '-q', package])
|
||||
|
||||
def _on_command_wrapper(self, worker_obj, client, _, c):
|
||||
_LOGGER.debug("on command wrapper for with %s: %s", c.topic, c.payload)
|
||||
|
||||
Reference in New Issue
Block a user