<?phpdefine('READ_HOLDING_REGISTERS', 0x03);define('READ_INPUT_REGISTERS', 0x04);define('MBAP_HEADER_SIZE', 7); //7bytesdefine('MODBUS_TCP_MAX_ADU_SIZE', 260); //260bytesdefine('MODBUS_TCP_MIN_RESPONSE_DATA_SIZE', 2); //2bytesdefine('MODBUS_TCP_UNPACK_FUNC_BYTECOUNT', 'Cfunc/Cbyte_count');//check MODBUS TCP MBAP headerfunction 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) commandfunction 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 itfunction 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 arrayfunction 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 handlerfunction 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 itfunction 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 Transactionfunction 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 = 3secif(!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通讯 示例源码用户还喜欢
- 18480 文章数
- 500万+ 热度
作者专栏
编辑推荐
- 淡抹u2引擎,修复内容较多,物有所值
- 界域传说·经典巨作=传世单机(一键安装)
- 丸子版本(175个传世版本大集合)
- GS版本:神话公益服务端+客户端
- 图片放大工具(放大图片不模糊)
- 剪映无限制VIP版
- 传奇世界客户端下载器,史上最全传世客户端
- 传世GS20220920商业引擎注册+登录配置器 解压密码是1
- U2官方排行榜游戏网关 支持元神,支持传家宝
- GS开战传世客户端+服务端
- (淡漠夕阳)u2引擎合区工具
- 传世GS引擎消除“你的游戏客户端版本号过旧,请及时更新”提示
- 传世一机多区双线路配置器--免密码版本
- 传世凤凰登陆器劫持修复软件
- SQLite3 for Navicat
- 传奇世界npc对话框编辑工具
- 传世GS落霞铭文服务器端
- gs_20210409引擎包+注册机(无限制)
- 传奇世界NPC对话封包查看器[支持时长版和极速版]
- 彩虹引擎传世脚本编辑工具1.7版来了,支持函数脚本翻译
评论