Added support for Switchbot (#60)
* Added worker for Switchbot * config.yaml example for switchbot
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user