Merge branch 'dev'

This commit is contained in:
Fanani M. Ihsan 2016-06-17 13:33:14 +07:00
commit a92f712851
4 changed files with 199 additions and 31 deletions

12
zk/attendance.py Normal file
View File

@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
class Attendance(object):
def __init__(self, user_id, timestamp, status):
self.user_id = user_id
self.timestamp = timestamp
self.status = status
def __str__(self):
return self.user_id
def __repr__(self):
return '<Attendance>: {}'.format(self.user_id)

View File

@ -1,8 +1,11 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from datetime import datetime
from struct import pack, unpack from struct import pack, unpack
from socket import socket, AF_INET, SOCK_DGRAM from socket import socket, AF_INET, SOCK_DGRAM
from zk import const from zk import const
from zk.exception import ZKErrorResponse, ZKNetworkError
from zk.attendance import Attendance
from zk.user import User from zk.user import User
class ZK(object): class ZK(object):
@ -59,9 +62,16 @@ class ZK(object):
return pack('H', checksum) return pack('H', checksum)
def __send_command(self, command, command_string, checksum, session_id, reply_id, response_size): def __send_command(self, command, command_string, checksum, session_id, reply_id, response_size):
'''
send command to the terminal
'''
buf = self.__create_header(command, command_string, checksum, session_id, reply_id) buf = self.__create_header(command, command_string, checksum, session_id, reply_id)
try:
self.__sock.sendto(buf, self.__address) self.__sock.sendto(buf, self.__address)
self.__data_recv = self.__sock.recv(response_size) self.__data_recv = self.__sock.recv(response_size)
except Exception, e:
raise ZKNetworkError(str(e))
self.__response = unpack('HHHH', self.__data_recv[:8])[0] self.__response = unpack('HHHH', self.__data_recv[:8])[0]
self.__reply_id = unpack('HHHH', self.__data_recv[:8])[3] self.__reply_id = unpack('HHHH', self.__data_recv[:8])[3]
@ -88,9 +98,43 @@ class ZK(object):
else: else:
return 0 return 0
def __reverse_hex(self, hex):
data = ''
for i in reversed( xrange( len(hex)/2 ) ):
data += hex[i*2:(i*2)+2]
return data
def __decode_time(self, t):
"""Decode a timestamp retrieved from the timeclock
copied from zkemsdk.c - DecodeTime"""
t = t.encode('hex')
t = int(self.__reverse_hex(t), 16)
second = t % 60
t = t / 60
minute = t % 60
t = t / 60
hour = t % 24
t = t / 24
day = t % 31+1
t = t / 31
month = t % 12+1
t = t / 12
year = t + 2000
d = datetime(year, month, day, hour, minute, second)
return d
def connect(self): def connect(self):
''' '''
connect to device connect to the device
''' '''
command = const.CMD_CONNECT command = const.CMD_CONNECT
@ -107,11 +151,11 @@ class ZK(object):
self.__sesion_id = unpack('HHHH', self.__data_recv[:8])[2] self.__sesion_id = unpack('HHHH', self.__data_recv[:8])[2]
return True return True
else: else:
raise Exception("Invalid response") raise ZKErrorResponse("Invalid response")
def disconnect(self): def disconnect(self):
''' '''
diconnect from connected device diconnect from the connected device
''' '''
command = const.CMD_EXIT command = const.CMD_EXIT
@ -125,11 +169,11 @@ class ZK(object):
if cmd_response.get('status'): if cmd_response.get('status'):
return True return True
else: else:
raise Exception("Invalid response") raise ZKErrorResponse("Invalid response")
def disable_device(self): def disable_device(self):
''' '''
disable (lock) connected device, make sure no activity when process run disable (lock) device, ensure no activity when process run
''' '''
command = const.CMD_DISABLEDEVICE command = const.CMD_DISABLEDEVICE
@ -143,11 +187,11 @@ class ZK(object):
if cmd_response.get('status'): if cmd_response.get('status'):
return True return True
else: else:
raise Exception("Invalid response") raise ZKErrorResponse("Invalid response")
def enable_device(self): def enable_device(self):
''' '''
re-enable connected device re-enable the connected device
''' '''
command = const.CMD_ENABLEDEVICE command = const.CMD_ENABLEDEVICE
@ -161,11 +205,11 @@ class ZK(object):
if cmd_response.get('status'): if cmd_response.get('status'):
return True return True
else: else:
raise Exception("Invalid response") raise ZKErrorResponse("Invalid response")
def get_firmware_version(self): def get_firmware_version(self):
''' '''
get firmware version name return the firmware version
''' '''
command = const.CMD_GET_VERSION command = const.CMD_GET_VERSION
@ -180,11 +224,29 @@ class ZK(object):
firmware_version = self.__data_recv[8:].strip('\x00|\x01\x10x') firmware_version = self.__data_recv[8:].strip('\x00|\x01\x10x')
return firmware_version return firmware_version
else: else:
raise Exception("Invalid response") raise ZKErrorResponse("Invalid response")
def get_serialnumber(self):
'''
return the serial number
'''
command = const.CMD_OPTIONS_RRQ
command_string = '~SerialNumber'
checksum = 0
session_id = self.__sesion_id
reply_id = self.__reply_id
response_size = 1024
cmd_response = self.__send_command(command, command_string, checksum, session_id, reply_id, response_size)
if cmd_response.get('status'):
serialnumber = self.__data_recv[8:].split('=')[-1].strip('\x00|\x01\x10x')
return serialnumber
else:
raise ZKErrorResponse("Invalid response")
def restart(self): def restart(self):
''' '''
restart connected device restart the device
''' '''
command = const.CMD_RESTART command = const.CMD_RESTART
@ -198,11 +260,11 @@ class ZK(object):
if cmd_response.get('status'): if cmd_response.get('status'):
return True return True
else: else:
raise Exception("Invalid response") raise ZKErrorResponse("Invalid response")
def power_off(self): def poweroff(self):
''' '''
shutdown connected device shutdown the device
''' '''
command = const.CMD_POWEROFF command = const.CMD_POWEROFF
@ -216,7 +278,7 @@ class ZK(object):
if cmd_response.get('status'): if cmd_response.get('status'):
return True return True
else: else:
raise Exception("Invalid response") raise ZKErrorResponse("Invalid response")
def test_voice(self): def test_voice(self):
''' '''
@ -234,7 +296,7 @@ class ZK(object):
if cmd_response.get('status'): if cmd_response.get('status'):
return True return True
else: else:
raise Exception("Invalid response") raise ZKErrorResponse("Invalid response")
def set_user(self, uid, name, privilege, password='', group_id='', user_id=''): def set_user(self, uid, name, privilege, password='', group_id='', user_id=''):
''' '''
@ -258,11 +320,31 @@ class ZK(object):
if cmd_response.get('status'): if cmd_response.get('status'):
return True return True
else: else:
raise Exception("Invalid response") raise ZKErrorResponse("Invalid response")
def delete_user(self, uid):
'''
delete specific user by uid
'''
command = const.CMD_DELETE_USER
uid = chr(uid % 256) + chr(uid >> 8)
command_string = pack('2s', uid)
checksum = 0
session_id = self.__sesion_id
reply_id = self.__reply_id
response_size = 1024
cmd_response = self.__send_command(command, command_string, checksum, session_id, reply_id, response_size)
if cmd_response.get('status'):
return True
else:
raise ZKErrorResponse("Invalid response")
def get_users(self): def get_users(self):
''' '''
get all users return all user
''' '''
command = const.CMD_USERTEMP_RRQ command = const.CMD_USERTEMP_RRQ
@ -311,7 +393,7 @@ class ZK(object):
userdata = userdata[72:] userdata = userdata[72:]
else: else:
raise Exception("Invalid response") raise ZKErrorResponse("Invalid response")
return users return users
@ -345,23 +427,86 @@ class ZK(object):
cmd_response = self.__send_command(command=command, command_string=command_string) cmd_response = self.__send_command(command=command, command_string=command_string)
print cmd_response print cmd_response
def clear_user(self): def clear_data(self):
''' '''
Not implemented yet clear all data (include: user, attendance report, finger database )
''' '''
command = const.CMD_CLEAR_DATA
command_string = ''
checksum = 0
session_id = self.__sesion_id
reply_id = self.__reply_id
response_size = 1024
pass cmd_response = self.__send_command(command, command_string, checksum, session_id, reply_id, response_size)
if cmd_response.get('status'):
return True
else:
raise ZKErrorResponse("Invalid response")
def get_attendance(self): def get_attendance(self):
''' '''
Not implemented yet return all attendance record
''' '''
command = const.CMD_ATTLOG_RRQ
command_string = ''
checksum = 0
session_id = self.__sesion_id
reply_id = self.__reply_id
response_size = 1024
cmd_response = self.__send_command(command, command_string, checksum, session_id, reply_id, response_size)
attendances = []
if cmd_response.get('status'):
if cmd_response.get('code') == const.CMD_PREPARE_DATA:
bytes = self.__get_data_size()
attendance_data = []
while bytes > 0:
data_recv = self.__sock.recv(1032)
attendance_data.append(data_recv)
bytes -= 1024
data_recv = self.__sock.recv(8)
response = unpack('HHHH', data_recv[:8])[0]
if response == const.CMD_ACK_OK:
if attendance_data:
# The first 4 bytes don't seem to be related to the user
for x in xrange(len(attendance_data)):
if x > 0:
attendance_data[x] = attendance_data[x][8:]
attendance_data = ''.join(attendance_data)
attendance_data = attendance_data[14:]
while len(attendance_data) >= 38:
user_id, sparator, timestamp, status, space = unpack( '24sc4sc10s', attendance_data.ljust(40)[:40])
user_id = user_id.strip('\x00|\x01\x10x')
timestamp = self.__decode_time(timestamp)
status = int(status.encode("hex"), 16)
attendance = Attendance(user_id, timestamp, status)
attendances.append(attendance)
attendance_data = attendance_data[40:]
else:
raise ZKErrorResponse("Invalid response")
return attendances
pass
def clear_attendance(self): def clear_attendance(self):
''' '''
Not implemented yet clear all attendance record
''' '''
command = const.CMD_CLEAR_ATTLOG
command_string = ''
checksum = 0
session_id = self.__sesion_id
reply_id = self.__reply_id
response_size = 1024
pass cmd_response = self.__send_command(command, command_string, checksum, session_id, reply_id, response_size)
if cmd_response.get('status'):
return True
else:
raise ZKErrorResponse("Invalid response")

8
zk/exception.py Normal file
View File

@ -0,0 +1,8 @@
class ZKError(Exception):
pass
class ZKErrorResponse(ZKError):
pass
class ZKNetworkError(ZKError):
pass

View File

@ -9,5 +9,8 @@ class User(object):
self.group_id = group_id self.group_id = group_id
self.user_id = user_id self.user_id = user_id
def __str__(self): def __repr__(self):
return self.name return self.name
def __repr__(self):
return '<User>: {}'.format(self.name)