Skip to content

Commit 3175309

Browse files
authored
Fix issue with SB password issue and Temp issue. (#28)
* Fix issue with SB password issue and Temp issue. -Revert master branch to V0.11.0 release. (Latest master runs scanner in separate thread, this causes memory leak on hassio leading to supervisor restarts every 2nd day.) -Add WoSensorTH key fix. * and model value as 1st bit indicates encryption. * Update __init__.py * Update __init__.py * Update __init__.py
1 parent 1219996 commit 3175309

File tree

2 files changed

+17
-46
lines changed

2 files changed

+17
-46
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,4 @@ venv.bak/
105105
switchbot/.vs/slnx.sqlite
106106
switchbot/.vs/switchbot/v16/.suo
107107
switchbot/.vs/VSWorkspaceState.json
108+
switchbot/.vs/ProjectSettings.json

switchbot/__init__.py

Lines changed: 16 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import binascii
55
import logging
6-
from multiprocessing import Manager, Process
6+
import threading
77
import time
88

99
import bluepy
@@ -31,6 +31,7 @@
3131
PRESS_KEY_SUFFIX = "00"
3232

3333
_LOGGER = logging.getLogger(__name__)
34+
CONNECT_LOCK = threading.Lock()
3435

3536

3637
def _process_wohand(data) -> dict:
@@ -93,34 +94,6 @@ def _process_wosensorth(data) -> dict:
9394
return _wosensorth_data
9495

9596

96-
class BLEScanner:
97-
"""Helper for bluepy device scanning."""
98-
99-
def __init__(self, scan_timeout=DEFAULT_SCAN_TIMEOUT, interface=None) -> None:
100-
"""Init class constructor."""
101-
self._scan_timeout = scan_timeout
102-
self._interface = interface
103-
self._devices = None
104-
105-
def start(self) -> dict | None:
106-
"""Start scan in seperate process."""
107-
with Manager() as manager:
108-
_devices = manager.dict()
109-
process = Process(target=self._scan, args=(_devices,))
110-
process.start()
111-
process.join()
112-
113-
return _devices.get(0, None)
114-
115-
def _scan(self, devices) -> dict | None:
116-
"""Scan for advertisement data."""
117-
try:
118-
devices[0] = bluepy.btle.Scanner(self._interface).scan(self._scan_timeout)
119-
120-
except bluepy.btle.BTLEDisconnectError:
121-
pass
122-
123-
12497
class GetSwitchbotDevices:
12598
"""Scan for all Switchbot devices and return by type."""
12699

@@ -137,9 +110,7 @@ def discover(
137110
devices = None
138111

139112
try:
140-
devices = BLEScanner(
141-
scan_timeout=scan_timeout, interface=self._interface
142-
).start()
113+
devices = bluepy.btle.Scanner(self._interface).scan(scan_timeout)
143114

144115
except bluepy.btle.BTLEManagementError:
145116
_LOGGER.error("Error scanning for switchbot devices", exc_info=True)
@@ -165,7 +136,7 @@ def discover(
165136
self._all_services_data[dev_id]["mac_address"] = dev.addr
166137
for (adtype, desc, value) in dev.getScanData():
167138
if adtype == 22:
168-
_model = binascii.unhexlify(value[4:6]).decode()
139+
_model = chr(binascii.unhexlify(value.encode())[2] & 0b01111111)
169140
if _model == "H":
170141
self._all_services_data[dev_id]["data"] = _process_wohand(
171142
value[4:]
@@ -229,7 +200,7 @@ def get_device_data(self, mac) -> dict | None:
229200
_switchbot_data = {}
230201

231202
for item in self._all_services_data:
232-
if self._all_services_data[item]["mac_address"] == mac.replace("-", ":").lower():
203+
if self._all_services_data[item]["mac_address"] == mac:
233204
_switchbot_data = self._all_services_data[item]
234205

235206
return _switchbot_data
@@ -241,7 +212,7 @@ class SwitchbotDevice:
241212
def __init__(self, mac, password=None, interface=None, **kwargs) -> None:
242213
"""Switchbot base class constructor."""
243214
self._interface = interface
244-
self._mac = mac.replace("-", ":").lower()
215+
self._mac = mac
245216
self._device = None
246217
self._switchbot_device_data = {}
247218
self._scan_timeout = kwargs.pop("scan_timeout", DEFAULT_SCAN_TIMEOUT)
@@ -307,13 +278,14 @@ def _sendcommand(self, key, retry) -> bool:
307278
send_success = False
308279
command = self._commandkey(key)
309280
_LOGGER.debug("Sending command to switchbot %s", command)
310-
try:
311-
self._connect()
312-
send_success = self._writekey(command)
313-
except bluepy.btle.BTLEException:
314-
_LOGGER.warning("Error talking to Switchbot", exc_info=True)
315-
finally:
316-
self._disconnect()
281+
with CONNECT_LOCK:
282+
try:
283+
self._connect()
284+
send_success = self._writekey(command)
285+
except bluepy.btle.BTLEException:
286+
_LOGGER.warning("Error talking to Switchbot", exc_info=True)
287+
finally:
288+
self._disconnect()
317289
if send_success:
318290
return True
319291
if retry < 1:
@@ -345,9 +317,7 @@ def get_device_data(self, retry=DEFAULT_RETRY_COUNT, interface=None) -> dict | N
345317
devices = None
346318

347319
try:
348-
devices = BLEScanner(
349-
scan_timeout=self._scan_timeout, interface=_interface
350-
).start()
320+
devices = bluepy.btle.Scanner(_interface).scan(self._scan_timeout)
351321

352322
except bluepy.btle.BTLEManagementError:
353323
_LOGGER.error("Error scanning for switchbot devices", exc_info=True)
@@ -371,7 +341,7 @@ def get_device_data(self, retry=DEFAULT_RETRY_COUNT, interface=None) -> dict | N
371341
self._switchbot_device_data["mac_address"] = dev.addr
372342
for (adtype, desc, value) in dev.getScanData():
373343
if adtype == 22:
374-
_model = binascii.unhexlify(value[4:6]).decode()
344+
_model = chr(binascii.unhexlify(value.encode())[2] & 0b01111111)
375345
if _model == "H":
376346
self._switchbot_device_data["data"] = _process_wohand(
377347
value[4:]

0 commit comments

Comments
 (0)