1.背景

最近在研究二代证读卡器,手头上的设备是新中新DKQ-A16D,在官网(https://www.onecardok.com.cn/download)逛了一圈,发现Win下的示例,浏览器插件很多,Linux下的就少的可怜了,只有“新中新身份证读卡器开发包Linux版V1.2.1”,“新中新读卡器麒麟ArmV8火狐扩展程序安装及使用说明V1.1”,意味着浏览器插件还只能在ARM的平台下才能使用。Linux的也只有C++和Java版本。

2.开搞C++

大概看了下C++的Demo,这个Demo主要就是调用CppDemo目录下的那些libx86,libx64等目录下的libSynReader.so文件,具体调用的函数如下:

  1. //打开USB通信
  2. int OpenUsbComm();
  3.  
  4. //读身份证文字和照片信息
  5. int getIDcard(St_IDCardDataUTF8 *pIDCardDataUTF8);
  6.  
  7. //解码照片函数,wltBuffer原始照片1024字节wlt数据,bmpPath 保存照片位置
  8. int saveWlt2Bmp( char* wltBuffer,const char* bmpPath);
  9. int saveWlt2BmpUseFork( char* wltBuffer,const char* bmpPath);
  10.  
  11. //关闭USB通信
  12. int CloseComm();

流程:先打开USB通信(OpenUsbComm) ---> 读取身份证文字和照片信息(getIDcard) ---> 解码照片(saveWlt2Bmp或者saveWlt2BmpUseFork) ---> 关闭USB通信(CloseComm)

至于saveWlt2Bmp和saveWlt2BmpUseFork这两个函数到底什么区别,不懂。两个函数调用结果好像都是一样。

这里需要注意的是getIDcard这个函数,它的参数是一个结构体指针 ,根据CppDemo中的头文件定义,这个结构体是这样的:

  1. typedef struct IDCardDataUTF8 {
  2. char CardType[]; //I为外国人居住证,J 为港澳台居住证,空格(0x20)为普通身份证
  3. char Name[]; //姓名
  4. char EngName[]; //英文名(外国人居住证)
  5. char Sex[]; //性别
  6. char Nation[]; //民族或国籍(外国人居住证)
  7. char Birthday[]; //出生日期
  8. char Address[]; //住址
  9. char IDCardNo[]; //身份证号或外国人居住证号(外国人居住证)
  10. char GrantDept[]; //发证机关
  11. char UserLifeBegin[]; //有效开始日期
  12. char UserLifeEnd[]; //有效截止日期
  13. char PassID[]; //通行证号码(港澳台)
  14. char IssuesTimes[]; //签发次数(港澳台)
  15. char CertVol[]; //证件版本号(外国人居住证)
  16. char wlt[]; //照片数据
  17. int isSavePhotoOK; //照片是否解码保存 0=no 1=yes
  18. char fp[]; //指纹数据
  19. int isFpRead; //是否读取了证内指纹 0=no 1=yes
  20. } St_IDCardDataUTF8, *PSt_IDCardDataUTF8;

3.开搞Python

知道了调用哪些函数,知道了流程,接下来就是Python的事了。

在Python中,要调用.so文件,主要是依靠ctypes这个库。

具体加载so库的代码也简单,

  1. import ctypes
  2. from ctypes import *
  3.  
  4. synR = ctypes.cdll.LoadLibrary("/usr/lib/libSynReader64.so")

加载完库,调用库中的函数也简单,

  1. nRet = synR.OpenUsbComm()

nRet是代表打开USB通信时是否成功,等于0代表开启成功,还有其他的值,具体参见官网下载的那个Linux包里有个word文档。

接下来就是本文的难点了,在Python中是没有结构体这个概念的,那getIDcard又要传一个结构体指针,该怎么办?

好在ctypes已经帮我们想好了,ctype内置了一个Structure这个类,只要我们创建一个类,继承自这个类,在类中定义一个_fields_的list,C++那边就会当作结构体了。具体实现如下:

  1. class IDCardDataUTF8(Structure):
  2. _fields_ = [
  3. ("CardType", c_char * 10), # I为外国人居住证,J 为港澳台居住证,空格(0x20)为普通身份证
  4. ("Name", c_char * 40), # 姓名
  5. ("EngName", c_char * 130), # 英文名(外国人居住证)
  6. ("Sex", c_char * 10), # 性别
  7. ("Nation", c_char*100), # 民族或国籍(外国人居住证)
  8. ("Birthday", c_char*18), # 出生日期
  9. ("Address", c_char*80), # 住址
  10. ("IDCardNo", c_char*40), # 身份证号或外国人居住证号(外国人居住证)
  11. ("GrantDept", c_char*40), # 发证机关
  12. ("UserLifeBegin", c_char*30), # 有效开始日期
  13. ("UserLifeEnd", c_char*30), # 有效截止日期
  14. ("PassID", c_char*30), # 通行证号码(港澳台)
  15. ("IssuesTimes", c_char*10), # 签发次数(港澳台)
  16. ("CertVol", c_char * 10), # 证件版本号(外国人居住证)
  17. ("wlt", c_byte*1024), # 照片数据
  18. ("isSavePhotoOK", c_int), # 照片是否解码保存 0=no 1=yes
  19. ("fp", c_char*1024), # 指纹数据
  20. ("isFpRead", c_int) # 是否读取了指纹
  21. ]

对比下这个结构体和上面C++的结构体,是不是很像?这里有个坑,在下不才,在坑了蹲了2天才跳出来。注意看wlt这项,wlt是存储照片数据的,C++是定义成char,刚开始我也是跟着用c_char,结果死活解码不了照片,后面经过2天的各种搜索,各种尝试,发现这个wlt是一个字节数组,所以需要定义成c_byte,一下子照片就解码出来了。

至于指纹数据,没去研究。

OK,结构体准备好了,实例化一个结构体对象,接着就可以调用getIDcard了。具体代码如下:

  1. data = IDCardDataUTF8()
  2. readRet = synR.getIDcard(byref(data))

这个有个byref代表的就是把data参数变成一个指针,也就是上面C++说的结构体指针。

执行完这句,如果readRet等于0,代表读取成功,接着就可以从data中拿到身份证上的基本信息了。

  1. print(data.Name.decode('utf-8')) #身份证上的姓名

接着就是要解码身份证上的照片信息了。

  1. synR.saveWlt2BmpUseFork(data.wlt, b'photo.bmp')

这行代码执行后,会在.py同级目录下生成一个名为photo.bmp的照片文件,照片解码成功。

最后,就是把USB通信关闭就可以了。

  1. synR.CloseComm()

4.结束

有一点要注意的是,需要把CppDemo目录下对应你系统的libx86或者libx64目录下的所有so文件拷贝到/usr/lib和/lib目录下

用Python在Linux下调用新中新DKQ-A16D读卡器,读二代证数据的更多相关文章

  1. 用Go语言在Linux下调用新中新DKQ-A16D读卡器,读二代证数据

    1.背景 前几天用Python在Linux下成功的获取了二代证数据,最近正在学Go语言,这两天想着用Go语言也实现一下试看看. 2.开搞C++ 这次就比较简单了,直接把CppDemo里面的SynRea ...

  2. [转载]linux下编译php中configure参数具体含义

    编译N次了   原来这么回事 原文地址:linux下编译php中configure参数具体含义作者:捷心特 php编译参数的含义 ./configure –prefix=/usr/local/php ...

  3. linux下查找文件中空行的行号

    linux下查找文件中空行的行号 linux下查找文件中空行的行号 以aa.txt举例: 方法1:sed -n '/[a-zA-Z0-9@#$%^&*]/!=' aa.txt 方法2:grep ...

  4. c# 新中新二代身份证阅读,包含头像,支持华视

    需要用到dll和文件: 其中3个dll文件是需要调用的dll,license.dat文件为解压图片的授权文件 以下是需要用到的dll里面的方法: /************************端口 ...

  5. 关于新中新二代身份证读卡器DKQ-A16D的一些问题

    今天拿到了新中新DKQ-A16D,随机光盘里有以下文件: 我遇到的问题是,如果直接打开\二代征SDK开发包\DLL\测试程序\C#_2008\WindowsFormsApplication1\目录下的 ...

  6. Linux下使用 github+hexo 搭建个人博客06-next主题接入数据统计

    之前说了 next 主题的优化和接入评论系统.让我们完成了自己所需的页面风格和排版,也可让访问用户在每篇博文评论,完成博主和访问用户的交互. 本章我们继续讲解其他重要功能. 既然是一个网站,那么我们就 ...

  7. python在linux下的使用

    1.查看python(解释器)的版本(什么版本的解释器支持哪一版版的语言标准) 一般在linux上已经预装了python,只要在Bash Shell中输入python,即可看到如下版本信息: 按Ctr ...

  8. Linux 2.6内核中新的锁机制--RCU

    转自:http://www.ibm.com/developerworks/cn/linux/l-rcu/ 一. 引言 众所周知,为了保护共享数据,需要一些同步机制,如自旋锁(spinlock),读写锁 ...

  9. Python之Linux下的virtualenv&&virtualenvwrapper

    virtualenv 可以在系统中建立多个不同并且相互不干扰的虚拟环境. #指定清华源下载pip的包 pip3 install -i https://pypi.tuna.tsinghua.edu.cn ...

随机推荐

  1. [推荐]icheck-bootstrap(漂亮的ckeckbox/radiobox)

    适用于Twitter Bootstrap框架的纯CSS样式的复选框/单选框按钮的插件. GitHub:https://github.com/bantikyan/icheck-bootstrap 如果你 ...

  2. Snipaste - 可以提高你工作效率的截图软件

    使用Snipaste提高您的工作效率 Snipaste是一个简单但功能强大的剪切工具,还允许您将屏幕截图固定在屏幕上.下载并启动应用程序,按F1开始剪切,然后按F3将其粘贴为浮动窗口.而已! 您还可以 ...

  3. Theia APIs——事件

    上一篇:Theia APIs——Preferences 事件 Theia中的事件或许会让你感到困惑,希望本节能阐述清楚. 来看下面的代码: (来自logger-watcher.ts) @injecta ...

  4. Linux下搭建C/C++编程环境

    Linux下搭建C/C++编程环境 1.KDevelop下载 wget -O KDevelop.AppImage https://download.kde.org/stable/kdevelop/5. ...

  5. OpenJ_Bailian 4103 踩方格(搜索 动态规划 )

    题目传送门OpenJ_Bailian 4103 描述 有一个方格矩阵,矩阵边界在无穷远处.我们做如下假设:a.    每走一步时,只能从当前方格移动一格,走到某个相邻的方格上:b.    走过的格子立 ...

  6. Qt5学习(1)

    1. In Qt, if you want to apply styles to the main window  itself, you must apply it to  its central ...

  7. Redis系列之----Redis的过期设置及淘汰策略

    Redis的过期时间机制和内存淘汰策略    Redis的数据是存储在内存中的,而服务器的内存大小是有限制的,除非宕机,否则这些数据会一直存在,对于一些不再使用的key,也应当进行删除,否则会浪费内存 ...

  8. Java之IO流用法总结

    Java的IO流概述:1.I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理设备之间的数据传输.如读/写文件,网络通讯等.2.Java程序中,对于数据的输入/输出操作以“流( ...

  9. cogs 3. 服务点设置 dijkstra

    3. 服务点设置 ★   输入文件:djsa.in   输出文件:djsa.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 为了进一步普及九年义务教育,政府要在某乡镇建 ...

  10. Window初始化Git环境

    安装Git 去到官网下载地址,找到自己电脑的对应版本,下载安装就好啦,这里就不一一说明了 https://git-scm.com/download/win 初始化Git环境 第一步:打开git-bas ...