Python 调用带指针参数DLL动态库函数读写IC卡

#!/usr/bin/env python

# -*- coding: utf-8 -*-

#QQ:954486673

#微信:13822155058

#淘宝:https://item.taobao.com/item.htm?spm=a1z10.5-c.w4002-17663462238.11.3614789e318TMs&id=615391857885

 

import ctypes             #调用DLL动态库要有这个引用

import sys

import os

import pdb               #引入程序调试功能,可用  pdb.set_trace()  设置程序调试断点

 

#IC卡操作错误代码解释

def PrintErrInf(Errcode):

    if(Errcode==8):

        print('错误代码:8,未寻到卡,请重新拿开卡后再放到感应区!')

    elif(Errcode==1):

        print('错误代码:1,0~2块都没读出来,可能刷卡太块。但卡序列号已被读出来!')

    elif(Errcode==2):

        print('错误代码:2,第0块已被读出,但1~2块读取失败。卡序列号已被读出来!')

    elif(Errcode==3):   

        print('错误代码:3,第0、1块已被读出,但2块读取失败。卡序列号已被读出来!')

    elif(Errcode==9):

        print('错误代码:9,有多张卡在感应区,寻卡过程中防冲突失败,读序列吗错误!')

    elif(Errcode==10):

        print('错误代码:10,该卡可能已被休眠,无法选中卡片!')

    elif(Errcode==11):

        print('错误代码:11,密码装载失败!')       

    elif(Errcode==12):

        print('错误代码:12,卡片密码认证失败!')

    elif(Errcode==13):

        print('错误代码:13,读本块失败,原因是刷卡太快或本块所对应的区还没通过密码认证!')

    elif(Errcode==14):

        print('错误代码:14,写本块失败,原因是刷卡太快或本块所对应的区还没通过密码认证!')

    elif(Errcode==21):

        print('错误代码:21,没有动态库!')

    elif(Errcode==22):

        print('错误代码:22,动态库或驱动程序异常!')

    elif(Errcode==23):

        print('错误代码:23,驱动程序错误或尚未安装!')

    elif(Errcode==24):

        print('错误代码:24,操作超时,一般是动态库没有反映!')

    elif(Errcode==25):

        print('错误代码:25,发送字数不够!')

    elif(Errcode==26):

        print('错误代码:26,发送的CRC错!')

    elif(Errcode==27):

        print('错误代码:27,接收的字数不够!')

    elif(Errcode==28):

        print('错误代码:28,接收的CRC错!')

    else:

        print('未知错误,错误代码:'+str(status))

       

#加载当前目录下的DLL

dllfile=sys.path[0]+'\OUR_MIFARE.dll'

Objdll = ctypes.windll.LoadLibrary(dllfile)

Objdll = ctypes.WinDLL(dllfile)

 

#控制字定义

BLOCK0_EN=eval('0x01')        #读写块0

BLOCK1_EN=eval('0x02')        #读写块1

BLOCK2_EN=eval('0x04')        #读写块2

NEEDSERIAL=eval('0x08')       #读写指定序列号的卡

EXTERNKEY=eval('0x10')        #需要每次指定密码

NEEDHALT=eval('0x20')         #写卡后是否休眠卡

 

#根据入口参数执行不同功能

if(len(sys.argv)>1):

    if(str(sys.argv[1])=='0'):    #驱动读写器发出响声

        Objdll.pcdbeep(50)

        print('驱动读卡器嘀一声!')

       

    elif(str(sys.argv[1])=='1'):  #读取设备的出厂编号

        devno=bytes(4)            #声明4个字节缓冲

        status=Objdll.pcdgetdevicenumber(devno) % 256

        if(status==0):

            Objdll.pcdbeep(38)           

            SerialNum=''

            for num in range(0,len(devno)):

                SerialNum=SerialNum+'%02x' % (devno[num])

                if(num<len(devno)-1):

                    SerialNum=SerialNum+'-'

            print('设备出厂编号:'+ SerialNum)

        else:

            print('读取设备编号失败,错误代码:'+str(status))

           

    elif(str(sys.argv[1])=='2'):  #轻松读取卡内某扇区3个块共48个字节数据

        myctrlword=BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY        #读写控制字

        myareano=8    #指定读写区号为第8区

        authmode=1    #大于0表示用A密码认证,推荐用A密码认证

        mypicckey=bytes([eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF')])  #卡片认证密码,16进制

        mypiccserial=bytes(4)            #4字节卡序列号缓冲

        mypiccdata=bytes(48)             #读卡数据缓冲,一个扇区共48个字节

        status = Objdll.piccreadex(myctrlword, mypiccserial, myareano, authmode, mypicckey, mypiccdata) % 256

        if(status==0):

            Objdll.pcdbeep(38)           

            Cardno=mypiccserial[0]

            Cardno=Cardno+(mypiccserial[1]*256)

            Cardno=Cardno+(mypiccserial[2]*65536)

            Cardno=Cardno+(mypiccserial[3]*16777216)

            CardnoStr='%010d' % Cardno

            print('10进制卡号:'+CardnoStr)           

            piccdataStr=''

            for num in range(0,len(mypiccdata)):

                piccdataStr=piccdataStr+'%02x ' % (mypiccdata[num])

            print('卡内数据:'+ piccdataStr)

        else:

            PrintErrInf(status)

           

    elif(str(sys.argv[1])=='3'):  #轻松改写卡内某扇区3个块共48个字节数据

        myctrlword=BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY        #读写控制字

        myareano=8                #指定读写区号为第8区

        authmode=1                #大于0表示用A密码认证,推荐用A密码认证

        mypicckey=bytes([eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF')])  #卡片认证密码,16进制

        mypiccserial=bytes(4)     #4字节卡序列号缓冲

       

        #mypiccdata=bytes([0,1,2,3,4,5,6,7,8,9,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个字节

        #如果要写字符串等信息,将字符串转成字节数组写入

        Writeinf='伟大的中华人民共和国万岁!2020-weidadezhonhuarenmingongheguowangshi'

        Writeinf=Writeinf[0:48]                     #一个扇区最多写48个字节

        mypiccdata=bytes(Writeinf, encoding='gbk')  #将要写入的信息转bytes    

        status = Objdll.piccwriteex(myctrlword, mypiccserial, myareano, authmode, mypicckey, mypiccdata) % 256

        if(status==0):

            Objdll.pcdbeep(38)

            print('16进制卡号:%02x%02x%02x%02x,写卡成功!' % (mypiccserial[0],mypiccserial[1],mypiccserial[2],mypiccserial[3]))

        else:

            PrintErrInf(status)

           

    elif(str(sys.argv[1])=='4'):  #修改卡片的A密码+控制字+B密码

        myctrlword=BLOCK0_EN + BLOCK1_EN + BLOCK2_EN + EXTERNKEY        #读写控制字

        myareano=8                #指定读写区号为第8区

        authmode=1                #大于0表示用A密码认证,推荐用A密码认证

        mypiccoldkey=bytes([eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF')])  #卡片认证密码,16进制

       

        #mypiccnewkey 指定6字节新A密码+4字节控制码+6字节B密码+1字节功能码 ,注意:指定新密码时一定要记住,否则有可能找不回密码,导致该卡报废!!!

        #功能码为:3 表示同时更改A、B 密码及权限访问字

        #功能码为:2 表示密码权限访问字不更改,只改A、B密码

        #功能码为:0 示只改A密码

       

        mypiccnewkey=bytes([eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0x07'),eval('0x80'),eval('0x69'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0x03')])

        mypiccserial=bytes(4)     #4字节卡序列号缓冲

        status = Objdll.piccchangesinglekeyex(myctrlword, mypiccserial, myareano, authmode, mypiccoldkey, mypiccnewkey) % 256

        if(status==0):

            Objdll.pcdbeep(38)

            print('16进制卡号:%02x%02x%02x%02x,更改卡密码成功!' % (mypiccserial[0],mypiccserial[1],mypiccserial[2],mypiccserial[3]))

        else:

            PrintErrInf(status)

           

    elif(str(sys.argv[1])=='5'):  #读取某块共16个字节数据

        myareano=8                #指定读写区号为第8区

        myblock=myareano*4+0      #块号为区号*4+0、1、2、3,其中第3块为密码控制块,

        authmode=1                #大于0表示用A密码认证,推荐用A密码认证

        mypicckey=bytes([eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF')])  #卡片认证密码,16进制

        mypiccserial=bytes(4)     #4字节卡序列号缓冲

        myblockdata=bytes(16)     #读卡数据缓冲,一个块共16个字节

       

        status = Objdll.piccrequest(mypiccserial) % 256                                     #寻找感应区内的卡片

        if(status==0):

            status = Objdll.piccauthkey1(mypiccserial,myareano,authmode,mypicckey) % 256    #寻到卡后,认证要读块所在扇区的密码

            if(status==0):

                status = Objdll.piccread(myblock,myblockdata) % 256                         #密码认证成功,读块数据

                if(status==0):

                    Objdll.pcdbeep(38)

                    ReadInf=''

                    for num in range(0,len(myblockdata)):

                        ReadInf=ReadInf+'%02x ' % (myblockdata[num])

                    print('卡号:%02x%02x%02x%02x,读块数据成功!' % (mypiccserial[0],mypiccserial[1],mypiccserial[2],mypiccserial[3]))

                    print('块内16进制数据:'+ReadInf)

                else:

                    PrintErrInf(status)

            else:

                PrintErrInf(status)

        else:

            PrintErrInf(status)

           

    elif(str(sys.argv[1])=='6'):      #写取某块共16个字节数据

        myareano=8                    #指定写区号为第8区

        blockid=0                     #指定写块号0、1、2、3,其中第3块为密码控制块,如改写第三块要确定写入的数据正确否这个扇区将报废!!!

        myblock=myareano*4+blockid    #块地址=扇区号*4+块号

        authmode=1                    #大于0表示用A密码认证,推荐用A密码认证

        mypicckey=bytes([eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF'),eval('0xFF')])  #卡片认证密码,16进制

        mypiccserial=bytes(4)         #4字节卡序列号缓冲

       

        if(blockid<3):

            myblockdata=bytes([0,1,2,3,4,5,6,7,8,9,10,11,12,13,15,15])     #写卡数据缓冲,一个块共16个字节

        else:

            #改写第3块是修改卡密码及控制字,修改前要确定数据是否正确,修改后要记住改写的密码!否则报废此扇区!!!以下信息表示改A\B密码:FFFFFFFFFFFF,不改控制位

            myblockdata=bytes([255,255,255,255,255,255,eval('0xFF'),eval('0x07'),eval('0x80'),eval('0x69'),255,255,255,255,255,255])    

           

        status = Objdll.piccrequest(mypiccserial) % 256                                     #寻找感应区内的卡片

        if(status==0):

            status = Objdll.piccauthkey1(mypiccserial,myareano,authmode,mypicckey) % 256    #寻到卡后,认证要读块所在扇区的密码

            if(status==0):

                status = Objdll.piccwrite(myblock,myblockdata) % 256                        #密码认证成功,写块数据

                if(status==0):

                    Objdll.pcdbeep(38)

                    print('卡号:%02x%02x%02x%02x,写块数据成功!' % (mypiccserial[0],mypiccserial[1],mypiccserial[2],mypiccserial[3]))

                else:

                    PrintErrInf(status)

            else:

                PrintErrInf(status)

        else:

            PrintErrInf(status)

           

    else:

        print('请加入正确的参数运行程序')

else:

    print('\n')

    print('请加以下参数运行程序:')

    print('参数 0 驱动读卡器嘀一声')

    print('参数 1 读4个字节设备编号')

    print('参数 2 读取某扇区3个块共48个字节卡内数据')

    print('参数 3 改写某扇区3个块共48个字节数据')

    print('参数 4 修改卡片密码及控制位')

    print('参数 5 读取某块16个字节数据')

    print('参数 6 改写某块16个字节数据')

       

sys.exit()

猜你喜欢

转载自blog.csdn.net/zhangjin7422/article/details/111307355