【導讀】物聯(lián)網技術飛速發(fā)展,智能家居領域也跟著愈演愈烈,成為互聯(lián)網巨頭及家電大佬們爭相深耕的“肥沃土壤”,本文主要針對智能家居的軟硬件架構技術做詳細分析。
HOW-想清楚要做哪些事情
以一款智能插座為例,我講的主題就是這個插座該怎么樣來生產、怎么樣來研發(fā)。第一步,我們先要把它分解。插座有很多結構件,比如五金件這些東西,所以我們要搭建一個團隊,包括做工業(yè)設計、結構設計的人,硬件工程師、電子類工程師、軟件的工程師,以及生活端的,甚至是運營和銷售的。如下圖所示。
我們從傳統(tǒng)的一個設備到智能設備轉變的過程中,這一個東西非常重要,即WiFi模塊。這個地方決定了這個設備到底能不能跟我們的App進行交互以及交互的效率如何。
大家可以看一下我們大概要做的事情,包括元器件選型、原理圖、結構、工業(yè)設計、PCBA、打手板、開模,這些東西完成的話代表著傳統(tǒng)的部分完成了,這里不再贅述。比較重要的是智能設備要怎樣實現(xiàn)通訊。現(xiàn)在ZigBee、WiFi、Z-Wave、BLE,這四種用得比較普遍,還有433、315等設備。谷歌也有一套協(xié)議,但是應用得稍微少一點。我今天主要是從WiFi設備方面來講,看到底一個WiFi設備到底要怎么樣來做。
WiFi聯(lián)網的難題
WiFi設備面臨一個很大的難題,比如說我做一個智能的水杯、一個智能的插座,這個水杯和插座是沒有交互界面的。但是我們必須解決一個問題,即這個設備一定要聯(lián)網,要連路由器。大家想到最直接的辦法是手機連路由器,打開手機的設置,進入WiFi列表,然后再輸入密碼。但是智能硬件里面沒有辦法進行操作,這就是要面臨的第一個難題了,所以很多人內心是非常憂傷的。
這里介紹幾種給WiFi設備配置的方法。第一種是AP,AP是最傳統(tǒng)的方式,在AP里面主要是讓智能設備首先進入AP模式里面,這樣能夠共享一個熱點出來。我們的手機直接連到這個設備里面,然后再把路由器的SSID推送給那個設備,那個設備可以在線連路由器。這里面AP有一個很麻煩的事情,就是它的交互特別復雜,特別是在iOS手機里面不允許手機的App直接調用WiFi的設置或是直接切換過去,我們可能要先退出后臺,然后切換到蘋果的那一套設置里面,設置好了之后又要切換回來,這樣特別麻煩。所以在演進過程中就進入了WPS。
WPS解決了第一步的問題,可以在路由器里面有一個按鍵,智能設備里面也有一個按鍵,可以根據(jù)WPS的協(xié)議交換它的密鑰。但是這里面有一個很大的問題,WPS需要進行專門的認證,而且現(xiàn)在支持的路由器非常少,所以用WPS技術來做的話可能會比較差一點。
再接下來又出了一個Smart Config,這一款應用非常多,因為它非常簡單,直接在手機上面向路由器發(fā)送SSID和密鑰,這個芯片再去抓路由器的包,抓到這個包之后再解密,解密出來之后就知道了路由器的SSID和密鑰,然后就可以去連。在這個基礎上微信也出了air kiss和另外的Smart link,也這個原理。
接下來又出現(xiàn)了光配置,屏幕按照一定的亮變把信息傳輸過去,但是這個應用比較少一點,問題也比較多。
再接下來是聲波配置,AA付款和面對面收款里面就用到這個技術。
總體來說,AP和第三個稍微比較好一點,但是我們在實際產品應用里面也會發(fā)現(xiàn),這一類技術面臨很多問題,就是對路由器的一些芯片、兼容性都會有比較高得要求。我們以前出現(xiàn)很多這樣的例子,測試的時候拿了幾十款、上百種路由器測得沒有問題,到了用戶家里,那一款路由器我們沒有測試過,結果發(fā)現(xiàn)不行,這是一方面的限制。為了解決這種限制,后面又改成了不抓路由器的包,就抓手機發(fā)出來的包。抓手機發(fā)出來的包之后又帶來更大的問題,正常手機的包是OK的,沒有那么多兼容性的問題。去年iOS包出來的之后,蘋果的iPhone6會有一個問題,連上WiFi離開一段時間再回來WiFi就會丟失了,這時候不重啟手機就永遠連不上WiFi了。蘋果為了解決這個問題又更新部件,然后對這個又沒有用了,又抓不了包了,所以對傳統(tǒng)應有還是有限制。還有一些跟技術沒有關系的限制,比如說現(xiàn)在比較好一點的路由器是支持2.5G和4G的?,F(xiàn)在我們使用的模塊都是只有2.4G的,如果手機是雙頻、路由器是雙頻的默認是是5G。所以我們又回到最原始的AP模式來,因為我們不用跟用戶解釋那么多東西,也沒有很多兼容性的問題。
軟件架構的選擇
這是一個軟件架構要怎么樣選擇的問題,就是我們現(xiàn)在智能設備聯(lián)網最基本的需求是什么。我們來看一下這個圖,智能設備聯(lián)網之后要實現(xiàn)跟手機APP的交互,一方面APP如果要去控制它,它必須能夠接收到APP發(fā)過來的控制信號。另一方面,如果直接在上面按,按完了之后這里面的狀態(tài)要能夠反饋到APP里面來。所以,我們在做技術選型的時候,最基本要實現(xiàn)這兩個需求。
控制命令的上傳和下發(fā)的問題,這里面決定了到底我們怎么來架構的問題。這是我昨天提出的問題,就是為了解釋剛剛提出的需求。比如說我在QQ上發(fā)布信息說插座開一下燈,然后它說已經開了。我問它是什么狀態(tài),然后它告訴我它已經關了。我們要對智能設備進行控制,這里面基本的需求一個是數(shù)據(jù),我要把想要的數(shù)據(jù)控制命令發(fā)給它,控制了之后又發(fā)回給我,這個做的事情其實就是IM的事情。我們做服務器端的架構的時候,最初考慮的方案就是選擇了IM的方案。
物聯(lián)網跟互聯(lián)網實際上看起來有很大的差異,真正我們在做的時候還是殊途同歸,我們還是都選擇了IM的方案。
看一下最簡單的IM架構,這里面要保持長連接,接下來做一些業(yè)務處理,下面是存儲,如果App要去控制Device的時候,發(fā)到業(yè)務層處理完了之后,這里面有一個推送的,可以找到Device到底連了哪一臺機,然后再把數(shù)據(jù)推送過來。如果Device自己的狀態(tài)發(fā)生變化,它的數(shù)據(jù)要推送給APP,基本上是這樣的工作流。如果App是黑莓等設備的,我們可能要專門推送到APNS里面來。
通信協(xié)議的選擇
接下來我們還需要一個好的通信協(xié)議,現(xiàn)在很多通信協(xié)議是XMPP,很多社交軟件都個在用,因為它開源做得比較好。MQTT是專門用來做物聯(lián)網的協(xié)議。另外,PROTOBUF是谷歌的,這三個比較的話,MQTT和PROTOBUF是最適合做物聯(lián)網通信協(xié)議的,因為這兩個協(xié)議對數(shù)據(jù)量利用率非常高,不會帶來額外的開銷的。
快速構建云服務
再回到上圖,如果我們要做這樣一個系統(tǒng),為了要簡單快速的出這樣一個產品,要利用很多開源的組件,比如說負載均衡這里,傳統(tǒng)的里面是比較難做的,我們用的比較多硬件負載均衡是F5或者是淘寶的LVS,我認為LVS對于目前做硬件的來說肯定是夠的。再下面Connect Server現(xiàn)在也有很現(xiàn)成的開源技術,如果采用XMPP協(xié)議的話可能要用F5,像很多也完完全全做好了,如果在TTP這一層優(yōu)化比較好,做到八十到一百萬長連接也沒有問題,而且會特別簡單。像很多軌道函數(shù)都寫的非常好,我們都不用關心怎么管理這些線程質量、怎么管理連接,只要在上面寫我們的業(yè)務代碼就行了。另外,我們這里面要做集群,我們有很多服務的時候直接在上面注冊,后面調用的時候不用關心今天多了一臺機器、明天少了一臺機器以及這個機器的ID是什么。另外,服務要遠程交易,我們要考慮IPC框架,像淘寶和Facebook的一些,都是開源領域利用的非常好的。
我們肯定還要用到很多緩存,緩存方面我們用的比較多的。如果我們對開源的框架用得比較好,簡單的這個系統(tǒng)很快就可以完成了,不需要我們寫很多東西,只需要在上面寫業(yè)務代碼就能夠直接做好了。
這里面就是剛剛說到的,如果你用Netty,只要在這里面寫業(yè)務代碼,當你接收到數(shù)據(jù)的時候這里面應該怎么做,包括這里面出了異常的時候要怎么做。如果選用Netty還要考慮到一個情況,高并發(fā)的時候需要對數(shù)據(jù)包做拆包的事情。我們經常發(fā)現(xiàn)這里接收到的數(shù)據(jù)并不是一個完整的數(shù)據(jù),比如說我們發(fā)了大概2K左右的數(shù)據(jù),它給到你的可能只有很少。如果這里面不完整,把組包放進來就可以了。具體的拆包、組包也提供了編碼性和解碼性,最重要的是在這個函數(shù)里面寫你的業(yè)務代碼。
嵌入式開發(fā)
我們要在設備端也實現(xiàn)接入,還要考慮嵌入式的開發(fā)。嵌入式也有一個問題,我們的設備都是需要成本的,不像寫服務代碼一樣,服務器資源非常多,給到你很好的服務器可以用。在嵌入式方面,我們必須用最低的成本、最少的資源做最多的事情。每一個產品研發(fā)出來,第一代選用的芯片可能比較好一點,第二代為了這個產品能夠賣得更好,可能會做更改,對我們來說可用的資源更多。通常我們用單片機,我們比較常用FreeRTOS,它沒有TCPP協(xié)議的。做嵌入式開發(fā)的時候我們還會遇到更多的問題,像LWIP之類的,寫這個協(xié)議站的人可能并沒有用到很多產品,所以里面還是殘留了很多BUG。這里面舉了兩個非常明顯而且一定會遇到的問題,一個是TIME_WAIT,還有一個是CLOSE_WAIT,如果對方沒有按照正常流程關閉,假如說我們的APP直接刷了,可能就會產生這個CLOSE_WAIT,它一直在那里等,我們可能只開放十多個端口接入,如果一直在等待,可能它就認為這個請求還是正常的,就不會把它釋放出來。等我們給它分配的端口滿了之后,下一個請求就再也接不進來了。一般有三次握手,如果斷開了標志著有四次握手,我們發(fā)現(xiàn)它沒有按照正常的四次握手,導致斷開的時候少發(fā)了一些命令,所以就一直在等待,等待的時候數(shù)據(jù)怎么發(fā)也發(fā)不出來了。
還有我們經常可能會遇到一些問題,比如說這里面可用的只有10幾K、64K,我們要在上面寫代碼,如果寫了多線程,又是單核的CPU,這里面用的時間長了會產生很多的內存碎片。當內存碎片產生了之后,多線程再申請內存做其他事情的時候,比如說有一個線程需要申請的資源比較大的時候會申請不到,就會一直在那里等,就會發(fā)現(xiàn)是怎么回事,這個地方本來十幾毫秒就可以處理完的,可能等了一秒鐘或者兩秒鐘甚至時間更長時間才能處理,這就是時間用了長了之后產生了內存碎片。我們回收內存也做不了,所以經常要做被動的事情,要軟重啟一下,所有的線程再重新跑起來。
事情是否已經結束
回到接下來的一個問題,我們按照剛才的思路,我們把樣品做好了,模塊也開發(fā)好了,APP也做好了,是不是所有事情都完成了呢?舉個例子,某手機廠商說要做“東半球最好的手機”,這等于是他的情懷,為什么呢?做硬件和軟件非常大的區(qū)別是,純互聯(lián)網的硬件把程序代碼寫好就可以使用了,但是硬件來說的話還會涉及到很多生產工藝,還要做一些認證。比如說像我們的插座,我們要經過3C認證等等,如果過不了這個東西就不能賣。像這個手機當時出了一個問題,它那個表面的玻璃像普通的安卓手機一樣,下面開了幾個孔,蘋果只開了五個孔,它開了三個孔,在生產里面要求的工藝非常高,開三個孔的情況下可能真正的良品率只能達到30%、40%,大部分開孔的時候會導致這個玻璃碎了。像這種情況下,我們會把一個產品設計的非常好,認為這個東西非常漂亮、工藝非常好,但實際上也要考慮我們的生產能不能做。
我們現(xiàn)在做出來一個整體的架構,上面是一些產品,下面是模塊這里面是為了解決家里面的很多設備,所以有一個ZigBee的網關,通過網關再來連接。
這是我們的一個系統(tǒng)構架,比較復雜一點,因為這里面整個系統(tǒng)涉及到的業(yè)務特別多,它的產品也特別多。這里面接入的時候,其實整體上來說也都差不多,一個是設備層的接入,還有一些業(yè)務層,里面做了一些報表、數(shù)據(jù)分析,還有一些OTA,可能還有一塊沒有畫出來,就是我們在做商業(yè)智能的時候實際上是剛剛那位朋友問了一個問題,就是我們有沒有嘗試做一些更加智能的分析之類的,實際上我們在根據(jù)用戶的需求在梳理一些模型,我們希望這些數(shù)據(jù)能夠幫我們分析用戶現(xiàn)在是在做什么。一個最簡單的例子,當某一個開關,可能是它每天晚上一點鐘都會亮一下,亮一兩分鐘又滅了,這可能意味著那個用戶有一個生物鐘,因為生物鐘時間非常準,他每天都是這個時間點做這個動作,比如說上廁所之類的,這個時候非常需要把房間的燈打開,包括走廊的燈、洗手間的燈都要打開。我們把這個事件分析出來,到了這個時間點之后就不用摸黑按這個開關了,我們會把這個幾個開關打開,這就是他的路線。如果要能夠做的更細致化一點的化,我們還會發(fā)現(xiàn),如果我們在睡覺的時候突然之間醒過來,然后燈亮了,實際上是非常刺眼、非常難受的事情,我們在打開燈的時候,是不是把燈的亮度只調出一點點,有一點微弱的光,不會刺眼,又有足夠的亮度可以照明,讓他走過去。這是我們做的更深層次的分析。