OHSCE入門教程(一)-高可靠性PHP通信&控制框架

  "PHP是最好的(互聯網+物聯網)語言!",據說發佈PHP開源產品都要慣例的喊上這麼一句。 -2016.10.17 發此文之際是OHSCEV0.1.22版本

        開啓第一篇教程前總要賣點情懷,本人本科學習建築電氣與智能化專業(即電氣工程及其自動化專業),一直是名正經的電氣工程師。其實本來和這個號稱是“Web語言”的PHP八竿子打不着,可是隨着國家所謂“互聯網+“的引導,也翻山越嶺的將WEB領域逐漸和各行各業拉到了一起。從很多行業的角度看“互聯網+“很大程度就是“WEB+”,於是PHP這門最好的語言便進入了我的技術棧,我發現PHP是最具潛力的工控、物聯網&智能化語言。

        打開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、百度等每個事物。

       工控工業4.0、物聯網、行業智能化將是PHP的下一個最具潛力的領域。本着不造輪子多改進的原則我曾用款現有的PHP通信框架(不含串口通信功能)做過一次控制系統的實現,結果那幾天攪合的我一團糟,很多奇怪的問題和很高的失誤率,其實人家的框架是非常優秀的WEB框架可能是控制領域的技術棧和傳統的WEB領域有着很大的區別,傳統的web工程師更多的工作內容和一個強大的瀏覽器或APP交互而控制工程師則不是,於是我決定從底層重寫一套代碼(同時也加上了串口通信和共享內存輔助託管功能)。這套代碼專爲控制環境量身定製,是專業針對工控工業4.0、物聯網、行業智能化場景(當然兼備了做WEB的能力,畢竟“”互聯網+“”嘛)。其實母程序已幾經實布和商布,我們將其核心部分剝離出來繼而做了開源化改動併合並了OpenIAC計劃成爲了爲控制場景量身定製的高可靠性PHP通信&控制框架-OHSCE。它簡單高效並且特別親切於工業自動化工程師、硬件工程師、物聯網工程師、追求效率的PHP工程師的寫法風格,也能讓傳統的PHP-WEB工程師輕鬆上手。

         言歸正傳我們以搭建一個簡單的串口服務器作爲第一教程的內容,一個簡單的串口服務器包含了上行網絡(以太網)和現場總線(這裏是RS485通信)。

         以太網做上行網絡是大勢所趨,RS485是目前使用最普遍廣泛也是最具性價比的現場通信手段,當然很多其它通信手段都可以和RS232/485轉接,故我們以它做例。

          #用UDP還是TCP?

          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')

          詳見:Ohsce_eng_serial_creat

         在創建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/

           

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章