#!/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()