Skip to content

Commit cee6a1d

Browse files
authored
Merge dev into master (#796)
2 parents ff4628d + 0a9acab commit cee6a1d

File tree

13 files changed

+854
-240
lines changed

13 files changed

+854
-240
lines changed

README.md

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,13 @@ broadlink.setup('myssid', 'mynetworkpass', 3)
5050

5151
Security mode options are (0 = none, 1 = WEP, 2 = WPA1, 3 = WPA2, 4 = WPA1/2)
5252

53+
#### Advanced options
54+
55+
You may need to specify a broadcast address if setup is not working.
56+
```python3
57+
broadlink.setup('myssid', 'mynetworkpass', 3, ip_address='192.168.0.255')
58+
```
59+
5360
### Discovery
5461

5562
Use this function to discover devices:
@@ -61,17 +68,19 @@ devices = broadlink.discover()
6168
#### Advanced options
6269
You may need to specify `local_ip_address` or `discover_ip_address` if discovery does not return any devices.
6370

71+
Using the IP address of your local machine:
6472
```python3
65-
devices = broadlink.discover(local_ip_address='192.168.0.100') # IP address of your local machine.
73+
devices = broadlink.discover(local_ip_address='192.168.0.100')
6674
```
6775

76+
Using the broadcast address of your subnet:
6877
```python3
69-
devices = broadlink.discover(discover_ip_address='192.168.0.255') # Broadcast address of your subnet.
78+
devices = broadlink.discover(discover_ip_address='192.168.0.255')
7079
```
7180

7281
If the device is locked, it may not be discoverable with broadcast. In such cases, you can use the unicast version `broadlink.hello()` for direct discovery:
7382
```python3
74-
device = broadlink.hello('192.168.0.16') # IP address of your Broadlink device.
83+
device = broadlink.hello('192.168.0.16')
7584
```
7685

7786
If you are a perfomance freak, use `broadlink.xdiscover()` to create devices instantly:
@@ -106,23 +115,33 @@ packet = device.check_data()
106115

107116
### Learning RF codes
108117

109-
Learning IR codes takes place in five steps.
118+
Learning RF codes takes place in six steps.
110119

111120
1. Sweep the frequency:
112121
```python3
113122
device.sweep_frequency()
114123
```
115124
2. When the LED blinks, point the remote at the Broadlink device for the first time and long press the button you want to learn.
116-
3. Enter learning mode:
125+
3. Check if the frequency was successfully identified:
126+
```python3
127+
ok = device.check_frequency()
128+
if ok:
129+
print('Frequency found!')
130+
```
131+
4. Enter learning mode:
117132
```python3
118133
device.find_rf_packet()
119134
```
120-
4. When the LED blinks, point the remote at the Broadlink device for the second time and short press the button you want to learn.
121-
5. Get the RF packet:
135+
5. When the LED blinks, point the remote at the Broadlink device for the second time and short press the button you want to learn.
136+
6. Get the RF packet:
122137
```python3
123138
packet = device.check_data()
124139
```
125140

141+
#### Notes
142+
143+
Universal remotes with product id 0x2712 use the same method for learning IR and RF codes. They don't need to sweep frequency. Just call `device.enter_learning()` and `device.check_data()`.
144+
126145
### Canceling learning
127146

128147
You can exit the learning mode in the middle of the process by calling this method:

broadlink/__init__.py

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
#!/usr/bin/env python3
22
"""The python-broadlink library."""
33
import socket
4-
import typing as t
4+
from typing import Generator, List, Optional, Tuple, Union
55

66
from . import exceptions as e
77
from .const import DEFAULT_BCAST_ADDR, DEFAULT_PORT, DEFAULT_TIMEOUT
88
from .alarm import S1C
9-
from .climate import hysen
10-
from .cover import dooya
9+
from .climate import hvac, hysen
10+
from .cover import dooya, dooya2, wser
1111
from .device import Device, ping, scan
1212
from .hub import s3
1313
from .light import lb1, lb2
1414
from .remote import rm, rm4, rm4mini, rm4pro, rmmini, rmminib, rmpro
15-
from .sensor import a1
16-
from .switch import bg1, mp1, sp1, sp2, sp2s, sp3, sp3s, sp4, sp4b
15+
from .sensor import a1, a2
16+
from .switch import bg1, ehc31, mp1, mp1s, sp1, sp2, sp2s, sp3, sp3s, sp4, sp4b
1717

1818
SUPPORTED_TYPES = {
1919
sp1: {
@@ -148,14 +148,19 @@
148148
0x653C: ("RM4 pro", "Broadlink"),
149149
},
150150
a1: {
151-
0x2714: ("e-Sensor", "Broadlink"),
151+
0x2714: ("A1", "Broadlink"),
152+
},
153+
a2: {
154+
0x4F60: ("A2", "Broadlink"),
152155
},
153156
mp1: {
154157
0x4EB5: ("MP1-1K4S", "Broadlink"),
155-
0x4EF7: ("MP1-1K4S", "Broadlink (OEM)"),
156158
0x4F1B: ("MP1-1K3S2U", "Broadlink (OEM)"),
157159
0x4F65: ("MP1-1K3S2U", "Broadlink"),
158160
},
161+
mp1s: {
162+
0x4EF7: ("MP1-1K4S", "Broadlink (OEM)"),
163+
},
159164
lb1: {
160165
0x5043: ("SB800TD", "Broadlink (OEM)"),
161166
0x504E: ("LB1", "Broadlink"),
@@ -177,26 +182,38 @@
177182
S1C: {
178183
0x2722: ("S2KIT", "Broadlink"),
179184
},
180-
s3: {
185+
s3: {
181186
0xA59C: ("S3", "Broadlink"),
182187
0xA64D: ("S3", "Broadlink"),
183188
},
189+
hvac: {
190+
0x4E2A: ("HVAC", "Licensed manufacturer"),
191+
},
184192
hysen: {
185193
0x4EAD: ("HY02/HY03", "Hysen"),
186194
},
187195
dooya: {
188196
0x4E4D: ("DT360E-45/20", "Dooya"),
189197
},
198+
dooya2: {
199+
0x4F6E: ("DT360E-45/20", "Dooya"),
200+
},
201+
wser: {
202+
0x4F6C: ("WSER", "Wistar"),
203+
},
190204
bg1: {
191205
0x51E3: ("BG800/BG900", "BG Electrical"),
192206
},
207+
ehc31: {
208+
0x6480: ("EHC31", "BG Electrical"),
209+
},
193210
}
194211

195212

196213
def gendevice(
197214
dev_type: int,
198-
host: t.Tuple[str, int],
199-
mac: t.Union[bytes, str],
215+
host: Tuple[str, int],
216+
mac: Union[bytes, str],
200217
name: str = "",
201218
is_locked: bool = False,
202219
) -> Device:
@@ -222,7 +239,7 @@ def gendevice(
222239

223240

224241
def hello(
225-
host: str,
242+
ip_address: str,
226243
port: int = DEFAULT_PORT,
227244
timeout: int = DEFAULT_TIMEOUT,
228245
) -> Device:
@@ -232,7 +249,11 @@ def hello(
232249
"""
233250
try:
234251
return next(
235-
xdiscover(timeout=timeout, discover_ip_address=host, discover_ip_port=port)
252+
xdiscover(
253+
timeout=timeout,
254+
discover_ip_address=ip_address,
255+
discover_ip_port=port,
256+
)
236257
)
237258
except StopIteration as err:
238259
raise e.NetworkTimeoutError(
@@ -244,33 +265,42 @@ def hello(
244265

245266
def discover(
246267
timeout: int = DEFAULT_TIMEOUT,
247-
local_ip_address: str = None,
268+
local_ip_address: Optional[str] = None,
248269
discover_ip_address: str = DEFAULT_BCAST_ADDR,
249270
discover_ip_port: int = DEFAULT_PORT,
250-
) -> t.List[Device]:
271+
) -> List[Device]:
251272
"""Discover devices connected to the local network."""
252-
responses = scan(timeout, local_ip_address, discover_ip_address, discover_ip_port)
273+
responses = scan(
274+
timeout, local_ip_address, discover_ip_address, discover_ip_port
275+
)
253276
return [gendevice(*resp) for resp in responses]
254277

255278

256279
def xdiscover(
257280
timeout: int = DEFAULT_TIMEOUT,
258-
local_ip_address: str = None,
281+
local_ip_address: Optional[str] = None,
259282
discover_ip_address: str = DEFAULT_BCAST_ADDR,
260283
discover_ip_port: int = DEFAULT_PORT,
261-
) -> t.Generator[Device, None, None]:
284+
) -> Generator[Device, None, None]:
262285
"""Discover devices connected to the local network.
263286
264287
This function returns a generator that yields devices instantly.
265288
"""
266-
responses = scan(timeout, local_ip_address, discover_ip_address, discover_ip_port)
289+
responses = scan(
290+
timeout, local_ip_address, discover_ip_address, discover_ip_port
291+
)
267292
for resp in responses:
268293
yield gendevice(*resp)
269294

270295

271296
# Setup a new Broadlink device via AP Mode. Review the README to see how to enter AP Mode.
272297
# Only tested with Broadlink RM3 Mini (Blackbean)
273-
def setup(ssid: str, password: str, security_mode: int) -> None:
298+
def setup(
299+
ssid: str,
300+
password: str,
301+
security_mode: int,
302+
ip_address: str = DEFAULT_BCAST_ADDR,
303+
) -> None:
274304
"""Set up a new Broadlink device via AP mode."""
275305
# Security mode options are (0 - none, 1 = WEP, 2 = WPA1, 3 = WPA2, 4 = WPA1/2)
276306
payload = bytearray(0x88)
@@ -299,5 +329,5 @@ def setup(ssid: str, password: str, security_mode: int) -> None:
299329
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Internet # UDP
300330
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
301331
sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
302-
sock.sendto(payload, (DEFAULT_BCAST_ADDR, DEFAULT_PORT))
332+
sock.sendto(payload, (ip_address, DEFAULT_PORT))
303333
sock.close()

0 commit comments

Comments
 (0)