From 3bdb6dfb92b7819e835406a9cb499508ee63924b Mon Sep 17 00:00:00 2001 From: Felipe Martins Diel <41558831+felipediel@users.noreply.github.com> Date: Sat, 19 Mar 2022 15:28:54 -0300 Subject: [PATCH 1/3] Merge new product ids into master (#667) * Add support for Broadlink LB26 R1 (0x644E) (#636) * Add support for Broadlink LB26 R1 (0x644E) * Add Broadlink LB26 R1 to README.md * Add missing device codes for LB27 R1 Smart Bulbs (#644) These are two missing codes. This closes issue #639 * Add support for Broadlink RM4 pro (0x5213) (#649) * Add support for Broadlink RM4 TV mate (0x5209) (#655) * Move 0x644C and 0x644E to the LB1 class (#666) Co-authored-by: Mathew Verdouw --- README.md | 4 ++-- broadlink/__init__.py | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 009315d..90fad7b 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,14 @@ A Python module and CLI for controlling Broadlink devices locally. The following devices are supported: -- **Universal remotes**: RM home, RM mini 3, RM plus, RM pro, RM pro+, RM4 mini, RM4 pro, RM4C mini, RM4S +- **Universal remotes**: RM home, RM mini 3, RM plus, RM pro, RM pro+, RM4 mini, RM4 pro, RM4C mini, RM4S, RM4 TV mate - **Smart plugs**: SP mini, SP mini 3, SP mini+, SP1, SP2, SP2-BR, SP2-CL, SP2-IN, SP2-UK, SP3, SP3-EU, SP3S-EU, SP3S-US, SP4L-AU, SP4L-EU, SP4L-UK, SP4M, SP4M-US, Ankuoo NEO, Ankuoo NEO PRO, Efergy Ego, BG AHC/U-01 - **Switches**: MCB1, SC1, SCB1E, SCB2 - **Outlets**: BG 800, BG 900 - **Power strips**: MP1-1K3S2U, MP1-1K4S, MP2 - **Environment sensors**: A1 - **Alarm kits**: S1C, S2KIT -- **Light bulbs**: LB1, LB2, SB800TD +- **Light bulbs**: LB1, LB26 R1, LB27 R1, SB800TD - **Curtain motors**: Dooya DT360E-45/20 - **Thermostats**: Hysen HY02B05H diff --git a/broadlink/__init__.py b/broadlink/__init__.py index fc64e84..db8f3e5 100644 --- a/broadlink/__init__.py +++ b/broadlink/__init__.py @@ -111,6 +111,7 @@ SUPPORTED_TYPES = { }, rm4mini: { 0x51DA: ("RM4 mini", "Broadlink"), + 0x5209: ("RM4 TV mate", "Broadlink"), 0x6070: ("RM4C mini", "Broadlink"), 0x610E: ("RM4 mini", "Broadlink"), 0x610F: ("RM4C mini", "Broadlink"), @@ -122,6 +123,7 @@ SUPPORTED_TYPES = { 0x653A: ("RM4 mini", "Broadlink"), }, rm4pro: { + 0x5213: ("RM4 pro", "Broadlink"), 0x6026: ("RM4 pro", "Broadlink"), 0x6184: ("RM4C pro", "Broadlink"), 0x61A2: ("RM4 pro", "Broadlink"), @@ -144,9 +146,12 @@ SUPPORTED_TYPES = { 0x60C7: ("LB1", "Broadlink"), 0x60C8: ("LB1", "Broadlink"), 0x6112: ("LB1", "Broadlink"), + 0x644C: ("LB27 R1", "Broadlink"), + 0x644E: ("LB26 R1", "Broadlink"), }, lb2: { 0xA4F4: ("LB27 R1", "Broadlink"), + 0xA5F7: ("LB27 R1", "Broadlink"), }, S1C: { 0x2722: ("S2KIT", "Broadlink"), From d870560e6e6a579e3fbd0793890e2dc16c3712fa Mon Sep 17 00:00:00 2001 From: Felipe Martins Diel <41558831+felipediel@users.noreply.github.com> Date: Sat, 19 Mar 2022 15:43:00 -0300 Subject: [PATCH 2/3] Bump version to 0.18.1 (#668) --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 505386b..ac01c08 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ from setuptools import setup, find_packages -version = '0.18.0' +version = '0.18.1' setup( name="broadlink", From 2b70440786c7b63eb4445676db78a2acd387eaf4 Mon Sep 17 00:00:00 2001 From: Steven Dodd Date: Sat, 19 Mar 2022 22:31:14 +0000 Subject: [PATCH 3/3] Add support for S3 Hub and LC-1 (1,2&3 gang) light switches (#654) * https://github.com/mjg59/python-broadlink/issues/647 * Added get_state(did) and update documentation * Fixed pwr3 set_state * Added get_subdevices() * Cleaned up get_subdevices * Updated S3 documentation * Added device id 0xA59C:("S3", "Broadlink") * Improve logic of get_subdevices() Prevents infinite loop. * Black * Move s3 closer to s1c * Update README.md Co-authored-by: Felipe Martins Diel <41558831+felipediel@users.noreply.github.com> --- README.md | 33 ++++++++++++++++- broadlink/__init__.py | 5 +++ broadlink/hub.py | 83 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 broadlink/hub.py diff --git a/README.md b/README.md index 90fad7b..675dfe0 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ A Python module and CLI for controlling Broadlink devices locally. The following - **Light bulbs**: LB1, LB26 R1, LB27 R1, SB800TD - **Curtain motors**: Dooya DT360E-45/20 - **Thermostats**: Hysen HY02B05H +- **Hubs**: S3 ## Installation @@ -194,4 +195,34 @@ devices[0].set_state(bulb_colormode=1) ### Fetching sensor data ```python3 data = device.check_sensors() -``` \ No newline at end of file +``` + +## Hubs + +### Discovering subdevices +```python3 +device.get_subdevices() +``` + +### Fetching data +Use the DID obtained from get_subdevices() for the input parameter to query specific sub-device. + +```python3 +device.get_state(did="00000000000000000000a043b0d06963") +``` + +### Setting state attributes +The parameters depend on the type of subdevice that is being controlled. In this example, we are controlling LC-1 switches: + +#### Turn on +```python3 +device.set_state(did="00000000000000000000a043b0d0783a", pwr=1) +device.set_state(did="00000000000000000000a043b0d0783a", pwr1=1) +device.set_state(did="00000000000000000000a043b0d0783a", pwr2=1) +``` +#### Turn off +```python3 +device.set_state(did="00000000000000000000a043b0d0783a", pwr=0) +device.set_state(did="00000000000000000000a043b0d0783a", pwr1=0) +device.set_state(did="00000000000000000000a043b0d0783a", pwr2=0) +``` diff --git a/broadlink/__init__.py b/broadlink/__init__.py index db8f3e5..7711f66 100644 --- a/broadlink/__init__.py +++ b/broadlink/__init__.py @@ -9,6 +9,7 @@ from .alarm import S1C from .climate import hysen from .cover import dooya from .device import Device, ping, scan +from .hub import s3 from .light import lb1, lb2 from .remote import rm, rm4, rm4mini, rm4pro, rmmini, rmminib, rmpro from .sensor import a1 @@ -156,6 +157,10 @@ SUPPORTED_TYPES = { S1C: { 0x2722: ("S2KIT", "Broadlink"), }, + s3: { + 0xA59C:("S3", "Broadlink"), + 0xA64D:("S3", "Broadlink"), + }, hysen: { 0x4EAD: ("HY02/HY03", "Hysen"), }, diff --git a/broadlink/hub.py b/broadlink/hub.py new file mode 100644 index 0000000..07b02e8 --- /dev/null +++ b/broadlink/hub.py @@ -0,0 +1,83 @@ +"""Support for hubs.""" +import struct +import json + +from . import exceptions as e +from .device import Device + + +class s3(Device): + """Controls a Broadlink S3.""" + + TYPE = "S3" + MAX_SUBDEVICES = 8 + + def get_subdevices(self) -> list: + """Return the lit of sub devices.""" + sub_devices = [] + step = 5 + + for index in range(0, self.MAX_SUBDEVICES, step): + state = {"count": step, "index": index} + packet = self._encode(14, state) + resp = self.send_packet(0x6A, packet) + e.check_error(resp[0x22:0x24]) + resp = self._decode(resp) + + sub_devices.extend(resp["list"]) + if len(sub_devices) == resp["total"]: + break + + return sub_devices + + def get_state(self, did: str = None) -> dict: + """Return the power state of the device.""" + state = {} + if did is not None: + state["did"] = did + + packet = self._encode(1, state) + response = self.send_packet(0x6A, packet) + e.check_error(response[0x22:0x24]) + return self._decode(response) + + def set_state( + self, + did: str = None, + pwr1: bool = None, + pwr2: bool = None, + pwr3: bool = None, + ) -> dict: + """Set the power state of the device.""" + state = {} + if did is not None: + state["did"] = did + if pwr1 is not None: + state["pwr1"] = int(bool(pwr1)) + if pwr2 is not None: + state["pwr2"] = int(bool(pwr2)) + if pwr3 is not None: + state["pwr3"] = int(bool(pwr3)) + + packet = self._encode(2, state) + response = self.send_packet(0x6A, packet) + e.check_error(response[0x22:0x24]) + return self._decode(response) + + def _encode(self, flag: int, state: dict) -> bytes: + """Encode a JSON packet.""" + # flag: 1 for reading, 2 for writing. + packet = bytearray(12) + data = json.dumps(state, separators=(",", ":")).encode() + struct.pack_into(" dict: + """Decode a JSON packet.""" + payload = self.decrypt(response[0x38:]) + js_len = struct.unpack_from("