|
@@ -0,0 +1,183 @@
|
|
|
|
+#!/usr/bin/python
|
|
|
|
+# -*- coding: UTF-8 -*-
|
|
|
|
+#
|
|
|
|
+# 读卡器读取身份证信息
|
|
|
|
+# 调用Dll
|
|
|
|
+# author: Scott Chen
|
|
|
|
+# date: 2019-12-13
|
|
|
|
+
|
|
|
|
+import ctypes
|
|
|
|
+import codecs
|
|
|
|
+from log_ware import LogWare
|
|
|
|
+logger = LogWare().get_logger()
|
|
|
|
+
|
|
|
|
+# 自定义异常
|
|
|
|
+class ReaderIdCardError:
|
|
|
|
+ pass
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+class IdCardReader:
|
|
|
|
+ def __init__(self, dll_lib="apps/idcard/biz/lib/dll/termb.dll", id_card_path="wz.txt"):
|
|
|
|
+ # 要调用的动态链接库位置
|
|
|
|
+ self.__dll_lib_local = dll_lib
|
|
|
|
+ # 身份证信息保存文件路径,当前项目目录下
|
|
|
|
+ self.__id_card_info_path = id_card_path
|
|
|
|
+ # 调用公安部统一动态识别库
|
|
|
|
+ self.__dll = ctypes.windll.LoadLibrary(self.__dll_lib_local)
|
|
|
|
+
|
|
|
|
+ self.__id_car_info = self.__id_car_info_build()
|
|
|
|
+ self.__sex_dict = self.__sex_dict_build()
|
|
|
|
+ self.__nation_dict = self.__nation_dict_build()
|
|
|
|
+
|
|
|
|
+ def recognize(self):
|
|
|
|
+ t1 = self.__init_machine()
|
|
|
|
+ if t1 is False:
|
|
|
|
+ self.__id_car_info['error'] = '[10001]打开设备失败'
|
|
|
|
+ return self.__id_car_info
|
|
|
|
+
|
|
|
|
+ t2 = self.__authc()
|
|
|
|
+ if t2 is False:
|
|
|
|
+ self.__id_car_info['error'] = '[10002]未放卡或卡片放置不正确,身份证认证失败'
|
|
|
|
+ return self.__id_car_info
|
|
|
|
+
|
|
|
|
+ t3 = self.__read()
|
|
|
|
+ if t3 is False:
|
|
|
|
+ self.__id_car_info['error'] = '[10003]读卡发生错误'
|
|
|
|
+ return self.__id_car_info
|
|
|
|
+ return self.__id_car_info
|
|
|
|
+
|
|
|
|
+ def __init_machine(self):
|
|
|
|
+ # 初始化读卡器
|
|
|
|
+ connPort = self.__dll.InitCommExt()
|
|
|
|
+ if connPort == 0:
|
|
|
|
+ logger.debug("查找并打开设备端口失败")
|
|
|
|
+ self.__close()
|
|
|
|
+ return False
|
|
|
|
+ else:
|
|
|
|
+ logger.debug("设备连接在%s", connPort)
|
|
|
|
+ return True
|
|
|
|
+
|
|
|
|
+ def __authc(self):
|
|
|
|
+ # 读卡器身份证认证
|
|
|
|
+ is_authc = self.__dll.Authenticate()
|
|
|
|
+ if is_authc == 1:
|
|
|
|
+ logger.debug("设备认证%s", is_authc)
|
|
|
|
+ return True
|
|
|
|
+ else:
|
|
|
|
+ self.__error_print("未放卡或卡片放置不正确,身份证认证失败")
|
|
|
|
+ self.__close()
|
|
|
|
+ return False
|
|
|
|
+
|
|
|
|
+ def __read(self):
|
|
|
|
+ # 1 读基本信息,形成文字信息文件wz.txt、相片文件xp.wlt、zp.bmp,如果有指纹信息形成指纹信息文件fp.dat
|
|
|
|
+ # 2 只读文字信息,形成文字信息文件wz.txt和相片文件xp.wlt
|
|
|
|
+ # 3 读最新住址信息,形成最新住址文件newadd.txt
|
|
|
|
+ read_result = self.__dll.Read_Content(2)
|
|
|
|
+ if read_result != 1:
|
|
|
|
+ self.__error_print("读卡发生错误")
|
|
|
|
+ return False
|
|
|
|
+ else:
|
|
|
|
+ self.__read_id_card()
|
|
|
|
+ logger.debug("身份证信息:%s", str(self.__id_car_info))
|
|
|
|
+ self.__close()
|
|
|
|
+ return True
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ ####################################################################################################
|
|
|
|
+
|
|
|
|
+ def __id_car_info_build(self):
|
|
|
|
+ return {
|
|
|
|
+ 'name': '',
|
|
|
|
+ 'sex': '',
|
|
|
|
+ 'nation': '',
|
|
|
|
+ 'born_date': '',
|
|
|
|
+ 'address': '',
|
|
|
|
+ 'id_no': '',
|
|
|
|
+ 'sign_gov': '',
|
|
|
|
+ 'start_date': '',
|
|
|
|
+ 'end_date': ''
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ def __sex_dict_build(self):
|
|
|
|
+ return {
|
|
|
|
+ '1': '男',
|
|
|
|
+ '2': '女',
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ def __nation_dict_build(self):
|
|
|
|
+ return {
|
|
|
|
+ '01': '汉', '02': '汉', '03': '回', '04': '藏', '05': '维吾尔', '06': '苗',
|
|
|
|
+ '07': '彝', '08': '壮', '09': '布依', '10': '朝鲜', '11': '满', '12': '侗',
|
|
|
|
+ '13': '瑶', '14': '白', '15': '土家', '16': '哈尼', '17': '哈萨克', '18': '傣',
|
|
|
|
+ '19': '黎', '20': '傈僳', '21': '佤', '22': '畲', '23': '高山', '24': '拉祜',
|
|
|
|
+ '25': '水', '26': '东乡', '27': '纳西', '28': '景颇', '29': '柯尔克孜', '30': '土',
|
|
|
|
+ '31': '达斡尔', '32': '仫佬', '33': '羌', '34': '布朗', '35': '撒拉', '36': '毛南',
|
|
|
|
+ '37': '仡佬', '38': '锡伯', '39': '阿昌', '40': '普米', '41': '塔吉克', '42': '怒',
|
|
|
|
+ '43': '乌孜别克', '44': '俄罗斯', '45': '鄂温克', '46': '德昂', '47': '保安', '48': '裕固',
|
|
|
|
+ '49': '京', '50': '塔塔尔', '51': '独龙', '52': '鄂伦春', '53': '赫哲', '54': '门巴',
|
|
|
|
+ '55': '珞巴', '56': '珞巴'
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ # 解码读取文件内容后的信息,共128个字符
|
|
|
|
+ # "总钻风 10119800918广东省深圳市南山区前海路1080号海之景A座102 440305198009183074深圳市公安局南山分局 2014120520341205 "
|
|
|
|
+
|
|
|
|
+ # 位置关系
|
|
|
|
+ # 1-15 姓名
|
|
|
|
+ # 16 性别
|
|
|
|
+ # 17-18 民族
|
|
|
|
+ # 19-26 出生
|
|
|
|
+ # 27-61 住址
|
|
|
|
+ # 62-79 身份证号
|
|
|
|
+ # 80-94 签发机关
|
|
|
|
+ # 95-102 有效期起始日期
|
|
|
|
+ # 103-128 有效期截止日期
|
|
|
|
+ # 读取文件信息
|
|
|
|
+ def __read_id_card(self):
|
|
|
|
+ try:
|
|
|
|
+ with codecs.open(self.__id_card_info_path, 'r', 'utf-16-le') as f:
|
|
|
|
+ content = f.read()
|
|
|
|
+ info_map = self.__format(content)
|
|
|
|
+ if (info_map is None):
|
|
|
|
+ logger.debug("格式化身份信息文件内容出异常")
|
|
|
|
+ logger.debug("身体份证信息读取成功")
|
|
|
|
+ except Exception as e:
|
|
|
|
+ info = "Error when read id card info from txt file."
|
|
|
|
+ logger.debug("%s, error: %s", info, e)
|
|
|
|
+ raise ReaderIdCardError(info)
|
|
|
|
+
|
|
|
|
+ def __format(self, content):
|
|
|
|
+ if (content is None):
|
|
|
|
+ logger.debug("不能获取身份证信息,文件内容为空")
|
|
|
|
+ return None
|
|
|
|
+ if (len(content) != 128):
|
|
|
|
+ logger.debug("文件内容解码错误,文本长度异常")
|
|
|
|
+ return None
|
|
|
|
+
|
|
|
|
+ self.__id_car_info['name'] = content[0:14].strip()
|
|
|
|
+ self.__id_car_info['sex'] = self.__sex_dict[content[15]]
|
|
|
|
+ # 数字要往后多取一位
|
|
|
|
+ self.__id_car_info['nation'] = self.__nation_dict[content[16:18]]
|
|
|
|
+ self.__id_car_info['born_date'] = content[18:26]
|
|
|
|
+ self.__id_car_info['address'] = content[26:61].strip()
|
|
|
|
+ self.__id_car_info['id_no'] = content[61:79]
|
|
|
|
+ self.__id_car_info['sign_gov'] = content[79:93].strip()
|
|
|
|
+ self.__id_car_info['start_date'] = content[93:102]
|
|
|
|
+ self.__id_car_info['end_date'] = content[102:128].strip()
|
|
|
|
+ return self.__id_car_info
|
|
|
|
+
|
|
|
|
+ def __error_print(self, txt):
|
|
|
|
+ logger.debug("%s,发生错误,请重新放置卡片", txt)
|
|
|
|
+
|
|
|
|
+ def __close(self):
|
|
|
|
+ if (self.__dll.CloseComm() == 1):
|
|
|
|
+ logger.debug("读卡器关闭")
|
|
|
|
+ else:
|
|
|
|
+ logger.debug("读卡器关闭失败")
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+# 单元测试
|
|
|
|
+if __name__ == '__main__':
|
|
|
|
+ id_card_reader = IdCardReader()
|
|
|
|
+ id_card_reader.recognize()
|
|
|
|
+
|