本示例使用设备: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)." "; //全屏显示信息长度>=34return 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)." "; //全屏显示信息长度>=34return 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';}
}?>