基于Laravel+Swoole開(kāi)發(fā)智能家居后端

在上一篇Laravel如何優(yōu)雅的使用Swoole中我已經(jīng)大概談到了Laravel結(jié)合Swoole的用法。今天,我參與的智能家居項(xiàng)目基本上已經(jīng)結(jié)束了Web服務(wù)器及android端的開(kāi)發(fā)(熬了個(gè)通宵突擊把剩下的做了,好累), 趁熱來(lái)聊聊基于Laravel+Swoole開(kāi)發(fā)智能家居后端的關(guān)鍵技術(shù)點(diǎn)。

16進(jìn)制ASCII碼協(xié)議的解析##

硬件結(jié)構(gòu)圖

硬件我不談,我只需要關(guān)心數(shù)據(jù)解析。如何基于Swoole如果在php中解析16進(jìn)制的ascii碼,這種文章還比較少呢。但核心的部分還是可以整理出來(lái)的,關(guān)鍵用到的就是chr()、hexdec()、bin2hex()這3個(gè)函數(shù),網(wǎng)上還提到了用pack()、unpack(),因?yàn)榍懊?個(gè)函數(shù)以及很好的解決了問(wèn)題,所以就沒(méi)有繼續(xù)深入。我建議在這里Php Manual官網(wǎng)先熟悉下這幾個(gè)函數(shù)。

chr()函數(shù)從不同的 ASCII 值返回字符,hexdec() 函數(shù)把十六進(jìn)制轉(zhuǎn)換為十進(jìn)制。通常結(jié)合這兩個(gè)函數(shù)把16進(jìn)制字符串轉(zhuǎn)換為ASCII字符串,理解起來(lái)有點(diǎn)繞。
例如: echo chr(hexdec('fe'));//輸出的就是下位機(jī)能認(rèn)識(shí)的16進(jìn)制的FE,大小寫(xiě)不敏感

bin2hex()函數(shù)把 ASCII 字符的字符串轉(zhuǎn)換為十六進(jìn)制值,用于從Swoole中讀取數(shù)據(jù)的轉(zhuǎn)換。
例如:$buffer = str_split(bin2hex($data), 2);//$data是Swoole中OnReceive事件傳遞的值

在解析協(xié)議時(shí),上例中的$buffer數(shù)組中,存放了協(xié)議的每一位。那么怎么解析呢?最快最懶的方法就是根據(jù)硬件研發(fā)的協(xié)議一位一位的去讀取數(shù)據(jù),例如頭是第一位,那么就是$buffer[0];如果連著好幾位組合起來(lái)是數(shù)據(jù),就寫(xiě)個(gè)小函數(shù)拼。


我從第0到12位拼起來(lái),就是我需要的數(shù)據(jù)了

是不是太弱雞了點(diǎn)(.NET和JAVA有很豐富的byte[]轉(zhuǎn)整形和字符串的方法集)?如果你需要,可以自己寫(xiě)個(gè)轉(zhuǎn)換工具類出來(lái)(我暫時(shí)用不上就沒(méi)整理)。

在下位機(jī)通信中還有一個(gè)很重要的技術(shù)點(diǎn)就是XOR校驗(yàn),我是從stackoverflow找到的源碼,直接貼地址。

16進(jìn)制ASCII碼協(xié)議的創(chuàng)建##

不廢話,直接上代碼:


按協(xié)議生成向硬件發(fā)送數(shù)據(jù)

對(duì)Laravel使用者,在這部分我強(qiáng)烈建議好好復(fù)習(xí)一下Laravel提供的快速數(shù)組函數(shù)輔助方法。

與硬件的曲線通信##

基于Swoole接收數(shù)據(jù)在上一篇中已經(jīng)詳細(xì)介紹不再累述,這里主要說(shuō)說(shuō)向硬件發(fā)送數(shù)據(jù)的問(wèn)題。上一篇中,我提到了2種方法,一種是利用fsockopen()函數(shù);一種是內(nèi)部端口監(jiān)聽(tīng)。這里還和搞硬件的大神鬧了個(gè)笑話,臉紅啊..對(duì)基于TCP/IP協(xié)議的通信,因?yàn)槎丝谝恢北唤邮毡O(jiān)聽(tīng)占用,所以用fsockopen()或者socket_write()函數(shù)是行不通的,必須基于第二種方式曲線實(shí)現(xiàn)硬件通信。

在Swoole打開(kāi)內(nèi)部監(jiān)聽(tīng)端口

首先在Command中添加內(nèi)部端口的監(jiān)聽(tīng),注意onReceive事件被自定義的InnerHandler接收(不知所云者請(qǐng)復(fù)習(xí)上一篇以及Swoole的文檔)。一定記得在iptables中把你的內(nèi)部監(jiān)聽(tīng)端口打開(kāi)!!

接收函數(shù),向硬件發(fā)送數(shù)據(jù)

在Innerhandler中,若接收到需要發(fā)送到硬件的命令(就是上一節(jié)說(shuō)的數(shù)據(jù)),從緩存里面提取該硬件的連接實(shí)體,然后發(fā)送數(shù)據(jù)(不知所云請(qǐng)參考Swoole文檔)。這里比較曲線的情況就是在這個(gè)緩存,這個(gè)緩存是在需要發(fā)送數(shù)據(jù)的時(shí)候設(shè)定的,那么怎么知道硬件的連接實(shí)體是什么?當(dāng)然是保持一個(gè)KV結(jié)構(gòu)的數(shù)據(jù)啦:)

整個(gè)曲線的通信過(guò)程就是:當(dāng)需要向硬件發(fā)送數(shù)據(jù)的時(shí)候,首先將數(shù)據(jù)發(fā)送到這個(gè)內(nèi)部監(jiān)聽(tīng)端口來(lái),然后再?gòu)倪@里發(fā)送到硬件去。怎么向內(nèi)部監(jiān)聽(tīng)端口發(fā)送數(shù)據(jù)呢?用fsockopen()或者socket_write()都是完全沒(méi)問(wèn)題的,這里的代碼就請(qǐng)自行搜索,權(quán)當(dāng)練習(xí),不要太懶了。

Event大有裨益##

這個(gè)要用過(guò)了才知道有多方便,來(lái)這里先好好復(fù)習(xí)一下。實(shí)現(xiàn)過(guò)程請(qǐng)自行感受,我就只說(shuō)說(shuō)我哪里用到了Event:

1.基于JPUSH推送消息
2.向內(nèi)部監(jiān)聽(tīng)發(fā)送數(shù)據(jù)

另外只補(bǔ)充一點(diǎn),想利用Event通過(guò)Swoole發(fā)送數(shù)據(jù)的路是行不通的。

優(yōu)雅的快速測(cè)試##

由于PHP是弱類型,因此理解起來(lái)比較費(fèi)解。接收數(shù)據(jù)和向硬件發(fā)送數(shù)據(jù)的數(shù)據(jù)類型是不一樣的。用bin2hex()得到的是形如"11 00 00 FE"字符串,用chr(hexdec())得到的是16進(jìn)制的ASCII碼,如果echo輸出的話,會(huì)是亂碼。那么如何測(cè)試(看到)自己生成的16進(jìn)制ASCII碼數(shù)據(jù)是否正確呢?1種是找一個(gè)TCP/IP工具發(fā)送過(guò)去,這種麻煩了點(diǎn),我推薦用fiddler監(jiān)聽(tīng)。

HexView中的黑色部分就是你發(fā)送的

你可以快速方便的用一個(gè)web頁(yè)面輸出你的ASCII碼,在fiddler的HexView中,就可以看到原汁原味你發(fā)送的16進(jìn)制數(shù)據(jù)了。另外,由于Swoole的監(jiān)聽(tīng)類是CLI運(yùn)行,因此我也非常推薦多寫(xiě)一點(diǎn)echo打印一下?tīng)顟B(tài),在phpstorm的SSH客戶端里可以快速的了解目前的情況,就像android-studio的Loger一樣。

echo Carbon::now() . '/Device Numbers:' . $devNum . PHP_EOL;//老司機(jī)勸你多寫(xiě)點(diǎn),最好packagist找個(gè)輪子或者自己寫(xiě)個(gè)Logger庫(kù)

魯棒性探討,可以搞得非常復(fù)雜##

算吐個(gè)槽吧,前年用.NET做下位機(jī)數(shù)據(jù)處理魯棒性的時(shí)候真是如坐針氈啊。搞下位機(jī)通信果然還是c++最合適啊,以下問(wèn)題在這里還需要后期逐步完善呢:

1.如果硬件發(fā)送的數(shù)據(jù)不是一個(gè)包發(fā)完而是分批發(fā)怎么辦?
2.看門狗是一定要寫(xiě)的,對(duì)吧?
3.與硬件通信的response處理要做吧?
4.TimeOut怎么辦?
....

啊啊啊啊啊....

喜歡Android的有福了##

仿典型電商UI的一個(gè)練習(xí)

預(yù)告下,基于學(xué)習(xí)的目的,最近正在仿鮮城、enjoy、半糖這3個(gè)很有代表性的電商APP首頁(yè)UI(是逆向著看smali和提取res在仿喲)。鮮城的android端已經(jīng)做的有模有樣了,這次是逼著自己android、ios都給仿出來(lái),沒(méi)老司機(jī)帶就自己想辦法提高。先做android的,有興趣的朋友可以耐心等待代碼和文章。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容