物聯網開發技術棧

GitChat的部落格發表於2018-04-12

內容簡介

作為網際網路技術的進化,物聯網開發並非孤立的技術棧,而是向上承接了網際網路,向下統領了嵌入式硬體開發的一個承上啟下的全棧開發技術。

雖然我們並不能預測物聯網技術棧最終的樣子:統一的開發語言是 JavaScript 還是 Python 亦或者其他程式語言;HTTP、WebSockets、MQTT、CoAP 等協議誰會是最後的贏家,並且隨著物聯網的不斷進化,甚至我們可能都無法預測其最終形態,也許根本就沒有一個最終的形態。但是,我們仍然可以看清物聯網發展的軌跡與必然趨勢——開發技術棧必然向全棧化方向發展。

網際網路的核心是資料的流動,資料的流動為我們帶來了難以想象的價值,而物聯網又將這一核心推到了更高的高度,打破了網際網路原有的邊界讓千千萬萬節點裝置中的資料流動了起來。全棧化的開發正是順應了這種趨勢,打破了在開發層面中那些阻礙資料流動的技術壁壘,將晶片、嵌入式、網路、大資料、人工智慧、資訊保安等諸多領域納入到物聯網的全棧開發中來,實現端到端的完整解決方案,真正實現資料的流動並讓資料為人類服務,讓我們以更高效更智慧的方式來發掘資料的價值,實現資料的價值。

本書內容

物聯網技術現狀與新可能

文/羅未

不管是從商業模式匯出的業務模型,還是從技術發展的角度看,文字都傾向於將物聯網技術構架看作是網際網路技術構架的延展。而與這個觀念對立的,是傳統嵌入式軟體開發的視角。

在網際網路技術基礎上長出來的物聯網構架

簡單來說,目前的網際網路技術構架主流是大前端與後端兩個世界:大前端包括 Web 的 JavaScript 技術、Android 和 iOS 技術,著眼於解決使用者互動;後端包括資料庫、服務構架、運維等,著眼於解決儲存、業務邏輯、安全與效率等。當然,現在前後端技術爭相更新,比如業務邏輯前置化、微服務構架、JavaScript 全棧化等新的解決方案也開始模糊前後端的差異。而物聯網裝置端的引入,著實讓這些技術有點難以歸類,從業務性質上物聯網是另外一種前端或是前端的延伸,比如共享單車應用中,自行車端的應用顯然是跟人互動的另一個業務場景,也在為後端源源不斷地提供著資料,但是自行車又不像網頁或者 App 完全是在解決視覺化 UI 的事情。而且,現在的裝置端開發技術跟前端技術太不像了,由於目前裝置端的開發技術都還偏底層,一般來說計算資源如處理能力、本地儲存都非常有限,反而像後端一樣要考慮資源效率。

那麼,我們只好為物聯網單獨命名一個端,不如我們暫時就叫它裝置端。

圖1  整體架構圖

圖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 份額並不大,各種實時作業系統各具特色,各有一片天地。

簡單總結一下相對於物聯網開發,傳統嵌入式開發的方式主要有以下幾個問題:

  1. 需要考慮中斷、暫存器、記憶體分配等過於底層的工作;
  2. 編譯、燒寫、觀察、藉助除錯裝置進行除錯的開發生命週期;
  3. 不同 SoC 和系統的差異過大;
  4. 缺乏程式碼複用與開源的習慣;
  5. 開發者在開發環境和韌體編譯上花費的時間過多。

所以我們看到裝置端的開發是基於晶片選型完成的。當裝置端產品面臨一個需求時,現有的流程是判斷產品的各項技術引數,從而確定一個晶片,進而使用這個晶片的一整套開發技術。這也是早期嵌入式場景使用的晶片自生技術特性所決定:計算資源(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物聯網作業系統

圖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 語言的流行,及物聯網領域的崛起,我們能看到它們結合的可能性,同時也發現它特別適合於物聯網開發。因此,在這篇文章裡,筆者將主要從以下三個方面進行介紹:

  1. 典型的物聯網架構,及多種語言帶來的問題;
  2. 只使用 JavaScript 語言的物聯網架構;
  3. 詳解基於 JavaScript 語言的物聯網不同層級結構。

那麼,先讓我們看看典型的物聯網架構是怎樣的吧。

典型的物聯網架構

我們甚至還可以認為,物聯網只是對網際網路的擴充套件。與傳統的 C/S 架構相比,它多了一個“資料採集層”,我們稱之為感測器層、硬體層等。資料的產出不再只是使用者,還來自於各式各樣的聯網裝置。物聯網不再侷限於使用 HTTP 協議來傳輸資料,它還會使用 CoAP(受限制的應用協議)、MQTT(訊息佇列遙測傳輸)協議。

物聯網的四個層級

當前的物聯網應用,所要做的就是控制和資料處理。指令,由使用者到終端一層一層往下下達,直到硬體端由裝置去執行。而資料,便是一層一層往上上報,直至被視覺化。

因此,與網際網路的架構相比(如圖1、圖2所示),起點與終點不一樣了:指令的終點與資料的起點,變成了硬體層,而非最後的使用者層。

圖1  網際網路架構

圖1 網際網路架構

圖2  典型的物聯網架構

圖2 典型的物聯網架構

資料由客戶端 A 傳送到服務端,客戶端 B 再從服務端獲取 A 的資料,如此便算是完成了一個迴路。而物聯網架構則稍微麻煩了一些,多了一個層級,便多了一個步驟。

硬體層上的微控制器通過直連的方式,採集各式各樣的資料,比如溫度、溼度等。而受限於微控制器的成本、環境條件等因素,它可能無法直接連線到網際網路。因此,需要連線到一些額外的聯網裝置才能實現。

而這些聯網裝置,會負責處理來自各個硬體裝置的資料,並將其上傳至伺服器。同時,它會提供一個無線(如藍芽、紅外、ZigBee)介面作為資料的入口。因此,這一層級需要有更好的資料處理能力,並且它應該要可以快速開發。因為這些裝置主要做的是協調工作,我們習慣於將其稱為“協調層”。

使用多種語言的物聯網

多年以前,筆者曾做過一個並不複雜的物聯網系統:

  1. 使用 Python 裡的 Django 作為 Web 服務框架,Django REST Framework 建立 RESTful API;
  2. 為了使用手機作為控制器,還用 Java 寫一個 Android 應用;
  3. 使用 Raspberry Pi 作為硬體端的協調層,用於連線網路,並傳輸控制訊號給硬體;
  4. 在硬體端使用 Arduino 作為控制器,寫起程式碼特別簡單;
  5. 還使用了 ZigBee 模組 XBee 及 I2C 作為連線不同 Arduino 模組的介質;
  6. 最後,還需在網頁上做一個圖表來顯示實時資料。

為此,我們需要使用 Python、Java、JavaScript、C、Arduino 五種語言。而如果我們要寫相應的 iOS 應用,還要用到 Objective-C。對於其他物聯網專案來說,也多是如此,這簡直是一場災難。

在做這樣的物聯網專案之前,我們需要找到六個不同型別的工程師:一個硬體工程師設計電路圖,一個懂硬體的嵌入式工程師,一個寫服務端應用的工程師,一個寫 Web 前端的工程師,以及對應的 Android 和 iOS 工程師。

且不考慮系統本身的協作,要找到這麼多的工程師就不是一件容易的事。而如果我們可以只使用一種語言,將大大地改善開發效率、開發人員的難題。

JavaScript 語言下的物聯網架構

JavaScript 語言在最近幾年裡特別流行,它流行起來有很多個原因,如:

  1. 使用 WebView 開發 UI 效率更高,也因此使得WebView 隨處可見;
  2. 基於事件驅動的程式設計模型;
  3. JavaScript 容易上手(這是優點,也是缺點);
  4. 也因此,React、Unity 等框架提供了更多的可能性,可以讓開發者用 JavaScript 開發遊戲、VR 應用等等。

那麼,只使用 JavaScript,我們可以設計出怎樣的物聯網系統呢?

基於純 JavaScript 的物聯網架構

如上所述,幾年前要想尋找一門能完成一個包含客戶端、服務端的系統的語言可謂相當地困難。而隨著客戶端(瀏覽器、移動裝置)效能的提升、Node.js 的出現,這樣的語言就浮現了出來,即 JavaScript。它不僅可以讓我們只用一門語言來降低開發成本,還能實現快速地開發出這樣的一個系統。那麼,剩下的問題就是,在不同的層級,如何選用合適的框架來實現快速開發。

如圖3所示,我們可以看到不同層級的可選用 JavaScript 方案。在此之中,有些純粹只是為了證明 JavaScript 是可行的;有一些則可以在開發效率與執行速率上達到最好的平衡。選用這些方案,可以讓我們實現更快速的 JavaScript 物聯網應用開發。

圖3  基於純JavaScript的物聯網參考架構

圖3 基於純 JavaScript 的物聯網參考架構

服務層

對於服務層來說,自主開發的物聯網服務端,主要採用的是基於 Node.js 的方案。然而,我們發現有越來越多的應用,在使用 Serverless 的架構,不僅可以快速推出一個可用的原型,未來也能夠輕鬆地基於這個原型來新增業務功能。

圖4  物聯網服務層

圖4 物聯網服務層

圖4便是我們看到的物聯網服務層的三種方案:

  1. 自主開發:即遵循傳統的服務端開發模式,定義自己所需要的功能;
  2. 使用雲服務:直接使用成熟的物聯網雲服務,它們在雲端整合了各種所需要的功能;
  3. Serverless:Server 可以看作是在雲服務之上的自主開發,集兩者之便利。每一種方案都有各自的特點,也適合於不同開發能力的專案。但如果要實現快速的開發,那麼理想的方式便是採用 Serverless 架構模式。

自主開發

出於不同的原因,諸如保密、安全、可擴充套件、核心技術等原因,一定規模的公司會採用自主開發的方式。這種開發方式與 Web 應用開發方式並沒有太大區別,都是在資料進行 CRUD 操作。並且和前後端分離架構一樣,使用 API 作為介面,同時再加上支援不同的傳輸協議,如 MQTT、CoAP 等。

圖5  Lan物聯網架構

圖5 Lan 物聯網架構

如筆者之前在 GitHub 上開源的 Lan(https://github.com/phodal/lan),便是一個精簡的物聯網服務端示例。基於 Node.js 與 MongoDB,其架構如圖5所示。

  1. 採用傳統的關係型資料庫來儲存使用者資訊;
  2. 採用 NoSQL 可以應對不同的感測器資料;
  3. 提供 UI 介面供管理人員管理使用者;
  4. 在協議上提供 HTTP、CoAP、MQTT、WebSocket 等的支援,方便不同的型別適配。

除此,物聯網系統在儲存上,採用 NoSQL 作為儲存介質會有更大的優勢。一般來說,物聯網系統的資料都是寫入遠遠多於讀取的場景。與此同時,由於裝置的種類繁多,不可能為每一類裝置建立表;或者考慮到大量裝置的特性,來建立一個通用的表,但在未來這樣的表可能仍不適用。

因此,對於物聯網資料來說,選用諸如 MongoDB 這一類的 NoSQL 資料庫,有這麼一些優點:

  1. 靈活性。採用非結構化的資料模型,可以儲存和處理任何結構的資料;
  2. 支援水平擴充套件。NoSQL 資料庫的分散式儲存架構,帶來了優秀的水平擴充套件性;
  3. 實時資料分析。如 MongoDB 可以通過豐富的索引和查詢支援,包括二次、地理空間和文字搜尋索引,聚合框架和本地 MapReduce,可以針對感測器資料就地執行報告分析。

然而,這樣的系統不免存在研發週期長的問題。如果需要快速驗證,那麼應該考慮使用雲服務來完成部分功能。

物聯網雲服務

對於硬體團隊來說,直接使用雲服務是一種更簡單、快速的搭建物聯網系統的方法。而使用物聯網雲服務,就意味著:我們可以直接上硬體層的感測器資料,並在應用層獲取、分析這些資料。這一類的服務,比較成熟的有 AWS IoT Things(如圖6所示)、Azure IoT 等。

圖6  AWS IoT Things參考架構

圖6 AWS IoT Things 參考架構

基於 AWS IoT Things,我們只需要在雲端,定義好對應的資料處理規則,便可以在硬體端直接對接服務。不過值得注意的是,單一的雲服務無法提供複雜的功能,這個時候就需要一些搭配額外的服務。

Serverless

Serverless 架構(如圖7所示)是雲服務的一種,但是它在可程式設計與雲服務之間做了一個折中。它是一種基於網際網路的技術架構理念,應用邏輯並非全部在服務端實現,而是採用 FaaS(Function as a Service)架構,通過功能組合來實現應用程式邏輯。

圖7  Serverless 物聯網參考架構

圖7 Serverless 物聯網參考架構

從理論上來講,這些服務提供的是一層 API 封裝,它不會限制我們所使用的語言。使用 Serverless 服務,我們可以具備更好的快速開發能力,並且能使用同一種語言(JavaScript)來完成程式設計。

在這個過程中,開發者要所做的便是:在不同的服務之間傳輸資料,每一次都只處理下一個服務所需要的資料,類似於 Pipe and Filters 架構模式。如一個典型的物聯網應用的資料傳輸過程中是這樣的:

  1. 對裝置進行鑑權;
  2. 轉換、儲存裝置的資料;
  3. 廣播通知其他監聽此裝置資料的服務;
  4. 後臺查詢資料;
  5. 分析資料(AI);
  6. 視覺化資料。

只需要少量的程式設計,我們就可以完成服務端的開發。隨後,專注於硬體層的開發,以及應用層的業務功能。

應用層

在應用層方面,已經有大量的地方使用到了 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  物聯網協調層

圖8 物聯網協調層

這一類應用,依賴於 Node.js 引擎來實現快速開發。它可以執行在帶有嵌入式系統的開發板上,如流行的 Raspberry Pi、OpenWRT 路由器等。

我們只需要一個執行嵌入式 Linux 系統的開發板,就可以完成這樣的工作。與此同時,主流的 ARM 開發板都提供相應的 Linux 移植,因此在這個層級,我們也只需要關注於業務的實現。

小結

如上所述,物聯網應用的架構與 Web 應用的架構區別並不是太大,只是在這上面做一系列的演進。除了上面提到的一系列快速實踐框架,當前在 Web 開發中流行的一些開發思想,勢必也會引導到物聯網系統中:

  1. 微服務化;
  2. DevOps;
  3. 容器化。

物聯網會吸引網際網路的優秀開發思想,並演進出更優秀的架構。

使用 JavaScript 和 MQTT 開發物聯網應用

文/劉彥瑋

如果說 Java 和 C# 哪個是最好的開發語言,無疑會挑起程式設計師之間的相互怒懟,那如果說 JavaScript 是動態性最好的語言,相信大家都不會有太大的爭議。隨著越來越多的硬體平臺和開發板開始支援J avaScript,JavaScript 在硬體端以及物聯網領域有了新的機會。

IoT 應用開發的資料鏈路

圖1是一個智慧家居物聯平臺的資料鏈路。

圖1  智慧家居物聯平臺的資料鏈路

圖1 智慧家居物聯平臺的資料鏈路

一般來說,可以把 IoT 應用分為如圖所示的四層。

  1. client 層:指的是 IoT 裝置,可以是冰箱、空調,也可以是一些溫溼度感測器。
  2. gateway 層:大多數場景中 gateway 是家裡的 WiFi 路由器,也有小部分是基於 Zigbee 或藍芽的閘道器裝置。智慧生活場景中的 gateway 數量相對於工業領域要少很多,在工業領域存在大量的邊緣計算放在 gateway 層進行處理(霧計算)。
  3. cloud 雲層:這裡是集中處理業務的地方。
  4. 應用層:這一層是直接與使用者打交道的地方,可以是通過電腦的 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的資料鏈路圖

圖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架構中常用的框架

圖3 JavaScript 在 MQTT 架構中常用的框架

實戰物聯網應用

這節我們運用之前介紹的框架,自己動手完成一個簡單的物聯網應用。應用場景如圖4所示,溫度感測器用於接收溫度,並把文件通過 MQTT 傳送到 Server 端,在 Server 端進行業務處理,根據溫度計算出穿衣提示,通過 MQTT 把資料傳送到特定的 Topic,App 訂閱 Topic 獲取資料後進行展現。

圖4  “穿衣提示”業務場景框架

圖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硬體演示

圖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 技術初探

閱讀全文: http://gitbook.cn/gitchat/geekbook/5a62a6755418822a9fb0c246

相關文章