modbustcp封裝使用獲取裝置資料示例

jucheng發表於2018-12-07

//接受資料請求
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( name::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;
    }

}

 

相關文章