Python写入URI网址到Ntag 424 DNA标签配置开启动态UID计数器镜像

本示例使用的发卡器:https://h5.m.taobao.com/awp/core/detail.htm?ft=t&id=615391857885

写入URI网址

python 复制代码
    def pb_WriteUil_clicked(self):
        myctrlword=eval('0x00')
        picckeystr="000000000000000000000000000000000000"    #不需要认证密钥

        if self.checkBox_AuthKey.isChecked():                #需要认证卡密钥
            authkeystr = self.lineEdit_NdefAuthKey.text().strip()
            if self.checkhexstr(authkeystr, 16) == False:
                QMessageBox.critical(None, "提示", '十六进制认证密钥输入错误,请输入 %d' % 16 + ' 字节的16进制认证密钥!', QMessageBox.Yes)
                self.lineEdit_NdefAuthKey.setFocus()
                return

            if self.comboBox_NdefConnModly.currentIndex()==0:
                myctrlword = eval('0x40')
            elif self.comboBox_NdefConnModly.currentIndex()==1:
                myctrlword = eval('0x41')
            else:
                myctrlword = eval('0x43')

            picckeystr="04"+ "%02X" %self.spinBox_NdefKeyId.value()
            picckeystr=picckeystr+authkeystr

        picckeybuf=bytes.fromhex(picckeystr)
        languagecodestr = "en".encode('gbk')
        titlestr = self.lineEdit_title.text().strip().encode('gbk')
        uriheaderindex = self.comboBox_headindex.currentIndex()
        uristr = self.lineEdit_uri.text().strip().encode('gbk')

        Objdll.tagbuf_forumtype4_clear()   #清空写卡缓冲区
        status = Objdll.tagbuf_adduri(languagecodestr, len(languagecodestr), titlestr, len(titlestr),uriheaderindex, uristr, len(uristr)) % 256   #将本次要写的信息加入数据缓冲
        if status==0:
            mypiccserial=bytes(7)
            mypiccseriallen=bytes(1)
            status = Objdll.forumtype4_write_ndeftag(myctrlword, mypiccserial, mypiccseriallen, picckeybuf)     #将缓冲冲区数据写入标签
            if status == 0:
                Objdll.pcdbeep(20)
                carduid = "ForumType4UID:"
                for num in range(0, mypiccseriallen[0]):
                    carduid = carduid + '%02X' % (mypiccserial[num])
                QMessageBox.information(None, "提示", carduid+",URI网址写入成功!" , QMessageBox.Yes)
            else:
                self.DispErrInf(status)
        else:
            QMessageBox.critical(None, "提示", '将写卡信息加入写卡缓冲时返回错误代码:%d' % status , QMessageBox.Yes)

配置卡片参数开启动态UID、计数器、加密数据MAC镜像

python 复制代码
    def pb_ChangeConfig_clicked(self):
        configdata = bytearray(32)

        configdata[0] = 0          #通讯模式明文
        if self.comboBox_ConfigConnModly.currentIndex()==1:
            configdata[0] = 1      #通讯模式MAC
        elif self.comboBox_ConfigConnModly.currentIndex()==2:
            configdata[0] = 3      #通讯模式密文+MAC

        if self.checkBox_SdmMirrorEn.isChecked():
            configdata[0]=configdata[0]+eval('0x40')      #启用SDM镜像

        #文件访问权限
        if self.comboBox_ChangeKeyId.currentIndex()<5:
            configdata[1]=self.comboBox_ChangeKeyId.currentIndex()     #更改指令需要先认证的密码
        elif self.comboBox_ChangeKeyId.currentIndex()==5:
            configdata[1] =eval('0x0e')        #无需密码,直接用明文
        else:
            configdata[1] = eval('0x0f')       #禁止该指令

        if self.comboBox_RWKeyId.currentIndex() < 5:
            configdata[1]=configdata[1]+self.comboBox_RWKeyId.currentIndex()*16   #读写指令 需要先认证的密码
        elif self.comboBox_RWKeyId.currentIndex() == 5:
            configdata[1] = configdata[1] +eval('0xe0')
        else:
            configdata[1] = configdata[1] + eval('0xf0')

        if self.comboBox_WriteOnlyKeyId.currentIndex()<5:
            configdata[2]=self.comboBox_WriteOnlyKeyId.currentIndex()     #只写指令 需要先认证的密码
        elif self.comboBox_WriteOnlyKeyId.currentIndex()==5:
            configdata[2] =eval('0x0e')        #无需密码,直接用明文
        else:
            configdata[2] = eval('0x0f')       #禁止该指令

        if self.comboBox_ReadOnlyKeyId.currentIndex() < 5:
            configdata[2]=configdata[2]+self.comboBox_ReadOnlyKeyId.currentIndex()*16   #只读指令 需要先认证的密码
        elif self.comboBox_ReadOnlyKeyId.currentIndex() == 5:
            configdata[2] = configdata[2] +eval('0xe0')
        else:
            configdata[2] = configdata[2] + eval('0xf0')

        j=3

        if (configdata[0] & eval('0x40'))>0:  #启用SDM镜像
            configdata[3]=1       #Encoding mode默认为ASCII
            if self.checkBox_UidMirrorEn.isChecked():
                configdata[3]=configdata[3]+eval('0x80')    #启用UID镜像
            if self.checkBox_CountMirrorEn.isChecked():
                configdata[3]=configdata[3]+eval('0x40')    #启用计数器镜像
            if self.checkBox_CountLimitEn.isChecked():
                configdata[3]=configdata[3]+eval('0x20')    #启用计数器限额
            if self.checkBox_SDMENCFileData.isChecked():
                configdata[3]=configdata[3]+eval('0x10')    #启用SDMENCFileData

            #SDMAccessRights
            configdata[4]=eval('0xf0')

            if self.comboBox_SDMKeyid.currentIndex() < 5:
                configdata[4] = configdata[4] + self.comboBox_SDMKeyid.currentIndex()   # 计数器访问 需要先认证的密码
            elif self.comboBox_SDMKeyid.currentIndex() == 5:
                configdata[4] = configdata[4] + eval('0x0e')  #明文
            else:
                configdata[4] = configdata[4] + eval('0x0f')  #禁止该指令

            if self.comboBox_SDM.currentIndex() < 5:
                configdata[5] =  self.comboBox_SDM.currentIndex() * 16  #SDMMetaRead 需要先认证的密码
            elif self.comboBox_SDM.currentIndex() == 5:
                configdata[5] =  eval('0xe0')       #明文
            else:
                configdata[5] =  eval('0xf0')       #禁止该指令

            j=j+1

            if self.comboBox_Cmackey.currentIndex() < 5:
                configdata[5] = configdata[5] + self.comboBox_Cmackey.currentIndex()   # 无需密码,直接用明文
            else:
                configdata[5] = configdata[5] + eval('0x0f')  #禁止该指令

            j=6

            if (configdata[5] & eval('0xf0'))==eval('0xe0'):
                if (configdata[3] & eval('0x80'))>0:  #UID镜像位置
                    Get3Byte=int_to_3bytes(self.numericUpDown1.value())
                    configdata[6] = Get3Byte[2]
                    configdata[7] = Get3Byte[1]
                    configdata[8] = Get3Byte[0]
                    j=9

                if (configdata[3] & eval('0x40')) > 0:  # 计数器镜像
                    Get3Byte = int_to_3bytes(self.numericUpDown5.value())
                    configdata[j] = Get3Byte[2]
                    configdata[j+1] = Get3Byte[1]
                    configdata[j+2] = Get3Byte[0]
                    j=j+3
            elif (configdata[5] & eval('0xf0'))<eval('0x50'):
                Get3Byte = int_to_3bytes(self.numericUpDown3.value())
                configdata[6] = Get3Byte[2]
                configdata[7] = Get3Byte[1]
                configdata[8] = Get3Byte[0]
                j = 9

            if (configdata[5] & eval('0x0f')) != eval('0x0f'):
                Get3Byte = int_to_3bytes(self.numericUpDown2.value())           #SDMMACInputOffset
                configdata[j] = Get3Byte[2]
                configdata[j + 1] = Get3Byte[1]
                configdata[j + 2] = Get3Byte[0]
                j=j+3

                if (configdata[3] & eval('0x10')) > 0:
                    Get3Byte = int_to_3bytes(self.numericUpDown7.value())       #SDMENCOffset
                    configdata[j] = Get3Byte[2]
                    configdata[j + 1] = Get3Byte[1]
                    configdata[j + 2] = Get3Byte[0]
                    j = j + 3

                    Get3Byte = int_to_3bytes(self.numericUpDown8.value())       #SDMENCLength
                    configdata[j] = Get3Byte[2]
                    configdata[j + 1] = Get3Byte[1]
                    configdata[j + 2] = Get3Byte[0]
                    j = j + 3

                Get3Byte = int_to_3bytes(self.numericUpDown4.value())       #SDMMACOffset
                configdata[j] = Get3Byte[2]
                configdata[j + 1] = Get3Byte[1]
                configdata[j + 2] = Get3Byte[0]
                j = j + 3

            if (configdata[3] & eval('0x20') >0):   #计数器限额值j
                Get3Byte = int_to_3bytes(self.numericUpDown6.value())  # SDMMACOffset
                configdata[j] = Get3Byte[2]
                configdata[j + 1] = Get3Byte[1]
                configdata[j + 2] = Get3Byte[0]
                j = j + 3

        #参数设定规则校验
        if (configdata[3] & eval('0x40') >0):
            if (configdata[3] & eval('0xC0')== 0):
                QMessageBox.critical(None, "提示", '当开启SDM镜像时,必须开启UID镜像或计数器镜像!', QMessageBox.Yes)
                return

            if (configdata[3] & eval('0x80') > 0):
                if (configdata[5] & eval('0xF0') == eval('0xF0')):
                    QMessageBox.critical(None, "提示", '当启用UID镜像时,SDM元数据读取访问权限不能为禁止!', QMessageBox.Yes)
                    return
            else:
                if (configdata[5] & eval('0xF0') < eval('0xF0')):
                    QMessageBox.critical(None, "提示", '当不开启UID镜像时,SDM元数据读取访问权限只能为禁止!', QMessageBox.Yes)
                    return

            if (configdata[3] & eval('0x40')== 0):
                if (configdata[4] & eval('0x0F') < eval('0x0F')):
                    QMessageBox.critical(None, "提示", '当不开启计数器镜像时,SDM计数器检索密钥只能为禁止!', QMessageBox.Yes)
                    return

            if (configdata[3] & eval('0x80')> 0) or (configdata[5] & eval('0xF0')< eval('0x50')):
                i=9
            else:
                i=6

            if (configdata[5]==eval('0xE0')):
                i = i+3

            SDMMACInputOffset = 0
            SDMENCOffset = 0
            SDMENCLength = 0
            SDMMACOffset = 0
            if (configdata[5] & eval('0x0F')< eval('0x05')):
                SDMMACInputOffset=configdata[i] + configdata[i + 1] * 256 + configdata[i + 2] * 65536
                i=i+3

                if (configdata[3] & eval('0x10') > eval('0x00')):
                    SDMENCOffset = configdata[i] + configdata[i + 1] * 256 + configdata[i + 2] * 65536
                    i = i + 3

                    SDMENCLength = configdata[i] + configdata[i + 1] * 256 + configdata[i + 2] * 65536
                    i = i + 3

                SDMMACOffset = configdata[i] + configdata[i + 1] * 256 + configdata[i + 2] * 65536
                i = i + 3

                if (configdata[3] & eval('0x10') > eval('0x00')):
                    if (SDMENCOffset < SDMMACInputOffset):
                        QMessageBox.critical(None, "提示", 'SDMENCOffset不能小于SDMMACInputOffset!', QMessageBox.Yes)
                        return

                    if (SDMENCLength < 32):
                        QMessageBox.critical(None, "提示", 'SDMENCLength不能小于32!', QMessageBox.Yes)
                        return

                    if (SDMMACOffset < (SDMENCOffset + SDMENCLength)):
                        QMessageBox.critical(None, "提示", 'SDMMACOffset不能小于(SDMENCOffset + SDMENCLength)!', QMessageBox.Yes)
                        return
                else:
                    if (SDMMACOffset < SDMMACInputOffset):
                        QMessageBox.critical(None, "提示", 'SDMMACOffset不能小于SDMMACInputOffset!', QMessageBox.Yes)
                        return

        datastr = ''
        for num in range(0, j):
            datastr = datastr + '%02X' % (configdata[num])
        self.lineEdit_ConfigData.setText(datastr)
        databuf = bytes.fromhex(datastr)

        retsw = bytes(2)
        status = Objdll.ntagchangefilesettings(self.comboBox_RWConfigConnModly.currentIndex(), 2,databuf, j, retsw) % 256
        retstr = "%02X%02X" % (retsw[0], retsw[1])
        if (retstr == "9100"):
            Objdll.pcdbeep(20)
            QMessageBox.information(None, "提示", "更改配置成功!", QMessageBox.Yes)
        elif (retstr == "91AE"):
            if self.comboBox_RWConfigConnModly.currentIndex()==1:
                QMessageBox.critical(None, "提示", "更改配置操作卡片返回代码:" + retstr + ",更改指令被禁止或密码未认证或密码不对,请先用正确的密码号进行认证再试!" ,QMessageBox.Yes)
            else:
                QMessageBox.critical(None, "提示", "更改配置操作卡片返回代码:" + retstr + ",更改指令被禁止或不支持明文操作,请先用正确的密码号进行认证并且选择"密文+MAC保护的通信模式"再试!!",QMessageBox.Yes)
        else:
            QMessageBox.critical(None, "提示", "更改配置操作卡片返回代码:" + retstr + ",说明:" + self.RetTextFromStr(retstr), QMessageBox.Yes)

卡片密钥认证

python 复制代码
    def pb_authkey_clicked(self):
        authkeystr = self.lineEdit_AuthKey.text().strip()
        if self.checkhexstr(authkeystr, 16) == False:
            QMessageBox.critical(None, "提示", '十六进制认证密钥输入错误,请输入 %d' % 16 + ' 字节的16进制认证密钥!', QMessageBox.Yes)
            self.lineEdit_AuthKey.setFocus()
            return

        authkeybuf = bytes.fromhex(authkeystr)
        keyid=self.spinBox_AuthKeyId.value()
        keytype=self.comboBox_KeyMode.currentIndex()
        retsw=bytes(2)
        status=Objdll.desfireauthkeyev2(authkeybuf, keyid, keytype, retsw) % 256
        retstr="%02X%02X" % (retsw[0],retsw[1])
        if (status == 0):
            QMessageBox.information(None, "提示", "认证密码操作,卡片返回代码:" + retstr + ",说明:" + self.RetTextFromStr(retstr), QMessageBox.Yes)
        else:
            QMessageBox.critical(None, "提示","认证密码操作返回异常:%d" % status + "卡片返回代码:" + retstr + ",说明:" + self.RetTextFromStr(retstr), QMessageBox.Yes)

更改卡片密钥

python 复制代码
    def pb_changekey_clicked(self):
        authkeystr = self.lineEdit_AuthKey.text().strip()
        if self.checkhexstr(authkeystr, 16) == False:
            QMessageBox.critical(None, "提示", '十六进制认证密钥输入错误,请输入 %d' % 16 + ' 字节的16进制认证密钥!', QMessageBox.Yes)
            self.lineEdit_AuthKey.setFocus()
            return

        newkeystr = self.lineEdit_NewKey.text().strip()
        if self.checkhexstr(newkeystr, 16) == False:
            QMessageBox.critical(None, "提示", '十六进制新密钥输入错误,请输入 %d' % 16 + ' 字节的16进制新密钥!', QMessageBox.Yes)
            self.lineEdit_NewKey.setFocus()
            return

        oldkeybuf = bytes.fromhex(authkeystr)
        newkeybuf = bytes.fromhex(newkeystr)
        keyid = self.spinBox_ChangeKeyid.value()
        retsw = bytes(2)
        status = Objdll.ntagchangkey(newkeybuf, keyid, 1,oldkeybuf, retsw) % 256
        retstr = "%02X%02X" % (retsw[0], retsw[1])
        if (status == 0):
            if (retstr=="91AE"):
                QMessageBox.critical(None, "提示", "更改卡密钥操作返回异常,卡片返回代码:" + retstr + ",说明:更改密码指令被禁止或密码未认证或密码不对,请先用0号密码认证后再试!" , QMessageBox.Yes)
            else:
                QMessageBox.information(None, "提示", "认证密码操作,卡片返回代码:" + retstr + ",说明:" + self.RetTextFromStr(retstr), QMessageBox.Yes)
        else:
            QMessageBox.critical(None, "提示","更改卡密钥操作返回异常:%d" % status + "卡片返回代码:" + retstr + ",说明:" + self.RetTextFromStr(retstr), QMessageBox.Yes)

读取标签内写入的网址信息

python 复制代码
    def pb_ReadNdef_clicked(self):
        myctrlword=eval('0x00')
        picckeystr="000000000000000000000000000000000000"    #不需求认证密钥

        if self.checkBox_AuthKey.isChecked():                #需要认证卡密钥
            authkeystr = self.lineEdit_NdefAuthKey.text().strip()
            if self.checkhexstr(authkeystr, 16) == False:
                QMessageBox.critical(None, "提示", '十六进制认证密钥输入错误,请输入 16 字节正确的认证密钥!', QMessageBox.Yes)
                self.lineEdit_NdefAuthKey.setFocus()
                return

            if self.comboBox_NdefConnModly.currentIndex()==0:
                myctrlword = eval('0x40')
            elif self.comboBox_NdefConnModly.currentIndex()==1:
                myctrlword = eval('0x41')
            else:
                myctrlword = eval('0x43')

            picckeystr="04"+ "%02X" %self.spinBox_NdefKeyId.value()
            picckeystr=picckeystr+authkeystr

        picckeybuf = bytes.fromhex(picckeystr)[0:18]

        if self.checkBox_MirrorImage.isChecked():   #解析镜像
            sdmkeystr = self.lineEdit_ReadDataKey.text().strip()
            if self.checkhexstr(sdmkeystr, 16) == False:
                QMessageBox.critical(None, "提示", '十六进制SDM元数据读取验证密码输入错误,请输入16字节正确的验证密钥!', QMessageBox.Yes)
                self.lineEdit_ReadDataKey.setFocus()
                return
            sdmkeybuf=bytes.fromhex(sdmkeystr)[0:16]
            picckeybuf=picckeybuf+sdmkeybuf

            cmcakeystr = self.lineEdit_CmacKey.text().strip()
            if self.checkhexstr(cmcakeystr, 16) == False:
                QMessageBox.critical(None, "提示", '十六进制CMAC验证密码输入错误,请输入16字节正确的CMAC验证密钥!', QMessageBox.Yes)
                self.lineEdit_CmacKey.setFocus()
                return
            cmcakeybuf=bytes.fromhex(cmcakeystr)[0:16]
            picckeybuf = picckeybuf + cmcakeybuf

            myctrlword=myctrlword+4

        Objdll.tagbuf_forumtype4_clear()  # 清空写卡缓冲区
        mypiccserial = bytes(7)
        mypiccseriallen = bytes(1)
        status = Objdll.forumtype4_read_ndeftag(myctrlword, mypiccserial, mypiccseriallen, picckeybuf)  # 读取标签内数据
        if (status == 0 or status == 55):
            Objdll.pcdbeep(20)
            carduid = "ForumType4UID:"
            for num in range(0, mypiccseriallen[0]):
                carduid = carduid + '%02X' % (mypiccserial[num])

            mypiccdata = bytes(2048)
            revstrlen = bytes(2)
            recordnumber = bytes(2)
            Objdll.tagbuf_read(mypiccdata, revstrlen, recordnumber)
            ndefstr = mypiccdata.decode('gbk')
            self.plainTextEdit_taginf.setPlainText(ndefstr)
        else:
            self.DispErrInf(status)
相关推荐
虾..2 小时前
Linux 信号的处理
linux·运维·服务器
Nautiluss2 小时前
一起调试XVF3800麦克风阵列(三)
linux·人工智能·嵌入式硬件·音频·语音识别·dsp开发·智能音箱
大聪明-PLUS2 小时前
如何在 Docker 中优化容器镜像大小
linux·嵌入式·arm·smarc
布史2 小时前
Linux软链接应用详解:从原理到实战案例
linux·运维·服务器
2401_841495642 小时前
【Python高级编程】Python 核心语法速查演示
python·字符串·集合·列表·元组·字典·运算符
顶点多余2 小时前
linux的基本指令
linux·运维·服务器
Peterrrr09112 小时前
深入理解 Shell 编程:正则表达式与 sed 文本处理器
linux·运维·正则表达式·sed·linux命令
海清河晏1113 小时前
Linux进阶篇:网络编程
linux·运维·网络
2301_811958383 小时前
服务器自己账号下安装conda
linux·python·conda