id_card_reader.py 7.0 KB

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