
    j                     D   d dl Z d dlZd dlZd dlmZmZ d dlZd dlZd dlZd dl	Z	d dl
Z
ddlmZmZ ddlmZ ddlmZmZmZmZmZmZmZ ddlmZ ddlmZmZmZmZmZ dd	l m!Z"m#Z$  ejJ                  e&      Z'e
jP                  d    d
k(  Z)d dZ*d!dZ+d Z,d Z-e"j\                  ddddddie"j^                  dddddie"j`                  ddddie"jb                  ddddie"jd                  ddddddie"jf                  dddddie"jh                  dddddie"jj                  ddg diie"jl                  ddi dii	e"jd                  e"jf                  dddddie"j^                  e"jf                  ddi dde"jf                  dddi die"jd                  e"jh                  i de"jh                  di iie"j^                  e"jf                  ddi dde"jf                  dddi die"jd                  e"jh                  i de"jh                  di iii i i e"j^                  ddddie"jd                  ddddiie"j^                  e"jf                  ddddidde"jf                  dddddidiie"j^                  e"jf                  ddddidde"jf                  dddddidiid
Z7 G d de8      Z9y)"    N)md5sha256   )
DEVICEFILETCPPORT)	AESCipher)ERR_CONNECTERR_DEVTYPEERR_JSONERR_KEY_OR_VERERR_OFFLINEERR_PAYLOAD
error_json)DecodeError)MessagePayloadTuyaMessagepack_messageunpack_messageparse_header)command_typesheader   c                 0   | 
|ddddi dS ddl m} | r| fnd}|r|fnd}|j                  dddd||      }d}|D ]7  }| r|| k7  r|r|||   d   k7  r||   }d	|vrd
n|d	   }	|d   |d   ||	|d} n |ddddi d}t        j	                  d|       |S )aX  Scans network for Tuya devices with either ID = dev_id or IP = address

    Parameters:
        dev_id = The specific Device ID you are looking for
        address = The IP address you are tring to find the Device ID for

    Response:
        {'ip':<ip>, 'version':<version>, 'id':<id>, 'product_id':<product_id>, 'data':<broadcast data>}
    N)ipversionid
product_iddatar   )scannerFT)verbosepoll	forcescanbyIDwantidswantipsr   
productKey r   zfind() is returning: %r)r'   r   deviceslogdebug)
dev_idaddressr   want_idswant_ipsall_resultsretgwIdresultr   s
             F/DATA/.local/lib/python3.12/site-packages/tinytuya/core/XenonDevice.pyfind_devicer4      s     ~'/T4PRSS"yH$z$H//%euSWais{/|K
Cdfnw+d"3D"99 T"'v5R6,;O
4LF9,=DWajpq  {Dt$rRII(#/J    c                 l   | st         } 	 t        | d      5 }t        j                  |      }ddd       t	        t
              r	d|v r|d   }t	        |t              sg }t        j                  d| t        |             |S # 1 sw Y   VxY w# t        $ r t        j                  d| d       g cY S w xY w)a  Load devices from a devices.json file.

    Handles both flat list and {"devices": [...]} dict formats.

    Parameters:
        fname = Path to the device file (default: DEVICEFILE)

    Response:
        list of device dicts, or empty list on failure
    rNr(   zloaded=%s [%d devices]z"Device file %s could not be loadedTexc_info)r   openjsonload
isinstancedictlistr)   r*   len	Exception)fnamefr   s      r3   load_devicefilerD   @   s     %99Q<D dD!i4&7	?D$%D		*E3t9=   		6	M	s(   B BAB B
B #B32B3c                     d}	 t               }|D ]/  }d|v s|d   | k(  st        j                  d| t               |} |S  	 |S #  Y |S xY w)zSearches the devices.json file for devices with ID = dev_id

    Parameters:
        dev_id = The specific Device ID you are looking for

    Response:
        {dict} containing the the device info, or None if not found
    Nr   zDevice %r found in %s)rD   r)   r*   r   )r+   devinfotuyadevicesdevs       r3   device_inforI   Z   sh     G	%'Cs{s4yF2		16:F
 N  N	Ns   A A A A A
c                 H   |rt        |t              rd|vrd|vr|D ]  }|dk(  rM||   rHt        ||   t              r5d| vst        | d   t              si | d<   ||   D ]  }||   |   | d   |<    U|dk(  r||   rt        ||   t              rd||   v r{t        ||   d   t              re|| vst        | |   t              sdi i| |<   d| |   vst        | |   d   t              si | |   d<   ||   d   D ]  }||   d   |   | |   d   |<    ||   | |<    yyyyy)zrMerge multiple receive() responses into a single dict

    `src` will be combined with and merged into `dest`
    ErrorErrdpsr   Nr=   r>   )destsrckdkeys       r3   merge_dps_resultsrS   q   s]   
 z#t$);S@PAEzc!fCFD)A$JtE{D,I"$DKFD(+AtDK% #fQJs1vt,DRUVWRX]ghklmhnothuw{]|D=
47D(A$bkDGQ'z$q'%.$/O%'DGENF5MD+.q6%=+>DGEN4( * a&Q  AQ);$sr5   commandr'   r1   devIduidt)rV   rW   rX   )r1   rV   dpId)         )reqTyper   )command_overriderT      int)protocolrX   r   )rX   cidrb   )
defaultdevice22zv3.4zv3.5gatewayzgateway_v3.4zgateway_v3.5zigbeezzigbee_v3.4zzigbee_v3.5c                   2   e Zd ZdddddddddddedfdZd	 Zd
 Zd Zd0dZd Z	d Z
d1dZd2dZd3dZd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd Zd0dZd4dZd  Zd0d!Zd" Zd# Zd$ Z d% Z!d& Z"d' Z#d( Z$d) Z%d* Z&d+ Z'd, Z(d- Z)e*d.        Z+d5d/Z,y)6XenonDeviceNr'   rc   r_   @Fr   c                 ~   || _         |r|n|	| _        || _        d| _        || _        | j                  dk(  | _        d| _        || _        d| _        d| _	        || _
        d| _        |sdnd| _        d| _        || _        || _        d| _        d| _        d| _        d| _        i | _        d| _        d| _        i | _        |
| _        i | _        g | _        d	| _        d
| _        d| _        i | _        i | _        d| _         |r|nd| _!        d| _"        g | _#        d| _$        |sd}|
stK        |      }|rd|v r
|d   r|d   }|jM                  d      | _'        | jN                  | _(        d| _)        | j0                  r| j                  s tK        |      }|rd|v r|d   r
|d   | _        | j                  stT        jW                  d       tX        j[                  | | j0                  j                          | j0                  j]                  |        y|r
|dk(  s|dk(  rtd| _        t_        |      }|d    tT        jW                  d       ta        d      |d   | _        | j[                  tc        |d                te        jf                  d       y|r| j[                  tc        |             ytX        j[                  | d       y)a  
        Represents a Tuya device.

        Args:
            dev_id (str): The device id.
            address (str): The network address.
            local_key (str, optional): The encryption key. Defaults to None.
            cid (str: Optional sub device id. Default to None.
            node_id (str: alias for cid)
            parent (object: gateway device this device is a child of)

        Attributes:
            port (int): The port to connect to.
        Frc   r'   TNr   r   g{Gz?   0123456789abcdefr5   keylatin1node_idz&Child device but no cid/node_id given!Autoz0.0.0.0r   5Unable to find device on network (specify IP address)r   皙?ri   )4r   rb   r,   auto_ipdev_typedev_type_autolast_dev_typeconnection_timeoutretrydisabledetectportsocketsocketPersistentsocketNODELAYsocketRetryLimitsocketRetryDelayr   version_strversion_bytesversion_headerdps_to_requestseqnosendWait	dps_cacheparentchildrenreceived_wrong_cid_queuelocal_nonceremote_noncepayload_dict_historic_status_last_status_have_statusmax_simultaneous_dpsraw_sentraw_recvcmd_retcoderI   encode	local_keyreal_local_keycipherr)   r*   rh   set_version_register_childr4   RuntimeErrorfloattimesleep)selfr+   r,   r   rs   rv   r   persistrb   rn   r   connection_retry_limitconnection_retry_delayry   r   rF   
bcast_datas                    r3   __init__zXenonDevice.__init__   s   , 37 !]]i7"4
"	-4$! 6 6!" 
(*%.  "!<P$8VW!I%v/u/GEN 'I"))(3"nn;;88%v/yG3	8J&y1DH88 		CE##D$++*=*=>KK''-g/7i3GDL$V,J$'		QR"#Z[[%d+DLU:i#89:JJsOU7^, ##D#.r5   c                 $    | j                          y N)closer   s    r3   __del__zXenonDevice.__del__Q  s    

r5   c                    | j                   r| j                   j                  }nd }| j                  j                  d| j                  d| j                  d| j
                  j                         d| j                  d| j                  d| j                  d| j                  d| j                  d	|d
| j                  dS )Nz( z
, address=z, local_key=z, dev_type=z, connection_timeout=z
, version=z
, persist=z, cid=z	, parent=z, children=z ))r   r   	__class____name__r,   r   decoders   rv   r   r{   rb   r   )r   r   s     r3   __repr__zXenonDevice.__repr__T  s    ;;[[^^FF(($''4<<ATATA[A[A]_c_l_lnr  oF  oF  HL  HT  HT  VZ  Vk  Vk  mq  mu  mu  w}  C  L  LM 	Nr5   c                    |r-| j                   !| j                   j                          d | _         | j                   d}t        }|| j                  k  r| j                  r| j
                  st        | j                        }|d   t        j                  d       t        S |d   | _        t        |d         }|| j                  k7  rv|| _        dt        | j                        z   | _        t        | j                        j                  d      | _        | j                  t         j"                  z   | _        d | _        | j
                  st        j                  d       t        S | j                  dkD  rf| j(                  rt+        | j(                        d	k7  rB| j(                  st        j                  d
       t,        S t        j                  d       t,        S t        j                   t         j.                  t         j0                        | _         | j2                  r9| j                   j5                  t         j6                  t         j8                  d       | j                   j;                  | j<                         	 |dz   }| j                   j?                  | j
                  | j@                  f       | j                  dk\  rD| jC                         ry| j                   r!| j                   j                          d | _         t,        S y|S y# t         jD                  $ r1}t        j                  d|| j                         t        }Y d }~nBd }~wtF        $ r3}t        j                  d|| j                  d       tH        }Y d }~nd }~ww xY w| j                   r!| j                   j                          d | _         || j                  k  rtK        jL                  | jN                         | j                  rd | _        || j                  k  r)Nr   r   rp   r   vrm   zNo address for device!ri      zNo local key for device!z Bad local key length for device!r   333333@Tz0socket unable to connect (timeout) - retry %d/%dz2socket unable to connect (exception) - retry %d/%dr8   )(rz   r   r   r}   rr   r,   r4   r   r)   r*   r   r   strr   r   r   HPROTOCOL_3x_HEADERr   r   r   r@   r   AF_INETSOCK_STREAMr|   
setsockoptIPPROTO_TCPTCP_NODELAY
settimeoutrv   connectry   _negotiate_session_keytimeoutrA   r	   r   r   r~   )r   renewretrieserrr   new_versiones          r3   _get_socketzXenonDevice._get_socket]  s   T[[,KKDK;;GCD111<<!,TWW!5J!$'/		"YZ**#-d#3DL"'
9(=">K"dll2 (3+.T\\1B+B(-0->-E-Eh-O*.2.@.@1CWCW.W+,0)||II67&&LL3&$..c$..FY]_F_>>		"<= *) 		"DE))$mmFNNF<N<NO%%KK**6+=+=v?Q?QSTU&&t'>'>?&%kGKK''tyy(AB||s*668#'#{{ $ 1 1 3.2#11#. J1 ~~ &IIJ!6!6 &C  &IIL!6!6   &C& ;;KK%%'"&DKT222JJt445<<#'DLE D111s+   =AL
 2L
 
N'M		N)NNc                     |s| j                   s?| j                  r2| j                  j                          d | _        | j                          y y y r   r{   rz   r   cache_clear)r   forces     r3   _check_socket_closezXenonDevice._check_socket_close  s?    ..DKKKKDK 5@.r5   c                 R   d}d}|dkD  r| j                   j                  |      }|rt        |      dk(  rWt        j	                  d|       |dz  }|dk(  rt        d      | j                  t        j                  | j                         ||z  }|t        |      z  }d}|dkD  r|S )Nr   r5   r   z_recv_all(): no data? %rr   z%No data received - connection closed?)	rz   recvr@   r)   r*   r   r   r   r   )r   lengthtriesr   newdatas        r3   	_recv_allzXenonDevice._recv_all  s    qjkk&&v.Gc'la/		4g>
A:%&MNN==,JJt}}-GODc'l"FE qj r5   c                    | j                   r| j                   j                         S t        j                  t        j
                        dz   dz   t        t        j                        z   }t        j                  t        j                        dz   dz   dz   t        t        j                        z   }||k  r|n|}t        t        j                        }| j                  |      }|j                  t        j                        }|j                  t        j                        }|dk7  r|dk7  rt        j                  d       t        j                  d|||       |dk  r|dk  r	|d|z
  d  }n|dk  r|n|}||d  }|| j                  |t        |      z
        z  }|j                  t        j                        }|j                  t        j                        }|dk7  r|dk7  rt        |      }	|	j                   t        |      z
  }
|
dkD  r|| j                  |
      z  }t        j                  dt#        j$                  |             | j&                  d	k\  r| j(                  nd }d
}t+        ||	||      S )N      r   r   z9Message prefix not at the beginning of the received data!z,Offset 55AA: %d, 6699: %d, Received data: %rr   zreceived data=%rr   F)r   hmac_key
no_retcode)r   _receivestructcalcsizer   MESSAGE_HEADER_FMT_55AAr@   
SUFFIX_BINMESSAGE_HEADER_FMT_6699PREFIX_55AA_BINr   findPREFIX_6699_BINr)   r*   r   total_lengthbinasciihexlifyr   r   r   )r   min_len_55AAmin_len_6699min_len
prefix_lenr   prefix_offset_55AAprefix_offset_6699prefix_offsetr   	remainingr   r   s                r3   r   zXenonDevice._receive  s    ;;;;''))q'@'@AAEICPQP\P\L]]q'@'@ABFJRORUVWVbVbRcc"."=,<!++-
~~w( "YY(9(9;!YY(9(9; A%*<*AIIQRIIDFXZlnrs!A%*<q*@AjLM*6H16L 2RdMN+DNNGc$i$799D!%A,=,=!?!%A,=,=!? !A%*<*A d#''#d)3	q=DNNI//D		$h&6&6t&<=%)\\S%84>>d
d6HQ[\\r5   c                    | j                   r| j                   j                  |||       S t        j                  d       d | _        g | _        d | _        | j                  d      dury t        |      t        k(  r| j                  |      n|}	 | j                  j                  |       	 t        |      | _        |sy|r	 | j                         }| j
                  j!                  |       |r6| j#                  | j                  |       t%        |j&                        dk7  r|S |dz  }|dk(  rt        j                  d|       nt        j                  d||       |ry#  | j                  d       Y y xY w#  d | _        Y xY w#  d }Y xY w)	N
from_childzsending payload quickFTr   r   z=received null payload (%r) but out of recv retries, giving upz@received null payload (%r), fetch new one - %s retries remaining)r   _send_receive_quickr)   r*   r   r   r   r   typer   _encode_messagerz   sendallr   r   r   append_get_retcoder@   payload)r   r   recv_retriesr   enc_payloadmsgs         r3   r   zXenonDevice._send_receive_quick  sp   ;;;;227LUY2ZZ		)*E"$.7;G}7Vd**73\c	KK,	!(5DM mmo$$S) !!$--5s{{#q(JALq 		Y[^_		\^acop  1	$$T*	! DMs$   E  +E8 +F  E58	FFc                 	   | j                   r | j                   j                  |||||       S |s|r| j                  rt| j                  r|s%| j                  d   }| j                  dd | _        |S d}| j                  D ]  }|d   |k(  s|} n |r | j                  j	                  |       |d   S d}	d}
d}d}| j
                  sdn| j                  }| j                  }d}d}g | _        d| _	        |	s| j                  d      }|dur(| j                  d       t        |r|      S t              S 	 ||rt        j                  d       t!        |      t"        k(  r| j%                  |      n|}| j&                  j)                  |       	 t+        |      | _        | j.                  t1        j2                  | j.                         |rd}| j5                         }|r=d}d}
|}| j                  j7                  |       | j9                  | j,                  |       |rt;        |j<                        dk(  r*||k  r%t        j                  d|||       |dz  }||kD  r-d}	n*d}	t        j                  d	|       n| j                          y|	s|s| j                          |S | jO                  |||||      S #  d| _        Y %xY w# t>        t@        f$ r}t        j                  d
        d}~wt&        jB                  $ r}|| j                          Y d}~yd}|dz  }| j                  d       t        j                  d|| j                         || j                  kD  r4t        j                  d| j                         t        tD              cY d}~S t1        j2                  d       Y d}~%d}~wtF        $ rj}t        j                  d||d       |dz  }||kD  r<|
r| j                          Y d}~y| j                  d       t        tH              cY d}~S Y d}~d}~wtJ        $ r}d}|dz  }| j                  d       t        j                  d|| j                  d       || j                  kD  rIt        j                  d| j                         t        j                  d       t        tL              cY d}~S t1        j2                  d       Y d}~Pd}~ww xY w)a9  
        Send single buffer `payload` and receive a single buffer.

        Args:
            payload(bytes): Data to send. Set to 'None' to receive only.
            minresponse(int): Minimum response size expected (default=28 bytes)
            getresponse(bool): If True, wait for and return response.
        r   r   r   NFTzsending payloadz9received null payload (%r), fetch new one - retry %s / %szreceived message=%rzKeyboard Interrupt - Exitingz*Timeout in _send_receive() - retry %s / %sz"Exceeded tinytuya retry limit (%s)rq   z/Error decoding received data - read retry %s/%sr8   z9Network connection error in _send_receive() - retry %s/%szUnable to connect to device )(r   _send_receiver   r   removerw   r}   rs   r   r   r   r   r   r   r)   r*   r   r   r   rz   r   r   r   r   r   r   r   r   r   r@   r   KeyboardInterrupt
SystemExitr   r   r   r   rA   r	   _process_message)r   r   minresponsegetresponsedecode_responser   r7   found_rqrqsuccesspartial_successr   r   max_recv_retriesrs   do_sendr   sock_resultr   rmsgr   s                        r3   r   zXenonDevice._send_receive  sz    ;;;;,,Wk;P_lp,qq[T-J-JMM:11!4040M0Mab0Q-H33a5J&!H 4 --44X>{"$(JJ1D4I4I==**51K$&((.!+;PP;PP\ &7II/0CG=TbCb$"6"6w"?hoKKK''4-(4[(A }}0

4==1#G==?D "&*.",,T2))$-->3s{{#3q#8lN^>^		"]_bdp  sC  D$)'*::&*G"&		"7= ,,.S R $$&J$$c8Zo__-(,4 &z2 		89>>  ?,,.1((.		@T22
 T222II<--
 &n55

3 
3		K\[kvz	{!"22&002#,,T2%k22 3   1((.		OT22T  
 T222II<-- II<=%k22

3) s   2AK J5 C+K 5	K>K SK))S?N-A6N-SN--S95P3PSS*BS7S=SSc                    |rt        |j                        dk(  r't        j                  d|       | j	                          y 	 t        j                  d|       | j                  |j                        }|t        j                  d       |r?|| j                  k7  r0t        j                  d|| j                         t        t              }d}| j                  r/d }|r
d	|v r|d	   }n*|r(d
|v r$t        |d
         t        k(  rd	|d
   v r|d
   d	   }|rC| j                  D ]4  }	| j                  |	   j                  |k(  s | j                  |	   x|d<   } n |r|dur||k7  rt        j                  d||j                         | j                  rd|r#|j                  |       |j!                  |      }n"| j                  |       | j!                  |      }| j"                  j%                  ||f       | j'                  d |d||      S | j	                          |r"|j                  |       |j!                  |      S | j                  |       | j!                  |      S #  t        j                  dd       t        t              }Y  xY w)Nr   zraw unpacked message = %rz_decode_payload() failed!z-error unpacking or decoding tuya JSON payloadTr8   zGDevice22 detected and updated (%s -> %s) - Update payload and try againFrb   r   devicezMRecieved async update for wrong CID %s while looking for CID %s, trying againr   )r@   r   r)   r*   r   _decode_payloadr   r   rs   r
   r   r   r>   rb   r{   _cache_response_process_responser   r   r   )
r   r   rs   r   r   r   r2   found_child	found_cidcs
             r3   r   zXenonDevice._process_message  sm   c#++&!+II137$$&		-II137))#++6F~		56 DMM1IIY
  ,F==I%6/"5M	Ff,fVn1E1MRW[abh[iRi"6N51	A}}Q'++y89=q9IIx(; '
 j4{9R		jlu  xB  xF  xF  H(( ##33F;!,!>!>v!F,,V4!%!7!7!?1188;:OQ))4dO`j)kk 	  "''/0088V$%%f--g	-IIEPTIU,Fs   AI   (Jc                 ^   t         j                  d|       t        | j                        }| j                  dk(  r`	 t         j                  d|       |j                  |dd      }t         j                  d	|       t         j                  d
t        |             |j                  t        j                        r4|t        t        j                        d  }|j                  |dd  d      }n| j                  dk\  rw|j                  | j                        r/|t        | j                        d  }t         j                  d|       nN| j                  dk(  r?t        |      dz  dk7  r.|t        | j                        d  }t         j                  d|       | j                  dk  r`	 t         j                  d|       |j                  |dd      }t         j                  d	|       t         j                  d
t        |             t!        |t"              r|j%                  d      }| j&                  szd|v rv| j                  dv rhd| _        dd i| _        t         j                  d| j                         y |j                  d      s&t         j                  d|       t        t        |      S d }t!        |t"              sF	 |j+                         }t!        |t"              s%t         j                  d       t        t.        |      S t         j                  d|       	 t1        j2                  |      }|rt!        |t4              r||d <   d!|vrd"|v rd!|d"   v r|d"   d!   |d!<   |S #  t         j                  d|t        |      d       t        t              cY S xY w#  t         j                  d|t        |      d       t        t              cY S xY w# t,        $ r1 |d d dk(  r%|dd  dk(  r	 |}|j+                  d      }n#  Y nxY wY = Y AxY w#  t        t.        |      }||d <   Y xY w)#Nzdecode payload=%rr   decrypting=%rFdecode_textzincomplete payload=%r (len:%d)Tr8   zdecrypted 3.x payload=%rzpayload type = %sr   皙	@zremoving 3.x=%rrd      r   zremoving device22 3.x header=%rutf-8s   data unvalid)gffffff
@r   1z7'data unvalid' error detected: switching to dev_type %r   {zUnexpected payload=%rr      }replace)errorsz/payload was not string type and decoding failedzdecoded results=%rinvalid_jsonrM   r   )r)   r*   r   r   r   decryptr@   r   r   r   
startswithr   PROTOCOL_VERSION_BYTES_31r   r   rs   r=   r   r   rx   r   r   UnicodeDecodeErrorr   r;   loadsr>   )r   r   r   r  json_payloads        r3   r  zXenonDevice._decode_payload  s   		%w/4>>*<<3/		/73 ..%U.K
 II0':II)4=9a99: c!"="=>@AG nnWRS\unEG\\S !!4#5#57!#d&9&9":"<=		+W5*,#g,2E!1K!#d&9&9":"<=		;WE||c!3IIow7$nnWenOG
 		4g>		-tG}='3'!..1%%/W*DYcIc *'*Dk#		MMM ##D)II-w7k733'3'
!..* gs+		KL!(G44		&0	3::g.L
 J|T:+7L( $<)?E\Z`MaDa".v"6u"=Lk/		:GS\\`	a!+..23II>W`dIe%k224 & BQK4'gbcld.B'.")..."D	3%h8L+2L(sM   *M# &*N ?O P #3N3OP-PPPPPP,c                     t        | j                  |       | j                  r| j                  syt        j                  d|       t        | j                  |       t        j                  d| j                         y)z9
        Save (cache) the last value of every DP
        Nzcaching: %sz
merged: %s)rS   r   r{   rz   r)   r*   r   r   responses     r3   r  zXenonDevice._cache_responseW  sX     	$//:%%t{{		-*$++X6		, 1 12r5   c                     |S )zn
        Override this function in a sub-class if you want to do some processing on the received data
         r"  s     r3   r	  zXenonDevice._process_responsed  s	     r5   c                     | j                  | j                         d      }| j                  |      }|sy| j                  |d        | j                          y)Nr   FT)r   &_negotiate_session_key_generate_step_1&_negotiate_session_key_generate_step_3(_negotiate_session_key_generate_finalize)r   rkeystep3s      r3   r   z"XenonDevice._negotiate_session_keyj  sS    '')T)T)VXY[;;TC  %/557r5   c                     d| _         d| _        | j                  | _        t	        t
        j                  | j                         S )Nrk   r5   )r   r   r   r   r   CTSESS_KEY_NEG_STARTr   s    r3   r'  z2XenonDevice._negotiate_session_key_generate_step_1s  s8    .,,b33T5E5EFFr5   c           	         |r*t        |      t        k7  st        |j                        dk  rt        j                  d       y|j                  t        j                  k7  r!t        j                  d|j                         y|j                  }| j                  dk(  r@	 t        j                  d|       t        | j                        }|j                  |dd      }t        j                  d|       t        j                  dt        |      t        |             t        |      dk  rt        j                  d       y|d d | _        t        j                  | j                   | j"                  t$              j'                         }||dd k7  rAt        j                  dt)        j*                  |      t)        j*                  |dd              yt        j                  d| j"                  | j                         t        j                  | j                   | j                  t$              j'                         }t-        t        j.                  |      S #  t        j                  d|t        |      d	
       Y yxY w)N0   z(session key negotiation failed on step 1Fz9session key negotiation step 2 returned wrong command: %dr   r  r  z6session key step 2 decrypt failed, payload=%r (len:%d)Tr8   z3decrypted session key negotiation step 2 payload=%rzpayload type = %s len = %dz9session key negotiation step 2 failed, too short responser   zFsession key negotiation step 2 failed HMAC check! wanted=%r but got=%rz(session local nonce: %r remote nonce: %r)r   r   r@   r   r)   r*   cmdr-  SESS_KEY_NEG_RESPr   r   r   r  r   hmacnewr   r   r   digestr   r   r   SESS_KEY_NEG_FINISH)r   r*  r   r   
hmac_check	rkey_hmacs         r3   r(  z2XenonDevice._negotiate_session_key_generate_step_3z  s   tDz[0C4E4JII@A88r+++IIQSWS[S[\,,<<3		/73"4#6#67 ..%U.K
 			GQ		.Ws7|Lw<"IIQR#CRLXXdnnd.>.>GNNP
B'II^`h`p`pq{`|  G  O  O  PW  XZ  []  P^  _  `		<d>N>NPTPaPabHHT^^T->->GNNP	b44i@@+		RT[]`ah]itx	ys   ?I $I7c           
      &   t         rgt        | j                  | j                        D cg c]%  \  }}t	        t        |      t        |      z        ' }}}dj                  |      | _        nDt        t        | j                  | j                        D cg c]
  \  }}||z   c}}      | _        t        j                  d| j                         t        | j                        }| j                  dk(  r$|j                  | j                  dd      | _        nL| j                  d d }t        j                  d|       |j                  | j                  dd|      dd	 | _        t        j                  d
| j                         yc c}}w c c}}w )Nr'   zSession nonce XOR'd: %rr   F)padr   zSession IV: %r)
use_base64r:  iv   z.Session key negotiate success! session key: %rT)IS_PY2zipr   r   chrordjoinr   bytesr)   r*   r   r   r   encrypt)r   abrQ   r   r<  s         r3   r)  z4XenonDevice._negotiate_session_key_generate_finalize  s=   25d6F6FtGXGX2Y[2Y!A#c!fSVm$2YA[WWQZDN"s4;K;KDL]L]7^$`7^eqac7^$`bDN		+T^^<4../<<3#^^T^^U^ODN!!#2&BII&+#^^T^^SX]_^abdeghDN		BDNNS \ %as   *FF
c           
         | j                   r| j                   j                  |      S d }d }|j                  }t        | j                        | _        | j                  dk\  r| j                  }|j                  t        j                  vr| j                  |z   }t        j                  d|       | j                  dk\  rd}t        | j                  |j                  d |ddt        j                  d      }| xj                  dz  c_        t!        || j                        }t        j                  d| j                  t#        j$                  |             |S | j
                  j'                  |d	      }n| j                  d
k\  rH| j
                  j'                  |d	      }|j                  t        j                  vr| j                  |z   }n|j                  t(        j*                  k(  r| j
                  j'                  |      }d|z   dz   t        j,                  z   dz   | j                  z   }t/               }|j1                  |       |j3                         }t        j,                  |dd  d d j5                  d      z   |z   }d | _        t        | j                  |j                  d|ddt        j6                  d	      }| xj                  dz  c_        t!        ||      }	t        j                  dt#        j$                  |	             |	S )Nr   zfinal payload: %r      @Tr   r   )r   zpayload [%d] encrypted=%rFr  s   data=s   ||lpv=s   ||   r   rm   zpayload encrypted=%r)r   r   r   r   r   r   r   r1  r   NO_PROTOCOL_HEADER_CMDSr   r)   r*   r   r   PREFIX_6699_VALUEr   r   r   rD  r-  CONTROLr  r   update	hexdigestr   PREFIX_55AA_VALUE)
r   r   r   r<  r   r   preMd5StringmrN  buffers
             r3   r   zXenonDevice._encode_message  s   ;;;;..55++/<<3~~Hwwa777--7II)73||s"!$**cggtWaqObObdhi

a
#C@		5djj(BRBRSWBXZkk))'59G\\S kk))'59Gwwa777--7WW

"kk))'2G --. 	
 ..!  AHH\"I ++AB-$++H56  $**cggq'1dADWDWY^_

a
c84		()9)9&)ABr5   c                     |r|sy|j                   |j                   k7  ry| j                  dk  r|j                  |j                  k7  ry|j                  | _        y)z0Try to get the retcode for the last sent messageNrH  )r1  r   r   retcoder   )r   sentr   s      r3   r   zXenonDevice._get_retcode  sH    c88sww<<#zzSYY&;;r5   c                     |j                   | j                  v r<|| j                  |j                      k7  r t        j                  d|j                          || j                  |j                   <   d| _        d | _        y )NzReplacing existing child %r!T)r   r   r)   r*   rx   r   )r   childs     r3   r   zXenonDevice._register_child  s[    88t}}$$--2I)III4ehh?"'ehh! r5   c                 $    | j                  d      S )zc
        Poll device to read any payload in the buffer.  Timeout results in None returned.
        Nr   r   s    r3   receivezXenonDevice.receive  s     !!$''r5   c                 *    | j                  |dd      S )zh
        Send single buffer `payload`.

        Args:
            payload(bytes): Data to send.
        r   Fr   rY  )r   r   s     r3   sendzXenonDevice.send  s     !!'1%!@@r5   c                 
   t         j                  }t        j                  d| j                         | j                  |      }| j                  |d|       }t        j                  d|       |s|rd|v r|d   t        t              k(  r9t        j                  d       | j                  |      }| j                  |      }|S |d   t        t              k(  r+t        j                  d| j                  | j                         |S )zReturn device status.zstatus() entry (dev_type is %s)r   r\  zstatus() received data=%rrL   z(status() rebuilding payload for device22zIStatus request returned an error, is version %r and local key %r correct?)r-  DP_QUERYr)   r*   rs   generate_payloadr   r   r
   r   r   r   )r   nowait
query_typer   r   s        r3   statuszXenonDevice.status  s    [[
		3T]]C''
3!!'1v:!G		-t4DUd]E{c+..		DE//
;))'2  eK 00		egkgsgsuy  vD  vD  Er5   c                    |r| j                   S | j                  r$| j                  r| j                  r| j                  s=|s%t
        j                  d       | j                         S t
        j                  d       y| j                  S )a  
        Return device last status if a persistent connection is open.

        Args:
            nowait(bool): If cached status is is not available, either call status() (when nowait=False) or immediately return None (when nowait=True)

        Response:
            json if cache is available, else
                json from status() if nowait=False, or
                None if nowait=True
        z@Last status caching not available, requesting status from devicez1Last status caching not available, returning NoneN)r   r   r{   rz   r   r)   r*   rc  )r   historicra  s      r3   cached_statuszXenonDevice.cached_status(  sm     (((!!4+@+@$++_c_p_p		\]{{}$IIIJ    r5   c                      i | _         d| _        y )NF)r   r   r   s    r3   r   zXenonDevice.cache_clear@  s    !r5   c                 t    | j                  t        j                  dg id      }| j                  |d|       S )z0Query for a list of sub-devices and their statuscidssubdev_online_stat_query)rawDatar]   r   r\  )r`  r-  LAN_EXT_STREAMr   )r   ra  r   s      r3   subdev_queryzXenonDevice.subdev_queryD  s@     ''(9(9F2;Xr's!!'1v:!GGr5   c                    i | _         g d}|D ]  }ddi| _        | j                  t        |        	 | j	                         }|d|v r|d   D ]  }d| j                   |<    | j                  dk(  sc| j                   | _        | j                   c S  t        j                  d| j                          | j                   | _        | j                   S # t
        $ r}t        j                  d|        d}~ww xY w)z4Return which datapoints are supported by the device.)	)r      )ro     )rp     )2   =   )rs  G   )d   o   )rv  y   )rw     )rx     r  NzFailed to get status: %srM   rc   zDetected dps: %s)
r   r   add_dps_to_requestrangerc  rA   r)   	exceptionrs   r*   )r   ranges	dps_ranger   exrQ   s         r3   detect_available_dpsz XenonDevice.detect_available_dpsJ  s     rI $'+D##E9$56{{} ETMeA(,DNN1% % }}	)&*nn#~~%!  " 			$dnn5"nn~~  8"=s   C	C3C..C3c                     t        |t              rd| j                  t        |      <   y| j                  j	                  |D ci c]  }t        |      d c}       yc c}w )z0Add a datapoint (DP) to be included in requests.N)r=   r`   r   r   rM  )r   dp_indiciesindexs      r3   rz  zXenonDevice.add_dps_to_requesti  sP    k3'48DK 01&&k'RkUE
D(8k'RS'Rs   Ac                 8   t        |      }|| _        dt        |      z   | _        t        |      j	                  d      | _        | j
                  t        j                  z   | _        d | _	        |dk(  r(d| _
        | j                  i k(  r| j                          y y y )Nr   rm   r  rd   )r   r   r   r   r   r   r   r   r   r   rs   r   r  )r   r   s     r3   r   zXenonDevice.set_versionp  s    .W- \00:"0013G3GG c>$DM""b())+ ) r5   c                     || _         | j                  r5|s2| j                  j                          d | _        | j                          y y y r   r   )r   r   s     r3   set_socketPersistentz XenonDevice.set_socketPersistent|  s=     ';;wKKDK  ';r5   c                    || _         | j                  rv|r:| j                  j                  t        j                  t        j                  d       y | j                  j                  t        j                  t        j                  d       y y )Nr   r   )r|   rz   r   r   r   )r   nodelays     r3   set_socketNODELAYzXenonDevice.set_socketNODELAY  s]    $;;&&v'9'96;M;MqQ&&v'9'96;M;MqQ	 r5   c                     || _         y r   )r}   )r   limits     r3   set_socketRetryLimitz XenonDevice.set_socketRetryLimit  
     %r5   c                     || _         y r   )r~   )r   delays     r3   set_socketRetryDelayz XenonDevice.set_socketRetryDelay  r  r5   c                 b    || _         | j                  r| j                  j                  |       y y r   )rv   rz   r   r   ss     r3   set_socketTimeoutzXenonDevice.set_socketTimeout  s(    "#;;KK""1% r5   c                     || _         y r   )r   )r   r   s     r3   set_dpsUsedzXenonDevice.set_dpsUsed  s
    ,r5   c                     || _         y r   )rw   )r   rw   s     r3   	set_retryzXenonDevice.set_retry  s	    
r5   c                     || _         y r   )r   r  s     r3   set_sendWaitzXenonDevice.set_sendWait  s	    r5   c                 |    	 | j                   r| j                   j                          d | _         y #  Y d | _         y xY wr   )rz   r   r   s    r3   r   zXenonDevice.close  s8    	{{!!# 	s   &0 ;c                 .    t        |       }|d   |d   fS )a  
        Mainly here for backwards compatibility.
        Calling tinytuya.find_device() directly is recommended.

        Parameters:
            did = The specific Device ID you are looking for (returns only IP and Version)

        Response:
            (ip, version)
        )r+   r   r   )r4   )didr   s     r3   r   zXenonDevice.find  s#     !,
4 *Y"788r5   c                    fdfd}| j                   r| j                  | j                  k7  ri | _          || j                   t         d          | j                  r || j                   t         d          | j                  r || j                   t         d          | j
                  t         v r$ || j                   t         | j
                            | j                  r<d| j
                  z   t         v r' || j                   t         d| j
                  z             | j                  r<d| j
                  z   t         v r' || j                   t         d| j
                  z             | j                  dk7  r$ || j                   t         | j                            t        j                  d| j                  | j
                  | j                  | j                          | j                  | _        d	x}	}
|| j                   v rFd
| j                   |   v r| j                   |   d
   }	d| j                   |   v r| j                   |   d   }
|
|}
|t        j                  k(  s|t        j                  k(  rd| _        |	ddddd}	|	j                         }	d|	v r=|||	d<   n5| j                  r| j                  j                  |	d<   n| j                  |	d<   d|	v r|||	d<   n| j                  |	d<   d|	v r|||	d<   n| j                  |	d<   | j                  r-| j                  |	d<   d|	v r| j                  |	d   d<   d|	d   d<   d|	v rR|	d   dk(  r!t        t!        j                                |	d<   n)t#        t        t!        j                                      |	d<   |
d|	v r||	d<   nP|d|	v r||	d<   nDd|	v r	||	d   d<   n7||	d<   n1| j                  dk(  r"|t        j                  k(  r| j$                  |	d<   |r	d|	v r||	d<   |	dk(  rd}nt'        j(                  |	      }|j+                  dd      }|j-                  d      }t        j                  d||       t/        |
|      S )a  
        Generate the payload to send.

        Args:
            command(str): The type of command.
                This is one of the entries from payload_dict
            data(dict, optional): The data to send.
                This is what will be passed via the 'dps' entry
            gwId(str, optional): Will be used for gwId
            devId(str, optional): Will be used for devId
            uid(str, optional): Will be used for uid
        c                 n    i }| D ],  }t        | |   t              r | |         ||<   %| |   ||<   . |S r   rN   )dict1r2   rQ   	_deepcopys      r3   r  z/XenonDevice.generate_payload.<locals>._deepcopy  sF    FuQx/ )58 5F1I %aF1I	 
 Mr5   c                     |D ]X  }|| vr ||         | |<   ||   D ];  }t        ||   |   t              s||   |   | |   |<   ( ||   |         | |   |<   = Z y r   rN   )r  dict2r1  varr  s       r3   _merge_payload_dictsz:XenonDevice.generate_payload.<locals>._merge_payload_dicts  sx    e#!*E#J!8E#J$Sz)5:c?DB.3CjoE#JsO /8sC.JE#JsO  * r5   rc   re   rf   gateway_zigbee_z%final payload_dict for %r (%r/%r): %rNrT   r^   Tr'   rU   r1   rV   rW   rb   r   r   ctyperX   r`   rY   rM   rd   r]    r  zbuilding command %s payload=%r)r   ru   rs   r   rb   r   r)   r*   r   r-  r_  DP_QUERY_NEWr   copyr   r`   r   r   r   r;   dumpsr  r   r   )r   rT   r   r1   rV   rW   rk  r]   r  	json_datar^   r   r  s               @r3   r`  zXenonDevice.generate_payload  s&   		K$   D$6$6$--$G "D $"3"3\)5LN}}$d&7&7i9PRxx$d&7&7h9OQ</$d&7&7dFVFV9WY}}*T-=-="=,!N$d&7&7jQUQaQaFa9bdxxYt'7'77LH$d&7&7iPTP`P`F`9ac}}	)$d&7&7dmm9TVII>IYIY[_[h[hjnj{j{}!%D'++	$d'''D--g66 --g6yA	!T%6%6w%??#'#4#4W#=>P#Q #&bkk!W%? $D "$b"EI NN$	Y$(	&!$(KKNN	&!$(GG	&!i %*	'"%)WW	'"I#&	% #'77	% 88#xxIe"+/88	&!%(-.	&!'* )~&!$TYY[!1	#!$S%5!6	#6Y#6 'If"$(	&!9$+/	&!%(#'	% ]]j(W-C#22IeyI-#*Ii  ?Gjj+G//#r*..)		2GWE .88r5   )Fr   )r=  TTN)NNr=  T)FF)NNNNNN)-r   
__module____qualname__r   r   r   r   r   r   r   r   r   r   r   r  r  r	  r   r'  r(  r)  r   r   r   rZ  r]  rc  rf  r   rm  r  rz  r   r  r  r  r  r  r  r  r  r   staticmethodr   r`  r%  r5   r3   rh   rh      s   "&"y]^tT$#$QW!"b/HNOb(']T%NS`jG.R^@3G%AN(:x
'!(A(!0"H>T
,R&&&
-	 9 9K9r5   rh   )NNr   ):r   r3  r;   hashlibr   r   loggingrz   r   r   sysconstr   r   crypto_helperr   error_helperr	   r
   r   r   r   r   r   
exceptionsr   message_helperr   r   r   r   r   r'   r   r-  r   r   	getLoggerr   r)   version_infor>  r4   rD   rI   rS   	AP_CONFIGrL  STATUS
HEART_BEATr_  CONTROL_NEWr  	UPDATEDPSrl  r   objectrh   r%  r5   r3   <module>r     s"           
 & $ r r r # c c .g! 
		!		!$L4.!D 	RD
 	

BR8
 			R0
 		B#<=
RD
 	b"$EF
)r"2%FG
y6<"89
YR(EF#. 	 "!#BR8
 	

 "#$5"= 	15"=
 	 "
 	r
$ 	

 "#$5"=
 	15"=
 	 "
 	r
" 


iuR!8:
yb"9;
 	

 "#$55*E
 	155*E
 	

 "#$55*E
 	155*E
cZxX9& X9r5   