python能调用身份证读卡器吗_用Python在Linux下调用新中新DKQ-A16D读卡器,读二代证数据...

本文介绍了如何在Linux环境下,使用Python调用新中新DKQ-A16D身份证读卡器,通过ctypes库加载.so文件,创建结构体并调用相应函数读取身份证信息和照片,实现身份证数据的获取和解码。
摘要由CSDN通过智能技术生成

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文件,具体调用的函数如下:

//打开USB通信

intOpenUsbComm();//读身份证文字和照片信息

int getIDcard(St_IDCardDataUTF8 *pIDCardDataUTF8);//解码照片函数,wltBuffer原始照片1024字节wlt数据,bmpPath 保存照片位置

int saveWlt2Bmp( char* wltBuffer,const char*bmpPath);int saveWlt2BmpUseFork( char* wltBuffer,const char*bmpPath);//关闭USB通信

int CloseComm();

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

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

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

typedef structIDCardDataUTF8 {char CardType[10]; //I为外国人居住证,J 为港澳台居住证,空格(0x20)为普通身份证

char Name[40]; //姓名

char EngName[130]; //英文名(外国人居住证)

char Sex[10]; //性别

char Nation[100]; //民族或国籍(外国人居住证)

char Birthday[18]; //出生日期

char Address[80]; //住址

char IDCardNo[40]; //身份证号或外国人居住证号(外国人居住证)

char GrantDept[40]; //发证机关

char UserLifeBegin[30]; //有效开始日期

char UserLifeEnd[30]; //有效截止日期

char PassID[30]; //通行证号码(港澳台)

char IssuesTimes[10]; //签发次数(港澳台)

char CertVol[10]; //证件版本号(外国人居住证)

char wlt[1024]; //照片数据

int isSavePhotoOK; //照片是否解码保存 0=no 1=yes

char fp[1024]; //指纹数据

int isFpRead; //是否读取了证内指纹 0=no 1=yes

} St_IDCardDataUTF8, *PSt_IDCardDataUTF8;

3.开搞Python

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

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

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

importctypesfrom ctypes import *synR= ctypes.cdll.LoadLibrary("/usr/lib/libSynReader64.so")

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

nRet = synR.OpenUsbComm()

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

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

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

classIDCardDataUTF8(Structure):

_fields_=[

("CardType", c_char * 10), #I为外国人居住证,J 为港澳台居住证,空格(0x20)为普通身份证

("Name", c_char * 40), #姓名

("EngName", c_char * 130), #英文名(外国人居住证)

("Sex", c_char * 10), #性别

("Nation", c_char*100), #民族或国籍(外国人居住证)

("Birthday", c_char*18), #出生日期

("Address", c_char*80), #住址

("IDCardNo", c_char*40), #身份证号或外国人居住证号(外国人居住证)

("GrantDept", c_char*40), #发证机关

("UserLifeBegin", c_char*30), #有效开始日期

("UserLifeEnd", c_char*30), #有效截止日期

("PassID", c_char*30), #通行证号码(港澳台)

("IssuesTimes", c_char*10), #签发次数(港澳台)

("CertVol", c_char * 10), #证件版本号(外国人居住证)

("wlt", c_byte*1024), #照片数据

("isSavePhotoOK", c_int), #照片是否解码保存 0=no 1=yes

("fp", c_char*1024), #指纹数据

("isFpRead", c_int) #是否读取了指纹

]

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

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

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

data =IDCardDataUTF8()

readRet= synR.getIDcard(byref(data))

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

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

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

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

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

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

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

synR.CloseComm()

4.结束

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值