
    si)I                         d Z ddlZddlmZ ddlmZ ddlmZmZ ddlZddl	m
Z
 i ddd	d
dddddddddddddddddddddd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1d2d3d4d5Zd6 Z G d7 d8      Zy)9a  
DahuaAPI module for interacting with Dahua biometric and access control devices.

This module provides a set of methods for managing and configuring Dahua devices,
including retrieving system information, managing users, setting up network configurations,
and interacting with attendance logs. It communicates with Dahua devices via HTTP requests
and supports basic operations such as system reboot, setting time, and language configuration.
    N)defaultdict)datetime)AnyDict)HTTPDigestAuthAttendanceStateattendance_stateCardIDcard_idCardName	card_nameCardNocard_noCardType	card_type
CreateTimecreate_timeCreateTimeRealUTCcreate_time_real_utcDoordoor	ErrorCode
error_code	FaceIndex
face_indexFacilityCodefacility_codeHatColor	hat_colorHatTypehat_typeMaskmaskMethodmethodNotesnotesPasswordpassword	reader_idrec_noremaining_timesreserved_intreserved_stringroom_numberstatustypeurluser_id	user_type
vto_number)ReaderIDRecNoRemainingTimesReservedIntReservedString
RoomNumberStatusTypeURLUserIDUserType	VTONumberc                    g }t        t              }d}| j                         D ]  \  }}|j                  d      s|j	                  d      }|d   }|r/||k7  r*|j                  t        |             |j                          ddg}|d   |v rt        j                  t        |            }||t        j                  |d         <   |} |r|j                  t        |             |S )a  
    Converts a dictionary of logs into a list of records.

    This function processes a dictionary containing log data, identifies records by
    the keys starting with "records[", and converts the corresponding values into
    a list of dictionaries with more readable keys. It also handles timestamp fields
    by converting them to `datetime` objects.

    Args:
        logs (dict): The dictionary containing the log data to be converted.

    Returns:
        list: A list of dictionaries representing individual log records, with
              formatted keys and values. Each record is a dictionary with keys
              mapped according to the `key_map` and timestamps converted to `datetime`.
    Nzrecords[.r   r   r   )r   dictitems
startswithsplitappendclearr   fromtimestampintkey_mapget)	logsrecords_listrecord_dictprevious_keykeyvaluepartscurrent_key	time_keyss	            3/var/www/python-projects/worksol/biometric/dahua.pyconvert_logs_to_listrY   3   s    " Ld#KLjjl '
U>>*%IIcNE(K ;##D$56!!#%':;IRyI% ..s5z:27KE"I./&L' D-.    c                   0   e Zd ZdZdededefdZd ZdCded	eeef   fd
Z	dedeeef   fdZ
d Zd Zd Zd Zd Zd	eeef   fdZd Zd	eeef   fdZd ZdedefdZd Zd Zd Zd ZdefdZd Zd	eeef   fd Zd! Zd" Z	 	 	 	 	 	 	 	 	 dDd#ed$ed%ed&ed'eded(ee   d)ee   d*ed+ed,ed-e fd.Z!d/ Z"defd0Z#	 dEdeded1ed2e d3e d4efd5Z$defd6Z%d7 Z&dFd8efd9Z'd: Z(d	eeef   fd;Z)d< Z*d	eeef   fd=Z+d> Z,d	eeef   fd?Z-	 	 	 dGd$ed@e.dAe.fdBZ/y)HDahuaAPIa  
    A class for interacting with Dahua biometric and access control devices.

    This class provides methods to interact with Dahua devices, including retrieving
    system information, configuring device settings (network, language, general, etc.),
    managing users, and processing logs related to attendance and access control.
    The class communicates with the Dahua device via HTTP requests and supports
    actions like enrolling users, rebooting the device, and fetching various device logs.
    ipusernamer)   c                     | d| _         t        ||      | _        t        j                         | _        | j                  | j
                  _        y )Nz	/cgi-bin/)base_urlr   authrequestsSessionsession)selfr]   r^   r)   s       rX   __init__zDahuaAPI.__init__g   s>    $i("8X6	'') IIrZ   c                 .   |j                   j                  d      j                         }|j                  }|dk(  r6d|vr	d|vr||dS 	 t	        d |j                  d      D              }||d<   |S |d	k(  rd
|dS ||dS # t        $ r d| |dcY S w xY w)a  
        Parses the response from the Dahua API request.

        This method processes the HTTP response from the Dahua device API. It decodes
        the content of the response, checks the status code, and returns a structured
        result. If the response is successful (status code 200), it attempts to parse
        the content as a dictionary of key-value pairs. If the response is an error,
        it returns a relevant error message
        zutf-8   z
=)resultstatus_codec              3   J   K   | ]  }d |v s|j                  d d        yw)ri      N)rH   ).0lines     rX   	<genexpr>z*DahuaAPI.parse_response.<locals>.<genexpr>   s'      $+/CSWKDJJsA&$s   	##rk   zInvalid parameter i  z)Error: Bad Request. Check the parameters.)contentdecodestriprk   rE   rH   	Exception)re   responserq   rk   content_dicts        rX   parse_responsezDahuaAPI.parse_responsen   s     ""))'288:**#W$G);")+FF
# $3:==3H$   /:]+## #E* 
 "+>>   27)<#. s   	'B   BBNendpointparamsc                 ~    | j                    | }| j                  j                  ||      }| j                  |      S )Nry   )r`   rd   rN   rw   )re   rx   ry   r2   ru   s        rX   _getzDahuaAPI._get   s>    z*<<##C#7""8,,rZ   datac                 ~    | j                    | }| j                  j                  ||      }| j                  |      S )Nr}   )r`   rd   postrw   )re   rx   r}   r2   ru   s        rX   _postzDahuaAPI._post   s>    z*<<$$St$4""8,,rZ   c                 (    d}| j                  |      S )zGet system information.z!magicBox.cgi?action=getSystemInfor|   re   rx   s     rX   get_system_infozDahuaAPI.get_system_info       6yy""rZ   c                 (    d}| j                  |      S )zGet the device serial number.zmagicBox.cgi?action=getSerialNor   r   s     rX   get_serial_numberzDahuaAPI.get_serial_number   s    4yy""rZ   c                 (    d}| j                  |      S )zGet the hardware version.z&magicBox.cgi?action=getHardwareVersionr   r   s     rX   get_hardware_versionzDahuaAPI.get_hardware_version   s    ;yy""rZ   c                 (    d}| j                  |      S )zGet the device type.z!magicBox.cgi?action=getDeviceTyper   r   s     rX   get_device_typezDahuaAPI.get_device_type   r   rZ   c                 (    d}| j                  |      S )iz/configManager.cgi?action=getConfig&name=Networkr   r   s     rX   get_basic_configzDahuaAPI.get_basic_config       Dyy""rZ   c                 ,    d}| j                  ||      S )z Set basic network configuration."configManager.cgi?action=setConfigr   r   re   ry   rx   s      rX   set_basic_configzDahuaAPI.set_basic_config       7zz(z00rZ   c                 (    d}| j                  |      S )z!Get general system configuration.z/configManager.cgi?action=getConfig&name=Generalr   r   s     rX   get_general_configzDahuaAPI.get_general_config   r   rZ   c                 ,    d}| j                  ||      S )z!Set general system configuration.r   r{   r   r   s      rX   set_general_configzDahuaAPI.set_general_config   s    7yy&y11rZ   c                 (    d}| j                  |      S )zGet the current system time.z global.cgi?action=getCurrentTimer   r   s     rX   get_system_timezDahuaAPI.get_system_time   s    5yy""rZ   datetimec                     d}t        j                  ||      st        d      d}t        j                  ||      st        d      | d| }d| }| j                  |      S )z
        Set the system time.
        Date format : YYYY-MM-DD
        Time format : HH-MM-SS
        Combines date and time with %20 between them.
        %20 character used for add space
        z^\d{4}-\d{2}-\d{2}$z)Invalid date format. Expected YYYY-MM-DD.z^\d{2}:\d{2}:\d{2}$z'Invalid time format. Expected HH:MM:SS.z%20z&global.cgi?action=setCurrentTime&time=)rematch
ValueErrorr|   )re   r   r   date_patterntime_patterndevice_datetimerx   s          rX   set_system_timezDahuaAPI.set_system_time   sp     .xxd+HII .xxd+FGG!F#dV,;O;LMyy""rZ   c                 ,    d}| j                  |i       S )zReboot the device.zconfigManager.cgi?action=rebootr   r   r   s     rX   reboot_devicezDahuaAPI.reboot_device   s    4zz(z,,rZ   c                 ,    d}| j                  |i       S )zShut down the device.z!configManager.cgi?action=shutdownr   r   r   s     rX   shutdown_devicezDahuaAPI.shutdown_device   s    6zz(z,,rZ   c                 (    d}| j                  |      S )z$Get supported language capabilities.z#magicBox.cgi?action=getLanguageCapsr   r   s     rX   get_language_capszDahuaAPI.get_language_caps   s    8yy""rZ   c                 (    d}| j                  |      S )z#Get current language configuration.z%magicBox.cgi?action=getLanguageConfigr   r   s     rX   get_language_configzDahuaAPI.get_language_config   s    :yy""rZ   languagec                 4    d}d|i}| j                  ||      S )zSet the device language.z%magicBox.cgi?action=setLanguageConfigLanguager   r   )re   r   rx   r}   s       rX   set_language_configzDahuaAPI.set_language_config   s$    :H%zz(z..rZ   c                 (    d}| j                  |      S )z"Get current locales configuration.z$magicBox.cgi?action=getLocalesConfigr   r   s     rX   get_locales_configzDahuaAPI.get_locales_config   s    9yy""rZ   c                 ,    d}| j                  ||      S )zSet locales configuration.z$magicBox.cgi?action=setLocalesConfigr   r   r   s      rX   set_locales_configzDahuaAPI.set_locales_config   s    9zz(z00rZ   c                 H    |st        d      d| }| j                  |      S )zD
        Retrieves information about a specific user group.
        5The 'name' parameter is required and cannot be empty.z,userManager.cgi?action=getGroupInfoAll&name=r   r|   )re   namerx   s      rX   get_group_infozDahuaAPI.get_group_info  s.     TUUA$Hyy""rZ   c                 (    d}| j                  |      S )z>
        Retrieves information about all user groups.
        z&userManager.cgi?action=getGroupInfoAllr   r   s     rX   get_group_info_allzDahuaAPI.get_group_info_all  s     <yy""rZ   r   r   r3   card_statusr   doorstime_sectionsvto_positionvalid_date_startvalid_date_endis_validc                 `   d}|d| z  }|d| z  }|d| z  }|d| z  }|d| z  }|r|d| z  }|rt        |      D ]  \  }}|d| d	| z  } |rt        |      D ]  \  }}|d
| d	| z  } |	r|d|	 z  }|
r|d|
 z  }|r|d| z  }|d|rdnd z  }| j                  |      S )a  
        Enroll a new user with access control card details.

        Args:
            card_name (str): Card name, up to 32 characters.
            card_no (str): Card number,Must be unique.
            user_id (str): User ID,Must be unique..
            card_status (int): Card status, default is 0 (Normal).
            card_type (int): Card type, default is 0 (Ordinary card).
            password (str): Card password (default is an empty string).
            doors (list[int]): Door permissions (default is None).
            time_sections (list[int]): Time sections corresponding to
                                        door permissions (default is None).
            vto_position (str): Door number linked with indoor monitor (default is an empty string).
            valid_date_start (str): Start time of the validity period,
                                    format "yyyyMMdd hhmmss" (default is an empty string).
            valid_date_end (str): End time of the validity period,
                                    format "yyyyMMdd hhmmss" (default is an empty string).
            is_valid (bool): Validity of the card, default is True.

        Returns:
            Response from the server.
        z6recordUpdater.cgi?action=insert&name=AccessControlCardz
&CardName=z&CardNo=z&UserID=z&CardStatus=z
&CardType=z
&Password=z&Doors[z]=z&TimeSections[z&VTOPosition=z&ValidDateStart=z&ValidDateEnd=z	&IsValid=truefalse)	enumerater|   )re   r   r   r3   r   r   r)   r   r   r   r   r   r   rx   indexr   sections                    rX   enroll_new_userzDahuaAPI.enroll_new_user  s?   L Lj,,hwi((hwi((l;-00j,,*XJ//H(/ 6tgeWBtf556"+M": @wnUG2gY??@-~66H*+;*<==H.(899Hi(@AAyy""rZ   c                 (    d}| j                  |      S )z8
        Retrieves information about all users.
        z%userManager.cgi?action=getUserInfoAllr   r   s     rX   get_user_info_allzDahuaAPI.get_user_info_allT  s     ;yy""rZ   c                 H    |st        d      d| }| j                  |      S )z>
        Retrieves information about a specific user.
        r   z(userManager.cgi?action=getUserInfo&name=r   re   r^   rx   s      rX   get_user_infozDahuaAPI.get_user_info[  s.     TUU=hZHyy""rZ   groupsharablereservedmemoc                    | j                         }|j                         D 	cg c]  \  }}	|j                  d      s|	 }
}}	||
vrt        d|
 d      d| d| d| d|rdnd	 d
|rdnd	 d| }| j	                  |      S c c}	}w )a  
        Add a new user.

        Args:
            username (str): The username of the new user.
            password (str): The password for the new user.
            group (str): The group of the new user, either "admin" or "user".
            sharable (bool): Whether the user can have multi-point login.
            reserved (bool): Whether the user is reserved and cannot be deleted.
            memo (str): An optional memo for the user.

        Returns:
            Response from the server.
        z.Namez#Invalid group. It must be comes in rC   z)userManager.cgi?action=addUser&user.Name=z&user.Password=z&user.Group=z&user.Sharable=r   r   z&user.Reserved=z&user.Memo=)r   rF   endswithr   r|   )re   r^   r)   r   r   r   r   all_groups_inforS   rT   	name_listrx   s               rX   add_userzDahuaAPI.add_userd  s    . 113$3$9$9$;
 c5s||G?TE
	 
 	!B9+QOPP!
 #%J ' !'/VW= >'/VW= >  	 yy""!
s
   BBc                 .    d| }| j                  |      S )zDelete an existing user.z'userManager.cgi?action=deleteUser&name=r   r   s      rX   delete_userzDahuaAPI.delete_user  s    <XJGyy""rZ   c                 :    d}ddddd}| j                  ||      S )z$Fetch attendance logs using the API.log.cgi?action=doFindAttendanceLog
session-idd   r   r   	SessionIDcountoffsetr{   r   )re   rx   ry   s      rX   fetch_attendance_logszDahuaAPI.fetch_attendance_logs  s/    *#%	
 yy&y11rZ   log_typec                 :    d}|dddd}| j                  ||      S )zFetch logs from the device.r   r   r   r   r   r{   r   )re   r   rx   ry   s       rX   get_logszDahuaAPI.get_logs  s/    *%	
 yy&y11rZ   c                 (    d}| j                  |      S )zGet record configuration.z.configManager.cgi?action=getConfig&name=Recordr   r   s     rX   get_record_configzDahuaAPI.get_record_config  s    Cyy""rZ   c                 ,    d}| j                  ||      S )zSet record configuration.r   r   r   r   s      rX   set_record_configzDahuaAPI.set_record_config  r   rZ   c                 (    d}| j                  |      S )zGet record mode configuration.z2configManager.cgi?action=getConfig&name=RecordModer   r   s     rX   get_record_mode_configzDahuaAPI.get_record_mode_config  s    Gyy""rZ   c                 ,    d}| j                  ||      S )zSet record mode configuration.r   r   r   r   s      rX   set_record_mode_configzDahuaAPI.set_record_mode_config  r   rZ   c                 (    d}| j                  |      S )zGet snapshot configuration.z,configManager.cgi?action=getConfig&name=Snapr   r   s     rX   get_snapshot_configzDahuaAPI.get_snapshot_config  s    Ayy""rZ   c                 ,    d}| j                  ||      S )zSet snapshot configuration.r   r   r   r   s      rX   set_snapshot_configzDahuaAPI.set_snapshot_config  r   rZ   
start_timeend_timec                    d}|r5t        |t              rt        |j                               }nt	        d      |r5t        |t              rt        |j                               }nt	        d      |r|d| z  }|r|d| z  }|r|d| z  }| j                  |      }t        |      }||j                  d      |j                  d      d	}|S )
z
        Get offline records from device.
        start_time and end_time must be Python datetime objects, used to convert to Unix timestamp.
        z6recordFinder.cgi?action=find&name=AccessControlCardRecz+start_time must be a Python datetime objectz)end_time must be a Python datetime objectz&condition.CardNo=z&StartTime=z	&EndTime=foundrk   )recordsr   rk   )
isinstancer   rL   	timestampr   r|   rY   rN   )re   r   r   r   rx   card_recordsr   rO   s           rX   get_control_card_reczDahuaAPI.get_control_card_rec  s     L*h/ !5!5!78
 !NOO(H-x1134 !LMM,WI66H+j\22H)H:..Hyy*&|4!%%g.'++M:
 rZ   )N)	r   r    NNr   r   r   T)r   )	SystemLog)NNN)0__name__
__module____qualname____doc__strrf   rw   r   r   r|   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rL   listboolr   r   r   r   r   r   r   r   r   r   r   r   r   r   r    rZ   rX   r\   r\   \   s   &3 &# & &#?J-S -$sCx. -
-c -c3h -
#
#
#
#
#
1tCH~ 1
#
2c3h 2
#
#C #s #.-
-
#
#
/C /#
1c3h 1
## #' " =#=# =# 	=#
 =# =# =# Cy=# Cy=# =# =# =# =#~##c #  (#(# (# 	(#
 (# (# (#T#C #
	2	2 	2#
1S#X 1
#
1T#s(^ 1
#
1$sCx. 1 #!	(( ( 	(rZ   r\   )r  r   collectionsr   r   typingr   r   rb   requests.authr   rM   rY   r\   r  rZ   rX   <module>r     s-   
 #    ()i  i	
  - / F   O  z F h  W!" 
#$ '!';B&RS SrZ   