PHP TCP服务端监听端口接收客户端RFID网络读卡器上传的读卡数据

news2024/11/27 11:56:42

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

<?php
header("content-type:text/html;charset=GBK");

set_time_limit(0);
$port=39169;    //监听端口

if(($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === FALSE){
    echo '初始化socket失败: ' . socket_strerror(socket_last_error($socket));
    exit;
}

socket_set_nonblock($socket);

// socket_bind(): 将socket资源绑定到指定地址
if(!socket_bind($socket, '0.0.0.0', $port)){
    echo '绑定端口失败: ' . socket_strerror(socket_last_error($socket));
    exit;
}

// socket_listen(): 监听socket的连接请求
if(!socket_listen($socket)){
    echo '监听端口: ' . socket_strerror(socket_last_error($socket));
    exit;
}else{echo "TCP服务已启动,正在侦听端口:".$port."\n";}

while(1){
    if(($client = socket_accept($socket)) !== FALSE){
        while(1){
            //这里不循环的话,只能接收到一次消息
            $content = socket_read($client, 10240);
            $content = trim($content);

            if($content){
                $response = AnalyzeData($content); //解析接收到的数据,并生成回应数据
                socket_write($client, $response);

                $Sendinf='';                    //将发送的信息用16进制数显示,方便调式
                for($i=0;$i<strlen($response);$i++){
                    $byte = ord($response[$i]);
                    $b=substr('00'.dechex($byte ),-2);
                    $Sendinf=$Sendinf.$b.' ';
                }
                echo "发送数据:".$Sendinf."\n\n";
            }
        }
    }
}
socket_close($socket);

//解析接收到的数据,并根据情况生成不同的回应数据
function AnalyzeData($inMsg)
{
    $len = strlen($inMsg);
    $bytes = array();
    $Getinf='';
    for($i=0;$i<$len;$i++)
    {
        $byte = ord($inMsg[$i]);
        $bytes[] =  $byte ;

        $b=substr('00'.dechex($byte ),-2);
        $Getinf=$Getinf.$b.' ';
    }
    echo "接收数据:".$Getinf. PHP_EOL;

    switch($bytes[0]){
        case hexdec('0xF3'):        //接收到设备的心跳数据包,设备心跳间隔可根据协议自行设置
            $Ipaddstr=$bytes[1].".".$bytes[2].".".$bytes[3] .".".$bytes[4] ;
            $Machine=($bytes[5]+$bytes[6]*256) ;
            $frame=($bytes[7]+$bytes[8]*256) ;
            $Heartbeattype=substr('00'.dechex($bytes[9]),-2);
            $heartlen=$bytes[10];
            $switch=substr('00'.dechex($bytes[11]),-2);
            $keyinput=substr('00'.dechex($bytes[12]),-2);
            $Randcode=substr('00'.dechex($bytes[13]),-2).substr('00'.dechex($bytes[14]),-2).substr('00'.dechex($bytes[15]),-2).substr('00'.dechex($bytes[16]),-2);
            $SerialNum="";
            for($i=17;$i<sizeof($bytes);$i++){
                $SerialNum=$SerialNum.substr('00'.dechex($bytes[$i]),-2);
            }
            $Dispinf="数据解析:设备心跳包,设备IP:".$Ipaddstr.",机号:".$Machine.",数据包序号:".$frame.",心跳类型:".$Heartbeattype.",长度:".$heartlen.",继电器状态:".$switch.",按键值:".$keyinput.",随机码:".$Randcode.",硬件序列号:".$SerialNum;
            echo $Dispinf."\n\n";
            break;
        case hexdec('0xC1') or hexdec('0xCF') :     //接收IC读卡器上传的读卡号数据、IC卡离开读卡器的信息
            if($bytes[0]==hexdec('0xC1')){
                $Dispinf="数据解析:IC读卡器读取卡号,";
            }else{$Dispinf="数据解析:IC卡离开读卡器,";}

            $Ipaddstr=$bytes[1].".".$bytes[2].".".$bytes[3] .".".$bytes[4] ;
            $Machine=($bytes[5]+$bytes[6]*256) ;
            $frame=($bytes[7]+$bytes[8]*256) ;
            $Cardlen=$bytes[9];
            $Card16H="";
            for($i=0;$i<$Cardlen;$i++)
            {
                $Card16H=$Card16H.substr('00'.dechex($bytes[10+$i]),-2);
            }
            $CardNo=$bytes[10] & 0xff;
            $CardNo=$CardNo+($bytes[11] & 0xff) *256;
            $CardNo=$CardNo+($bytes[12] & 0xff) *65536;
            $CardNo=$CardNo+($bytes[13] & 0xff) *16777216;
            $CardNo=substr("0000000000".$CardNo,-10);
            $SerialNum ="";
            for($i=10+$Cardlen;$i<$len;$i++){
                $SerialNum=$SerialNum.substr('00'.dechex($bytes[$i]),-2);
            }
            $Dispinf=$Dispinf."设备IP:".$Ipaddstr.",机号:".$Machine.",数据包序号:".$frame.",卡号长度:".$Cardlen.",16进制卡号:".$Card16H.",转十进制卡号:".$CardNo.",硬件序列号:".$SerialNum;
            echo $Dispinf."\n\n";

            //此处加入业务对数据库的查、增、删、减等操作

            $DispStr="卡号:".$CardNo."  ".substr(date('Y-m-d h:i:s', time()),0,16)."            "; //全屏显示信息长度>=34
            return GetResponseData(4,$DispStr); //生成回应数据

            break;
        case hexdec('0xD1') or hexdec('0xDF') :     //接收ID读卡器上传的读卡号数据、ID卡离开读卡器的信息
            if($bytes[0]==hexdec('0xD1')){
                $Dispinf="数据解析:ID读卡器读取卡号,";
            }else{$Dispinf="数据解析:ID卡离开读卡器,";}

            $Ipaddstr=$bytes[1].".".$bytes[2].".".$bytes[3] .".".$bytes[4] ;
            $Machine=($bytes[5]+$bytes[6]*256) ;
            $frame=($bytes[7]+$bytes[8]*256) ;
            $Card16H="";
            for($i=9;$i<14;$i++)
            {
                $Card16H=$Card16H.substr('00'.dechex($bytes[10+$i]),-2);
            }
            $CardNo=$bytes[9] & 0xff;
            $CardNo=$CardNo+($bytes[10] & 0xff) *256;
            $CardNo=$CardNo+($bytes[11] & 0xff) *65536;
            $CardNo=$CardNo+($bytes[12] & 0xff) *16777216;
            $CardNo=substr("0000000000".$CardNo,-10);
            $SerialNum ="";
            for($i=14;$i<$len;$i++){
                $SerialNum=$SerialNum.substr('00'.dechex($bytes[$i]),-2);
            }
            $Dispinf=$Dispinf."设备IP:".$Ipaddstr.",机号:".$Machine.",数据包序号:".$frame.",16进制卡号:".$Card16H.",转十进制卡号:".$CardNo.",硬件序列号:".$SerialNum;
            echo $Dispinf."\n\n";

            //此处加入业务对数据库的查、增、删、减等操作

            $DispStr="卡号:".$CardNo."  ".substr(date('Y-m-d h:i:s', time()),0,16)."            "; //全屏显示信息长度>=34
            return GetResponseData(4,$DispStr); //生成回应数据

            break;
        default:
    }
}

//根据情况生成不同的回应数据
function GetResponseData($respcode,$DispStr)
{
    $sdata = array();
    switch($respcode){
        case 0:     //回只应蜂鸣响声
            $sdata[0] = hexdec('0x96');    //指令码
            $sdata[1] = 0;                          //机号低位,
            $sdata[2] = 0;                          //机号高位,高低位都为0表示任意机号
            $sdata[3] = 1;                          //蜂鸣响声代码,取值范围0-12,代表12种不同的蜂鸣响声
            $sendBuf = '';
            for ($i = 0; $i < 4; $i++) {
                $sendBuf = $sendBuf . chr($sdata[$i]);
            }
            return $sendBuf;
            break;
        case 1:     //回应只开启继电器
            $sdata[0] = hexdec('0x78');    //指令码
            $sdata[1] = 0;                          //机号低位,
            $sdata[2] = 0;                          //机号高位,高低位都为0表示任意机号
            $sdata[3] = hexdec('0xF0');    //继电器代码 F0表示全部继电器、F1表示1号继电器 、F2表示2号继电器、F3表示3号继电器......
            $sdata[4] = hexdec('0x2C');    //继电器开启延时低位16进制
            $sdata[5] = hexdec('0x01');    //继电器开启延时高位16进制,高低位取值FFFF表示继电器一直开启
            $sendBuf = '';
            for ($i = 0; $i < 6; $i++) {
                $sendBuf = $sendBuf . chr($sdata[$i]);
            }
            return $sendBuf;
            break;
        case 2:     //回应只关闭已开启的继电器
            $sdata[0] = hexdec('0x78');    //指令码
            $sdata[1] = 0;                          //机号低位,
            $sdata[2] = 0;                          //机号高位,高低位都为0表示任意机号
            $sdata[3] = hexdec('0xE0');    //继电器代码 E0表示全部继电器、E1表示1号继电器 、E2表示2号继电器、E3表示3号继电器......
            $sdata[4] = hexdec('0x2C');    //继电器关闭延时低位16进制
            $sdata[5] = hexdec('0x01');    //继电器关闭延时高位16进制,高低位取值FFFF表示继电器一直关闭
            $sendBuf = '';
            for ($i = 0; $i < 6; $i++) {
                $sendBuf = $sendBuf . chr($sdata[$i]);
            }
            return $sendBuf;
            break;
        case 3:     //回应蜂鸣响声+文字显示
            $sdata[0]=hexdec('0x5A');    //指令码
            $sdata[1]=0;                          //机号低位
            $sdata[2]=0;                          //机号高位,高低位都为0表示任意机号
            $sdata[3]=2;                          //蜂鸣声代码,取值范围0-12,代表12种不同的蜂鸣响声
            $sdata[4]=20;                         //显示时长,单位秒,取值范围0-255,取值255时表示永久显示
            $sendBuf='';
            for($i=0;$i<5;$i++)
            {
                $sendBuf=$sendBuf.chr($sdata[$i]);
            }
            $sendBuf=$sendBuf.$DispStr;
            return $sendBuf;
            break;
        case 4:     //回应蜂鸣响声+继电器开关+文字显示+播报TTS语音
            $SpeakStr="[v10]";                    //[v10]是语音大小,取值范围0-16,可加在任何地方,其他语音策略请看文档说明
            $SpeakStr=$SpeakStr."刷卡成功,感谢您使用我们的网络读卡器!";//要播报的TTS语音,每条指令最大不能超过126字符
            $Splen = strlen($SpeakStr);           //TTS语音长度
            //
            $sdata[0]=hexdec('0x5C');    //指令码
            $sdata[1]=0;                          //机号低位
            $sdata[2]=0;                          //机号高位,高低位都为0表示任意机号
            $sdata[3]=2;                          //蜂鸣声代码,取值范围0-12,代表12种不同的蜂鸣响声
            $sdata[4]=hexdec('0xF0');    //继电器代码 F0表示全部继电器 F1表示1号继电器 F2表示2号继电器

            $sdata[5]=hexdec('0x2C');    //继电器开启时长低位
            $sdata[6]=hexdec('0x01');    //继电器开启时长高位

            $sdata[7]=hexdec('0x14');    //显示保留时间,单位为秒,为0xFF时表示永久显示
            $sdata[8]=0;                          //在显示屏中的哪个位置开始
            $sdata[9]=hexdec('0x22');    //显示字符串长度 为全屏显示为 34 个字符
            $sdata[10]=$Splen;                    //语音长度

            $suffixStr=chr(hexdec('0x55')).chr(hexdec('0xaa')).chr(hexdec('0x66')).chr(hexdec('0x99'));  //固定的抗干扰后缀

            $sendBuf='';
            for($i=0;$i<11;$i++)
            {
                $sendBuf=$sendBuf.chr($sdata[$i]);
            }
            $sendBuf=$sendBuf.substr($DispStr,0,34).$SpeakStr.$suffixStr;   //最长显示34个字符

            return $sendBuf;
            break;
        default:
    }
}

//获取本机IP地址------------------------------------------------------------------------------------------------------------------------
function get_local_ip()
{
    $preg = "/\A((([0-9]?[0-9])|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))\.){3}(([0-9]?[0-9])|(1[0-9]{2})|(2[0-4][0-9])|(25[0-5]))\Z/";
    //获取操作系统为win2000/xp、win7的本机IP真实地址
    $Netdriv=array();
    exec("ipconfig", $out, $stats);
    if (!empty($out)) {
        foreach ($out AS $row) {
            if (strstr($row, "IP") && strstr($row, ":") && !strstr($row, "IPv6")) {
                $tmpIp = explode(":", $row);
                if (preg_match($preg, trim($tmpIp[1]))) {
                    $Netdriv[]=trim($tmpIp[1]);
                    echo trim($tmpIp[1])."\n";
                }
            }
        }
    }
    //获取操作系统为linux类型的本机IP真实地址
    //exec("ifconfig", $out, $stats);
    //if (!empty($out)) {
    //    if (isset($out[1]) && strstr($out[1], 'addr:')) {
    //        $tmpArray = explode(":", $out[1]);
    //        $tmpIp = explode("", $tmpArray[1]);
    //        if (preg_match($preg, trim($tmpIp[0]))) {
    //            return trim($tmpIp[0]);
    //        }
    //    }
    //}
    if (!empty($Netdriv)) {
        return $Netdriv[0];   //如果有多张网块,可以修改数组取值来绑定相应的网卡
    }else{
        return '127.0.0.1';
    }
}

?>

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1261024.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pycharm 怎么切换Anaconda简单粗暴

&#xff08;1&#xff09;创建一个环境 &#xff08;2&#xff09;选择一下自己conda的安装路径中conba.exe (3)选择存在的环境&#xff0c;一般会自动检测到conda创建有哪些环境&#xff0c;导入就行

C++二分查找视频教程:两数之和

作者推荐 利用广度优先或模拟解决米诺骨牌 本文涉及的基础知识点 二分查找算法合集 题目 给你一个下标从 1 开始的整数数组 numbers &#xff0c;该数组已按 非递减顺序排列 &#xff0c;请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 n…

单片机学习11——矩阵键盘

矩阵键盘&#xff1a; 这个矩阵键盘可以接到P0、P1、P2、P3都是可以的。 使用矩阵键盘是能节省单片机的IO口。 P3.0 P3.1 P3.2 P3.3 称之为行号。 P3.4 P3.5 P3.6 P3.7 称之为列号。 矩阵键盘检测原理&#xff1a; 1、检查是否有键按下&#xff1b; 2、键的抖动处理&#xf…

XIAO ESP32S3之套件简绍

很高兴收到柴火创客空间寄来的XIAO ESP32S3开发套件。 一、套件介绍 1、电路板部分 一块XIAO ESP32S3主板、一块摄像头接口板&#xff08;可接SD卡&#xff09;&#xff0c;一根2.4G天线。 2、配件部分 一根USB-A转TypeC数据线、一个USB3.0转TypeC转接头、一个SD卡读卡器&am…

集动作捕捉与表情捕捉的系统,怎么用于动画制作?

对于传统动画制作来说&#xff0c;将要处理数字人的动作与表情&#xff0c;最原始的方式是打关键帧&#xff0c;通过关键帧的形式来展现数字人的弹跳、行走、奔跑等动作&#xff0c;但这种制作方式往往时间长&#xff0c;成本高&#xff0c;效率低。而一个集动作捕捉与表情捕捉…

spring boot的redis连接数过多导致redis服务器压力过大的一次问题排查

一、背景 在今天上午的时候&#xff0c;突然收到大量的sentry报错&#xff0c;都是关于redis连接超时的警告。 首先想到的是去查看redis的监控&#xff0c;发现那个时间段&#xff0c;redis的请求数剧增&#xff0c;cpu使用率和带宽都陡增双倍。 下面的是redis监控的cpu情况 …

【MySql】14- 实践篇(十二)-grant权限/分区表/自增Id用完怎么办

文章目录 1.grant之后要跟着flush privileges吗&#xff1f;1.1 全局权限1.2 db 权限1.3 表权限和列权限1.4 flush privileges 使用场景 2. 要不要使用分区表?2.1 分区表是什么?2.2 分区表的引擎层行为2.3 分区策略2.4 分区表的 server 层行为2.5 分区表的应用场景 3. 自增Id…

高效视频剪辑:按指定时长批量分割视频,释放无尽创意

随着数字媒体技术的不断发展&#xff0c;视频剪辑已经成为日常生活中不可或缺的一部分。无论是制作电影、电视剧&#xff0c;还是创意生活短视频&#xff0c;视频剪辑都扮演着重要的角色。然而&#xff0c;对于许多非专业人士来说&#xff0c;视频剪辑可能是一项复杂而耗时的任…

数字营销:概述和类型

数字营销无处不在。公司已经开始采用密集的数字营销活动来接触目标受众。从社交媒体句柄到网站&#xff0c;数字营销彻底改变了互联网时代产品和服务的营销和推广方式。本文将详细讨论数字营销的范围和类型。 什么是数字营销&#xff1f; 数字营销使用社交媒体、电子邮件、网…

免费SSL证书有效期只有90天?太短?

随着网络安全问题日益受到重视&#xff0c;SSL证书成为了网站安全的必需品。然而&#xff0c;在许多情况下&#xff0c;免费提供的SSL证书往往只有90天的有效期&#xff0c;这种期限对于很多用户来说显得过于短暂。 首先&#xff0c;我们要理解为什么 SSL 证书的有效期设定为90…

P8A003-系统加固-系统管理员账户安全

【预备知识】 Administrator 原意为管理人或行政官员或遗产管理人&#xff0c;在计算机名词中&#xff0c;它的意思是系统超级管理员或超级用户。但是在Windows系统中此用户名只在安全模式中使用。 【实验步骤】 网络拓扑&#xff1a;server2008-basic windows server 2008 …

Ps:转换路径

在 Photoshop 中&#xff0c;路径 Path是一种非常灵活的手段&#xff0c;可以被转换成多种不同的形式&#xff0c;以适应各种不同的设计和编辑需求。 ◆ ◆ ◆ 将路径转换为选区 方法一&#xff1a; 在使用路径类工具的状态下&#xff0c;在路径上右键选择“建立选区” Make …

WordPress:构建强大的网站和博客的完美选择

WordPress&#xff1a;构建强大的网站和博客的完美选择 一、WordPress 简介1.1 WordPress 介绍1.2 WordPress 优势 二、部署LNMP环境2.1 前提条件2.2 关闭防火墙和SELinux2.3 安装Nginx2.4 安装MySQL2.5 安装PHP2.6 配置Nginx2.7 配置MySQL2.8 配置PHP2.9 测试访问LNMP平台 三、…

3D模型纹理集合并【Python|C#】

使用 Substance Painter 时&#xff0c;将模型的各个部分分成不同的纹理集非常有用。 这可以帮助遮罩&#xff0c;或者只是保持层栈干净。 不幸的是&#xff0c;Painter 无法将多个纹理集中的所有贴图导出为单个图集&#xff0c;即使在创建单独对象的 UV 时考虑到了这一点。 显…

比特币上的有状态多重签名

无需链下通信 介绍 随着区块链和加密货币空间的发展&#xff0c;越来越需要增强安全措施来保护数字资产。 应对这一挑战的突出解决方案之一是多重签名&#xff08;多重签名&#xff09;钱包。 这些钱包在执行交易之前需要多方签名&#xff0c;从而提供额外的安全层来防止未经授…

如何解决主从数据库同步延迟问题?

如何解决主从数据库同步延迟问题&#xff1f; 前言 最近&#xff0c;系统上频繁出现主从延迟的问题&#xff0c;因此针对主从架构、主从同步以及主从延迟问题进行了一次学习。 主从架构浅析 在了解主从延迟之前&#xff0c;我们有必要对主从架构有一些简单的认识。在如今的…

shell脚本正则表达式

目录 一. 正则表达式定义 二. 基本正则表达式 1. 元字符 2. 表示次数 3. 位置锚定 4. 分组或其他 二. 拓展正则表达式 1. 表示次数 2. 表示分组 一. 正则表达式定义 正则表达式&#xff08;REGEXP &#xff09;&#xff1a;由一类特殊字符及文本字符所编写的模式&…

使用 ChatGPT 创建 Makefile 构建系统:从 Docker 开始

使用 Docker 搭配 ChatGPT 创建 Makefile 构建系统 Makefile 构建系统是嵌入式软件团队实现其开发流程现代化的基础。构建系统不仅允许开发人员选择各种构建目标&#xff0c;还可以将这些构建集成到持续集成/持续部署 (CI/CD) 流程中。使用诸如 ChatGPT 这样的人工智能 (AI) 工…

vatee万腾的科技征途:Vatee数字化力量的新视野

在科技的浪潮中&#xff0c;Vatee万腾正展开一场引人注目的科技征途&#xff0c;以其独特的数字化力量描绘出一片新的视野。这不仅是一次技术的升级&#xff0c;更是一场对未来的全新探索&#xff0c;为我们带来了前所未有的数字化时代。 Vatee万腾以其卓越的技术实力和前瞻性的…

VR全景技术助力政务服务大厅数字化,打造全新政务服务体验

引言&#xff1a; 随着科技的飞速发展&#xff0c;虚拟现实&#xff08;VR&#xff09;技术逐渐走进人们的视野。VR全景技术作为VR领域的一项重要应用&#xff0c;以其沉浸式、交互式的特点&#xff0c;正逐渐渗透到各行各业。政务服务大厅作为相关部门与民众之间的桥梁&#…