Added support for Switchbot (#60)

* Added worker for Switchbot

* config.yaml example for switchbot
This commit is contained in:
AS137430
2019-03-07 17:15:53 +01:00
committed by zewelor
parent 23fea388e6
commit bc681fd85f
3 changed files with 94 additions and 1 deletions
+3
View File
@@ -23,6 +23,7 @@ See [Wiki](https://github.com/zewelor/bt-mqtt-gateway/wiki) for more information
* Xiaomi Aqara thermometer via [mithermometer](https://github.com/hobbypunk90/mithermometer)
* Bluetooth Low Power devices (BLE)
* [Oral-B connected toothbrushes](https://oralb.com/en-us/products#viewtype:gridview/facets:feature=feature-bluetooth-connectivity/category:products/page:0/sortby:Featured-Sort/productsdisplayed:undefined/promotilesenabled:undefined/cwidth:3/pscroll:)
* [Switchbot](https://www.switch-bot.com/)
## Getting Started
@@ -163,6 +164,8 @@ class TimeWorker(BaseWorker):
* [**bbbenji**](https://github.com/bbbenji) - *Minor contributions*
* [**elviosebastianelli**](https://github.com/elviosebastianelli) - *BLEscanmulti*
* [**jumping2000**](https://github.com/jumping2000) - *BLEscan*
* [**AS137430**](https://github.com/AS137430) - *Switchbot*
## License
+9 -1
View File
@@ -41,7 +41,6 @@ manager:
herbs: 00:11:22:33:44:55
topic_prefix: miflora
update_interval: 300
mithermometer:
args:
devices:
@@ -68,3 +67,12 @@ manager:
ia: 11:22:33:44:55:66
topic_prefix: toothbrush
update_interval: 10
switchbot:
args:
devices:
heater: 00:11:22:33:44:55
topic_prefix: switchbot/bathroom
state_topic_prefix: switchbot/bathroom
topic_subscription: switchbot/+/+/set
update_interval: 60
+82
View File
@@ -0,0 +1,82 @@
from builtins import staticmethod
import logging
from mqtt import MqttMessage
from workers.base import BaseWorker
import logger
REQUIREMENTS = ['bluepy']
_LOGGER = logger.get(__name__)
STATE_ON = 'ON'
STATE_OFF = 'OFF'
class SwitchbotWorker(BaseWorker):
def _setup(self):
_LOGGER.info("Adding %d %s devices", len(self.devices), repr(self))
for name, mac in self.devices.items():
_LOGGER.info("Adding %s device '%s' (%s)", repr(self), name, mac)
self.devices[name] = {"bot":None,"state":STATE_OFF,"mac":mac}
def format_state_topic(self, *args):
return '/'.join([self.state_topic_prefix, *args])
def status_update(self):
from bluepy import btle
ret = []
_LOGGER.debug("Updating %d %s devices", len(self.devices), repr(self))
for name, bot in self.devices.items():
_LOGGER.debug("Updating %s device '%s' (%s)", repr(self), name, bot["mac"])
try:
ret += self.update_device_state(name, bot["state"])
except btle.BTLEException as e:
logger.log_exception(_LOGGER, "Error during update of %s device '%s' (%s): %s", repr(self), name, bot["mac"], type(e).__name__, suppress=True)
return ret
def on_command(self, topic, value):
from bluepy import btle
import binascii
from bluepy.btle import Peripheral
_, _ , device_name, _ = topic.split('/')
bot = self.devices[device_name]
value = value.decode('utf-8')
# It needs to be on separate if because first if can change method
_LOGGER.debug("Setting %s on %s device '%s' (%s)", value, repr(self), device_name, bot["mac"])
try:
bot["bot"] = Peripheral(bot["mac"],"random")
hand_service = bot["bot"].getServiceByUUID("cba20d00-224d-11e6-9fb8-0002a5d5c51b")
hand = hand_service.getCharacteristics("cba20002-224d-11e6-9fb8-0002a5d5c51b")[0]
if value == STATE_ON:
hand.write(binascii.a2b_hex("570101"))
elif value == STATE_OFF:
hand.write(binascii.a2b_hex("570102"))
elif value == "PRESS":
hand.write(binascii.a2b_hex("570100"))
bot["bot"].disconnect()
except btle.BTLEException as e:
logger.log_exception(_LOGGER, "Error setting %s on %s device '%s' (%s): %s", value, repr(self), device_name, bot["mac"], type(e).__name__)
return []
try:
return self.update_device_state(device_name, value)
except btle.BTLEException as e:
logger.log_exception(_LOGGER, "Error during update of %s device '%s' (%s): %s", repr(self), device_name, bot["mac"], type(e).__name__, suppress=True)
return []
def update_device_state(self, name, value):
ret = []
ret.append(MqttMessage(topic=self.format_state_topic(name), payload=value))
return ret
def device_for(self, mac):
for key in self.devices:
if key.addr == mac:
return key