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)
|
* Xiaomi Aqara thermometer via [mithermometer](https://github.com/hobbypunk90/mithermometer)
|
||||||
* Bluetooth Low Power devices (BLE)
|
* 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:)
|
* [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
|
## Getting Started
|
||||||
|
|
||||||
@@ -163,6 +164,8 @@ class TimeWorker(BaseWorker):
|
|||||||
* [**bbbenji**](https://github.com/bbbenji) - *Minor contributions*
|
* [**bbbenji**](https://github.com/bbbenji) - *Minor contributions*
|
||||||
* [**elviosebastianelli**](https://github.com/elviosebastianelli) - *BLEscanmulti*
|
* [**elviosebastianelli**](https://github.com/elviosebastianelli) - *BLEscanmulti*
|
||||||
* [**jumping2000**](https://github.com/jumping2000) - *BLEscan*
|
* [**jumping2000**](https://github.com/jumping2000) - *BLEscan*
|
||||||
|
* [**AS137430**](https://github.com/AS137430) - *Switchbot*
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
+9
-1
@@ -41,7 +41,6 @@ manager:
|
|||||||
herbs: 00:11:22:33:44:55
|
herbs: 00:11:22:33:44:55
|
||||||
topic_prefix: miflora
|
topic_prefix: miflora
|
||||||
update_interval: 300
|
update_interval: 300
|
||||||
|
|
||||||
mithermometer:
|
mithermometer:
|
||||||
args:
|
args:
|
||||||
devices:
|
devices:
|
||||||
@@ -68,3 +67,12 @@ manager:
|
|||||||
ia: 11:22:33:44:55:66
|
ia: 11:22:33:44:55:66
|
||||||
topic_prefix: toothbrush
|
topic_prefix: toothbrush
|
||||||
update_interval: 10
|
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