forked from platypush/platypush
Added native support for switch entities to switchbot.bluetooth plugin
This commit is contained in:
parent
91ff8d811f
commit
b9c78ad913
1 changed files with 52 additions and 17 deletions
|
@ -1,6 +1,6 @@
|
||||||
import enum
|
import enum
|
||||||
import time
|
import time
|
||||||
from typing import List
|
from typing import List, Optional
|
||||||
|
|
||||||
from platypush.message.response.bluetooth import BluetoothScanResponse
|
from platypush.message.response.bluetooth import BluetoothScanResponse
|
||||||
from platypush.plugins import action
|
from platypush.plugins import action
|
||||||
|
@ -8,7 +8,9 @@ from platypush.plugins.bluetooth.ble import BluetoothBlePlugin
|
||||||
from platypush.plugins.switch import SwitchPlugin
|
from platypush.plugins.switch import SwitchPlugin
|
||||||
|
|
||||||
|
|
||||||
class SwitchbotBluetoothPlugin(SwitchPlugin, BluetoothBlePlugin): # lgtm [py/missing-call-to-init]
|
class SwitchbotBluetoothPlugin( # lgtm [py/missing-call-to-init]
|
||||||
|
SwitchPlugin, BluetoothBlePlugin
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Plugin to interact with a Switchbot (https://www.switch-bot.com/) device and
|
Plugin to interact with a Switchbot (https://www.switch-bot.com/) device and
|
||||||
programmatically control switches over a Bluetooth interface.
|
programmatically control switches over a Bluetooth interface.
|
||||||
|
@ -31,6 +33,7 @@ class SwitchbotBluetoothPlugin(SwitchPlugin, BluetoothBlePlugin): # lgtm [py/m
|
||||||
"""
|
"""
|
||||||
Base64 encoded commands
|
Base64 encoded commands
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# \x57\x01\x00
|
# \x57\x01\x00
|
||||||
PRESS = 'VwEA'
|
PRESS = 'VwEA'
|
||||||
# # \x57\x01\x01
|
# # \x57\x01\x01
|
||||||
|
@ -38,8 +41,14 @@ class SwitchbotBluetoothPlugin(SwitchPlugin, BluetoothBlePlugin): # lgtm [py/m
|
||||||
# # \x57\x01\x02
|
# # \x57\x01\x02
|
||||||
OFF = 'VwEC'
|
OFF = 'VwEC'
|
||||||
|
|
||||||
def __init__(self, interface=None, connect_timeout=None,
|
def __init__(
|
||||||
scan_timeout=2, devices=None, **kwargs):
|
self,
|
||||||
|
interface=None,
|
||||||
|
connect_timeout=None,
|
||||||
|
scan_timeout=2,
|
||||||
|
devices=None,
|
||||||
|
**kwargs
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
:param interface: Bluetooth interface to use (e.g. hci0) default: first available one
|
:param interface: Bluetooth interface to use (e.g. hci0) default: first available one
|
||||||
:type interface: str
|
:type interface: str
|
||||||
|
@ -59,17 +68,21 @@ class SwitchbotBluetoothPlugin(SwitchPlugin, BluetoothBlePlugin): # lgtm [py/m
|
||||||
self.scan_timeout = scan_timeout if scan_timeout else 2
|
self.scan_timeout = scan_timeout if scan_timeout else 2
|
||||||
self.configured_devices = devices or {}
|
self.configured_devices = devices or {}
|
||||||
self.configured_devices_by_name = {
|
self.configured_devices_by_name = {
|
||||||
name: addr
|
name: addr for addr, name in self.configured_devices.items()
|
||||||
for addr, name in self.configured_devices.items()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def _run(self, device: str, command: Command):
|
def _run(self, device: str, command: Command):
|
||||||
if device in self.configured_devices_by_name:
|
device = self.configured_devices_by_name.get(device, '')
|
||||||
device = self.configured_devices_by_name[device]
|
|
||||||
n_tries = 1
|
n_tries = 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.write(device, command.value, handle=self.handle, channel_type='random', binary=True)
|
self.write(
|
||||||
|
device,
|
||||||
|
command.value,
|
||||||
|
handle=self.handle,
|
||||||
|
channel_type='random',
|
||||||
|
binary=True,
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.exception(e)
|
self.logger.exception(e)
|
||||||
n_tries -= 1
|
n_tries -= 1
|
||||||
|
@ -78,7 +91,7 @@ class SwitchbotBluetoothPlugin(SwitchPlugin, BluetoothBlePlugin): # lgtm [py/m
|
||||||
raise e
|
raise e
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
|
||||||
return self.status(device)
|
return self.status(device) # type: ignore
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def press(self, device):
|
def press(self, device):
|
||||||
|
@ -91,11 +104,11 @@ class SwitchbotBluetoothPlugin(SwitchPlugin, BluetoothBlePlugin): # lgtm [py/m
|
||||||
return self._run(device, self.Command.PRESS)
|
return self._run(device, self.Command.PRESS)
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def toggle(self, device, **kwargs):
|
def toggle(self, device, **_):
|
||||||
return self.press(device)
|
return self.press(device)
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def on(self, device, **kwargs):
|
def on(self, device, **_):
|
||||||
"""
|
"""
|
||||||
Send a press-on button command to a device
|
Send a press-on button command to a device
|
||||||
|
|
||||||
|
@ -105,7 +118,7 @@ class SwitchbotBluetoothPlugin(SwitchPlugin, BluetoothBlePlugin): # lgtm [py/m
|
||||||
return self._run(device, self.Command.ON)
|
return self._run(device, self.Command.ON)
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def off(self, device, **kwargs):
|
def off(self, device, **_):
|
||||||
"""
|
"""
|
||||||
Send a press-off button command to a device
|
Send a press-off button command to a device
|
||||||
|
|
||||||
|
@ -115,7 +128,9 @@ class SwitchbotBluetoothPlugin(SwitchPlugin, BluetoothBlePlugin): # lgtm [py/m
|
||||||
return self._run(device, self.Command.OFF)
|
return self._run(device, self.Command.OFF)
|
||||||
|
|
||||||
@action
|
@action
|
||||||
def scan(self, interface: str = None, duration: int = 10) -> BluetoothScanResponse:
|
def scan(
|
||||||
|
self, interface: Optional[str] = None, duration: int = 10
|
||||||
|
) -> BluetoothScanResponse:
|
||||||
"""
|
"""
|
||||||
Scan for available Switchbot devices nearby.
|
Scan for available Switchbot devices nearby.
|
||||||
|
|
||||||
|
@ -129,9 +144,13 @@ class SwitchbotBluetoothPlugin(SwitchPlugin, BluetoothBlePlugin): # lgtm [py/m
|
||||||
for dev in devices:
|
for dev in devices:
|
||||||
try:
|
try:
|
||||||
characteristics = [
|
characteristics = [
|
||||||
chrc for chrc in self.discover_characteristics(
|
chrc
|
||||||
dev['addr'], channel_type='random', wait=False,
|
for chrc in self.discover_characteristics(
|
||||||
timeout=self.scan_timeout).characteristics
|
dev['addr'],
|
||||||
|
channel_type='random',
|
||||||
|
wait=False,
|
||||||
|
timeout=self.scan_timeout,
|
||||||
|
).characteristics
|
||||||
if chrc.get('uuid') == self.uuid
|
if chrc.get('uuid') == self.uuid
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -140,10 +159,12 @@ class SwitchbotBluetoothPlugin(SwitchPlugin, BluetoothBlePlugin): # lgtm [py/m
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.warning('Device scan error', e)
|
self.logger.warning('Device scan error', e)
|
||||||
|
|
||||||
|
self.publish_entities(compatible_devices) # type: ignore
|
||||||
return BluetoothScanResponse(devices=compatible_devices)
|
return BluetoothScanResponse(devices=compatible_devices)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def switches(self) -> List[dict]:
|
def switches(self) -> List[dict]:
|
||||||
|
self.publish_entities(self.configured_devices) # type: ignore
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
'address': addr,
|
'address': addr,
|
||||||
|
@ -154,5 +175,19 @@ class SwitchbotBluetoothPlugin(SwitchPlugin, BluetoothBlePlugin): # lgtm [py/m
|
||||||
for addr, name in self.configured_devices.items()
|
for addr, name in self.configured_devices.items()
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def transform_entities(self, devices: dict):
|
||||||
|
from platypush.entities.switches import Switch
|
||||||
|
|
||||||
|
return super().transform_entities( # type: ignore
|
||||||
|
[
|
||||||
|
Switch(
|
||||||
|
id=addr,
|
||||||
|
name=name,
|
||||||
|
state=False,
|
||||||
|
)
|
||||||
|
for addr, name in devices.items()
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# vim:sw=4:ts=4:et:
|
# vim:sw=4:ts=4:et:
|
||||||
|
|
Loading…
Reference in a new issue