內容簡介
作為互聯網技術的進化,物聯網開發并非孤立的技術棧,而是向上承接了互聯網,向下統領了嵌入式硬件開發的一個承上啟下的全棧開發技術。
雖然我們并不能預測物聯網技術棧最終的樣子:統一的開發語言是 JavaScript 還是 Python 亦或者其他編程語言;HTTP、WebSockets、MQTT、CoAP 等協議誰會是最后的贏家,并且隨著物聯網的不斷進化,甚至我們可能都無法預測其最終形態,也許根本就沒有一個最終的形態。但是,我們仍然可以看清物聯網發展的軌跡與必然趨勢——開發技術棧必然向全?;较虬l展。
互聯網的核心是數據的流動,數據的流動為我們帶來了難以想象的價值,而物聯網又將這一核心推到了更高的高度,打破了互聯網原有的邊界讓千千萬萬節點設備中的數據流動了起來。全?;拈_發正是順應了這種趨勢,打破了在開發層面中那些阻礙數據流動的技術壁壘,將芯片、嵌入式、網絡、大數據、人工智能、信息安全等諸多領域納入到物聯網的全棧開發中來,實現端到端的完整解決方案,真正實現數據的流動并讓數據為人類服務,讓我們以更高效更智慧的方式來發掘數據的價值,實現數據的價值。
本書內容
物聯網技術現狀與新可能
文/羅未
不管是從商業模式導出的業務模型,還是從技術發展的角度看,文本都傾向于將物聯網技術構架看作是互聯網技術構架的延展。而與這個觀念對立的,是傳統嵌入式軟件開發的視角。
在互聯網技術基礎上長出來的物聯網構架
簡單來說,目前的互聯網技術構架主流是大前端與后端兩個世界:大前端包括 Web 的 JavaScript 技術、Android 和 iOS 技術,著眼于解決用戶交互;后端包括數據庫、服務構架、運維等,著眼于解決存儲、業務邏輯、安全與效率等。當然,現在前后端技術爭相更新,比如業務邏輯前置化、微服務構架、JavaScript 全棧化等新的解決方案也開始模糊前后端的差異。而物聯網設備端的引入,著實讓這些技術有點難以歸類,從業務性質上物聯網是另外一種前端或是前端的延伸,比如共享單車應用中,自行車端的應用顯然是跟人交互的另一個業務場景,也在為后端源源不斷地提供著數據,但是自行車又不像網頁或者 App 完全是在解決可視化 UI 的事情。而且,現在的設備端開發技術跟前端技術太不像了,由于目前設備端的開發技術都還偏底層,一般來說計算資源如處理能力、本地存儲都非常有限,反而像后端一樣要考慮資源效率。
那么,我們只好為物聯網單獨命名一個端,不如我們暫時就叫它設備端。
圖1 整體架構圖
新后端
MQTT
新后端核心問題在于加入了面向設備的接入服務,實際上在這里,除類似視頻對講或是安防監控的多媒體實時通道外,這個接入服務已經基本事實化為 MQTT。
消息隊列遙感傳輸協議是在TCP/IP協議之上使用的,基于發布/訂閱的“輕量級”消息協議,目前為 ISO 標準(ISO/IEC PRF 20922)。它被設計用于輕量級和低帶寬的遠程連接,發布/訂閱消息傳遞模式需要消息代理,消息代理負責根據消息的主題向需要的端發布消息。
如果需要連接的設備沒有超過10萬臺,使用 8GB 內存的云主機跑 Mosquitto 就可以;如果設備量是幾十萬臺,可以考慮 Mosquitto 做集群負載均衡;如果設備量是大幾十萬臺乃至百萬臺以上,那你需要專業的團隊或專門的投入來維護這件事情,這個細節就不在本文討論范圍了。
OTA
固件組件在線升級是必須要做的事情,MQTT傳 大文件不靠譜,所以一般傳過去一個帶 Token 的 URL,設備端去下載就好,HTTP 或者 HTTPS 都可以。業務比較簡單,設備端幾十萬以內沒有什么特別的地方。
數據存儲與服務
Mosquitto 作為 MQTT 的引擎,需要后端按照業務邏輯去調用,這里按照業務需求寫好后端邏輯即可。在各種后端語言中調用 Mosquitto 都非常簡單。
設備端
設備端是物聯網領域最五花八門并且正在發展中的地方。其他領域,后端或者前端,經過十幾年的發展,已經出現每個細節的主流技術,基本沒有碎片化的情況,但是在設備端,開發技術的碎片化是應用發展還不到位的充分表現。舉例講,選用不同的芯片,就要用不同的操作系統,不同的 C 庫封裝,各家 IDE 也不盡相同,編譯工具鏈更是從芯片原廠給出。開發起來呢,寄存器、內存分配、硬件中斷都要深入進去。這就是傳統嵌入式開發的現狀,也是物聯網設備端開發的現狀。
到目前為止,真正生產環境中用到的語言就是 C/C++,極個別會在設備端用到 Python,基本沒有其他語言。操作系統超過50種,主流的也有10種以上,其中嵌入式 Linux 份額并不大,各種實時操作系統各具特色,各有一片天地。
簡單總結一下相對于物聯網開發,傳統嵌入式開發的方式主要有以下幾個問題:
需要考慮中斷、寄存器、內存分配等過于底層的工作;
編譯、燒寫、觀察、借助調試設備進行調試的開發生命周期;
不同 SoC 和系統的差異過大;
缺乏代碼復用與開源的習慣;
開發者在開發環境和固件編譯上花費的時間過多。
所以我們看到設備端的開發是基于芯片選型完成的。當設備端產品面臨一個需求時,現有的流程是判斷產品的各項技術參數,從而確定一個芯片,進而使用這個芯片的一整套開發技術。這也是早期嵌入式場景使用的芯片自生技術特性所決定:計算資源(CPU 主頻、存儲)、外圍接口、使用溫度、通訊協議等核心參數的不同導致芯片碎片化,芯片碎片化導致嵌入式開發碎片化。
目前這個領域的大趨勢是:物聯網芯片有望走向趨同,物聯網開發環境與技術有望趨同。
物聯網芯片
早期由于成本所限,物聯網領域使用的芯片總是表現得非常缺資源,很難找到一個各方面(計算資源、外圍接口、使用溫度、通訊協議等)都比較合適的芯片去適應普遍的場景。隨著半導體門檻逐步降低,中國半導體制造業逐步成型,芯片資源開始走向富余,其中的代表芯片是 MTK 的 MT7697、MT7688 和樂鑫的 ESP32。
MT7697 主要參數為:ARM Cortex M4 CPU,帶浮點單元,最大主頻 192Mhz,內存為 256KB SRAM,可配置 4MB 以上的存儲空間,芯片內嵌 WiFi 和 BLE 4.2,有足夠的外圍接口,并能夠適應工業級的使用溫度。
MT7688 主要參數為:MIPS 580Mhz CPU,內存最大支持 256MB,可配置 16GB 級別的存儲空間,芯片內嵌 WiFi,接口除模擬接口之外數字接口豐富,價格在幾十元人民幣,功耗較高不適于電池長期使用。但是非常有優勢的是其提供的 Linux 開發環境,能夠讓開發者有一種在普通 x86 機器上使用 linux CLI 的體驗,Node.js、MySQL、OpenCV、Nginx 等等在阿里云上怎么用,在這個幾十塊的物聯網小模塊上也怎么用。穩定性超強,幾年不死機也是正常的。
ESP32 的主要參數為:Tensilica LX6 CP,主頻 240 MHz,內存為 520KB SRAM,可配置 4MB 以上的存儲空間,芯片內嵌 WiFi 和藍牙以及 BLE,有足夠的外圍接口,并能夠適應工業級的使用溫度。
這幾顆芯片共同的特征是計算資源和通訊能力以及接口資源相對于傳統 MCU 來說有足夠的富余,并保持在同樣的價位。因此,在這類芯片上,有足夠的資源做抽象化的封裝和開發框架實施。我們看到除了這幾顆芯片原廠提供的傳統嵌入式開發包之外,社區和其他廠商已經在這幾顆芯片上加快了新開發技術的實現。
開發技術
物聯網設備端開發技術目前有兩個比較大的發展方向,一是統一化的物聯網操作系統,二是統一化的物聯網開發框架。他們共同的目的是形成“軟件定義物聯網”,與傳統從芯片選型開始的,著陸于原廠 SDK 中完成應用開發,與需求和產品設計匯合的流程完全相反,希望從需求和產品設計入手,通過公開統一的軟件構架完成開發,再根據開發使用到的資源去落地芯片和外圍設備。這樣做的好處主要在于提高開發效率和形成可以復用的應用代碼。
操作系統
雖然市場上存在的設備端操作系統有數十種之多,但是我們看到活躍的,明顯向“軟件定義物聯網”方向發展的有三家:
Zephyr
Zephyr 是 Linux 基金會于2016年2月發布的物聯網操作系統,背后主要的支持力量來自于 ARM 和 Linaro,具有目前嵌入式小型實時操作系統的普遍特征,比如:輕量到 KB 級的最小系統內存占用,支持多種芯片構架:從 ARM Cortex-M、Intel x86、ARC(DSP 內核)、NIOS II(FPGA 軟核)到開源的 RISC V 等,跟 Linux 一樣的模塊化內核組織方式,如圖2所示。
Zephyr 目前已經升級到 V1.7 版本,逐步向一個可以用到生產環境的系統靠攏了。Zephyr 最大的特色并不在于其完備性而在于其開發理念完全來自于“軟件定義物聯網”,并且有很好的資源支持,在未來應該會有自己的位置。
圖2 Zephyr 物聯網操作系統
RTthreadRTthread 是純國產的小型操作系統,植根于中國的各種使用場景,10年來已經確立了自己的地位,在很多行業有自己的一席之地,目前社區非常活躍,核心團隊以創業公司的形式推進,非常專注。技術上的特征作為一個成熟的系統,沒有什么可以吐槽的地方。Zephyr 有的技術優勢 RTT 都有,而且 RTT 在生產環境的裝機量較為可觀。
華為 LiteOS
華為是全球范圍內物聯網技術的根源廠商之一,LiteOS 是一個華為內部很多產品都在用的系統,目前也以開源的形式在全力推廣。LiteOS 最大的優勢在于華為很多根源技術將利用 LiteOS 進行輸出,目前最大的例子就是即將全面商用的 NB-IoT 技術,設備端的開發包將會用 LiteOS 輸出。
以上幾個系統一致的特點包括小型化、芯片適應范圍廣、通信協議適配比較廣泛等,他們也都是開源的系統,研發或推動力量比較活躍。有可能在物聯網領域里的類似 Linux 地位的主流操作系統會是其中某個,也或許會一直都存在下去但是在技術上越來越趨同。
開發框架
首先解釋一下開發框架,開發框架可以小到是一個細節的工具,也可以大到規定開發的全部邊界。最典型的例子是 Android,純粹操作系統意義上,Android 是 Linux 的一個分支,但是從 App 開發角度,除 NDK 之外,沒有任何與 Linux 打交道的地方,所以也把 Android 叫做操作系統。再廣泛地看,Android 除了面向手機應用的開發框架,還準備了 Google play 這樣的應用分發渠道,這是開發者生態建設。同理,我們看 Node.js 在后端的種種開發模式,也是將所有后端資源都封裝到 JavaScript 里,開發時可以隨時 npm install 各種包來 require,解決了代碼復用問題。
因此我的觀點是,開發框架以及背后的代碼復用和開發者生態才是真正的操作系統。
目前在物聯網領域,正在嘗試向生產環境演進的開發框架基本都基于 JavaScript,而在小型實時操作系統上使用的 JavaScript runtime 目前也基本集中到了 JerryScript 上。JerryScript 是三星開發和開源的一個小資源占用的引擎,內存需要 64KB,存儲需要 200KB 即可,能夠實現完整的事件驅動,符合 ECMAScript 5.1。
如同前文所說,開發框架或是操作系統在當下需要包括以代碼復用為目的的開發者生態,甚至需要包括應用分發,所以我們看到在 JerryScript 的基礎上,有兩家做這類工作的團隊值得關注:
WRTnodeWRTnode 是一個北京的開源硬件團隊,提供從開發到硬件交付的全流程服務。他們最近開放的 node.system 和 noyun.io 即是著眼于實現物聯網 JavaScript 的開發框架和開發者生態。在 WRTnode 的實現里,設備端的 JavaScript 開發已經變得像 cloud9.io 一樣全案在線開發,為開發者屏蔽了嵌入式開發的繁瑣編譯燒寫工作。
RuffRuff 是位于上海的創業公司,2015年開始一直在演進基于物聯網設備端 JavaScript 的開發者生態,提供了較為可行的代碼復用框架。目前他們已經開始服務商業客戶,為物聯網應用的快速實現提供了可能。
同時,Zephyr 和華為 LiteOS 也都有各自的 JavaScript runtime 發布計劃。
以上我們看到了設備端開發的一些新的發展,目前這些新的設備端開發技術,已經逐步面向交付轉移了。有理由相信經過一段時間的發展,面向效率的商業模式驅動下的物聯網開發技術將迎來一大波更新,從而導向物聯網應用的真正大發展。
基于 JavaScript 語言的快速物聯網開發架構
文/黃峰達
隨 JavaScript 語言的流行,及物聯網領域的崛起,我們能看到它們結合的可能性,同時也發現它特別適合于物聯網開發。因此,在這篇文章里,筆者將主要從以下三個方面進行介紹:
典型的物聯網架構,及多種語言帶來的問題;
只使用 JavaScript 語言的物聯網架構;
詳解基于 JavaScript 語言的物聯網不同層級結構。
那么,先讓我們看看典型的物聯網架構是怎樣的吧。
典型的物聯網架構
我們甚至還可以認為,物聯網只是對互聯網的擴展。與傳統的 C/S 架構相比,它多了一個“數據采集層”,我們稱之為傳感器層、硬件層等。數據的產出不再只是用戶,還來自于各式各樣的聯網設備。物聯網不再局限于使用 HTTP 協議來傳輸數據,它還會使用 CoAP(受限制的應用協議)、MQTT(消息隊列遙測傳輸)協議。
物聯網的四個層級
當前的物聯網應用,所要做的就是控制和數據處理。指令,由用戶到終端一層一層往下下達,直到硬件端由設備去執行。而數據,便是一層一層往上上報,直至被可視化。
因此,與互聯網的架構相比(如圖1、圖2所示),起點與終點不一樣了:指令的終點與數據的起點,變成了硬件層,而非最后的用戶層。
圖1 互聯網架構
圖2 典型的物聯網架構
數據由客戶端 A 發送到服務端,客戶端 B 再從服務端獲取 A 的數據,如此便算是完成了一個回路。而物聯網架構則稍微麻煩了一些,多了一個層級,便多了一個步驟。
硬件層上的微控制器通過直連的方式,采集各式各樣的數據,比如溫度、濕度等。而受限于微控制器的成本、環境條件等因素,它可能無法直接連接到互聯網。因此,需要連接到一些額外的聯網設備才能實現。
而這些聯網設備,會負責處理來自各個硬件設備的數據,并將其上傳至服務器。同時,它會提供一個無線(如藍牙、紅外、ZigBee)接口作為數據的入口。因此,這一層級需要有更好的數據處理能力,并且它應該要可以快速開發。因為這些設備主要做的是協調工作,我們習慣于將其稱為“協調層”。
使用多種語言的物聯網
多年以前,筆者曾做過一個并不復雜的物聯網系統:
使用 Python 里的 Django 作為 Web 服務框架,Django REST Framework 創建 RESTful API;
為了使用手機作為控制器,還用 Java 寫一個 Android 應用;
使用 Raspberry Pi 作為硬件端的協調層,用于連接網絡,并傳輸控制信號給硬件;
在硬件端使用 Arduino 作為控制器,寫起代碼特別簡單;
還使用了 ZigBee 模塊 XBee 及 I2C 作為連接不同 Arduino 模塊的介質;
最后,還需在網頁上做一個圖表來顯示實時數據。
為此,我們需要使用 Python、Java、JavaScript、C、Arduino 五種語言。而如果我們要寫相應的 iOS 應用,還要用到 Objective-C。對于其他物聯網項目來說,也多是如此,這簡直是一場災難。
在做這樣的物聯網項目之前,我們需要找到六個不同類型的工程師:一個硬件工程師設計電路圖,一個懂硬件的嵌入式工程師,一個寫服務端應用的工程師,一個寫 Web 前端的工程師,以及對應的 Android 和 iOS 工程師。
且不考慮系統本身的協作,要找到這么多的工程師就不是一件容易的事。而如果我們可以只使用一種語言,將大大地改善開發效率、開發人員的難題。
JavaScript 語言下的物聯網架構
JavaScript 語言在最近幾年里特別流行,它流行起來有很多個原因,如:
使用 WebView 開發 UI 效率更高,也因此使得WebView 隨處可見;
基于事件驅動的編程模型;
JavaScript 容易上手(這是優點,也是缺點);
也因此,React、Unity 等框架提供了更多的可能性,可以讓開發者用 JavaScript 開發游戲、VR 應用等等。
那么,只使用 JavaScript,我們可以設計出怎樣的物聯網系統呢?
基于純 JavaScript 的物聯網架構
如上所述,幾年前要想尋找一門能完成一個包含客戶端、服務端的系統的語言可謂相當地困難。而隨著客戶端(瀏覽器、移動設備)性能的提升、Node.js 的出現,這樣的語言就浮現了出來,即 JavaScript。它不僅可以讓我們只用一門語言來降低開發成本,還能實現快速地開發出這樣的一個系統。那么,剩下的問題就是,在不同的層級,如何選用合適的框架來實現快速開發。
如圖3所示,我們可以看到不同層級的可選用 JavaScript 方案。在此之中,有些純粹只是為了證明 JavaScript 是可行的;有一些則可以在開發效率與運行速率上達到最好的平衡。選用這些方案,可以讓我們實現更快速的 JavaScript 物聯網應用開發。
圖3 基于純 JavaScript 的物聯網參考架構
服務層
對于服務層來說,自主開發的物聯網服務端,主要采用的是基于 Node.js 的方案。然而,我們發現有越來越多的應用,在使用 Serverless 的架構,不僅可以快速推出一個可用的原型,未來也能夠輕松地基于這個原型來添加業務功能。
圖4 物聯網服務層
圖4便是我們看到的物聯網服務層的三種方案:
自主開發:即遵循傳統的服務端開發模式,定義自己所需要的功能;
使用云服務:直接使用成熟的物聯網云服務,它們在云端集成了各種所需要的功能;
Serverless:Server 可以看作是在云服務之上的自主開發,集兩者之便利。每一種方案都有各自的特點,也適合于不同開發能力的項目。但如果要實現快速的開發,那么理想的方式便是采用 Serverless 架構模式。
自主開發
出于不同的原因,諸如保密、安全、可擴展、核心技術等原因,一定規模的公司會采用自主開發的方式。這種開發方式與 Web 應用開發方式并沒有太大區別,都是在數據進行 CRUD 操作。并且和前后端分離架構一樣,使用 API 作為接口,同時再加上支持不同的傳輸協議,如 MQTT、CoAP 等。
圖5 Lan 物聯網架構
如筆者之前在 GitHub 上開源的 Lan(https://github.com/phodal/lan),便是一個精簡的物聯網服務端示例。基于 Node.js 與 MongoDB,其架構如圖5所示。
采用傳統的關系型數據庫來存儲用戶信息;
采用 NoSQL 可以應對不同的傳感器數據;
提供 UI 界面供管理人員管理用戶;
在協議上提供 HTTP、CoAP、MQTT、WebSocket 等的支持,方便不同的類型適配。
除此,物聯網系統在存儲上,采用 NoSQL 作為存儲介質會有更大的優勢。一般來說,物聯網系統的數據都是寫入遠遠多于讀取的場景。與此同時,由于設備的種類繁多,不可能為每一類設備創建表;或者考慮到大量設備的特性,來建立一個通用的表,但在未來這樣的表可能仍不適用。
因此,對于物聯網數據來說,選用諸如 MongoDB 這一類的 NoSQL 數據庫,有這么一些優點:
靈活性。采用非結構化的數據模型,可以存儲和處理任何結構的數據;
支持水平擴展。NoSQL 數據庫的分布式存儲架構,帶來了優秀的水平擴展性;
實時數據分析。如 MongoDB 可以通過豐富的索引和查詢支持,包括二次、地理空間和文本搜索索引,聚合框架和本地 MapReduce,可以針對傳感器數據就地運行報告分析。
然而,這樣的系統不免存在研發周期長的問題。如果需要快速驗證,那么應該考慮使用云服務來完成部分功能。
物聯網云服務
對于硬件團隊來說,直接使用云服務是一種更簡單、快速的搭建物聯網系統的方法。而使用物聯網云服務,就意味著:我們可以直接上硬件層的傳感器數據,并在應用層獲取、分析這些數據。這一類的服務,比較成熟的有 AWS IoT Things(如圖6所示)、Azure IoT 等。
圖6 AWS IoT Things 參考架構
基于 AWS IoT Things,我們只需要在云端,定義好對應的數據處理規則,便可以在硬件端直接對接服務。不過值得注意的是,單一的云服務無法提供復雜的功能,這個時候就需要一些搭配額外的服務。
Serverless
Serverless 架構(如圖7所示)是云服務的一種,但是它在可編程與云服務之間做了一個折中。它是一種基于互聯網的技術架構理念,應用邏輯并非全部在服務端實現,而是采用 FaaS(Function as a Service)架構,通過功能組合來實現應用程序邏輯。
圖7 Serverless 物聯網參考架構
從理論上來講,這些服務提供的是一層 API 封裝,它不會限制我們所使用的語言。使用 Serverless 服務,我們可以具備更好的快速開發能力,并且能使用同一種語言(JavaScript)來完成編程。
在這個過程中,開發者要所做的便是:在不同的服務之間傳輸數據,每一次都只處理下一個服務所需要的數據,類似于 Pipe and Filters 架構模式。如一個典型的物聯網應用的數據傳輸過程中是這樣的:
對設備進行鑒權;
轉換、存儲設備的數據;
廣播通知其他監聽此設備數據的服務;
后臺查詢數據;
分析數據(AI);
可視化數據。
只需要少量的編程,我們就可以完成服務端的開發。隨后,專注于硬件層的開發,以及應用層的業務功能。
應用層
在應用層方面,已經有大量的地方使用到了 JavaScript。除了傳統的桌面瀏覽器,還有更多的領域也可以用 JavaScript 來開發。比如移動應用,已經有基于 Cordova + WebView 的成熟方案,還有近兩三年流行起來的 React Native,都可以讓開發者使用 JavaScript 完成物聯網移動應用的開發。又如微信小程序,可以直接用藍牙來連接硬件設備,也是使用 JavaScript 來編程。
因此,就目前的 Web 趨勢來看,在應用層,JavaScript 將是快速開始的主流選擇。
在日常中的應用中,我們可以發現物聯網的應用層,經常作為協調裝置來連接硬件,并上傳應用的數據。諸如共享單車、智能手環應用等,它們既通過藍牙來獲取數據,又上傳數據到服務端。與此同時,有相當多的應用是運行在桌面客戶端上的。故而在這一層級的應用,可謂是種類繁多。
今天,開發人員在做移動端的技術選型時,都會優先考慮到跨平臺能力(Android、iOS)。而在這些跨平臺框架里,混合應用框架 Cordova(WebView)和 React Native 是使用最為廣泛的兩個框架,且它們都是使用 JavaScript 作為核心開發語言。
Cordova 是使用 WebView 來渲染頁面的。因此與 Reavt Native 相比,使用 Cordova 的最大優勢是,可以復用已有的 Web 前端應用的邏輯,并且有大量的圖表工具可以直接使用——這一點在物聯網應用中特別重要。而在混合應用框架中,Ionic 是這個領域使用最多的 UI 框架。
React Native 使用原生組件來渲染 UI 組件,不僅可以解決 Cordova 飽受詬病的性能問題;同時,它還能嵌入 WebView,解決一些復雜的圖表顯示問題。
但是如果只能藍牙的交互,可以考慮 PWA 或微信小程序。運行在 Chrome 瀏覽器上的 PWA 應用,可以直接使用 Web Devices API,如Bluetooth、NFC、USB,即在瀏覽器上直接調用原生接口,并實現對設備的控制。而諸如最近一年內流行的微信小程序,則也可以訪問藍牙、GPS、羅盤、加速度計等硬件接口,同時用戶不存在安裝成本,打開即用。
另外,諸如 Electron、NW.js 這樣的框架,可以讓開發者直接使用 WebView + Node.js 模塊開發物聯網桌面應用。它可以加速 UI 界面的開發,并輕松地美化 UI 界面。
硬件層
在硬件層上,就當前而言,Arduino 是最合適的原型開發硬件,除此還有自帶 Wi-Fi 的 ESP8266 開發板。盡管使用 JavaScript 的開發板數量較少,也沒有 Arduino 這樣的成熟生態,但是未來可期。在嵌入式領域,使用 JavaScript 編寫的代碼,具有移植性強、事件驅動、天生支持異步等特點。
令人遺憾的是,為了保持上面提到的那些 JavaScript 特性,當前的 JavaScript 開發板都需要處理性能比較高的處理器,這也導致了此類開發板在生產上存在較高的成本。不過,好在多數使用 JavaScript 作為開發語言的設備,都具有網絡功能連接到互聯網,直接作為物聯網設備使用。
就目前而言,這一類的設備有 Tessel、Espruino、Ruff 等等,它們的處理器性能都相當不錯,價格也相對較高一些。但是,它們可以直接使用 JavaScript,能為軟件開發工程師屏蔽底層相關細節,及事件驅動、異步特性,帶來更好的開發體驗。
幸運的是,Samsung 公司推出的開源物網框架 IoT.js,只需要 64KB RAM、200 KB ROM。在未來,或許它能解決一些制造成本上的問題。
協調層
當我們的硬件層不能直接聯網時,協調層就可以完成這樣的功能。作為一個協調層的設備,它應該能與一定數量的微控制器連接,接收它們的數據,并上傳到服務端;又能與服務端通訊,獲取一些控制指令,并將這些指令準時地發送給不同的控制器。所以,它需要有更好的處理能力、更多的 RAM、ROM 等等。因此,在這一層級使用 JavaScript 便不存在成本問題。我們只需要使用和服務端、應用層相似的知識,就可以快速地連接設備到網絡中心。還能直接在本地的 Linux 機器上編寫代碼,并無縫地運行在設備上。
圖8 物聯網協調層
這一類應用,依賴于 Node.js 引擎來實現快速開發。它可以運行在帶有嵌入式系統的開發板上,如流行的 Raspberry Pi、OpenWRT 路由器等。
我們只需要一個運行嵌入式 Linux 系統的開發板,就可以完成這樣的工作。與此同時,主流的 ARM 開發板都提供相應的 Linux 移植,因此在這個層級,我們也只需要關注于業務的實現。
小結
如上所述,物聯網應用的架構與 Web 應用的架構區別并不是太大,只是在這上面做一系列的演進。除了上面提到的一系列快速實踐框架,當前在 Web 開發中流行的一些開發思想,勢必也會引導到物聯網系統中:
微服務化;
DevOps;
容器化。
物聯網會吸引互聯網的優秀開發思想,并演進出更優秀的架構。
使用 JavaScript 和 MQTT 開發物聯網應用
文/劉彥瑋
如果說 Java 和 C# 哪個是最好的開發語言,無疑會挑起程序員之間的相互怒懟,那如果說 JavaScript 是動態性最好的語言,相信大家都不會有太大的爭議。隨著越來越多的硬件平臺和開發板開始支持J avaScript,JavaScript 在硬件端以及物聯網領域有了新的機會。
IoT 應用開發的數據鏈路
圖1是一個智能家居物聯平臺的數據鏈路。
圖1 智能家居物聯平臺的數據鏈路
一般來說,可以把 IoT 應用分為如圖所示的四層。
client 層:指的是 IoT 設備,可以是冰箱、空調,也可以是一些溫濕度傳感器。
gateway 層:大多數場景中 gateway 是家里的 WiFi 路由器,也有小部分是基于 Zigbee 或藍牙的網關設備。智能生活場景中的 gateway 數量相對于工業領域要少很多,在工業領域存在大量的邊緣計算放在 gateway 層進行處理(霧計算)。
cloud 云層:這里是集中處理業務的地方。
應用層:這一層是直接與用戶打交道的地方,可以是通過電腦的 Web 瀏覽器、手機 App,也可以是有屏幕的智能設備的顯示器。隨著語音技術的發展,無屏設備也可以通過語音交互,作為一個應用存在于物聯網的交互層。
物聯設備(下文統稱為 client),可以是單個設備或多個設備組成的應用場景。比如冰箱把運行的功耗數據、庫存數據、溫度數據采集,通過 gateway 發送到 cloud 層,cloud 層收集數據后進行異常判斷,做智能模式推薦等業務處理后到 application 層進行展現和交互。用戶可以通過冰箱的設備數據進行模式選擇,還可以做一些與設備無關的增值服務,比如聽音樂、買菜等,這就是一個智能冰箱的數據鏈路。還有些 client 是成組智能場景的,比如溫濕度傳感器將數據上傳到 cloud,經過處理和加工,動態控制家中空調的溫度,調節空氣凈化器的運行模式等。這么描述好像沒有體現出 cloud 層的作用,那如果運行模式是用戶預先配置好的呢?如“當溫度超過25度,請幫我打開空調”,這些業務都可以通過 cloud 層進行處理。
client 層的連接方式有 WiFi、Bluetooth、Zigbee,而 MQTT 是為了讓物聯網設備更加互聯互通而出現的應用層數據協議。
MQTT+JavaScript
MQTT 是一個長連接的通訊應用層協議,最大的特點是數據精簡、消息可靠、Publish-Subscribe 模式靈活易用。MQTT 已經成為 IoT 傳輸的標準協議,應用非常廣泛。
圖2中 Client 指的是物聯網設備。Client 通過對 Topic 的訂閱和發布數據管理應用中的數據流動,而 Broker 是 MQTT 應用中用于管理 Topic 的角色。Server 是物聯網應用中的服務端,用于處理業務邏輯。
MQTT 被廣泛使用的一個重要的原因是 MQTT 的生態非常完善,同時也支持 JavaScript。因此圖2所示的所有鏈路和模塊,都可以通過 JavaScript 實現。
圖2 MQTT 的數據鏈路圖
JavaScript 在 MQTT 架構中常用的框架
mosca(https://github.com/mcollina/mosca)
mosca 是一個用 JavaScript 實現的 MQTT Broker。不僅如此,mosca 還增加了對數據庫,如 Redis、MongoDB 的支持,用來實現消息數據的存儲。MQTT.js(https://github.com/mqttjs/MQTT.js)MQTT.js 是官網推薦的 JavaScript 實現的 Client 端。
KOA 和 Express
這兩者都是非常主流的 Node 版本的 Server,簡單易用。
圖3 JavaScript 在 MQTT 架構中常用的框架
實戰物聯網應用
這節我們運用之前介紹的框架,自己動手完成一個簡單的物聯網應用。應用場景如圖4所示,溫度傳感器用于接收溫度,并把文檔通過 MQTT 發送到 Server 端,在 Server 端進行業務處理,根據溫度計算出穿衣提示,通過 MQTT 把數據發送到特定的 Topic,App 訂閱 Topic 獲取數據后進行展現。
圖4 “穿衣提示”業務場景框架
Broker 端的實現
Broker 端使用 mosca,參考網頁https://github.com/mcollina/mosca。
安裝 mosca。
nmp install mosca --save
啟動 mosca。這里需要注意,如果本地沒有配置 MongoDB,則需要把 ascoltatore 中的內容全部注釋掉。
var mosca = require('mosca');var ascoltatore = { //using ascoltatore // type: 'mongo', // url: 'mongodb://localhost:27017/mqtt', // pubsubCollection: 'ascoltatori', // mongo: {}};var settings = { port: 1883, backend: ascoltatore};var server = new mosca.Server(settings);server.on('clientConnected', function(client) { console.log('client connected', client.id);});// fired when a message is receivedserver.on('published', function(packet, client) { console.log('Published', packet.payload); //{"clientId":"mqttjs_02fea7b4","topic":"/tips"} // console.log('>>>packet', packet); //{"clientId":"mqttjs_02fea7b4","topic":"/tips"}});server.on('ready', setup);// fired when the mqtt server is readyfunction setup() { console.log('Mosca server is up and running');}
代碼完成后,啟動文件,本地的一個 Broker 就跑在 localhost 的1883端口上了。
Client 端的溫度傳感器實現
Client 使用 MQTT.js 實現,參考網頁https://github.com/mqttjs/MQTT.js
安裝
npm install mqtt --save
啟動
var mqtt = require('mqtt');var client = mqtt.connect('mqtt://localhost:1883');client.on('connect', function () { console.log('>>> connected') // client.subscribe('/tips') setInterval( ()=>{client.publish('/temperature', '30');}, 3000 );})client.on('message', function (topic, message) { // message is Buffer console.log(message.toString())})// client.end();
執行 Node index 后 Client 就啟動了,可以看到在 MQTT.connect 方法中連接了上一節中啟動的 Broker 地址,連接成功后,Client 會輸出日志,“>>> connected”,Broker 的控制臺也會輸出 Client 的連接信息。
這里模擬了溫度傳感器,定時3秒向 /temperature 的 Topic 中發送溫度數據。
本節的溫度器可以在電腦中使用 Node 方式運行,也可以運行在支持 JavaScript 的開發板中,如 RUFF、NodeMCU、Raspberry Pi,并且可以使用真實的傳感器。
Server 的實現
Server 使用 MQTT.js 訂閱 Client 發送到 /temperature Topic 的數據進行處理,把處理后的數據轉譯成 JSON 發送到另一業務主題 /tips 中。
實現代碼如下:
'use strict'const mqtt = require('mqtt');var client = mqtt.connect('mqtt://localhost:1883');client.on('connect', function () { console.log('>>> connected'); client.subscribe('/temperature');})client.on('message', function (topic, message) { var temperature = parseInt(message.toString()); var data = {temperature}; if (temperature >= 60) { data.tips = "熱... 500服務器故障"; } else if (temperature >= 50) { data.tips = "今天天氣非常熱,建議不要穿衣服了"; } else if (temperature >= 40) { data.tips = "今天天氣十分的熱,建議穿短袖T恤+短褲"; } else if (temperature >= 30) { data.tips = "今天天氣有點的熱,建議穿短袖T恤"; } else if (temperature >= 0) { data.tips = "今天天氣正好,可以穿上一件薄衣服"; } else if (temperature >= -10) { data.tips = "今天天氣十分寒冷,棉襖可以穿上一件"; } else { data.tips = "今天天氣十分十分寒冷,棉襖可以穿上二件"; } client.publish('/tips', JSON.stringify(data)); // if (temperature+1) {} // message is Buffer console.log(JSON.stringify(data));})
App 的實現
Demo 的 App 使用 KOA 啟動一個 Web,在 Web 中展現當前溫度對應的穿衣提示,通過訂閱 tips 獲取數據。
安裝 koa
$ npm install koa
實現代碼
'use strict'const Koa = require('koa');const mqtt = require('mqtt');const app = new Koa();var msg = {temperature:"-",tips:""};// responseapp.use(ctx => { ctx.body = "當前溫度:" + msg.temperature + "度" + "\n" + '穿衣提示:'+msg.tips + "\n" ;});app.listen(3000);//mqttvar client = mqtt.connect('mqtt://localhost:1883');client.on('connect', function () { console.log('>>> connected'); client.subscribe('/tips');})client.on('message', function (topic, message) { var data = JSON.parse(message.toString()); console.log(message.toString()); console.log(data.tips); msg = data; // if (temperature+1) {} // message is Buffer // let str = message.toString(); // let data = JSON.parse(message); // console.log(data.tips); // msg = message.toString();})
Demo 小節
本章給出了一個簡單的物聯網業務的業務場景和實現邏輯,其中 Client 也可以運行在電腦上進行 Demo 查看,或是跑在真實物聯設備或開發版上。如圖5,筆者使用 RUFF 開發板實現了一次。
完整 Demo 代碼已經分享在 github 中,大家可以輸入 URL 下載。
https://github.com/coolnameismy/javascript-mqtt-demo-wearingTip
圖5 Demo 硬件演示
總結
本文和大家交流了物聯網應用的一般數據鏈路、MQTT 協議的架構,并基于 MQTT 實現了一個簡單的物聯網應用。現在正是前端工程師的大好機會,越來越多的嵌入式設備都開始支持 JavaScript,原因是現在有很多 JavaScript 引擎可以把 JavaScript 轉換成各種平臺的底層代碼,比較有名的有 Jerryscript、Duktape 等。隨著越來越多的 JavaScript 工程師進入嵌入式開發的領域,嵌入式應用開發也會出現前后端分離的情況(應用開發或是驅動開發),類似于 Web 開發的前后端分離。前端關注在應用、創意、數據鏈路、用戶體現上,而后端則關心 GPIO、I2C 的底層數據接口和驅動,平臺兼容性等方向。
游歷 JavaScript IoT 應用開發平臺
使用 Python 進行物聯網端到端原型開發
管中窺豹:一線工程師看 MQTT
物聯網安全與實戰
未來物聯網全棧開發 JavaScript or Python?
IoT 通訊技術選型及模型設計的思考
微軟百度阿里三大物聯網云平臺探析
如何基于 Android Things 構建一個智能家居系統?
淺析物聯網應用層協議 CoAP
藍牙 Mesh 技術初探
---------------------
作者:GitChat的博客
來源:CSDN
原文:https://blog.csdn.net/valada/article/details/79910133
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
藝之都網絡公司轉載!致敬作者辛苦編寫!