"PHP是最好的(互联网+物联网)语言!",听说发布PHP开源产品都要惯例的喊上这么一句。 -2016.10.17 发此文之际是OHSCEV0.1.22版本php
开启第一篇教程前总要卖点情怀,本人本科学习建筑电气与智能化专业(即电气工程及其自动化专业),一直是名正经的电气工程师。其实原本和这个号称是“Web语言”的PHP八竿子打不着,但是随着国家所谓“互联网+“的引导,也翻山越岭的将WEB领域逐渐和各行各业拉到了一块儿。从不少行业的角度看“互联网+“很大程度就是“WEB+”,因而PHP这门最好的语言便进入了个人技术栈,我发现PHP是最具潜力的工控、物联网&智能化语言。html
打开PHP的官网,咱们能够看见两行白色的欢迎语:“PHP is a popular general-purpose scripting language that is especially suited to web development.Fast, flexible and pragmatic, PHP powers everything from your blog to the most popular websites in the world.” -意译:PHP是一各流行且全能的脚本语言,特别合适于与互联网相关的领域。它快速、灵活且实用,健壮的PHP能驱动小到你的博客大到著名的FACEBOOK、百度等每一个事物。linux
工控工业4.0、物联网、行业智能化将是PHP的下一个最具潜力的领域。本着不造轮子多改进的原则我曾用款现有的PHP通讯框架(不含串口通讯功能)作过一次控制系统的实现,结果那几天搅合的我一团糟,不少奇怪的问题和很高的失误率,其实人家的框架是很是优秀的WEB框架多是控制领域的技术栈和传统的WEB领域有着很大的区别,传统的web工程师更多的工做内容和一个强大的浏览器或APP交互而控制工程师则不是,因而我决定从底层重写一套代码(同时也加上了串口通讯和共享内存辅助托管功能)。这套代码专为控制环境量身定制,是专业针对工控工业4.0、物联网、行业智能化场景(固然兼备了作WEB的能力,毕竟“”互联网+“”嘛)。其实母程序已几经实布和商布,咱们将其核心部分剥离出来继而作了开源化改动并合并了OpenIAC计划成为了为控制场景量身定制的高可靠性PHP通讯&控制框架-OHSCE。它简单高效而且特别亲切于工业自动化工程师、硬件工程师、物联网工程师、追求效率的PHP工程师的写法风格,也能让传统的PHP-WEB工程师轻松上手。git
言归正传咱们以搭建一个简单的串口服务器做为第一教程的内容,一个简单的串口服务器包含了上行网络(以太网)和现场总线(这里是RS485通讯)。github
以太网作上行网络是大势所趋,RS485是目前使用最广泛普遍也是最具性价比的现场通讯手段,固然不少其它通讯手段均可以和RS232/485转接,故咱们以它作例。web
#用UDP仍是TCP?windows
UDP是一个很是好的选择,它无连接、高效而且节约资源,可是缺点是会有丢包的可能性,不过您能够经过主从应答来保证您的数据的可靠性,并且您能够灵活的掌握是否应答,甚至这各特性均可以逻辑中的一部分。不过对于串口服务器这个场景来讲TCP是更合适的选择,由于作一个串口的需求很简单,可靠链接读写数据并转发到串口上,串口写读数据并回转回来。咱们肯定使用TCP数组
示例所使用的机器的COM7是将使用的串口。浏览器
#欲善其事必利其器服务器
下载最新版本的OHSCE:
您能够到OHSCE的官网(http://www.ohsce.org)或GITHUB(https://github.com/OpenIBC/Ohsce)下载到最新的OHSCE。PS.记得支持我一下哦
安装PHP5.4+ 并配置PHP.INI至可用状态。
配置OHSCE的配置文件 位于.../config/
开启Curl扩展、Shmop扩展、Sockets扩展
建立OhsceComserver.php文件
加载OHSCE
<?php ini_set('memory_limit',"64M"); //重置php可使用的内存大小为64M set_time_limit(0); //重置运行时长为无限制 ob_implicit_flush(1); include('loadohsce.php'); //载入Ohsce加载文件
#开始构造串口服务器的身躯
首先咱们打开咱们须要转发的串口
<?php //...... $comid="COM7"; //windows下是comx linux下是/dev/ttyX Ohsce_eng_serial_creat($hscecom,$comid); //建立一个COM7 9600,n,8,1的待调用串口资源 Ohsce_eng_serial_open($hscecom); //调用资源并占用该串口
PS:Ohsce_eng_serial_creat函数默认为您填充了您所省略的全部相关参数,固然您能够手动指定他们以建立各类串口资源。
Ohsce_eng_serial_creat(&$OHSCESerial,$com,$flags="1",$mode=0,$baud=9600,$parity='n',$data=8,$stop=1,$fc='none',$xon='off',$to='off',$octs='off',$odsr='off',$idsr='off',$dtr='on',$rts='on')
在建立TCP服务器以前咱们须要先构造它的回调函数。 所谓回调函数就是当有新的TCP客户端到达、客户端发送新的消息到达是会调用的函数。
<?php //................... function comserveraccept(&$socket,$ip,$port,$zv){ global $hscecom; //调用$hscecom串口资源 $ohsce_cs_data=Ohsce_socketread($socket,1024); //读取1024字节数据 if(($ohsce_cs_data!=null)or($ohsce_cs_data[0]!=false)){ Ohsce_eng_serial_write($hscecom,$ohsce_cs_data[1],false);//写入串口 Ohsce_eng_serial_read($hscecom,$data,null,true); //读取返回数据 Ohsce_socketwrite($socket,$data); //回转所读取的数据 } return true; } function comservera(&$socket,$buf,$len,$zv){ global $hscecom; Ohsce_eng_serial_write($hscecom,$buf,false); Ohsce_eng_serial_read($hscecom,$data,null,true); Ohsce_socketwrite($socket,$data); return true; } function comserveralways(&$oibc_clients_zv){ global $hscecom; Ohsce_eng_serial_read($hscecom,$data,null,true); if((!is_null($data))and(strlen($data)>0)){ foreach($oibc_clients_zv['clients'] as $okey => $osclient){ if($okey=="0"){ continue; } Ohsce_socketwrite($osclient,$data); } } return true; }
其中comserveralways函数是每圈循环都会执行一次的函数,也就是常驻函数。在咱们的串口服务器程序中,他会将最新收到的串口数据转发广播出去。
comservera(&$socket,$buf,$len,$zv)和comserveraccept(&$socket,$ip,$port,$zv)函数会被固定传入这些变量。其中$socket是本次活动的socket资源的指针。$buf是收到的数据。$len是数据长度。$ip是新到客户端的ip地址。$port是其端口。$zv是固定结构体,其结构以下:$oibc_clients_zv=array("clients"=>&$oibc_clients,"ip"=>&$oibc_clients_id_ip,"id"=>&$oibc_clients_id)
其中$oibc_clients数组为当前全部socket资源,key值为0者为服务监听者。$ip数组为ip对照表。$id数组为id备份表。固然若是有须要您也能够print_r之一探究竟。
小提示:print_r函数是您的好帮手,不少时候文档很难面面俱到QQ群我也很难随时关注,这时候print_r可能比度娘还亲切。
#赋予它生命的力量
好了,回调函数和常驻函数都造好了,下面咱们改让它拥有跑起来的能力了。首先先建立一个可复用的TCP服务端资源,第二步传入让它跑起来,就那么简单。
<?php Ohsce_eng_socket_server($ohsceserver,'tcp','7626','127.0.0.1',array('callback'=>'comservera','accept'=>'comserveraccept','fap'=>'comserveralways'),'comserveraccept'); //建立一个能够复用的SOCKETSERVER资源$ohsceserver,协议为TCP,监听端口为7626,绑定IP127.0.0.1,回调函数为comservera,首次回调函数为comserveraccept,常驻函数为comserveralways.最后一个comserveraccept是为了兼容OHSCEV0.1.22之前的版本。 Ohsce_eng_socket_server_runtcp($ohsceserver); //运行它
固然更详细的能够参考手册文档: Ohsce_eng_socket_server Ohsce_eng_socket_server_runtcp
PS:一个彩蛋,当你的实际生产中最好不要使用7626端口,由于它太著名了,曾经咱们漫游在整个互联网上寻找开了7626端口的小伙伴。简单的来讲,容易招黑,并且招来的都是老黑:)
#一个我的认为的好习惯
不管您的程序多么的完美,最后记得阻截并跳转去抛出错误。这样当您的程序扩展和改动其它部分时至少能保证某一部分运行的不错。
<?php //..程序头...... $errmsg='Unknow'; //............. //..程序身躯.... //............. goto terror; //前往并抛出错误 //............. terror: //抛出错误的锚点 exit($errmsg);
关于goto,能够理解为JMP指令,熟悉的身影可是用法略有不一样。在PHP中GOTO是不能够从一个函数跳到另外一个函数的,同时也是不能够从一个文件跳到另外一个文件的。其实,这个限制带来了您程序可读性的提高和性能&一致性的平衡。
PS.其实在不少高级语言中别说凶残的SETJMP了,连GOTO/JMP都被取缔了。缘由是在号几十年前觉得叫“Edsger Wybe Dijkstra”的先生提出了GOTO有害论,因而被不少人奉为圣旨而流传下来甚至在很多语言中干脆就被砍掉了(如JAVA)。这的确,大大的下降了程序设计对人员要求的门槛,但随着发展,尤为咱们进入了泛(互)物(联)联(网)网(+)时代,GOTO的亲切与做用显得愈发的重要。不过进入21世纪不久 Dijkstra先生就去世了,英明的PHP设计团队在2009年将GOTO关键字从新引入了这门“世界上最好的语言”,因此从5.3开始咱们又可使用高效、简洁、具有自底向上一致性的GOTO关键字了。
#牛刀小试
至此,一个简单的串口服务器原型工程完成了。其实它不只仅是一个教程案例,更是一个很是实用的功能,我将它包装了一下,这个原型便以Alpha的身份加入了V0.1.22_BETA开源版的Engine中。在后续的版本中它将跟随着OHSCE的版本更新变得愈来愈健壮。
<?php //....................................... comserver: $oibc_cnp_csa=getopt('r:m:p:c:'); Ohsce_eng_serial_creat($hscecom,trim($oibc_cnp_csa['c'])); Ohsce_eng_serial_open($hscecom); function comserveraccept(&$socket,$ip,$port,$zv){ global $hscecom; $ohsce_cs_data=Ohsce_socketread($socket,1024); if(($ohsce_cs_data!=null)or($ohsce_cs_data[0]!=false)){ Ohsce_eng_serial_write($hscecom,$ohsce_cs_data[1],false); Ohsce_eng_serial_read($hscecom,$data,null,true); Ohsce_socketwrite($socket,$data); } return true; } function comservera(&$socket,$buf,$len,$zv){ global $hscecom; Ohsce_eng_serial_write($hscecom,$buf,false); Ohsce_eng_serial_read($hscecom,$data,null,true); Ohsce_socketwrite($socket,$data); return true; } function comserveralways(&$oibc_clients_zv){ global $hscecom; Ohsce_eng_serial_read($hscecom,$data,null,true); if((!is_null($data))and(strlen($data)>0)){ foreach($oibc_clients_zv['clients'] as $okey => $osclient){ if($okey=="0"){ continue; } Ohsce_socketwrite($osclient,$data); } } return true; } Ohsce_eng_socket_server($ohsceserver,'tcp',intval(trim($oibc_cnp_csa['p'])),OHSCE_MYIP_SYSTEM,array('callback'=>'comservera','accept'=>'comserveraccept','fap'=>'comserveralways'),'comserveraccept'); Ohsce_eng_socket_server_runtcp($ohsceserver); //开始运行 goto terror; //.......................................
好了下面咱们启动它并使用TCP链接串口服务器在COM7串口上使用MODBUS-RTU协议读取一台压力变送器的数据。
tcpComClient.php:
<?php ini_set('memory_limit',"88M");//重置php可使用的内存大小为64M set_time_limit(0); ob_implicit_flush(1); error_reporting(0); include('loadohsce.php'); Ohsce_eng_socket_client($ohsceclient,'tcp',7628,'127.0.0.1'); //建立一个TCP客户端资源并链接27.0.0.1:7626 Ohsce_socketsend($ohsceclient['socket'],"\x01\x03\x00\x01\x00\x04\x15\xc9"); //发送数据 //Ohsce_socketsend($ohsceclient['socket'],array('in'=>"01030001000415c9",'bin'=>true)); echo Ohsce_socketread($ohsceclient['socket'],1024)[1]; //收取回复数据 sleep(30);
运行效果:
PHP是一个健壮的全能脚本语言,特别适合于网络有关的场景。工业控制、物联网、行业智能化方向,OHSCE是您强大的战舰。
OHSCE官方网站: HTTP://WWW.OHSCE.ORG
技术&交流:Q群-374756165 (随风星海@做者)
手册地址:http://www.ohsce.com/index.php/book/ohscelib/
GITHUB:https://github.com/OpenIBC/Ohsce
GIT@OSC:https://git.oschina.net/SFXH/Ohsce
捐助&支持:http://www.ohsce.com/index.php/company/