Skip to content

Commit 0cae224

Browse files
authored
Merge pull request #519 from uzlonewolf/forcescan-fix-2
Fix scanner IP address binding when netifaces/psutil are not available
2 parents 2b84315 + 62c9ad4 commit 0cae224

File tree

6 files changed

+33
-27
lines changed

6 files changed

+33
-27
lines changed

README.md

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@ TinyTuya can also connect to the Tuya Cloud to poll status and issue commands to
2323
# Example Usage of TinyTuya
2424
import tinytuya
2525

26-
d = tinytuya.OutletDevice('DEVICE_ID_HERE', 'IP_ADDRESS_HERE', 'LOCAL_KEY_HERE')
27-
d.set_version(3.3)
26+
d = tinytuya.Device('DEVICE_ID_HERE', 'IP_ADDRESS_HERE', 'LOCAL_KEY_HERE', version=3.3)
2827
data = d.status()
2928
print('Device status: %r' % data)
3029
```
@@ -276,8 +275,7 @@ import tinytuya
276275
"""
277276
OUTLET Device
278277
"""
279-
d = tinytuya.OutletDevice('DEVICE_ID_HERE', 'IP_ADDRESS_HERE', 'LOCAL_KEY_HERE')
280-
d.set_version(3.3)
278+
d = tinytuya.Device('DEVICE_ID_HERE', 'IP_ADDRESS_HERE', 'LOCAL_KEY_HERE', version=3.3)
281279
data = d.status()
282280
283281
# Show status and state of first controlled switch on device
@@ -342,34 +340,31 @@ You can set up a persistent connection to a device and then monitor the state ch
342340
```python
343341
import tinytuya
344342
345-
d = tinytuya.OutletDevice('DEVICEID', 'DEVICEIP', 'DEVICEKEY')
346-
d.set_version(3.3)
347-
d.set_socketPersistent(True)
343+
d = tinytuya.OutletDevice('DEVICEID', 'DEVICEIP', 'DEVICEKEY', version=3.3, persist=True)
348344
349345
print(" > Send Request for Status < ")
350-
payload = d.generate_payload(tinytuya.DP_QUERY)
351-
d.send(payload)
346+
d.status(nowait=True)
352347
353348
print(" > Begin Monitor Loop <")
354349
while(True):
355350
# See if any data is available
356351
data = d.receive()
357352
print('Received Payload: %r' % data)
358353
359-
# Send keyalive heartbeat
360-
print(" > Send Heartbeat Ping < ")
361-
payload = d.generate_payload(tinytuya.HEART_BEAT)
362-
d.send(payload)
354+
# Send keep-alive heartbeat
355+
if not data:
356+
print(" > Send Heartbeat Ping < ")
357+
d.heartbeat()
363358
364359
# NOTE If you are not seeing updates, you can force them - uncomment:
365360
# print(" > Send Request for Status < ")
366-
# payload = d.generate_payload(tinytuya.DP_QUERY)
367-
# d.send(payload)
361+
# d.status(nowait=True)
368362
369363
# NOTE Some smart plugs require an UPDATEDPS command to update power data
370364
# print(" > Send DPS Update Request < ")
371365
# payload = d.generate_payload(tinytuya.UPDATEDPS)
372366
# d.send(payload)
367+
373368
```
374369
375370
### Tuya Cloud Access
@@ -565,9 +560,9 @@ In addition to the built-in `OutletDevice`, `BulbDevice` and `CoverDevice` devic
565560
566561
```python
567562
# Example usage of community contributed device modules
568-
from tinytuya import Contrib
563+
from tinytuya.Contrib import ThermostatDevice
569564
570-
thermo = Contrib.ThermostatDevice( 'abcdefghijklmnop123456', '172.28.321.475', '1234567890123abc' )
565+
thermo = ThermostatDevice( 'abcdefghijklmnop123456', '172.28.321.475', '1234567890123abc' )
571566
```
572567
573568
## Tuya Data Points - DPS Table
@@ -869,9 +864,9 @@ NOTE (*) - Depending on the firmware, either 18/19/20/26/27 or 108/109/110/111/x
869864
A user contributed module is available for this device in the [Contrib library](https://github.com/jasonacox/tinytuya/tree/master/tinytuya/Contrib):
870865
871866
```python
872-
from tinytuya import Contrib
867+
from tinytuya.Contrib import ThermostatDevice
873868
874-
thermo = Contrib.ThermostatDevice( 'abcdefghijklmnop123456', '172.28.321.475', '1234567890123abc' )
869+
thermo = ThermostatDevice( 'abcdefghijklmnop123456', '172.28.321.475', '1234567890123abc' )
875870
```
876871
877872
For info on the Sensor Data lists, see https://github.com/jasonacox/tinytuya/discussions/139

RELEASE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# RELEASE NOTES
22

3+
## v1.15.1 - Scanner Fixes
4+
5+
* Fix scanner broadcast attempting to bind to the wrong IP address, introduced in v1.15.0
6+
37
## v1.15.0 - Scanner Fixes
48

59
* Fix force-scanning bug in scanner introduced in last release and add broadcast request feature to help discover Tuya version 3.5 devices by @uzlonewolf in https://github.com/jasonacox/tinytuya/pull/511.

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
cryptography>=3.1 # Encryption - AES can also be provided via PyCryptodome or pyaes or pyca/cryptography
33
requests # Used for Setup Wizard - Tuya IoT Platform calls
44
colorama # Makes ANSI escape character sequences work under MS Windows.
5-
netifaces # Used to get the IP address of the local machine for scanning for devices.
5+
#netifaces # Used to get the IP address of the local machine for scanning for devices, mainly useful for multi-interface machines.

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
INSTALL_REQUIRES = [
1010
'requests', # Used for Setup Wizard - Tuya IoT Platform calls
1111
'colorama', # Makes ANSI escape character sequences work under MS Windows.
12-
'netifaces', # Used for device discovery
12+
#'netifaces', # Used for device discovery, mainly required on multi-interface machines
1313
]
1414

1515
CHOOSE_CRYPTO_LIB = [

tinytuya/core.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@
123123
# Colorama terminal color capability for all platforms
124124
init()
125125

126-
version_tuple = (1, 15, 0)
126+
version_tuple = (1, 15, 1)
127127
version = __version__ = "%d.%d.%d" % version_tuple
128128
__author__ = "jasonacox"
129129

tinytuya/scanner.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,16 @@
9696
log = logging.getLogger(__name__)
9797

9898
# Helper Functions
99-
def getmyIP():
99+
def getmyIPaddr():
100100
# Fetch my IP address and assume /24 network
101101
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
102102
s.connect(("8.8.8.8", 80))
103-
r = s.getsockname()[0]
103+
r = str(s.getsockname()[0])
104104
s.close()
105-
r = str(r).split('.')
105+
return r
106+
107+
def getmyIP():
108+
r = getmyIPaddr().split('.')
106109
# assume a /24 network
107110
return '%s.%s.%s.0/24' % tuple(r[:3])
108111

@@ -196,7 +199,7 @@ def get_ip_to_broadcast():
196199
if ip_to_broadcast:
197200
return ip_to_broadcast
198201

199-
ip_to_broadcast['255.255.255.255'] = getmyIP()
202+
ip_to_broadcast['255.255.255.255'] = getmyIPaddr()
200203
return ip_to_broadcast
201204

202205
def send_discovery_request( iface_list=None ):
@@ -215,7 +218,11 @@ def send_discovery_request( iface_list=None ):
215218
if 'socket' not in iface:
216219
iface['socket'] = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
217220
iface['socket'].setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
218-
iface['socket'].bind( (address,0) )
221+
try:
222+
iface['socket'].bind( (address,0) )
223+
except:
224+
log.debug( 'Failed to bind to address %r for discovery broadcasts, skipping interface!', address, exc_info=True )
225+
continue
219226

220227
if 'payload' not in iface:
221228
bcast = json.dumps( {"from":"app","ip":address} ).encode()

0 commit comments

Comments
 (0)