在好例子网,分享、交流、成长!
您当前所在位置:首页PHP 开发实例PHP语言基础 → php modbus通讯 示例源码

php modbus通讯 示例源码

PHP语言基础

下载此实例
  • 开发语言:PHP
  • 实例大小:9.38KB
  • 下载次数:50
  • 浏览次数:1653
  • 发布时间:2019-05-15
  • 实例类别:PHP语言基础
  • 发 布 人:1134144870
  • 文件格式:.php
  • 所需积分:2
 相关标签: 代码

实例介绍

【实例简介】
【实例截图】

【核心代码】

<?php

define('READ_HOLDING_REGISTERS', 0x03);
define('READ_INPUT_REGISTERS', 0x04);
define('MBAP_HEADER_SIZE', 7); //7bytes
define('MODBUS_TCP_MAX_ADU_SIZE', 260); //260bytes
define('MODBUS_TCP_MIN_RESPONSE_DATA_SIZE', 2); //2bytes
define('MODBUS_TCP_UNPACK_FUNC_BYTECOUNT', 'Cfunc/Cbyte_count');

//check MODBUS TCP MBAP header
function check_mbap_header(&$header)
{
    assert(is_array($header));
    
    if($header['pid'] !== 0)
    {
        return false;
    }
    
    if($header['len'] < MODBUS_TCP_MIN_RESPONSE_DATA_SIZE || $header['len'] > (MODBUS_TCP_MAX_ADU_SIZE - MBAP_HEADER_SIZE   1)) 
    {       
        return false;
    }        
    
    return true;
}


//check response from 
function modbus_tcp_check_read_reg_response_pdu(&$pdu, $func, &$exception, $byte_count)
{
    assert(is_string($pdu));
    assert(is_int($func));
    assert(isset($exception)); 
    assert(is_int($byte_count));
    
    //check function code and byte count
    if( ord($pdu{0}) == $func and $byte_count == ord($pdu{1}))
    {
        return true;
    }        
    
    $exception = 0;
    if(ord($pdu{0}) === ($func | 0x80))
    {    
        $exception = ord($pdu{1});
    }
    
    return false;
}


//generate MODBUS TCP read holding register(s) or input register(s) command
function modbus_tcp_build_read_reg_cmd(&$tid, $uid, $func, $address, $quantity)
{
    assert(is_int($tid));
    assert(is_int($uid));
    assert($func === READ_HOLDING_REGISTERS || $func === READ_INPUT_REGISTERS);
    assert(is_int($func));
    assert(is_int($quantity));
    $pdu = pack('Cnn', $func, $address, $quantity);
    $header = pack('nxxnC',   $tid, strlen($pdu)   1, $uid);
    return ($header . $pdu);
}


//receive TCP packet until done it
function tcp_recv_until_done($fp, &$buffer, $length)
{
    assert(is_resource($fp)); 
    assert(is_int($length));
    $count = 0;
    while($length > $count)
    {
        $tmp = fread($fp, $length - $count);
        if(!$tmp)
        {
            return false;
        }            
        $count  = strlen($tmp);
        $buffer .= $tmp;
    }
    
    return true;
}


//convert MBAP header to array
function unpack_mbap_header(&$buffer)
{
    assert(is_string($buffer));
    //tid,pid,len
    $tmp = unpack('ntid/npid/nlen', $buffer);
    $tmp['len'] -= 1; // remove uid size
    return $tmp;
}


// receive MODBUS TCP ADU and then callback response handler
function modbus_tcp_recv_adu($fp, &$response_handlers, &$error_msg)
{
    assert(is_resource($fp));
    assert(is_array($response_handlers));
    
    //read packet header
    $packed_header = '';
    if(!tcp_recv_until_done($fp, $packed_header, MBAP_HEADER_SIZE))
    {
        return false;
    }

    //check packet header
    $unpacked_header = unpack_mbap_header($packed_header);
    if(!check_mbap_header($unpacked_header))
    {
        return false;
    }
    
    //read PDU
    $packed_pdu = '';
    if(!tcp_recv_until_done($fp, $packed_pdu, $unpacked_header['len']))
    {
        return false;
    }
    
    //validate TID
    if(!isset($response_handlers[$unpacked_header['tid']]))
    {
        return false;
    }
    
    //callback response handler
    assert(isset($response_handlers[$unpacked_header['tid']]['handler']));
    assert(isset($response_handlers[$unpacked_header['tid']]['address']));
    assert(isset($response_handlers[$unpacked_header['tid']]['data']));
    return $response_handlers[$unpacked_header['tid']]['handler']($response_handlers[$unpacked_header['tid']]['address'], $packed_pdu, $error_msg, $response_handlers[$unpacked_header['tid']]['data']);
}


//send tcp packet until done it
function tcp_send_until_done($fp, &$buffer)
{
    assert(is_resource($fp) and is_string($buffer));
    
    $length = strlen($buffer);
    if($length == 0)
        return false;
        
    $count = 0;    
    while($length > $count)
    {
        $tmp = fwrite($fp, substr($buffer, $count, $length - $count));
        if(!$tmp)
            return false;
        $count  = $tmp;
    }    
    return true;
}


//make MODBUS TCP Transaction
function modbus_tcp_transact($fp, &$commands, &$response_handlers, &$error_msg)
{
    assert(is_array($commands));
    //send modbus tcp request(s)
    for($i = 0; $i < count($commands);   $i)
    {
        if(!tcp_send_until_done($fp, $commands[$i]))
        {
            return false;
        }
    }
    
    //receive modbus tcp response(s)
    for($i = 0; $i < count($commands);   $i)
    {
        if(!modbus_tcp_recv_adu($fp, $response_handlers, $error_msg))
        {
            return false;
        }        
    }
    return true;
    
}


function read_holding_registers_0_handler($address, &$pdu, &$error_msg, &$data)
{
  assert(is_int($address));
  assert(is_string($pdu)); 
  assert(is_string($error_msg));  
  
  $exception = 0;
  if(!modbus_tcp_check_read_reg_response_pdu($pdu, READ_HOLDING_REGISTERS, $exception, 4))
  {
    if($exception == 0)
    {
        //invalid protocol
        return false;   
    }            
    //send back exception code
    return true;                
  }         
  
  $unpacked_pdu = unpack(MODBUS_TCP_UNPACK_FUNC_BYTECOUNT . '/ndata1low/ndata1high', $pdu);
  printf("holding register address %d-%d: %d\n", $address, $address 1, ($unpacked_pdu['data1high']<<16) | $unpacked_pdu['data1low']);
  return true;
}


function read_holding_registers_300_handler($address, &$pdu, &$error_msg, &$data)
{
  assert(is_int($address));
  assert(is_string($pdu)); 
  assert(is_string($error_msg));  
  
  $exception = 0;
  if(!modbus_tcp_check_read_reg_response_pdu($pdu, READ_HOLDING_REGISTERS, $exception, 4))
  {
    if($exception == 0)
    {
        //invalid protocol
        return false;   
    }            
    //send back exception code
    return true;                
  }         
  
  $unpacked_pdu = unpack(MODBUS_TCP_UNPACK_FUNC_BYTECOUNT . '/Ndata2', $pdu);
  printf("holding register address %d-%d: %d\n", $address, $address 1, $unpacked_pdu['data2']);
  return true;
}


function read_inpu_registers_0_handler($address, &$pdu, &$error_msg, &$data)
{
  assert(is_int($address));
  assert(is_string($pdu)); 
  assert(is_string($error_msg));  
  
  $exception = 0;
  if(!modbus_tcp_check_read_reg_response_pdu($pdu, READ_INPUT_REGISTERS, $exception, 4))
  {
    if($exception == 0)
    {
        //invalid protocol
        return false;   
    }            
    //send back exception code
    return true;                
  }         

  $unpacked_pdu = unpack(MODBUS_TCP_UNPACK_FUNC_BYTECOUNT . '/ndata3high/ndata3low', $pdu);
  $data3 = unpack('f', pack('SS', $unpacked_pdu['data3high'], $unpacked_pdu['data3low']));
  printf("input register address %d-%d: %f\n", $address, $address 1, $data3[1]);
  return true;
}


function read_inpu_registers_200_handler($address, &$pdu, &$error_msg, &$data)
{
  assert(is_int($address));
  assert(is_string($pdu)); 
  assert(is_string($error_msg));  
  
  $exception = 0;
  if(!modbus_tcp_check_read_reg_response_pdu($pdu, READ_INPUT_REGISTERS, $exception, 8))
  {
    if($exception == 0)
    {
        //invalid protocol
        return false;   
    }            
    //send back exception code
    return true;                
  }         

  $unpacked_pdu = unpack(MODBUS_TCP_UNPACK_FUNC_BYTECOUNT . '/nd3/nd2/nd1/nd0', $pdu);
  $data4 = unpack('d', pack('SSSS', $unpacked_pdu['d3'], $unpacked_pdu['d2'], $unpacked_pdu['d1'], $unpacked_pdu['d0']));
  printf("input register address %d-%d: %f\n", $address, $address 3, $data4[1]);
  return true;
}

//connect 127.0.0.1, port:502, timeout:3sec
$fp = @fsockopen('tcp://127.0.0.1', 502, $errno, $errstr, 3);
if(!$fp)
{
    printf("can\'t connect modbus tcp device\n");
    die();
}

//set send/receive timeout = 3sec
if(!stream_set_timeout($fp, 3))
{
    fclose($fp);
    printf("failed to change communication timeout\n");
    die();    
}

$tid = 0; //initialize TID
$test_commands = array();
$test_response_handlers = array();
//read holding register address:0 quantity:2 type: long
$test_commands[] = modbus_tcp_build_read_reg_cmd($tid, 1, READ_HOLDING_REGISTERS, 0, 2);
$response_handlers[$tid] = array();
$response_handlers[$tid]['address'] = 0;
$response_handlers[$tid]['handler'] = 'read_holding_registers_0_handler';
//read holding register address:300 quantity:2 type: long inverse
$test_commands[] = modbus_tcp_build_read_reg_cmd($tid, 1, READ_HOLDING_REGISTERS, 300, 2);
$response_handlers[$tid] = array();
$response_handlers[$tid]['address'] = 300;
$response_handlers[$tid]['handler'] = 'read_holding_registers_300_handler';
//read input register address:0 quantity:2 type: float
$test_commands[] = modbus_tcp_build_read_reg_cmd($tid, 1, READ_INPUT_REGISTERS, 0, 2);
$response_handlers[$tid] = array();
$response_handlers[$tid]['address'] = 0;
$response_handlers[$tid]['handler'] = 'read_inpu_registers_0_handler';
//read input register address:0 quantity:4 type: double
$test_commands[] = modbus_tcp_build_read_reg_cmd($tid, 1, READ_INPUT_REGISTERS, 200, 4);
$response_handlers[$tid] = array();
$response_handlers[$tid]['address'] = 200;
$response_handlers[$tid]['handler'] = 'read_inpu_registers_200_handler';

if(!modbus_tcp_transact($fp, $test_commands, $response_handlers))
{
  fclose($fp);
  printf("shit happen!\n");
  die();  
}

fclose($fp);

?>

标签: 代码

实例下载地址

php modbus通讯 示例源码

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警