platypush/platypush/plugins/bluetooth/_ble/_plugins/switchbot.py

66 lines
1.8 KiB
Python

from enum import Enum
from typing import Iterable
from uuid import UUID
from platypush.entities import Entity
from platypush.entities.bluetooth import BluetoothDevice
from platypush.entities.switches import EnumSwitch
from platypush.plugins.bluetooth.model import ServiceClass
from platypush.plugins.bluetooth._plugins import BaseBluetoothPlugin
def _make_uuid(prefix: str) -> UUID:
"""
Utility method to create a Switchbot characteristic UUID given a hex
prefix.
"""
return UUID(f'cba20{prefix}-224d-11e6-9fb8-0002a5d5c51b')
class Command(Enum):
"""
Supported commands.
"""
PRESS = b'\x57\x01\x00'
ON = b'\x57\x01\x01'
OFF = b'\x57\x01\x02'
class Characteristic(Enum):
"""
GATT characteristic UUIDs supported by Switchbot devices.
"""
TX = _make_uuid('002')
RX = _make_uuid('003')
SRV = _make_uuid('d00')
# pylint: disable=too-few-public-methods
class SwitchbotPlugin(BaseBluetoothPlugin):
"""
Implements support for Switchbot devices.
"""
def supports_device(self, device: BluetoothDevice) -> bool:
return any(
srv.service_class == ServiceClass.SWITCHBOT for srv in device.services
)
def _extract_entities(self, device: BluetoothDevice) -> Iterable[Entity]:
return [
EnumSwitch(
id=f'{device.address}::switchbot',
name='Switchbot',
values=[cmd.name.lower() for cmd in Command],
is_write_only=True,
)
]
def set(self, device: BluetoothDevice, value: str, **_) -> None:
value = value.upper()
cmd = getattr(Command, value, None)
assert cmd, f'No such command: {value}. Available commands: {list(Command)}.'
self._manager.write(device.address, cmd.value, Characteristic.TX.value)