
     j80                    >   S r SSKJr  SSKrSSKrSSKJr  SSKJr  SSKJ	r	  Sr
SrSrS	rS
rSr\SSSSSSSSS\SSSSSSS0	rSrSrSrSrS4S  jrS5S! jr\ " S" S#5      5       r\ " S$ S%5      5       r " S& S'\5      rS6S( jrS7S) jr " S* S+5      rS,S-S.S/S0.rS1S2S3.rg)8ue   
Cliente protocolo Anviz (TCP puerto 5010).
Basado en coyotevz/anviz y documentación del protocolo.
    )annotationsN)	dataclass)datetime)Iterator            g   _7Au!   operación rechazada por el reloj   zmemoria de usuarios llena   zsin usuarios   zusuario no existe   ztiempo de espera agotadou'   contraseña de comunicación incorrecta
   zusuario ya existe   zhuella ya registrada   zdispositivo bloqueado<   @   8   (   r   i  i#  i2  i$F  iW  i6e  it  iH  i  iZ  iӾ  il  i  i~  i  i  i  i3  i"  iV  i,G  iu  i>d  iɜ  i@  iۿ  iR  i  id  i  iv  i!  i0  i  i  i&g  iv  i4D  iU  iJ  iü  iX  iџ  in  i  i|  i  i1  i
   i  i  iw  i.f  iT  i<E  i˽  iB  iٞ  iP  i  if  i  it  iB  iS  ia  ip  i   i  i2'  i6  iL  i  i^  i  ih  i  iz  i  iR  iC  iq  i`  i  i(  i7  i:&  i  iD  i  iV  i  i`  i  ir  ic  ir  i@  iQ  i"%  i4  i0  i  iN  i  i\  i  ij  i  ix  i  is  ib  iP  iA  i5  i*$  i  i8  i  iF  i  iT  i  ib  i  ip  i  i  i  i  i,  i  i>  i  i@  i  iR+  i:  idN  i_  ivm  i|  i  i   i  i  i  i$  i  i6  i  iH	  i;  iZ*  i^  ilO  i}  i~l  i
  i  i  i  i.  i  i<  i  iB)  i8  iP
  i  ifo  i~  itL  i]  i  i  i  i  i  i&  i  i4  i9  iJ(  i  iX  i  inn  i\  i|M  i  i  i  i  i(  i  i:  i  iDJ  i[  iVi  ix  i`  i  ir/  i>  i  i  i  i  i  i   i  i2  iZ  iLK  iy  i^h  i  ih  i?  iz.  i  i  i  i  i*  i  i8  i  iFk  iz  iTH  iY  ib-  i<  ip  i  i  i  i  i  i  i"  i  i0  i{  iNj  iX  i\I  i=  ij,  i  ix  c                r    SnU  H  nX-  nUS-	  [         US-     -  nM     [        R                  " SU5      $ )Ni  r      z<H)
_CRC_TABLEstructpack)datacrcbs      +/var/www/reloj-farallon/app/anviz_client.pycrc16r   E   sB    
Cax:cDj11  ;;tS!!    c                ,    SU-  [        U 5      -   U* S  $ )N    )bytes)r   ns     r   
_left_fillr$   M   s    aK%("QBC((r   c                  H    \ rS rSr% S\S'   S\S'   S\S'   S\S'   S\S'   S	rg
)AnvizRecordQ   int	user_coder   	timestampbackup_typerecord_type	work_type N__name__
__module____qualname____firstlineno____annotations____static_attributes__r.   r   r   r&   r&   Q   s    NNr   r&   c                  *    \ rS rSr% S\S'   S\S'   Srg)RecordsInfoZ   r(   all_recordsnew_recordsr.   Nr/   r.   r   r   r7   r7   Z   s    r   r7   c                      \ rS rSrSrg)
AnvizError`   r.   N)r0   r1   r2   r3   r5   r.   r   r   r<   r<   `   s    r   r<   c                    U b  U S:X  d  U S:X  a  g[        U 5      R                  5       nUR                  5       (       d  [        S5      e[	        U5      S:  a  [        S5      e[        U5      nUR                  SSS	9$ )
u   
Codifica la contraseña de comunicación Anviz (Comm.PW / PW Setting).
Formato: 3 bytes según protocolo SET_INFO (valor numérico, ej. 12345 → 00 30 39).
N r   uE   La contraseña de comunicación debe ser numérica (máx. 5 dígitos)r   u9   La contraseña de comunicación admite máximo 5 dígitos   big)	byteorder)strstripisdigit
ValueErrorlenr(   to_bytes)passwordpwdvalues      r   encode_comm_passwordrL   d   su    
 8r>X]
h-


C;;==`aa
3x!|TUUHE>>!u>--r   c                ,   [        U 5      R                  5       n[        [        U5      S5      nSR	                  S U 5       5      nUSS n[        X$-   S5      n[        USS S5      n[        U5      S:  a  [        USS S5      OS	n[        XVU/5      $ )
uA   Formato alternativo BCD por dígito (algunos firmwares antiguos).04br?   c              3  L   #    U  H  n[        [        U5      S 5      v   M     g7f)rN   N)formatr(   ).0ds     r   	<genexpr>+encode_comm_password_bcd.<locals>.<genexpr>x   s     :cvc!fe,,cs   "$Nr            r   )rC   rD   rP   rG   joinr(   r"   )rI   rJ   pass_len_binpass_binfirst4byte0byte1byte2s           r   encode_comm_password_bcdr_   t   s    
h-


C#c(E*Lww:c::Hbq\F%q)E2"E'*8}':CB#E%&''r   c                      \ rS rSr   S         SS jjrSS jrSS jrSS jrSS jrSSS jjr	SS	 jr
SS
 jrSS jrSSS jjrS S jrS!S jr\S"S j5       r\S#S j5       rS$S jrS%S jrS%S jrSrg)&AnvizDevicer   Nc                n    Xl         X l        X0l        X@l        XPl        [        U5      U l        S U l        g N)	device_idhostporttimeoutcomm_passwordrL   _comm_password_bytes_sock)selfrd   re   rf   rg   rh   s         r   __init__AnvizDevice.__init__   s2     #		*2F}2U!+/
r   c                   U R                  5         [        R                  " [        R                  [        R                  5      nUR	                  U R
                  5        UR                  U R                  U R                  45        Xl	        g rc   )
closesocketAF_INETSOCK_STREAM
settimeoutrg   connectre   rf   rj   )rk   socks     r   rt   AnvizDevice.connect   sS    

}}V^^V-?-?@%dii+,
r   c                    U R                   (       a#   U R                   R                  5         S U l         g g ! [         a     Nf = frc   )rj   ro   OSErrorrk   s    r   ro   AnvizDevice.close   s@    ::

  " DJ   s   6 
AAc                &    U R                  5         U $ rc   )rt   ry   s    r   	__enter__AnvizDevice.__enter__   s    r   c                $    U R                  5         g rc   )ro   )rk   _s     r   __exit__AnvizDevice.__exit__   s    

r   c                |   [        [        /5      nUR                  [        R                  " SU R
                  5      5        UR                  U5        UR                  [        R                  " S[        U5      5      5        U(       a  UR                  U5        UR                  [        U5      5        [        U5      $ )Nz>L>H)
	bytearraySTXextendr   r   rd   appendrG   r   r"   )rk   cmdr   reqs       r   _build_requestAnvizDevice._build_request   sx    

6;;tT^^45

3

6;;tSY/0JJt

5:Szr   c                   U R                   c   e[        5       n[        U5      U:  a[  U R                   R                  U[        U5      -
  5      nU(       d  [	        S5      eUR                  U5        [        U5      U:  a  M[  [        U5      $ )Nu   Conexión cerrada por el reloj)rj   r   rG   recvr<   r   r"   )rk   r#   bufchunks       r   _recv_exactAnvizDevice._recv_exact   sr    zz%%%k#hlJJOOACL1E !ABBJJu	 #hl
 Szr   c                F    U R                   (       d  U$ U R                   U-   $ rc   )ri   )rk   r   s     r   _prepend_passwordAnvizDevice._prepend_password   s!    ((K((4//r   c                B   [        U5      S:  d  US   [        :w  a  [        S5      e[        R                  " SUS S 5      u  p4n[        U5      nX0R                  :w  a  [        SU R                   SU S35      eU[        U[        -   /5      :w  a  [        SUS	 35      eU[        :w  au  [        R                  US
US	 35      nU[        [        4;   a  U R                  (       a  US-  nO&U[        [        4;   a  U R                  (       d  US-  n[        SU 35      eg )Nr   r   u   Respuesta inválida del relojz>xLccz*ID de dispositivo incorrecto (configurado u   , respondió z#). Revise device_id en relojes.jsonzACK incorrecto para comando 0x02Xu
   código 0xu3    — verifique comm_password (PW Setting del reloj)uC    — el reloj puede tener Comm.PW activado; configure comm_passwordu   El reloj rechazó el comando: )rG   r   r<   r   unpackordrd   r"   ACK_SUMRET_SUCCESSRET_MESSAGESgetRET_FAILRET_PASSWORDri   )rk   r   respdev_idackretret_codehints           r   _check_responseAnvizDevice._check_response   s#   t9q=DGsN<==!==$r(;Ss8^^#<T^^<L M$X%HJ  %w((=c#YGHH{"##H
8C..IJDHl338Q8QMMh55d>W>W]]=dVDEE #r   c                
   U R                   c  [        S5      eU(       a  [        U5      OSnU R                  U5      nU R	                  X5      nU R                   R                  U5        U R                  S5      nU R                  X5        U R                  S5      n[        R                  " SU5      S   nU(       a  U R                  U5      OSnU R                  S5      n	XV-   U-   n
[        U
5      U	:w  a  [        S5      eU$ )Nu   No hay conexión con el relojr   r   rU   r   r   zError de checksum en respuesta)rj   r<   r"   r   r   sendr   r   r   r   r   )rk   r   argsr   r   headerrlendata_lenpayloadr   fulls              r   _get_responseAnvizDevice._get_response   s    ::<=="uT{%%d+!!#,

!!!$S)"==t,Q/08$""8,cq!}w&;#=>>r   c                    U R                  [        5      n[        R                  " SUS S 5      u  p#pEpg[	        SU-   X4XVU5      $ )NBBBBBBr   i  )r   CMD_GET_DATETIMEr   r   r   )rk   r   ymrR   hmiss           r   get_datetimeAnvizDevice.get_datetime   sE    !!"23"MM(D!H=aBq!q11r   c                   U R                  [        5      n[        U5      n[        S5       H$  n[	        U5        [	        U5        [	        U5        M&     [        [        R                  " S[        [	        U5      [	        U5      [	        U5      /5      5      5      n[        [        R                  " S[        [	        U5      [	        U5      [	        U5      /5      5      5      n[        XES9$ )Nr   z>BH)r9   r:   )
r   CMD_GET_RECORD_INFOiterrangenextsumr   r   r"   r7   )rk   r   itr   r9   r:   s         r   get_record_infoAnvizDevice.get_record_info   s    !!"56$ZqAHHH  &--ud2hR$r(5S/TUV&--ud2hR$r(5S/TUV{LLr   c                R   [         R                  " S[        U S S S5      5      S   n[         R                  " S[        U SS 5      5      S   nU S   nU S   n[         R                  " S[        U SS	 S
5      5      S   n[        R
                  " [        U-   5      n[        XX4U5      $ )Nz>Qr   r   r   z>I	   r   r      r   )r   r   r$   r"   r   fromtimestampSSECr&   )rawuidsecbkprtypewtypetss          r   _parse_recordAnvizDevice._parse_record   s    mmD*S!Wa"89!<mmD%Aa/215!fBdJs2bz1$=>qA##D3J/3C66r   c                R   [        U 5      nU(       d  / $ UR                  S5      n/ nSnUS-   [        U5      ::  ak  [        U5      U:  a\  XUS-    nUR                  [        R                  [        U5      5      5        US-  nUS-   [        U5      ::  a  [        U5      U:  a  M\  U$ )Nr   r   )r   poprG   r   ra   r   )r   r   countrecordsoffsetr   s         r   _parse_records_block AnvizDevice._parse_records_block  s    oI
%'rkSX%#g,*>"-ENN;44Yu5EFGbLF rkSX%#g,*> r   c                   U R                  5       nUR                  nUS:X  a  / $ [        SU5      n/ nU R                  [        SU/5      nUR                  U R                  U5      5        X#-
  nUS:  aP  [        SU5      nU R                  [        SU/5      nUR                  U R                  U5      5        Xc-  nUS:  a  MP  U$ )Nr      r	   )r   r9   minr   CMD_DOWNLOAD_RECORDSr   r   )rk   infototalbatchr9   r   lefts          r   download_all_records AnvizDevice.download_all_records  s    ##%  A:IB)+!!"6E
C444T:;}QhDME%%&:QJGDt88>?MD	 Qh r   c                    U R                  5       nU R                  5       nSUR                  SS9UR                  UR                  S.$ )NT )sep)	connecteddevice_timer9   r:   )r   r   	isoformatr9   r:   )rk   dtr   s      r   
_ping_onceAnvizDevice._ping_once&  sK     ##%<<C<0++++	
 	
r   c                h   U R                   (       d  U R                  5       $ [        U R                   5      R                  5       n[	        U5      [        U5      /nSnU H#  nU(       d  M  X@l         U R                  5       s  $    U=(       d    [        S5      e! [         a  nUn SnAMM  SnAff = f)z2Verifica conectividad y devuelve estado del reloj.Nz"No se pudo autenticar con el reloj)rh   r   rC   rD   rL   r_   ri   r<   )rk   rJ   	encodings
last_errorencodedexcs         r   pingAnvizDevice.ping0  s    !!??$$$$$%++- %$S)
	 )-
 G(/%!(( ! LJ'KLL  ! 
!s   2B
B1$B,,B1)ri   rj   rh   rd   re   rf   rg   )i  g      $@N)
rd   r(   re   rC   rf   r(   rg   floatrh   str | int | None)returnNone)r   ra   )r   )r   r(   r   r"   r   r"   )r#   r(   r   r"   )r   r"   r   r"   )r   r(   r   r"   r   r   rc   )r   r(   r   zlist[int] | Noner   r"   )r   r   )r   r7   )r   r   r   r&   )r   r"   r   list[AnvizRecord])r   r   )r   dict)r0   r1   r2   r3   rl   rt   ro   r|   r   r   r   r   r   r   r   r   staticmethodr   r   r   r   r   r5   r.   r   r   ra   ra      s    
 *.00 0 	0
 0 (0 0
F(*2

M 7 7  (
Mr   ra   zHuella 1zHuella 2u   ContraseñaTarjeta)r   r	   rU   r@   EntradaSalida)r   r	   )r   zbytes | bytearrayr   r"   )r   r   r#   r(   r   r"   )rI   r   r   zbytes | None)rI   rC   r   r"   ) __doc__
__future__r   rp   r   dataclassesr   r   typingr   r   r   r   r   r   r   r   r   r   r   r   r   r$   r&   r7   	Exceptionr<   rL   r_   ra   BACKUP_LABELSTYPE_LABELSr.   r   r   <module>r     s  
 #   !  

  1
%.

$;

 
!
    
<")      
	 	. 	(CM CML :-IN)r   