MEGA UPDATE!
now with TCP support (on test!) mayor fixes but trying to keep functionality
This commit is contained in:
parent
7304c41a37
commit
86826f9f7c
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@
|
|||||||
build/
|
build/
|
||||||
dist/
|
dist/
|
||||||
*.egg-info/
|
*.egg-info/
|
||||||
|
*.test
|
139
test_machine.py
Normal file → Executable file
139
test_machine.py
Normal file → Executable file
@ -1,11 +1,19 @@
|
|||||||
# -*- coding: utf-8 -*-
|
#!/usr/bin/env python2
|
||||||
|
# # -*- coding: utf-8 -*-
|
||||||
import sys
|
import sys
|
||||||
|
import traceback
|
||||||
import argparse
|
import argparse
|
||||||
|
import time
|
||||||
from zk import ZK, const
|
import datetime
|
||||||
|
|
||||||
sys.path.append("zk")
|
sys.path.append("zk")
|
||||||
|
|
||||||
|
from zk import ZK, const
|
||||||
|
from zk.attendance import Attendance
|
||||||
|
from zk.exception import ZKErrorResponse, ZKNetworkError
|
||||||
|
from zk.user import User
|
||||||
|
from zk.finger import Finger
|
||||||
|
|
||||||
conn = None
|
conn = None
|
||||||
|
|
||||||
|
|
||||||
@ -15,19 +23,27 @@ parser.add_argument('-a', '--address',
|
|||||||
parser.add_argument('-p', '--port', type=int,
|
parser.add_argument('-p', '--port', type=int,
|
||||||
help='device port', default=4370)
|
help='device port', default=4370)
|
||||||
parser.add_argument('-T', '--timeout', type=int,
|
parser.add_argument('-T', '--timeout', type=int,
|
||||||
help='timeout', default=60)
|
help='timeout', default=10)
|
||||||
parser.add_argument('-P', '--password', type=int,
|
parser.add_argument('-P', '--password', type=int,
|
||||||
help='Device code/password', default=0)
|
help='Device code/password', default=0)
|
||||||
#parser.add_argument('-f', '--firmware', type=int,
|
parser.add_argument('-f', '--force-udp', action="store_true",
|
||||||
# help='test firmware', default=8)
|
help='Force UDP communication')
|
||||||
parser.add_argument('-t', '--templates', action="store_true",
|
parser.add_argument('-t', '--templates', action="store_true",
|
||||||
help='get templates')
|
help='get templates')
|
||||||
parser.add_argument('-r', '--records', action="store_true",
|
parser.add_argument('-r', '--records', action="store_true",
|
||||||
help='get records')
|
help='get records')
|
||||||
|
parser.add_argument('-u', '--updatetime', action="store_true",
|
||||||
|
help='Update Date / Time')
|
||||||
|
parser.add_argument('-D', '--deleteuser', type=int,
|
||||||
|
help='Delete a User', default=0)
|
||||||
|
parser.add_argument('-A', '--adduser', type=int,
|
||||||
|
help='Add a User', default=0)
|
||||||
|
parser.add_argument('-F', '--finger', type=int,
|
||||||
|
help='Finger for register', default=0)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
zk = ZK(args.address, port=args.port, timeout=args.timeout, password=args.password) # , firmware=args.firmware
|
zk = ZK(args.address, port=args.port, timeout=args.timeout, password=args.password, force_udp=args.force_udp) # , firmware=args.firmware
|
||||||
try:
|
try:
|
||||||
print 'Connecting to device ...'
|
print 'Connecting to device ...'
|
||||||
conn = zk.connect()
|
conn = zk.connect()
|
||||||
@ -35,14 +51,15 @@ try:
|
|||||||
conn.disable_device()
|
conn.disable_device()
|
||||||
fmt = conn.get_extend_fmt()
|
fmt = conn.get_extend_fmt()
|
||||||
print 'ExtendFmt : {}'.format(fmt)
|
print 'ExtendFmt : {}'.format(fmt)
|
||||||
if fmt == 1:
|
now = datetime.datetime.today().replace(microsecond=0)
|
||||||
print "Firmware 6"
|
if args.updatetime:
|
||||||
conn.firmware = 6
|
print '--- Updating Time---'
|
||||||
else:
|
conn.set_time(now)
|
||||||
print "Firmware 8"
|
zk_time = conn.get_time()
|
||||||
conn.firmware = 8
|
dif = abs(zk_time - now).total_seconds()
|
||||||
|
print 'Time : {}'.format(zk_time)
|
||||||
print 'Time : {}'.format(conn.get_time())
|
if dif > 120:
|
||||||
|
print("WRN: TIME IS NOT SYNC!!!!!! (local: %s)" % now)
|
||||||
print 'Firmware Version : {}'.format(conn.get_firmware_version())
|
print 'Firmware Version : {}'.format(conn.get_firmware_version())
|
||||||
print 'Platform : %s' % conn.get_platform()
|
print 'Platform : %s' % conn.get_platform()
|
||||||
print 'DeviceName : %s' % conn.get_device_name()
|
print 'DeviceName : %s' % conn.get_device_name()
|
||||||
@ -50,20 +67,73 @@ try:
|
|||||||
print 'Serial Number : %s' % conn.get_serialnumber()
|
print 'Serial Number : %s' % conn.get_serialnumber()
|
||||||
print 'MAC: %s' % conn.get_mac()
|
print 'MAC: %s' % conn.get_mac()
|
||||||
print ''
|
print ''
|
||||||
conn.read_sizes()
|
|
||||||
print conn
|
|
||||||
print ''
|
|
||||||
print '--- Get User ---'
|
print '--- Get User ---'
|
||||||
users = conn.get_users()
|
users = conn.get_users()
|
||||||
for user in users:
|
max_uid = 0
|
||||||
privilege = 'User'
|
prev = None
|
||||||
if user.privilege == const.USER_ADMIN:
|
if not args.deleteuser:
|
||||||
privilege = 'Admin'
|
for user in users:
|
||||||
|
privilege = 'User'
|
||||||
|
if user.uid > max_uid:
|
||||||
|
max_uid = user.uid
|
||||||
|
privilege = 'User' if user.privilege == const.USER_DEFAULT else 'Admin-%s' % user.privilege
|
||||||
|
print '-> UID #{:<5} Name : {:<27} Privilege : {}'.format(user.uid, user.name, privilege)
|
||||||
|
print ' Group ID : {:<8} User ID : {:<8} Password : {:<8} Card : {}'.format(user.group_id, user.user_id, user.password, user.card)
|
||||||
|
#print len (user.repack73()), user.repack73().encode('hex')
|
||||||
|
#print ''
|
||||||
|
if args.adduser and user.uid == args.adduser:
|
||||||
|
prev = user
|
||||||
|
if args.deleteuser:
|
||||||
|
print ''
|
||||||
|
print '-- Delete User UID#%s ---' % args.deleteuser
|
||||||
|
#TODO implementar luego
|
||||||
|
conn.delete_user(args.deleteuser)
|
||||||
|
users = conn.get_users() #update
|
||||||
|
for user in users:
|
||||||
|
if user.uid > max_uid:
|
||||||
|
max_uid = user.uid
|
||||||
|
privilege = 'User' if user.privilege == const.USER_DEFAULT else 'Admin-%s' % user.privilege
|
||||||
|
print '-> UID #{:<5} Name : {:<27} Privilege : {}'.format(user.uid, user.name, privilege)
|
||||||
|
print ' Group ID : {:<8} User ID : {:<8} Password : {:<8} Card : {}'.format(user.group_id, user.user_id, user.password, user.card)
|
||||||
|
#print len (user.repack73()), user.repack73().encode('hex')
|
||||||
|
#print ''
|
||||||
|
if args.adduser and user.uid == args.adduser:
|
||||||
|
prev = user
|
||||||
|
|
||||||
print '-> UID #{:<5} Name : {:<27} Privilege : {}'.format(user.uid, user.name, privilege)
|
if args.adduser:
|
||||||
print ' Group ID : {:<8} User ID : {:<8} Password : {:<8} Card : {}'.format(user.group_id, user.user_id, user.password, user.card)
|
uid = int(args.adduser)
|
||||||
#print len (user.repack73()), user.repack73().encode('hex')
|
if prev:
|
||||||
#print ''
|
user = prev
|
||||||
|
privilege = 'User' if user.privilege == const.USER_DEFAULT else 'Admin-%s' % user.privilege
|
||||||
|
print ''
|
||||||
|
print '--- Modify User %i ---' % user.uid
|
||||||
|
print '-> UID #{:<5} Name : {:<27} Privilege : {}'.format(user.uid, user.name, privilege)
|
||||||
|
print ' Group ID : {:<8} User ID : {:<8} Password : {:<8} Card : {}'.format(user.group_id, user.user_id, user.password, user.card)
|
||||||
|
#discard prev
|
||||||
|
else:
|
||||||
|
print '--- Add new User %i ---' % uid
|
||||||
|
name = raw_input('Name :')
|
||||||
|
admin = raw_input('Admin (y/n):')
|
||||||
|
privilege = 14 if admin == 'y' else 0
|
||||||
|
password = raw_input('Password :')
|
||||||
|
user_id = raw_input('User ID2 :')
|
||||||
|
card = int(raw_input('Card :'))
|
||||||
|
if prev:
|
||||||
|
conn.delete_user(uid) #borrado previo
|
||||||
|
try:
|
||||||
|
conn.set_user(uid, name, privilege, password, '', user_id, card)
|
||||||
|
except ZKErrorResponse, e:
|
||||||
|
print "error: ", e
|
||||||
|
#try new format
|
||||||
|
zk_user = User(uid, name, privilege, password, '', user_id, card)
|
||||||
|
conn.save_user_template(zk_user)
|
||||||
|
conn.delete_user_template(uid, args.finger)
|
||||||
|
conn.reg_event(0xFFFF) #
|
||||||
|
if conn.enroll_user(uid, args.finger):
|
||||||
|
conn.test_voice(18) # register ok
|
||||||
|
else:
|
||||||
|
conn.test_voice(23) # not registered
|
||||||
|
conn.refresh_data()
|
||||||
print "Voice Test ..."
|
print "Voice Test ..."
|
||||||
conn.test_voice(10)
|
conn.test_voice(10)
|
||||||
if args.templates:
|
if args.templates:
|
||||||
@ -74,13 +144,24 @@ try:
|
|||||||
if args.records:
|
if args.records:
|
||||||
print "Read Records..."
|
print "Read Records..."
|
||||||
attendance = conn.get_attendance()
|
attendance = conn.get_attendance()
|
||||||
|
i = 0
|
||||||
for att in attendance:
|
for att in attendance:
|
||||||
print "ATT: uid:{:>3}, t: {}".format(att.uid, att.timestamp)
|
i +=1
|
||||||
print 'Enabling device ...'
|
print "ATT {:>6}: uid:{:>3}, t: {}".format(i, att.uid, att.timestamp)
|
||||||
conn.enable_device()
|
print ''
|
||||||
|
print '--- sizes & capacity ---'
|
||||||
|
conn.read_sizes()
|
||||||
|
print conn
|
||||||
|
print ''
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print "Process terminate : {}".format(e)
|
print "Process terminate : {}".format(e)
|
||||||
print "Error: %s" % sys.exc_info()[0]
|
print "Error: %s" % sys.exc_info()[0]
|
||||||
|
print '-'*60
|
||||||
|
traceback.print_exc(file=sys.stdout)
|
||||||
|
print '-'*60
|
||||||
finally:
|
finally:
|
||||||
if conn:
|
if conn:
|
||||||
|
print 'Enabling device ...'
|
||||||
|
conn.enable_device()
|
||||||
conn.disconnect()
|
conn.disconnect()
|
||||||
|
print ''
|
||||||
|
1
test_voice.py
Normal file → Executable file
1
test_voice.py
Normal file → Executable file
@ -1,3 +1,4 @@
|
|||||||
|
#!/usr/bin/env python2
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
|
443
zk/base.py
443
zk/base.py
@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import sys
|
import sys
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from socket import AF_INET, SOCK_DGRAM, socket
|
from socket import AF_INET, SOCK_DGRAM, SOCK_STREAM, socket
|
||||||
from struct import pack, unpack
|
from struct import pack, unpack
|
||||||
|
|
||||||
from zk import const
|
from zk import const
|
||||||
@ -44,17 +44,55 @@ def make_commkey(key, session_id, ticks=50):
|
|||||||
B,
|
B,
|
||||||
k[3] ^ B)
|
k[3] ^ B)
|
||||||
return k
|
return k
|
||||||
|
class ZK_helper(object):
|
||||||
|
""" helper class """
|
||||||
|
def __init__(self, ip, port=4370):
|
||||||
|
self.address = (ip, port)
|
||||||
|
self.ip = ip
|
||||||
|
self.port = port
|
||||||
|
#self.timeout = timeout
|
||||||
|
#self.password = password # passint
|
||||||
|
#self.firmware = int(firmware) #TODO check minor version?
|
||||||
|
#self.tcp = tcp
|
||||||
|
def test_ping(self):
|
||||||
|
"""
|
||||||
|
Returns True if host responds to a ping request
|
||||||
|
"""
|
||||||
|
import subprocess, platform
|
||||||
|
|
||||||
|
# Ping parameters as function of OS
|
||||||
|
ping_str = "-n 1" if platform.system().lower()=="windows" else "-c 1"
|
||||||
|
args = "ping " + " " + ping_str + " " + self.ip
|
||||||
|
need_sh = False if platform.system().lower()=="windows" else True
|
||||||
|
# Ping
|
||||||
|
return subprocess.call(args,
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
stderr=subprocess.PIPE,
|
||||||
|
shell=need_sh) == 0
|
||||||
|
def test_tcp(self):
|
||||||
|
self.client = socket(AF_INET, SOCK_STREAM)
|
||||||
|
self.client.settimeout(10) # fixed test
|
||||||
|
res = self.client.connect_ex(self.address)
|
||||||
|
self.client.close()
|
||||||
|
return res
|
||||||
|
def test_udp(self):
|
||||||
|
self.client = socket(AF_INET, SOCK_DGRAM)
|
||||||
|
self.client.settimeout(10) # fixed test
|
||||||
class ZK(object):
|
class ZK(object):
|
||||||
""" Clase ZK """
|
""" Clase ZK """
|
||||||
def __init__(self, ip, port=4370, timeout=60, password=0, firmware=8):
|
def __init__(self, ip, port=4370, timeout=60, password=0, force_udp=False, ommit_ping=False):
|
||||||
""" initialize instance """
|
""" initialize instance """
|
||||||
self.is_connect = False
|
self.is_connect = False
|
||||||
|
self.helper = ZK_helper(ip, port)
|
||||||
self.__address = (ip, port)
|
self.__address = (ip, port)
|
||||||
self.__sock = socket(AF_INET, SOCK_DGRAM)
|
self.__sock = socket(AF_INET, SOCK_DGRAM)
|
||||||
self.__sock.settimeout(timeout)
|
self.__sock.settimeout(timeout)
|
||||||
|
self.__timeout = timeout
|
||||||
self.__password = password # passint
|
self.__password = password # passint
|
||||||
self.firmware = int(firmware) #TODO check minor version?
|
#self.firmware = int(firmware) #dummy
|
||||||
|
self.force_udp = force_udp
|
||||||
|
self.ommit_ping = ommit_ping
|
||||||
|
self.tcp = False
|
||||||
self.users = 0
|
self.users = 0
|
||||||
self.fingers = 0
|
self.fingers = 0
|
||||||
self.records = 0
|
self.records = 0
|
||||||
@ -68,9 +106,24 @@ class ZK(object):
|
|||||||
self.fingers_av = 0
|
self.fingers_av = 0
|
||||||
self.users_av = 0
|
self.users_av = 0
|
||||||
self.rec_av = 0
|
self.rec_av = 0
|
||||||
|
self.user_packet_size = 28 # default zk6
|
||||||
self.__session_id = 0
|
self.__session_id = 0
|
||||||
self.__reply_id = const.USHRT_MAX-1
|
self.__reply_id = const.USHRT_MAX-1
|
||||||
self.__data_recv = None
|
self.__data_recv = None
|
||||||
|
def __create_socket(self):
|
||||||
|
""" based on self.tcp"""
|
||||||
|
if self.tcp:
|
||||||
|
self.__sock = socket(AF_INET, SOCK_STREAM)
|
||||||
|
self.__sock.connect_ex(self.__address)
|
||||||
|
else:
|
||||||
|
self.__sock = socket(AF_INET, SOCK_DGRAM)
|
||||||
|
|
||||||
|
|
||||||
|
def __create_tcp_top(self, packet):
|
||||||
|
""" witch the complete packet set top header """
|
||||||
|
length = len(packet)
|
||||||
|
top = pack('<HHI', const.MACHINE_PREPARE_DATA_1, const.MACHINE_PREPARE_DATA_2, length)
|
||||||
|
return top + packet
|
||||||
def __create_header(self, command, command_string, session_id, reply_id):
|
def __create_header(self, command, command_string, session_id, reply_id):
|
||||||
'''
|
'''
|
||||||
Puts a the parts that make up a packet together and packs them into a byte string
|
Puts a the parts that make up a packet together and packs them into a byte string
|
||||||
@ -121,13 +174,23 @@ class ZK(object):
|
|||||||
|
|
||||||
buf = self.__create_header(command, command_string, self.__session_id, self.__reply_id)
|
buf = self.__create_header(command, command_string, self.__session_id, self.__reply_id)
|
||||||
try:
|
try:
|
||||||
self.__sock.sendto(buf, self.__address)
|
if self.tcp:
|
||||||
self.__data_recv = self.__sock.recv(response_size)
|
top = self.__create_tcp_top(buf)
|
||||||
|
self.__sock.send(top)
|
||||||
|
self.__tcp_data_recv = self.__sock.recv(response_size + 8)
|
||||||
|
self.__tcp_header = unpack('HHI', self.__tcp_data_recv[:8])
|
||||||
|
self.__tcp_length = self.__tcp_header[2]
|
||||||
|
self.__header = unpack('HHHH', self.__tcp_data_recv[8:16])
|
||||||
|
self.__data_recv = self.__tcp_data_recv[8:] # dirty hack
|
||||||
|
else:
|
||||||
|
self.__sock.sendto(buf, self.__address)
|
||||||
|
self.__data_recv = self.__sock.recv(response_size)
|
||||||
|
self.__header = unpack('HHHH', self.__data_recv[:8])
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise ZKNetworkError(str(e))
|
raise ZKNetworkError(str(e))
|
||||||
|
|
||||||
self.__response = unpack('HHHH', self.__data_recv[:8])[0]
|
self.__response = self.__header[0]
|
||||||
self.__reply_id = unpack('HHHH', self.__data_recv[:8])[3]
|
self.__reply_id = self.__header[3]
|
||||||
|
|
||||||
if self.__response in [const.CMD_ACK_OK, const.CMD_PREPARE_DATA, const.CMD_DATA]:
|
if self.__response in [const.CMD_ACK_OK, const.CMD_PREPARE_DATA, const.CMD_DATA]:
|
||||||
return {
|
return {
|
||||||
@ -139,10 +202,14 @@ class ZK(object):
|
|||||||
'code': self.__response
|
'code': self.__response
|
||||||
}
|
}
|
||||||
def __ack_ok(self):
|
def __ack_ok(self):
|
||||||
""" ack ok """
|
""" event ack ok """
|
||||||
buf = self.__create_header(const.CMD_ACK_OK, "", self.__session_id, const.USHRT_MAX - 1)
|
buf = self.__create_header(const.CMD_ACK_OK, "", self.__session_id, const.USHRT_MAX - 1)
|
||||||
try:
|
try:
|
||||||
self.__sock.sendto(buf, self.__address)
|
if self.tcp:
|
||||||
|
top = self.__create_tcp_top(buf)
|
||||||
|
self.__sock.send(top)
|
||||||
|
else:
|
||||||
|
self.__sock.sendto(buf, self.__address)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise ZKNetworkError(str(e))
|
raise ZKNetworkError(str(e))
|
||||||
|
|
||||||
@ -208,11 +275,17 @@ class ZK(object):
|
|||||||
'''
|
'''
|
||||||
connect to the device
|
connect to the device
|
||||||
'''
|
'''
|
||||||
|
if not self.ommit_ping and not self.helper.test_ping():
|
||||||
|
raise ZKNetworkError("can't reach device (ping %s)" % self.__address[0])
|
||||||
|
if not self.force_udp and self.helper.test_tcp() == 0: #ok
|
||||||
|
self.tcp = True
|
||||||
|
self.user_packet_size = 72 # default zk8
|
||||||
|
self.__create_socket()# tcp based
|
||||||
self.__session_id = 0
|
self.__session_id = 0
|
||||||
self.__reply_id = const.USHRT_MAX - 1
|
self.__reply_id = const.USHRT_MAX - 1
|
||||||
cmd_response = self.__send_command(const.CMD_CONNECT)
|
cmd_response = self.__send_command(const.CMD_CONNECT)
|
||||||
self.__session_id = unpack('HHHH', self.__data_recv[:8])[2]
|
self.__session_id = self.__header[2]
|
||||||
if cmd_response.get('code')==const.CMD_ACK_UNAUTH:
|
if cmd_response.get('code') == const.CMD_ACK_UNAUTH:
|
||||||
#print "try auth"
|
#print "try auth"
|
||||||
command_string = make_commkey(self.__password, self.__session_id)
|
command_string = make_commkey(self.__password, self.__session_id)
|
||||||
cmd_response = self.__send_command(const.CMD_AUTH, command_string)
|
cmd_response = self.__send_command(const.CMD_AUTH, command_string)
|
||||||
@ -221,7 +294,9 @@ class ZK(object):
|
|||||||
# set the session iduid, privilege, password, name, card, group_id, timezone, user_id = unpack('HB5s8s5sBhI',userdata.ljust(28)[:28])
|
# set the session iduid, privilege, password, name, card, group_id, timezone, user_id = unpack('HB5s8s5sBhI',userdata.ljust(28)[:28])
|
||||||
return self
|
return self
|
||||||
else:
|
else:
|
||||||
print "connect err {} ".format(cmd_response["code"])
|
if cmd_response["code"] == const.CMD_ACK_UNAUTH:
|
||||||
|
raise ZKErrorResponse("Unauthenticated")
|
||||||
|
print "connect err response {} ".format(cmd_response["code"])
|
||||||
raise ZKErrorResponse("Invalid response: Can't connect")
|
raise ZKErrorResponse("Invalid response: Can't connect")
|
||||||
|
|
||||||
def disconnect(self):
|
def disconnect(self):
|
||||||
@ -231,6 +306,8 @@ class ZK(object):
|
|||||||
cmd_response = self.__send_command(const.CMD_EXIT)
|
cmd_response = self.__send_command(const.CMD_EXIT)
|
||||||
if cmd_response.get('status'):
|
if cmd_response.get('status'):
|
||||||
self.is_connect = False
|
self.is_connect = False
|
||||||
|
if self.__sock:
|
||||||
|
self.__sock.close() #leave to GC
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
raise ZKErrorResponse("can't disconnect")
|
raise ZKErrorResponse("can't disconnect")
|
||||||
@ -253,7 +330,7 @@ class ZK(object):
|
|||||||
if cmd_response.get('status'):
|
if cmd_response.get('status'):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
raise ZKErrorResponse("Can't enable")
|
raise ZKErrorResponse("Can't enable device")
|
||||||
|
|
||||||
def get_firmware_version(self):
|
def get_firmware_version(self):
|
||||||
'''
|
'''
|
||||||
@ -391,18 +468,18 @@ class ZK(object):
|
|||||||
if len(fields) > 20:
|
if len(fields) > 20:
|
||||||
self.faces = fields[20]
|
self.faces = fields[20]
|
||||||
self.faces_cap = fields[22]
|
self.faces_cap = fields[22]
|
||||||
#TODO: get faces size...
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
raise ZKErrorResponse("can't read sizes")
|
raise ZKErrorResponse("can't read sizes")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
""" for debug"""
|
""" for debug"""
|
||||||
return "ZK%i adr:%s:%s users:%i/%i fingers:%i/%i, records:%i/%i faces:%i/%i" % (
|
return "ZK %s://%s:%s users[%i]:%i/%i fingers:%i/%i, records:%i/%i faces:%i/%i" % (
|
||||||
self.firmware, self.__address[0], self.__address[1],
|
"tcp" if self.tcp else "udp", self.__address[0], self.__address[1],
|
||||||
self.users, self.users_cap, self.fingers, self.fingers_cap,
|
self.user_packet_size, self.users, self.users_cap,
|
||||||
self.records, self.rec_cap, self.faces, self.faces_cap
|
self.fingers, self.fingers_cap,
|
||||||
|
self.records, self.rec_cap,
|
||||||
|
self.faces, self.faces_cap
|
||||||
)
|
)
|
||||||
|
|
||||||
def restart(self):
|
def restart(self):
|
||||||
@ -549,18 +626,12 @@ class ZK(object):
|
|||||||
#uid = chr(uid % 256) + chr(uid >> 8)
|
#uid = chr(uid % 256) + chr(uid >> 8)
|
||||||
if privilege not in [const.USER_DEFAULT, const.USER_ADMIN]:
|
if privilege not in [const.USER_DEFAULT, const.USER_ADMIN]:
|
||||||
privilege = const.USER_DEFAULT
|
privilege = const.USER_DEFAULT
|
||||||
privilege = chr(privilege)
|
privilege = int(privilege)
|
||||||
if self.firmware == 6:
|
if self.user_packet_size == 28: #self.firmware == 6:
|
||||||
print "uid : %i" % uid
|
if not group_id:
|
||||||
print "pri : %c" % privilege
|
group_id = 0
|
||||||
print "pass: %s" % str(password)
|
|
||||||
print "name: %s" % str(name)
|
|
||||||
print type(name)
|
|
||||||
print "group %i" % int(group_id)
|
|
||||||
print "uid2: %i" % int(user_id)
|
|
||||||
try:
|
try:
|
||||||
command_string = pack('Hc5s8s5sBHI', uid, privilege, str(password), str(name), chr(0), int(group_id), 0, int(user_id))
|
command_string = pack('HB5s8s5sBHI', uid, privilege, str(password), str(name), chr(0), int(group_id), 0, int(user_id))
|
||||||
print "cmd : %s" % command_string
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print "s_h Error pack: %s" % e
|
print "s_h Error pack: %s" % e
|
||||||
print "Error pack: %s" % sys.exc_info()[0]
|
print "Error pack: %s" % sys.exc_info()[0]
|
||||||
@ -568,14 +639,13 @@ class ZK(object):
|
|||||||
else:
|
else:
|
||||||
name_pad = name.ljust(24, '\x00')[:24]
|
name_pad = name.ljust(24, '\x00')[:24]
|
||||||
card_str = pack('i', int(card))[:4]
|
card_str = pack('i', int(card))[:4]
|
||||||
command_string = pack('Hc8s24s4sc7sx24s', uid, privilege, password, name_pad, card_str, chr(0), group_id, user_id)
|
command_string = pack('HB8s24s4sc7sx24s', uid, privilege, password, name_pad, card_str, chr(0), group_id, str(user_id))
|
||||||
response_size = 1024
|
response_size = 1024 #TODO check response?
|
||||||
cmd_response = self.__send_command(command, command_string, response_size)
|
cmd_response = self.__send_command(command, command_string, response_size)
|
||||||
if cmd_response.get('status'):
|
if not cmd_response.get('status'):
|
||||||
return True
|
|
||||||
else:
|
|
||||||
raise ZKErrorResponse("Cant set user")
|
raise ZKErrorResponse("Cant set user")
|
||||||
|
self.refresh_data()
|
||||||
|
|
||||||
def save_user_template(self, user, fingers=[]):
|
def save_user_template(self, user, fingers=[]):
|
||||||
""" save user and template """
|
""" save user and template """
|
||||||
#TODO: grabado global
|
#TODO: grabado global
|
||||||
@ -591,9 +661,9 @@ class ZK(object):
|
|||||||
table += pack("<bHbI", 2, user.uid, fnum + finger.fid, tstart)
|
table += pack("<bHbI", 2, user.uid, fnum + finger.fid, tstart)
|
||||||
tstart += len(tfp)
|
tstart += len(tfp)
|
||||||
fpack += tfp
|
fpack += tfp
|
||||||
if self.firmware == 6:
|
if self.user_packet_size == 28: #self.firmware == 6:
|
||||||
upack = user.repack29()
|
upack = user.repack29()
|
||||||
else:
|
else: # 72
|
||||||
upack = user.repack73()
|
upack = user.repack73()
|
||||||
head = pack("III", len(upack), len(table), len(fpack))
|
head = pack("III", len(upack), len(table), len(fpack))
|
||||||
packet = head + upack + table + fpack
|
packet = head + upack + table + fpack
|
||||||
@ -645,21 +715,31 @@ class ZK(object):
|
|||||||
else:
|
else:
|
||||||
return False # probably empty!
|
return False # probably empty!
|
||||||
|
|
||||||
def delete_user(self, uid):
|
def delete_user(self, uid=0, user_id=''):
|
||||||
'''
|
'''
|
||||||
delete specific user by uid
|
delete specific user by uid
|
||||||
'''
|
'''
|
||||||
|
"""if self.tcp: should work but not tested
|
||||||
|
if not user_id:
|
||||||
|
#we need user_id (uid2)
|
||||||
|
users = self.get_users()
|
||||||
|
users = filter(lambda x: x.uid==uid, users)
|
||||||
|
if len(users) == 1:
|
||||||
|
user_id = users[0].user_id
|
||||||
|
else: #double? posibly empty
|
||||||
|
return False #can't enrool
|
||||||
|
command = 133 #const.CMD_DELETE_USER_2
|
||||||
|
command_string = pack('24s',str(user_id))
|
||||||
|
else:"""
|
||||||
command = const.CMD_DELETE_USER
|
command = const.CMD_DELETE_USER
|
||||||
#uid = chr(uid % 256) + chr(uid >> 8)
|
|
||||||
#command_string = pack('2s', uid)
|
|
||||||
command_string = pack('h', uid)
|
command_string = pack('h', uid)
|
||||||
cmd_response = self.__send_command(command, command_string)
|
cmd_response = self.__send_command(command, command_string)
|
||||||
if cmd_response.get('status'):
|
if not cmd_response.get('status'):
|
||||||
return True
|
|
||||||
else:
|
|
||||||
raise ZKErrorResponse("can't delete user")
|
raise ZKErrorResponse("can't delete user")
|
||||||
|
self.refresh_data()
|
||||||
|
|
||||||
def get_user_template(self, uid, temp_id):
|
def get_user_template(self, uid, temp_id):
|
||||||
|
""" ZKFinger VX10.0 """
|
||||||
command = 88 # comando secreto!!!
|
command = 88 # comando secreto!!!
|
||||||
command_string = pack('hb', uid, temp_id)
|
command_string = pack('hb', uid, temp_id)
|
||||||
response_size = 1024
|
response_size = 1024
|
||||||
@ -698,36 +778,34 @@ class ZK(object):
|
|||||||
return []
|
return []
|
||||||
total_size = unpack('i', templatedata[0:4])[0]
|
total_size = unpack('i', templatedata[0:4])[0]
|
||||||
templatedata = templatedata[4:] #total size not used
|
templatedata = templatedata[4:] #total size not used
|
||||||
if self.firmware == 6: #tested!
|
# ZKFinger VX10.0 the only finger firmware tested
|
||||||
while total_size:
|
while total_size:
|
||||||
size, uid, fid, valid = unpack('HHbb',templatedata[:6])
|
size, uid, fid, valid = unpack('HHbb',templatedata[:6])
|
||||||
template = unpack("%is" % (size-6), templatedata[6:size])[0]
|
template = unpack("%is" % (size-6), templatedata[6:size])[0]
|
||||||
finger = Finger(size, uid, fid, valid, template)
|
finger = Finger(size, uid, fid, valid, template)
|
||||||
#print finger # test
|
#print finger # test
|
||||||
templates.append(finger)
|
templates.append(finger)
|
||||||
templatedata = templatedata[size:]
|
templatedata = templatedata[size:]
|
||||||
total_size -= size
|
total_size -= size
|
||||||
else: # tested with ZEM800_TFT - iFace402/ID
|
|
||||||
while total_size:
|
|
||||||
size, uid, fid, valid = unpack('HHbb',templatedata[:6])
|
|
||||||
template = unpack("%is" % (size-6), templatedata[6:size])[0]
|
|
||||||
finger = Finger(size - 6, uid, fid, valid, template)
|
|
||||||
#print finger # test
|
|
||||||
templates.append(finger)
|
|
||||||
templatedata = templatedata[(size):]
|
|
||||||
total_size -= size
|
|
||||||
return templates
|
return templates
|
||||||
|
|
||||||
def get_users(self):
|
def get_users(self): #ALWAYS CALL TO GET correct user_packet_size
|
||||||
""" return all user """
|
""" return all user """
|
||||||
|
self.read_sizes() # last update
|
||||||
|
if self.users == 0: #lazy
|
||||||
|
return []
|
||||||
users = []
|
users = []
|
||||||
userdata, size = self.read_with_buffer(const.CMD_USERTEMP_RRQ, const.FCT_USER)
|
userdata, size = self.read_with_buffer(const.CMD_USERTEMP_RRQ, const.FCT_USER)
|
||||||
#print "user size %i" % size
|
#print "user size %i" % size
|
||||||
if size < 4:
|
if size <= 4:
|
||||||
print "WRN: no user data" # debug
|
print "WRN: no user data" # debug
|
||||||
return []
|
return []
|
||||||
userdata = userdata[4:] #total size not used
|
total_size = unpack("I",userdata[:4])[0]
|
||||||
if self.firmware == 6:
|
self.user_packet_size = total_size / self.users
|
||||||
|
if not self.user_packet_size in [28, 72]:
|
||||||
|
print "WRN packet size would be ", self.user_packet_size
|
||||||
|
userdata = userdata[4:]
|
||||||
|
if self.user_packet_size == 28:
|
||||||
while len(userdata) >= 28:
|
while len(userdata) >= 28:
|
||||||
uid, privilege, password, name, card, group_id, timezone, user_id = unpack('HB5s8s5sBhI',userdata.ljust(28)[:28])
|
uid, privilege, password, name, card, group_id, timezone, user_id = unpack('HB5s8s5sBhI',userdata.ljust(28)[:28])
|
||||||
password = unicode(password.split('\x00')[0], errors='ignore')
|
password = unicode(password.split('\x00')[0], errors='ignore')
|
||||||
@ -796,58 +874,95 @@ class ZK(object):
|
|||||||
cmd_response = self.__send_command(command, command_string)
|
cmd_response = self.__send_command(command, command_string)
|
||||||
if not cmd_response.get('status'):
|
if not cmd_response.get('status'):
|
||||||
raise ZKErrorResponse("can't set sdk build ")
|
raise ZKErrorResponse("can't set sdk build ")
|
||||||
def enroll_user(self, uid, temp_id=0):
|
def enroll_user(self, uid=0, temp_id=0, user_id=''):
|
||||||
'''
|
'''
|
||||||
start enroll user
|
start enroll user
|
||||||
'''
|
'''
|
||||||
command = const.CMD_STARTENROLL
|
command = const.CMD_STARTENROLL
|
||||||
command_string = pack('hhb', uid, 0, temp_id) # el 0 es misterio
|
done = False
|
||||||
|
if self.tcp:
|
||||||
|
if not user_id:
|
||||||
|
#we need user_id (uid2)
|
||||||
|
users = self.get_users()
|
||||||
|
users = filter(lambda x: x.uid==uid, users)
|
||||||
|
if len(users) == 1:
|
||||||
|
user_id = users[0].user_id
|
||||||
|
else: #double? posibly empty
|
||||||
|
return False #can't enrool
|
||||||
|
command_string = pack('<24sbb',str(user_id), temp_id, 1) # el 1 es misterio
|
||||||
|
else:
|
||||||
|
command_string = pack('hhb', int(uid), 0, temp_id) # el 0 es misterio
|
||||||
|
self.cancel_capture()
|
||||||
cmd_response = self.__send_command(command, command_string)
|
cmd_response = self.__send_command(command, command_string)
|
||||||
if not cmd_response.get('status'):
|
if not cmd_response.get('status'):
|
||||||
raise ZKErrorResponse("Cant Enroll user #%i [%i]" %(uid, temp_id))
|
raise ZKErrorResponse("Cant Enroll user #%i [%i]" %(uid, temp_id))
|
||||||
print "enroll", cmd_response
|
|
||||||
#retorna rapido toca esperar un reg event
|
#retorna rapido toca esperar un reg event
|
||||||
|
self.__sock.settimeout(60)# default 1min for finger
|
||||||
attempts = 3
|
attempts = 3
|
||||||
while attempts:
|
while attempts:
|
||||||
print "A:%i esperando primer regevent" % attempts
|
print "A:%i esperando primer regevent" % attempts
|
||||||
data_recv = self.__sock.recv(1032) # timeout? tarda bastante...
|
data_recv = self.__sock.recv(1032) # timeout? tarda bastante...
|
||||||
self.__ack_ok()
|
self.__ack_ok()
|
||||||
print (data_recv).encode('hex')
|
print (data_recv).encode('hex')
|
||||||
if len(data_recv) > 8: #not empty
|
if self.tcp:
|
||||||
res = unpack("H", data_recv.ljust(16,"\x00")[8:10])[0]
|
if len(data_recv) > 16: #not empty
|
||||||
print "res", res
|
res = unpack("H", data_recv.ljust(24,"\x00")[16:18])[0]
|
||||||
if res == 6:
|
print "res", res
|
||||||
print ("posible timeout")
|
if res == 0 or res == 6 or res == 4:
|
||||||
return False
|
# 6 timeout, 4 mismatch error, 0 can't start(why?)
|
||||||
|
print ("posible timeout o reg Fallido")
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if len(data_recv) > 8: #not empty
|
||||||
|
res = unpack("H", data_recv.ljust(16,"\x00")[8:10])[0]
|
||||||
|
print "res", res
|
||||||
|
if res == 6 or res == 4:
|
||||||
|
print ("posible timeout o reg Fallido")
|
||||||
|
break
|
||||||
print "A:%i esperando 2do regevent" % attempts
|
print "A:%i esperando 2do regevent" % attempts
|
||||||
data_recv = self.__sock.recv(1032) # timeout? tarda bastante...
|
data_recv = self.__sock.recv(1032) # timeout? tarda bastante...
|
||||||
self.__ack_ok()
|
self.__ack_ok()
|
||||||
print (data_recv).encode('hex')
|
print (data_recv).encode('hex')
|
||||||
if len(data_recv) > 8: #not empty
|
if self.tcp:
|
||||||
|
if len(data_recv) > 8: #not empty
|
||||||
|
res = unpack("H", data_recv.ljust(24,"\x00")[16:18])[0]
|
||||||
|
print "res", res
|
||||||
|
if res == 6 or res == 4:
|
||||||
|
print ("posible timeout o reg Fallido")
|
||||||
|
break
|
||||||
|
elif res == 0x64:
|
||||||
|
print ("ok, continue?")
|
||||||
|
attempts -= 1
|
||||||
|
else:
|
||||||
|
if len(data_recv) > 8: #not empty
|
||||||
|
res = unpack("H", data_recv.ljust(16,"\x00")[8:10])[0]
|
||||||
|
print "res", res
|
||||||
|
if res == 6 or res == 4:
|
||||||
|
print ("posible timeout o reg Fallido")
|
||||||
|
break
|
||||||
|
elif res == 0x64:
|
||||||
|
print ("ok, continue?")
|
||||||
|
attempts -= 1
|
||||||
|
if attempts == 0:
|
||||||
|
print "esperando 3er regevent"
|
||||||
|
data_recv = self.__sock.recv(1032) # timeout? tarda bastante...
|
||||||
|
self.__ack_ok()
|
||||||
|
print (data_recv).encode('hex')
|
||||||
|
if self.tcp:
|
||||||
|
res = unpack("H", data_recv.ljust(24,"\x00")[16:18])[0]
|
||||||
|
else:
|
||||||
res = unpack("H", data_recv.ljust(16,"\x00")[8:10])[0]
|
res = unpack("H", data_recv.ljust(16,"\x00")[8:10])[0]
|
||||||
print "res", res
|
if res == 6 or res == 4:
|
||||||
if res == 6:
|
print ("posible timeout o reg Fallido")
|
||||||
print ("posible timeout")
|
if res == 0:
|
||||||
return False
|
size = unpack("H", data_recv.ljust(16,"\x00")[10:12])[0]
|
||||||
elif res == 0x64:
|
pos = unpack("H", data_recv.ljust(16,"\x00")[12:14])[0]
|
||||||
print ("ok, continue?")
|
print "enroll ok", size, pos
|
||||||
attempts -= 1
|
done = True
|
||||||
|
self.__sock.settimeout(self.__timeout)
|
||||||
print "esperando 3er regevent"
|
self.cancel_capture()
|
||||||
data_recv = self.__sock.recv(1032) # timeout? tarda bastante...
|
self.verify_user()
|
||||||
self.__ack_ok()
|
return done
|
||||||
print (data_recv).encode('hex')
|
|
||||||
res = unpack("H", data_recv.ljust(16,"\x00")[8:10])[0]
|
|
||||||
if res == 4:
|
|
||||||
print "registro Fallido"
|
|
||||||
self.cancel_capture()
|
|
||||||
return False
|
|
||||||
if res == 0:
|
|
||||||
size = unpack("H", data_recv.ljust(16,"\x00")[10:12])[0]
|
|
||||||
pos = unpack("H", data_recv.ljust(16,"\x00")[12:14])[0]
|
|
||||||
print "enroll ok", size, pos
|
|
||||||
return True
|
|
||||||
|
|
||||||
def clear_data(self, clear_type=5): # FCT_USER
|
def clear_data(self, clear_type=5): # FCT_USER
|
||||||
'''
|
'''
|
||||||
clear all data (include: user, attendance report, finger database )
|
clear all data (include: user, attendance report, finger database )
|
||||||
@ -871,29 +986,68 @@ class ZK(object):
|
|||||||
raise ZKErrorResponse("can't read chunk %i:[%i]" % (start, size))
|
raise ZKErrorResponse("can't read chunk %i:[%i]" % (start, size))
|
||||||
#else
|
#else
|
||||||
if cmd_response.get('code') == const.CMD_DATA: # less than 1024!!!
|
if cmd_response.get('code') == const.CMD_DATA: # less than 1024!!!
|
||||||
return self.__data_recv[8:]
|
if self.tcp:
|
||||||
|
return self.__data_recv[16:] #TODO: check size?
|
||||||
|
else:
|
||||||
|
return self.__data_recv[8:]
|
||||||
if cmd_response.get('code') == const.CMD_PREPARE_DATA:
|
if cmd_response.get('code') == const.CMD_PREPARE_DATA:
|
||||||
data = []
|
data = []
|
||||||
bytes = self.__get_data_size() #TODO: check with size
|
bytes = self.__get_data_size() #TODO: check with size
|
||||||
|
#print "prepare data size is", bytes
|
||||||
|
if self.tcp:
|
||||||
|
data_recv = self.__sock.recv(bytes + 32)
|
||||||
|
recieved = len(data_recv)
|
||||||
|
tcp_length = unpack('HHI', data_recv[:8])[2] #bytes+8
|
||||||
|
if tcp_length < (bytes + 8):
|
||||||
|
print "request chunk too big!"
|
||||||
|
response = unpack('HHHH', data_recv[8:16])[0]
|
||||||
|
if recieved >= (bytes + 32): #complete
|
||||||
|
if response == const.CMD_DATA:
|
||||||
|
resp = data_recv[16:bytes+16] # no ack?
|
||||||
|
#print "resp len", len(resp)
|
||||||
|
return resp
|
||||||
|
else:
|
||||||
|
print "broken packet!!!"
|
||||||
|
return '' #broken
|
||||||
|
else: # incomplete
|
||||||
|
data.append(data_recv[16:]) # w/o tcp and header
|
||||||
|
bytes -= recieved-16
|
||||||
|
while bytes>0: #jic
|
||||||
|
data_recv = self.__sock.recv(bytes) #ideal limit?
|
||||||
|
recieved = len(data_recv)
|
||||||
|
data.append(data_recv) # w/o tcp and header
|
||||||
|
bytes -= recieved
|
||||||
|
data_recv = self.__sock.recv(16)
|
||||||
|
response = unpack('HHHH', data_recv[8:16])[0]
|
||||||
|
if response == const.CMD_ACK_OK:
|
||||||
|
return ''.join(data)
|
||||||
|
#data_recv[bytes+16:].encode('hex') #included CMD_ACK_OK
|
||||||
|
print "bad response ", data_recv.encode('hex')
|
||||||
|
#print data
|
||||||
|
return ''
|
||||||
|
#else udp
|
||||||
while True: #limitado por respuesta no por tamaño
|
while True: #limitado por respuesta no por tamaño
|
||||||
data_recv = self.__sock.recv(1032)
|
data_recv = self.__sock.recv(response_size)
|
||||||
response = unpack('HHHH', data_recv[:8])[0]
|
response = unpack('HHHH', data_recv[:8])[0]
|
||||||
#print "# %s packet response is: %s" % (pac, response)
|
#print "# %s packet response is: %s" % (pac, response)
|
||||||
if response == const.CMD_DATA:
|
if response == const.CMD_DATA:
|
||||||
data.append(data_recv[8:]) #header turncated
|
data.append(data_recv[8:]) #header turncated
|
||||||
bytes -= 1024
|
bytes -= 1024 #UDP
|
||||||
elif response == const.CMD_ACK_OK:
|
elif response == const.CMD_ACK_OK:
|
||||||
break #without problem.
|
break #without problem.
|
||||||
else:
|
else:
|
||||||
#truncado! continuar?
|
#truncado! continuar?
|
||||||
#print "broken!"
|
print "broken!"
|
||||||
break
|
break
|
||||||
#print "still needs %s" % bytes
|
#print "still needs %s" % bytes
|
||||||
return ''.join(data)
|
return ''.join(data)
|
||||||
|
|
||||||
def read_with_buffer(self, command, fct=0 ,ext=0):
|
def read_with_buffer(self, command, fct=0 ,ext=0):
|
||||||
""" Test read info with buffered command (ZK6: 1503) """
|
""" Test read info with buffered command (ZK6: 1503) """
|
||||||
MAX_CHUNK = 16 * 1024
|
if self.tcp:
|
||||||
|
MAX_CHUNK = 0xFFc0 #arbitrary, below 0x10008
|
||||||
|
else:
|
||||||
|
MAX_CHUNK = 16 * 1024
|
||||||
command_string = pack('<bhii', 1, command, fct, ext)
|
command_string = pack('<bhii', 1, command, fct, ext)
|
||||||
#print "rwb cs", command_string
|
#print "rwb cs", command_string
|
||||||
response_size = 1024
|
response_size = 1024
|
||||||
@ -902,6 +1056,10 @@ class ZK(object):
|
|||||||
cmd_response = self.__send_command(1503, command_string, response_size)
|
cmd_response = self.__send_command(1503, command_string, response_size)
|
||||||
if not cmd_response.get('status'):
|
if not cmd_response.get('status'):
|
||||||
raise ZKErrorResponse("RWB Not supported")
|
raise ZKErrorResponse("RWB Not supported")
|
||||||
|
if cmd_response['code'] == const.CMD_DATA:
|
||||||
|
#direct!!! small!!!
|
||||||
|
size = len(self.__data_recv)-8
|
||||||
|
return self.__data_recv[8:], size
|
||||||
size = unpack('I', self.__data_recv[9:13])[0] # extra info???
|
size = unpack('I', self.__data_recv[9:13])[0] # extra info???
|
||||||
#print "size fill be %i" % size
|
#print "size fill be %i" % size
|
||||||
remain = size % MAX_CHUNK
|
remain = size % MAX_CHUNK
|
||||||
@ -918,13 +1076,19 @@ class ZK(object):
|
|||||||
|
|
||||||
def get_attendance(self):
|
def get_attendance(self):
|
||||||
""" return attendance record """
|
""" return attendance record """
|
||||||
|
self.read_sizes()
|
||||||
|
if self.records == 0: #lazy
|
||||||
|
return []
|
||||||
attendances = []
|
attendances = []
|
||||||
attendance_data, size = self.read_with_buffer(const.CMD_ATTLOG_RRQ)
|
attendance_data, size = self.read_with_buffer(const.CMD_ATTLOG_RRQ)
|
||||||
if size < 4:
|
if size < 4:
|
||||||
print "WRN: no attendance data" # debug
|
print "WRN: no attendance data" # debug
|
||||||
return []
|
return []
|
||||||
|
total_size = unpack("I", attendance_data[:4])[0]
|
||||||
|
record_size = total_size/self.records
|
||||||
|
#print "record_size is ", record_size
|
||||||
attendance_data = attendance_data[4:] #total size not used
|
attendance_data = attendance_data[4:] #total size not used
|
||||||
if self.firmware == 6:
|
if record_size == 8 : #ultra old format
|
||||||
while len(attendance_data) >= 8:
|
while len(attendance_data) >= 8:
|
||||||
uid, status, timestamp = unpack('HH4s', attendance_data.ljust(8)[:8])
|
uid, status, timestamp = unpack('HH4s', attendance_data.ljust(8)[:8])
|
||||||
attendance_data = attendance_data[8:]
|
attendance_data = attendance_data[8:]
|
||||||
@ -934,6 +1098,16 @@ class ZK(object):
|
|||||||
timestamp = self.__decode_time(timestamp)
|
timestamp = self.__decode_time(timestamp)
|
||||||
attendance = Attendance(uid, user_id, timestamp, status)
|
attendance = Attendance(uid, user_id, timestamp, status)
|
||||||
attendances.append(attendance)
|
attendances.append(attendance)
|
||||||
|
elif record_size == 16: # extended
|
||||||
|
while len(attendance_data) >= 16:
|
||||||
|
uid, timestamp, status, verified, reserved, workcode = unpack('<I4sBB2sI', attendance_data.ljust(16)[:16])
|
||||||
|
attendance_data = attendance_data[16:]
|
||||||
|
if uid == 0: #(on zk it's 16 bytes, extrauid 0, status 255, timestamp 0x0)
|
||||||
|
continue # probably
|
||||||
|
user_id = str(uid) #TODO revisar posibles valores cruzar con userdata
|
||||||
|
timestamp = self.__decode_time(timestamp)
|
||||||
|
attendance = Attendance(uid, user_id, timestamp, status)
|
||||||
|
attendances.append(attendance)
|
||||||
else:
|
else:
|
||||||
while len(attendance_data) >= 40:
|
while len(attendance_data) >= 40:
|
||||||
uid, user_id, sparator, timestamp, status, space = unpack('H24sc4sc8s', attendance_data.ljust(40)[:40])
|
uid, user_id, sparator, timestamp, status, space = unpack('H24sc4sc8s', attendance_data.ljust(40)[:40])
|
||||||
@ -945,64 +1119,7 @@ class ZK(object):
|
|||||||
attendances.append(attendance)
|
attendances.append(attendance)
|
||||||
attendance_data = attendance_data[40:]
|
attendance_data = attendance_data[40:]
|
||||||
return attendances
|
return attendances
|
||||||
def _get_attendance(self):
|
|
||||||
'''
|
|
||||||
return all attendance record
|
|
||||||
'''
|
|
||||||
command = const.CMD_ATTLOG_RRQ
|
|
||||||
command_string = ''
|
|
||||||
response_size = 1024
|
|
||||||
cmd_response = self.__send_command(command, command_string, response_size)
|
|
||||||
attendances = []
|
|
||||||
if cmd_response.get('status'):
|
|
||||||
if cmd_response.get('code') == const.CMD_PREPARE_DATA:
|
|
||||||
bytes = self.__get_data_size()
|
|
||||||
attendance_data = []
|
|
||||||
pac = 1
|
|
||||||
while True: #limitado por respuesta no por tamaño
|
|
||||||
data_recv = self.__sock.recv(1032)
|
|
||||||
response = unpack('HHHH', data_recv[:8])[0]
|
|
||||||
#print "# %s packet response is: %s" % (pac, response)
|
|
||||||
if response == const.CMD_DATA:
|
|
||||||
pac += 1
|
|
||||||
attendance_data.append(data_recv[8:]) #header turncated
|
|
||||||
bytes -= 1024
|
|
||||||
elif response == const.CMD_ACK_OK:
|
|
||||||
break #without problem.
|
|
||||||
else:
|
|
||||||
#truncado! continuar?
|
|
||||||
#print "broken!"
|
|
||||||
break
|
|
||||||
#print "still needs %s" % bytes
|
|
||||||
if response == const.CMD_ACK_OK:
|
|
||||||
if attendance_data:
|
|
||||||
attendance_data = ''.join(attendance_data)
|
|
||||||
attendance_data = attendance_data[4:]
|
|
||||||
if self.firmware == 6:
|
|
||||||
while len(attendance_data) >= 8:
|
|
||||||
uid, status, timestamp = unpack('HH4s', attendance_data.ljust(8)[:8])
|
|
||||||
attendance_data = attendance_data[8:]
|
|
||||||
if uid == 0: #(on zk it's 16 bytes, extrauid 0, status 255, timestamp 0x0)
|
|
||||||
continue # probably
|
|
||||||
user_id = str(uid) #TODO revisar posibles valores cruzar con userdata
|
|
||||||
timestamp = self.__decode_time(timestamp)
|
|
||||||
attendance = Attendance(uid, user_id, timestamp, status)
|
|
||||||
attendances.append(attendance)
|
|
||||||
else:
|
|
||||||
while len(attendance_data) >= 40:
|
|
||||||
uid, user_id, sparator, timestamp, status, space = unpack('H24sc4sc8s', attendance_data.ljust(40)[:40])
|
|
||||||
user_id = user_id.split('\x00')[0]
|
|
||||||
timestamp = self.__decode_time(timestamp)
|
|
||||||
status = int(status.encode("hex"), 16)
|
|
||||||
|
|
||||||
attendance = Attendance(uid, user_id, timestamp, status)
|
|
||||||
attendances.append(attendance)
|
|
||||||
|
|
||||||
attendance_data = attendance_data[40:]
|
|
||||||
self.free_data()
|
|
||||||
else:
|
|
||||||
raise ZKErrorResponse("can't _get attendance")
|
|
||||||
return attendances
|
|
||||||
|
|
||||||
def clear_attendance(self):
|
def clear_attendance(self):
|
||||||
'''
|
'''
|
||||||
|
@ -94,6 +94,8 @@ EF_FPFTR = (1<<8)# be real-time capture fingerprint minutia
|
|||||||
EF_ALARM = (1<<9)# Alarm signal
|
EF_ALARM = (1<<9)# Alarm signal
|
||||||
|
|
||||||
USER_DEFAULT = 0
|
USER_DEFAULT = 0
|
||||||
|
USER_ENROLLER = 2
|
||||||
|
USER_MANAGER = 6
|
||||||
USER_ADMIN = 14
|
USER_ADMIN = 14
|
||||||
|
|
||||||
FCT_ATTLOG = 1
|
FCT_ATTLOG = 1
|
||||||
@ -103,3 +105,6 @@ FCT_OPLOG = 4
|
|||||||
FCT_USER = 5
|
FCT_USER = 5
|
||||||
FCT_SMS = 6
|
FCT_SMS = 6
|
||||||
FCT_UDATA = 7
|
FCT_UDATA = 7
|
||||||
|
|
||||||
|
MACHINE_PREPARE_DATA_1 = 20560 # 0x5050
|
||||||
|
MACHINE_PREPARE_DATA_2 = 32130 # 0x7282
|
Loading…
Reference in New Issue
Block a user