1010
1111 Classes
1212 * AESCipher - Cryptography Helpers
13- * XenonDevice(dev_id, address=None, local_key="", dev_type="default", connection_timeout=5, version="3.1", persist=False) - Base Tuya Objects and Functions
13+ * XenonDevice(...) - Base Tuya Objects and Functions
14+ XenonDevice(dev_id, address=None, local_key="", dev_type="default", connection_timeout=5, version="3.1", persist=False, cid/node_id=None, parent=None)
1415 * Device(XenonDevice) - Tuya Class for Devices
1516
1617 Functions
@@ -675,23 +676,25 @@ def device_info( dev_id ):
675676
676677class XenonDevice (object ):
677678 def __init__ (
678- self , dev_id , address = None , local_key = "" , dev_type = "default" , connection_timeout = 5 , version = 3.1 , persist = False , cid = None , parent = None # pylint: disable=W0621
679+ self , dev_id , address = None , local_key = "" , dev_type = "default" , connection_timeout = 5 , version = 3.1 , persist = False , cid = None , node_id = None , parent = None # pylint: disable=W0621
679680 ):
680681 """
681682 Represents a Tuya device.
682683
683684 Args:
684685 dev_id (str): The device id.
685- cid (str: Optional sub device id. Default to None.
686686 address (str): The network address.
687687 local_key (str, optional): The encryption key. Defaults to None.
688+ cid (str: Optional sub device id. Default to None.
689+ node_id (str: alias for cid)
690+ parent (object: gateway device this device is a child of)
688691
689692 Attributes:
690693 port (int): The port to connect to.
691694 """
692695
693696 self .id = dev_id
694- self .cid = cid
697+ self .cid = cid if cid else node_id
695698 self .address = address
696699 self .connection_timeout = connection_timeout
697700 self .retry = True
@@ -716,14 +719,25 @@ def __init__(
716719
717720 if not local_key :
718721 local_key = ""
719- devinfo = device_info ( dev_id )
720- if devinfo and 'key' in devinfo and devinfo ['key' ]:
721- local_key = devinfo ['key' ]
722+ # sub-devices do not need a local key, so only look it up if we are not a sub-device
723+ if not parent :
724+ devinfo = device_info ( dev_id )
725+ if devinfo and 'key' in devinfo and devinfo ['key' ]:
726+ local_key = devinfo ['key' ]
722727 self .local_key = local_key .encode ("latin1" )
723728 self .real_local_key = self .local_key
724729 self .cipher = None
725730
726731 if self .parent :
732+ # if we are a child then we should have a cid/node_id but none were given - try and find it the same way we look up local keys
733+ if not self .cid :
734+ devinfo = device_info ( dev_id )
735+ if devinfo and 'node_id' in devinfo and devinfo ['node_id' ]:
736+ self .cid = devinfo ['node_id' ]
737+ if not self .cid :
738+ # not fatal as the user could have set the device_id to the cid
739+ # in that case dev_type should be 'zigbee' to set the proper fields in requests
740+ log .debug ( 'Child device but no cid/node_id given!' )
727741 XenonDevice .set_version (self , self .parent .version )
728742 self .parent ._register_child (self )
729743 elif (not address ) or address == "Auto" or address == "0.0.0.0" :
@@ -742,8 +756,11 @@ def __init__(
742756 # them (such as BulbDevice) make connections when called
743757 XenonDevice .set_version (self , 3.1 )
744758
745- if cid and self .dev_type == 'default' :
759+ if self . cid and self .dev_type == 'default' :
746760 self .dev_type = 'zigbee'
761+ elif self .dev_type == 'zigbee' and not self .cid :
762+ # this probably won't work, but it might
763+ log .debug ( 'Zigbee device but no cid/node_id given, using dev_id as the cid!' )
747764
748765 def __del__ (self ):
749766 # In case we have a lingering socket connection, close it
@@ -1101,8 +1118,8 @@ def _process_message( self, msg, dev_type=None, from_child=None, minresponse=28,
11011118 else :
11021119 result = self ._process_response (result )
11031120 self .received_wrong_cid_queue .append ( (found_child , result ) )
1104- # do not pass from_child this time to make sure we do not get stuck in a loop
1105- return self ._send_receive ( None , minresponse , True , decode_response , from_child = True )
1121+ # events should not be coming in so fast that we will never timeout a read, so don't worry about loops
1122+ return self ._send_receive ( None , minresponse , True , decode_response , from_child = from_child )
11061123
11071124 # legacy/default mode avoids persisting socket across commands
11081125 self ._check_socket_close ()
0 commit comments