id_card_reader.py 6.5 KB

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