//接受数据请求public function client($pz){ //参数1是:网络协议, //AF_INET: IPv4 网络协议。TCP 和 UDP 都可使用此协议。一般都用这个,你懂的。 //AF_INET6: IPv6 网络协议。TCP 和 UDP 都可使用此协议。 //AF_UNIX: 本地通讯协议。具有高性能和低成本的 IPC(进程间通讯)。 //参数2是:套接字流,选项有: //SOCK_STREAM TCP 协议套接字。 //SOCK_DGRAM UDP协议套接字。 //参数3:protocol协议,选项有: //SOL_TCP: TCP 协议。 //SOL_UDP: UDP协议。 $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); //统一配置 $xgcs=array( 'surface'=>'equipment_config_'.$pz['surface'],//表名 ); $biao=db($xgcs['surface'])->where(array('id'=>1))->find(); $xgcs=array( 'identification'=>$pz['surface'],//唯一标识 'ip'=>$biao['ip'],//ip地址 'port'=>$biao['port'],//端口 'surface'=>'equipment_config_'.$pz['surface'],//表名 ); //获取数据字段表 $data_cxzd=array( array('name'=>'tem_sub1_t3'),//二次供水温度,513,3 array('name'=>'tem_sub1_t4'),//二次回水温度,516,3 array('name'=>'pre_sub1_p3'),//二次供水压力,507,3 array('name'=>'pre_sub1_p4'),//二次回水压力,508,3 array('name'=>'pre_sub1_p1'),//一次供水压力,505,3 array('name'=>'pre_sub1_p2'),//一次回水压力,506,3 array('name'=>'valve_sub1_tcal'),//二次供水温度设定值,519,3 array('name'=>'tem_sub1_t1'),//一次供水温度,511,3 array('name'=>'tem_sub1_t2'),//一次回水温度,512,3 array('name'=>'tem_tout'),//室外温度,517,3 array('name'=>'valve_sub1_feedback'),//调节阀1阀位,518,3 array('name'=>'valve_sub1_controlmode'),//控制方式,22,1 array('name'=>'tem_sub1_t3hset'),//二次最大供水温度,514,3 array('name'=>'tem_sub1_t3lset'),//二次最小供水温度,515,3 array('name'=>'heatmeter_pri_power'),//总热功率,834,3 array('name'=>'heatmeter_pri_energy'),//总热耗,836,3 array('name'=>'heatmeter_pri_flow'),//一次侧流量,830,3 array('name'=>'cp_sub1_cp1frequency'),//循环泵1频率,502,3 array('name'=>'cp_sub1_cp2frequency'),//循环泵2频率,490,3 array('name'=>'heatmeter_sub1_flow'),//二次侧流量,530,3 array('name'=>'mp_sub1_mp1frequency'),//1号补水泵频率反馈,504,3 array('name'=>'mp_sub1_mp2frequency'),//2号补水泵频率反馈,592,3 array('name'=>'hmeter_ref_volume'),//补水累计流量,632,3 array('name'=>'heatmeter_pri_volume'),//一次网累计流量,832,3 array('name'=>'heatmeter_pri_flow'),//一次网瞬时流量,830,3 ); //获取的数据 $datas=array(); //转换参数(字段名、类型:bit则为线圈寄存器,其余则为保持寄存器、转换参数、寄存器地址) $data_zhcs = db(\tname::register_relationship)->where(array('identification'=>$xgcs['identification']))->column('variable_name,variable_type,conversion_coefficient,register_address'); //建立链接 $con=socket_connect($socket,$xgcs['ip'],$xgcs['port']); foreach ($data_cxzd as $k_1 => $value) { //定义标识符 //转16进制 $value['qian4']=dechex($k_1); //获取长度 $value['chang4']=strlen($value['qian4']); //判断长度 if($value['chang4']==1){ $value['zu1_5']='00 0'.$value['qian4']; }elseif($value['chang4']==2){ $value['zu1_5']='00 '.$value['qian4']; }elseif($value['chang4']==3){ $value['zu1_5']='0'.substr($value['qian4'],0,1).' '.substr($value['qian4'],1,2); }elseif($value['chang4']==4){ $value['zu1_5']=substr($value['qian4'],0,2).' '.substr($value['qian4'],2,2); } $value['zu6_21']=' 00 00 00 06 15 '; //类型获取bit为线圈寄存器,其余为保持寄存器 $value['type']=$data_zhcs[$value['name']]['variable_type']; if($value['type']=='bit'){ $value['zu22_23']='01'; }else{ $value['zu22_23']='03'; } //获取10进制的寄存器 $value['jcq_10']=$data_zhcs[$value['name']]['register_address']-1; //转16进制的寄存器 $value['jcq_16']=dechex($value['jcq_10']); //获取16进制的寄存器长度 $value['chang_jcq']=strlen($value['jcq_16']); //判断16进制的寄存器长度 if($value['chang_jcq']==1){ $value['zu24_29']=' 00 0'.$value['jcq_16']; }elseif($value['chang_jcq']==2){ $value['zu24_29']=' 00 '.$value['jcq_16']; }elseif($value['chang_jcq']==3){ $value['zu24_29']=' 0'.substr($value['jcq_16'],0,1).' '.substr($value['jcq_16'],1,2); }elseif($value['chang_jcq']==4){ $value['zu24_29']=' '.substr($value['jcq_16'],0,2).' '.substr($value['jcq_16'],2,2); } //获取个数(这个基本不会改变,如若改变则接收要全改) //判断是32位的变为02 if($value['type']=='int32'){ $value['zu30_35']=' 00 02'; }else{ $value['zu30_35']=' 00 01'; } $value['zu']=$value['zu1_5'].$value['zu6_21'].$value['zu22_23'].$value['zu24_29'].$value['zu30_35']; $sendStrArray[$k_1] = str_split(str_replace(' ', '', $value['zu']), 2); // 将16进制数据转换成两个一组的数组 for ($j = 0; $j < count($sendStrArray[$k_1]); $j++) { socket_write($socket, chr(hexdec($sendStrArray[$k_1][$j]))); // 逐组数据发送 } $receiveStr[$k_1] = ""; $receiveStr[$k_1] = socket_read($socket, 1024, PHP_BINARY_READ); // 采用2进制方式接收数据 $receiveStrHex[$k_1] = bin2hex($receiveStr[$k_1]); // 将2进制数据转换成16进制 //响应状态 $value['xyzt']=substr($receiveStrHex[$k_1],14,2); //如果返回成功 if($value['xyzt']==$value['zu22_23']){ //返回参数(16进制) $value['fhcs_16']=substr($receiveStrHex[$k_1],18);//截取数据 //转为10进制 $value['fhcs_10']=hexdec($value['fhcs_16']); //进行换算 $value['value']=$value['fhcs_10']*$data_zhcs[$value['name']]['conversion_coefficient']; //键入到修改数组 $datas[$value['name']]=$value['value']; } } //断开链接 socket_shutdown($socket); socket_close($socket); $cc=db($xgcs['surface'])->where(array('id'=>1))->update($datas); return $datas; if($cc){ return 1; }else{ return 0; }}
转载于:https://www.cnblogs.com/jucheng/p/10082359.html
相关资源:C# Modbus-TCP协议封装