Python TCP服务端多线程接收RFID网络读卡器上传数据

news/2024/5/17 20:22:43 标签: 网络, 服务器, TCP, Python, 多线程

本示例使用设备介绍:WIFI/TCP/UDP/HTTP协议RFID液显网络读卡器可二次开发语音播报POE-淘宝网 (taobao.com) 

#python通过缩进来表示代码块,不可以随意更改每行前面的空白,否则程序会运行错误!!!如果缩进不一致,就会报错: IndentationError
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#python -m pdb xxx.py 调试程度 n命令单步执行,s命令单步执行 会进入函数内部  b xx ,c
#import pdb    pdb.set_trace() 设断点

import sys
import socketserver
import os
import socket
import time
import pdb

class Server(socketserver.BaseRequestHandler):
    def handle(self):
        print("conn is :", self.request)  # conn
        print("client_address is :", self.client_address)  # addr

        while True:
            if self.request:
                # 接收收消息
                data = self.request.recv(1024).strip()
                if not data:
                    print("no data break")
                    break
                    print("no data continue")
                    continue

                GetData = 'Received from %s:%s' % (self.client_address) + " :"
                for num in range(0, len(data)):
                    GetData = GetData + '%02X ' % (data[num])
                print(GetData)

                #解析接收到的数据
                if (data[0] == eval('0xC1') or data[0] == eval('0xCF')):  # 接收IC读卡器上传的读卡号数据、IC卡离开读卡器的信息
                    FunCode = '%02X' % (data[0])
                    DEvIp = '%d.%d.%d.%d' % (data[1], data[2], data[3], data[4])  # 设备IP
                    DevNo = '%05d' % (data[5] + data[6] * 256)  # 机号
                    FrameNo = '%d' % (data[7] + data[8] * 256)  # 数据包序号
                    Cardlen=data[9];    #卡号长度
                    Card16H=""          #16进制卡号
                    for num in range(10, 10+Cardlen):
                        Card16H = Card16H + '%02X' % (data[num])
                    Cardno = data[10]   #转10进制卡号
                    Cardno = Cardno + (data[11] * 256)
                    Cardno = Cardno + (data[12] * 65536)
                    Cardno = Cardno + (data[13] * 16777216)
                    CardnoStr = '%010d' % Cardno

                    SerialNum = ''  # 设备硬件序列号
                    for num in range(10+Cardlen, len(data)):
                        SerialNum = SerialNum + '%02X' % (data[num])
                    if (data[0] == eval('0xC1')):
                        print('数据解析:IC读卡器刷卡数据,设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo +",卡号长度:"+"%d" %(Cardlen)+ ",16进制卡号:" + Card16H + " 转10进制卡号:" + CardnoStr + ",硬件序列号:" + SerialNum+"\n")
                    else:
                        print('数据解析:IC卡离开读卡器,设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo +",卡号长度:"+"%d" %(Cardlen)+ ",16进制卡号:" + Card16H + " 转10进制卡号:" + CardnoStr + ",硬件序列号:" + SerialNum + "\n")

                    RespByte=GetResponseData(2)     #根据不同情况生成要回应指令码
                    self.request.sendall(RespByte)  #发送回应指令码
                    SendData = 'Send Data to %s:%s' % (self.client_address) + " :"
                    for num in range(0, len(RespByte)):
                        SendData = SendData + '%02X ' % (RespByte[num])
                    print(SendData+"\n")

                elif (data[0] == eval('0xD1') or data[0] == eval('0xDF')):   # 接收ID读卡器上传的读卡号数据、ID卡离开读卡器数据
                    FunCode = '%02X' % (data[0])
                    DEvIp = '%d.%d.%d.%d' % (data[1], data[2], data[3], data[4])  # 设备IP
                    DevNo = '%05d' % (data[5] + data[6] * 256)  # 机号
                    FrameNo = '%d' % (data[7] + data[8] * 256)  # 数据包序号
                    Card16H = '%02X%02X%02X%02X%02X' % (data[9],data[10], data[11], data[12], data[13])  # 16进制卡号
                    Cardno = data[9]       #转10进制卡事情
                    Cardno = Cardno + (data[10] * 256)
                    Cardno = Cardno + (data[11] * 65536)
                    Cardno = Cardno + (data[12] * 16777216)
                    CardnoStr = '%010d' % Cardno
                    SerialNum = ''  # 设备硬件序列号
                    for num in range(14, len(data)):
                        SerialNum = SerialNum + '%02X' % (data[num])

                    if (data[0] == eval('0xD1')):
                        print('数据解析:ID读卡器刷卡数据,设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",16进制卡号:" + Card16H + " 转10进制卡号:" + CardnoStr + ",硬件序列号:" + SerialNum + "\n")
                    else:
                        print('数据解析:ID卡离开读卡器,设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",16进制卡号:" + Card16H + " 转10进制卡号:" + CardnoStr + ",硬件序列号:" + SerialNum + "\n")

                    RespByte = GetResponseData(2)  # 根据不同情况生成要回应指令码
                    self.request.sendall(RespByte)  # 发送回应指令码
                    SendData = 'Send Data to %s:%s' % (self.client_address) + " :"
                    for num in range(0, len(RespByte)):
                        SendData = SendData + '%02X ' % (RespByte[num])
                    print(SendData + "\n")

                elif (data[0] == eval('0xF3')):  # 接收到设备的心跳数据包,设备心跳间隔可根据协议自行设置
                    FunCode = '%02X' % (data[0])
                    DEvIp = '%d.%d.%d.%d' % (data[1], data[2], data[3], data[4])  # 设备IP
                    DevNo = '%05d' % (data[5] + data[6] * 256)  # 机号
                    FrameNo = '%d' % (data[7] + data[8] * 256)  # 数据包序号
                    heartbeattype='%02X' % (data[9])
                    outleng='%d' % (data[10])
                    switchon='%02X' % (data[11])
                    inputinf='%02X' % (data[12])
                    rand='%02X%02X%02X%02X' % (data[13], data[14], data[15], data[16])
                    SerialNum = ''
                    for num in range(17, len(data)):
                        SerialNum = SerialNum + '%02X' % (data[num])
                    print('接收数据解析:设备心跳包,设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",心跳类型:" + heartbeattype + ",长度:" + outleng+ ",继电器状态:" + switchon + ",输入接口状态:" + inputinf + ",随机校验码:" + rand  + ",硬件序列号:" + SerialNum + "\n")

def GetResponseData(respcode):      # 生成不同的回应数据
    sdata=bytearray()
    if (respcode==0):               # 生成蜂鸣响声的回应数据
        sdata.append(eval('0x96'))  # 蜂鸣响声的指令码
        sdata.append(eval('0x00'))  # 机号低
        sdata.append(eval('0x00'))  # 机号高,0000表示任意机号
        sdata.append(eval('0x01'))  # 蜂鸣响声代码,取值范围0-12

    elif(respcode==1):              # 生成显示文字+蜂鸣响声的 回应数据
        DispStr = "本次刷卡成功,感谢您的使用,再见!            "
        DispByte = bytes(DispStr, encoding='gbk')    # 将要显示的文字转bytes
        DispByte = DispByte[0:34]                    # 两行屏可以显示34个字符
        CommByte=bytes([eval('0x5A'), 0, 0, 2, 30])  # 5A是指令码+2字节机号+1字节蜂鸣代码+1字节显示时长
        sdata = CommByte + DispByte                  # 加入显示文字的ASC码

    elif (respcode == 2):           # 生成显示文字+蜂鸣响声的+继电器开关+TTS中文语音的 回应数据
        DispStr = "本次刷卡成功,感谢您的使用,再见!            "
        DispByte = bytes(DispStr, encoding='gbk')   # 将要显示的文字转bytes
        DispByte = DispByte[0:34]                   # 两行屏可以显示34个字符

        SpkStr = '[v1]欢迎您使用我们的网络读卡器,谢谢!'     # 要播报的TTS语音,[v10]表示音量,取值0-16,可放置字符串的任意地方,一次最多126个字节
        Spkb = bytes(SpkStr, encoding='gbk')            # 将要播报的TTS语音转bytes,
        Spkl = len(Spkb)  # TTS语音长度

        sufb = bytes([eval('0x55'), eval('0xaa'), eval('0x66'), eval('0x99')])      # 固定的抗干扰后缀
        comb = bytes([eval('0x5C'), 0, 0, 1, eval('0xF0'), 20, 0, 20, 0, 34,Spkl])  # 5C是指令码+2字节机号+1字节蜂鸣代码+1字节继电器代码+2字节继电器延时+1字节显示时长+1字节显示起始位+1字节显示长度+1语音长度
        sdata = comb + DispByte + Spkb + sufb

    elif (respcode == 3):  # 生成开启继电器开关的 回应数据
        sdata.append(eval('0x78'))  # 蜂鸣响声的指令码
        sdata.append(eval('0x00'))  # 机号低
        sdata.append(eval('0x00'))  # 机号高,0000表示任意机号
        sdata.append(eval('0xF0'))  # 继电器代码 F0表示全部继电器、F1表示1号继电器 、F2表示2号继电器......
        sdata.append(eval('0x2c'))  # 继电器开启延时低位
        sdata.append(eval('0x01'))  # 继电器开启延时高位,FFFF表示继电器一直开启
    return sdata


if __name__ == "__main__":
    IpList = []
    if sys.platform == 'linux' or sys.platform == 'mac':  # linux、mac系统获取电脑所有网卡IP
        ips = [ip.split('/')[0] for ip in os.popen("ip addr | grep 'inet '|awk '{print $2}'").readlines()]
        for i in ips:
            IpList.append(i)
            print('%d   ' % (len(IpList)) + i)
    else:
        addrs = socket.getaddrinfo(socket.gethostname(), None)  # windows获取电脑所有网卡IP
        for item in addrs:
            if ':' not in item[4][0]:
                IpList.append(item[4][0])
                print('%d   ' % (len(IpList)) + item[4][0])

    Bindip = IpList[0]          # 如有多张网卡,可选择绑定不同的网卡
    address = ('', 39169)       # 未指定绑定网卡,可侦听本机所有网卡信息,读卡器出厂默认39169通讯端口

    with socketserver.ThreadingTCPServer(address, Server) as server:
        try:
            server.serve_forever()
        except Exception as e:
            print(e)
            pass
    pass

 


http://www.niftyadmin.cn/n/5158392.html

相关文章

获取当前时间为本周的第几小时,getHourOfWeek

/*** 获取Date时间为本周的第几小时* param currentDate* return*/public static Integer getHourOfWeekForDate(Date currentDate) {LocalDateTime localDateTime LocalDateTime.ofInstant(currentDate.toInstant(), ZoneId.systemDefault());return getHourOfWeekForLocalDa…

应用在触摸显示屏中的高性能低功耗触摸芯片

触摸屏显示器(Touch Screen)可以让使用者只要用手指轻轻地碰计算机显示屏上的图符或文字就能实现对主机操作,这样摆脱了键盘和鼠标操作,使人机交互更为直截了当。简单的说,只是在显示器上安装了触摸屏,成为带有触摸功能的显示器。…

2311d游戏引擎适配ios

原文 通过遵循arsd:simpledisplay(v11.0.0之前)上的一些旧代码,Apple的文档和Jacob的这一惊人贡献桥, 我已从金属绑定中删除了所有extern(Objective-C)代码,现在,所有Objective-C桥接代码都是使用D的反射生成的. 因此,给定此例代码: import core.attribute : selector; extern…

2023年【金属非金属矿山(地下矿山)安全管理人员】实操考试视频及金属非金属矿山(地下矿山)安全管理人员操作证考试

题库来源:安全生产模拟考试一点通公众号小程序 金属非金属矿山(地下矿山)安全管理人员实操考试视频考前必练!安全生产模拟考试一点通每个月更新金属非金属矿山(地下矿山)安全管理人员操作证考试题目及答案…

算法通关村第十四关黄金挑战——堆解决数据流的中位数和数组求中位数的方法总结

关注微信公众号:怒码少年。回复关键词【电子书】,领取多本计算机相关电子书 遇到任何问题都可以在后台向我提问,完全免费!!大家共同进步!! 大家好,我是怒码少年小码。 本篇主要是讲…

极简web集成 rtsp/rtmp免插件播放,web rtsp/rtmp推流方案

一直有客户要求在Web上集成rtsp/rtmp播放和web推流功能,测试对比各种流服务平台和播放器后,发现在github的ovsyunlive不管是延时,便捷和集成易用性都是非常好,还是看效果吧,直接下载测试如下: github 搜ovsyunlive下载…

「Verilog学习笔记」使用generate…for语句简化代码

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点,刷题网站用的是牛客网 分析 generate…for语句是Verilog HDL语言特有的语句,使用循环结构编写可综合的多个形式相近的代码,循环变量必须由特定关键字genvar声明。 timesca…

玻色量子“揭秘”之最大割(Max-Cut)问题与QUBO建模

Max-Cut问题简单地说,就是求一种分割方法。给定一张无向图, 将所有顶点分割成两群, 同时使得被切断的边数量最大,或边的权重最大。 QUBO(Quadratic Unconstrained Binary Optimization)问题即二次无约束二值优化问题,…