戰(zhàn):從PaaS到SaaS的物聯(lián)網(wǎng)應(yīng)用開(kāi)發(fā)新捷徑)
前陣子整理項(xiàng)目筆記翻出當(dāng)年帶著小團(tuán)隊(duì)做設(shè)備遠(yuǎn)程運(yùn)維的方案文檔。當(dāng)時(shí)為了給客戶展示一個(gè)能看設(shè)備狀態(tài)、能收回遙測(cè)、能發(fā)告警的演示環(huán)境我先用 IoTHub 搭數(shù)據(jù)鏈路然后又自己寫(xiě) Web 管理界面、用戶權(quán)限、看板前后折騰了兩周。后來(lái)我換成 IoT Central一個(gè)下午就把能演示的原型跑通了。這件事給我的印象很深所以當(dāng)它宣布公開(kāi)預(yù)覽Public Preview的時(shí)候我?guī)缀跏堑谝粫r(shí)間去注冊(cè)了一個(gè)試用實(shí)例。很多人聽(tīng)到“IoT Central”第一反應(yīng)是這不就是把 IoTHub 包了一層殼嗎實(shí)際用完會(huì)知道它更像是直接從“平臺(tái)”跳躍到了“應(yīng)用”而且這個(gè)定位差異恰恰是它最有價(jià)值的地方。這篇文章會(huì)圍繞 IoT Central 公開(kāi)預(yù)覽階段的實(shí)際使用體驗(yàn)展開(kāi)重點(diǎn)講清楚它解決了什么問(wèn)題、核心模型長(zhǎng)什么樣、怎么從零跑通一個(gè)應(yīng)用以及我在實(shí)操中踩過(guò)和排查過(guò)的坑。如果你正在做物聯(lián)網(wǎng)項(xiàng)目選型或者準(zhǔn)備給客戶做設(shè)備接入類(lèi) PoC這篇文章值得你花十分鐘讀完。1. 為什么微軟要做 IoT CentralSaaS 化 IoT 平臺(tái)到底解決什么痛點(diǎn)1.1 從自建 IoTHub 到 SaaS兩周的項(xiàng)目被壓成一個(gè)下午先說(shuō)一個(gè)很現(xiàn)實(shí)的現(xiàn)象。很多團(tuán)隊(duì)做物聯(lián)網(wǎng)項(xiàng)目最早的切入點(diǎn)都是 IoTHub 或類(lèi)似的消息接入服務(wù)因?yàn)樵O(shè)備數(shù)據(jù)總得有個(gè)地方收。但 IoTHub 本質(zhì)上是一個(gè) PaaS 層的消息管道它只管設(shè)備接入、消息收發(fā)、認(rèn)證鑒權(quán)這些底層能力。設(shè)備數(shù)據(jù)進(jìn)來(lái)之后你要做的大頭活兒一件都沒(méi)少搭一個(gè)后端服務(wù)負(fù)責(zé)把設(shè)備上報(bào)的數(shù)據(jù)落庫(kù)還要處理設(shè)備在線狀態(tài)。寫(xiě)一套設(shè)備管理界面至少能看設(shè)備列表、設(shè)備詳情、歷史數(shù)據(jù)。做一個(gè)規(guī)則引擎比如溫度超過(guò)閾值要告警光照異常要提醒。再配一套用戶權(quán)限系統(tǒng)讓不同角色看到不同的頁(yè)面。最后還得接消息通知郵件、短信、Webhook 都要考慮。這些工作如果全部自己寫(xiě)兩周是樂(lè)觀估計(jì)。我當(dāng)年那個(gè)項(xiàng)目光是把設(shè)備列表頁(yè)做得“能見(jiàn)人”就花了一星期更別提規(guī)則引擎的輪詢邏輯和告警去重了。IoT Central 的做法是把上面這些“應(yīng)用層”能力直接內(nèi)置成一個(gè) SaaS 服務(wù)。你用瀏覽器登錄進(jìn)去創(chuàng)建應(yīng)用、定義設(shè)備模板、拖拽儀表板、配置規(guī)則一個(gè)可運(yùn)行的物聯(lián)網(wǎng)應(yīng)用外殼就出來(lái)了。感受上就像是買(mǎi)了一套帶精裝修的房子不用再自己從毛坯開(kāi)始砌墻、拉電線、鋪水管。當(dāng)然這不是說(shuō) IoTHub 沒(méi)有價(jià)值。對(duì)于設(shè)備量大、業(yè)務(wù)邏輯復(fù)雜、需要自定義協(xié)議的團(tuán)隊(duì)IoTHub 依然是更靈活的底座。但如果你只是想把一個(gè)設(shè)備接入加監(jiān)控告警的閉環(huán)快速跑起來(lái)IoT Central 的性價(jià)比明顯高得多。1.2 IoT Central 和 IoTHub 的定位差異不是升級(jí)而是不同物種我在公開(kāi)預(yù)覽階段幫朋友做過(guò)一次選型對(duì)比當(dāng)時(shí)用一張表把幾個(gè)關(guān)鍵維度拉出來(lái)看結(jié)論就很清晰了對(duì)比維度IoT CentralAzure IoT Hub完全自建交付模式SaaS 托管應(yīng)用PaaS 消息服務(wù)自建服務(wù)器 自研組件物模型抽象內(nèi)置設(shè)備模板機(jī)制需自行設(shè)計(jì)完全自研管理后臺(tái)/UI內(nèi)置可直接用不包含需自研自研規(guī)則與告警內(nèi)置規(guī)則引擎需通過(guò) Functions 等集成自研用戶與角色權(quán)限內(nèi)置應(yīng)用級(jí)管理需自建自研多租戶/多項(xiàng)目隔離支持多應(yīng)用需手動(dòng)規(guī)劃 Hub 與分組自研按設(shè)備接入與消息計(jì)費(fèi)有且含平臺(tái)能力按消息量和設(shè)備數(shù)計(jì)費(fèi)按服務(wù)器成本估算適合階段PoC、中小規(guī)模、標(biāo)準(zhǔn)化業(yè)務(wù)大規(guī)模、深度定制極高定制或私有化要求這張表的核心邏輯其實(shí)很簡(jiǎn)單IoTHub 給你的是發(fā)動(dòng)機(jī)和底盤(pán)IoT Central 給你的是可以直接開(kāi)上路的整車(chē)。選錯(cuò)類(lèi)型的代價(jià)很大我見(jiàn)過(guò)有團(tuán)隊(duì)用 IoTHub 硬懟一個(gè)“設(shè)備演示管理平臺(tái)”結(jié)果發(fā)現(xiàn)權(quán)限、看板、告警這些模塊每個(gè)都要自己造最后工期翻了一倍不止。反過(guò)來(lái)如果團(tuán)隊(duì)已經(jīng)積累了設(shè)備影子、OTA、批量配置等復(fù)雜邏輯硬套 IoT Central 反而會(huì)被模板模型束縛住。1.3 公開(kāi)預(yù)覽階段的核心玩法模板化加低代碼公開(kāi)預(yù)覽版本里IoT Central 最打動(dòng)我的一點(diǎn)就是“模板化”的屬性。微軟在應(yīng)用里預(yù)置了一批參考模板覆蓋互聯(lián)物流、建筑物自動(dòng)化、能耗監(jiān)控、醫(yī)療設(shè)備監(jiān)測(cè)等場(chǎng)景。你可以直接基于這些模板復(fù)制出一個(gè)應(yīng)用再改設(shè)備模型和界面。這里要特別強(qiáng)調(diào)一下這些模板不是簡(jiǎn)單的“代碼腳手架”而是把物聯(lián)網(wǎng)應(yīng)用的組織方式都搭好了。比如物流模板里設(shè)備模板已經(jīng)幫你定義好定位信息、溫度傳感器、加速度計(jì)等常見(jiàn)字段儀表板也預(yù)設(shè)了地圖、溫度趨勢(shì)、設(shè)備狀態(tài)卡片。你只需要在模板上增刪字段而不是從零搭建整個(gè)數(shù)據(jù)結(jié)構(gòu)。低代碼主要體現(xiàn)在三塊設(shè)備模板用界面化配置定義字段儀表板用拖拽方式添加圖表規(guī)則引擎用條件配置生成觸發(fā)邏輯。整個(gè)過(guò)程不需要寫(xiě)前后端代碼業(yè)務(wù)人員經(jīng)過(guò)短暫培訓(xùn)也能上手。公開(kāi)預(yù)覽階段我見(jiàn)過(guò)不少 SI系統(tǒng)集成商合作伙伴用這套東西給客戶做快速演示效果很好因?yàn)椤澳芸茨茳c(diǎn)”的原型比 PPT 有說(shuō)服力得多。2. 設(shè)備模板、規(guī)則引擎、儀表板這三大核心模型怎么用2.1 設(shè)備模板給設(shè)備寫(xiě)的“數(shù)字簡(jiǎn)歷”設(shè)備模板是 IoT Central 里最核心的概念沒(méi)有之一。你可以把它理解成給設(shè)備類(lèi)型寫(xiě)的一份“數(shù)字簡(jiǎn)歷”規(guī)定了一類(lèi)設(shè)備到底有哪些 Telemetry遙測(cè)數(shù)據(jù)、Properties屬性、Commands命令需要被管理。Telemetry 是設(shè)備主動(dòng)上報(bào)的數(shù)據(jù)比如溫度、濕度、電壓、GPS 坐標(biāo)。它是一條連續(xù)的、帶時(shí)間戳的數(shù)據(jù)流適合展示在趨勢(shì)圖上做實(shí)時(shí)監(jiān)控。Properties 代表設(shè)備的配置或狀態(tài)又分只讀和可寫(xiě)。只讀屬性比如固件版本、設(shè)備型號(hào)可寫(xiě)屬性比如上報(bào)周期、目標(biāo)溫度閾值平臺(tái)可以把用戶修改的值下發(fā)到設(shè)備。Commands 是平臺(tái)可以叫設(shè)備執(zhí)行的命令比如遠(yuǎn)程重啟、打開(kāi)繼電器、開(kāi)始固件升級(jí)。設(shè)備需要實(shí)現(xiàn)對(duì)應(yīng)的命令處理邏輯。一個(gè)設(shè)備模板定義得好不好直接決定后面所有功能好不好用。我在實(shí)際操作中發(fā)現(xiàn)定義字段的時(shí)候就要把單位寫(xiě)清楚比如溫度用攝氏度還是華氏度濕度是百分比還是小數(shù)。IoT Central 的 UI 里允許設(shè)置顯示單位和顯示名但這只是展示層面的轉(zhuǎn)換原始 JSON 數(shù)據(jù)里傳什么值還是什么值。如果你在設(shè)備端已經(jīng)用了“30.5”這種數(shù)值模板里最好把語(yǔ)義標(biāo)注準(zhǔn)確否則后續(xù)做規(guī)則和導(dǎo)出的時(shí)候很容易被單位繞暈。還有一點(diǎn)值得注意設(shè)備模板是可以“版本化”的。你在草稿狀態(tài)改模板不影響在線設(shè)備只有發(fā)布新版本并顯式遷移設(shè)備設(shè)備才會(huì)用新模型。這個(gè)設(shè)計(jì)我在實(shí)際項(xiàng)目里覺(jué)得非常關(guān)鍵因?yàn)槲锫?lián)網(wǎng)設(shè)備是分布式的不可能像 Web 前端一樣一刀切升級(jí)。舊設(shè)備繼續(xù)用舊版本模型新設(shè)備用新版本模型是 IoT 場(chǎng)景里經(jīng)常要面對(duì)的現(xiàn)實(shí)。2.2 規(guī)則引擎不止是發(fā)個(gè)郵件通知很多人看到“規(guī)則引擎”就以為是閾值告警實(shí)際用起來(lái)才發(fā)現(xiàn)它更像一個(gè)“條件-動(dòng)作”的自動(dòng)化框架。它能夠?qū)崟r(shí)分析設(shè)備上報(bào)的遙測(cè)數(shù)據(jù)也能感知設(shè)備上下線、屬性變化等情況然后觸發(fā)對(duì)應(yīng)的動(dòng)作。從動(dòng)作類(lèi)型上看公開(kāi)預(yù)覽階段常用的有發(fā)送郵件、推送 Webhook、調(diào)用 Azure Functions、通過(guò) Power Automate 再做二次編排。我第一次用的時(shí)候只配了郵件告警后來(lái)發(fā)現(xiàn) Webhook 才是最實(shí)用的。把 Webhook 接到企業(yè)微信或者釘釘機(jī)器人上設(shè)備告警能直接推到群里比郵件及時(shí)得多。規(guī)則條件里有一個(gè)隱藏很深的“時(shí)間聚合”設(shè)置我一開(kāi)始沒(méi)注意就踩了坑。你在配置溫度告警的時(shí)候可以選擇在“過(guò)去 5 分鐘平均值 45°C”或者“任意采樣值 45°C”之間做選擇。前者是聚合窗口后者是瞬時(shí)值。如果選的是聚合窗口規(guī)則不會(huì)在你第一次超過(guò)閾值時(shí)就觸發(fā)而是要等窗口期內(nèi)的數(shù)據(jù)滿足條件才觸發(fā)。這個(gè)機(jī)制能有效減少抖動(dòng)和誤報(bào)但也意味著規(guī)則觸發(fā)有延遲。我在測(cè)試環(huán)境調(diào)規(guī)則時(shí)常常因?yàn)椤霸趺催€不觸發(fā)”而懷疑規(guī)則壞了后來(lái)才意識(shí)到是窗口還沒(méi)結(jié)束。我自己的經(jīng)驗(yàn)是高頻遙測(cè)比如每 10 秒上報(bào)一次用 2 到 5 分鐘的聚合窗口比較合理低頻遙測(cè)比如每小時(shí)上報(bào)一次就不要用聚合窗口了直接采用單次閾值判斷這樣告警才及時(shí)。2.3 儀表板與多角色視角讓非技術(shù)人員也能看設(shè)備儀表板是 IoT Central 里最直觀的一層。公開(kāi)預(yù)覽階段儀表板默認(rèn)支持卡片、折線圖、條形圖、地圖、KPI 值等可視化組件。你可以拖拽生成一個(gè)“運(yùn)營(yíng)大屏”把設(shè)備在線率、關(guān)鍵遙測(cè)、告警數(shù)量放在一屏里。比較容易被忽略的是角色權(quán)限和儀表板之間的關(guān)系。IoT Central 內(nèi)置了管理員、操作員、開(kāi)發(fā)者等角色不同角色登錄后看到的內(nèi)容不一樣。管理員可以修改應(yīng)用配置開(kāi)發(fā)者可以編輯設(shè)備模板操作員只能看儀表板和設(shè)備列表、處理告警。這種應(yīng)用級(jí)的多角色權(quán)限對(duì)客戶交付特別有用。我之前做項(xiàng)目時(shí)給客戶的管理層開(kāi)一個(gè)“只讀儀表板”賬號(hào)給現(xiàn)場(chǎng)工程師開(kāi)一個(gè)“可操作設(shè)備命令”的賬號(hào)兩邊不需要互相干擾也避免了誤操作風(fēng)險(xiǎn)。儀表板組件綁定的是設(shè)備組或設(shè)備模板。要注意的是如果設(shè)備模板發(fā)布了新版本而儀表板還引用舊版本的數(shù)據(jù)源部分圖表可能顯示空白。排查的時(shí)候先看看組件綁定的設(shè)備模板版本和實(shí)際設(shè)備使用的是否一致這個(gè)坑比較隱蔽。2.4 數(shù)據(jù)導(dǎo)出平臺(tái)只做中轉(zhuǎn)數(shù)據(jù)資產(chǎn)還是你的IoT Central 本身帶有數(shù)據(jù)保留和展示能力但一般也就是近期的熱數(shù)據(jù)。公開(kāi)預(yù)覽階段官方就提供了持續(xù)數(shù)據(jù)導(dǎo)出Continuous Data Export能力可以把遙測(cè)、屬性、設(shè)備生命周期事件導(dǎo)出到 Blob Storage、Data Lake Storage Gen2、Event Hubs、Service Bus 和 Azure Data Explorer。這里我強(qiáng)烈建議任何生產(chǎn)級(jí)項(xiàng)目都要配置數(shù)據(jù)導(dǎo)出原因有三個(gè)平臺(tái)的數(shù)據(jù)保留策略不等于你的數(shù)據(jù)倉(cāng)庫(kù)你無(wú)法在平臺(tái)里跑任意復(fù)雜的分析。設(shè)備數(shù)據(jù)一旦多了查歷史數(shù)據(jù)會(huì)很慢導(dǎo)出到自己的存儲(chǔ)里用 SQL 或 Spark 分析更順手。你要做機(jī)器學(xué)習(xí)訓(xùn)練或者和業(yè)務(wù)系統(tǒng)打通數(shù)據(jù)最終必須在自己的數(shù)據(jù)管道里。實(shí)際配置導(dǎo)出的時(shí)候建議把 JSON 的原始消息體一起落下來(lái)不要只導(dǎo)平臺(tái)解析后的字段。因?yàn)樵枷Ⅲw里可能帶著平臺(tái)暫時(shí)不認(rèn)識(shí)的擴(kuò)展字段保留完整原始數(shù)據(jù)以后想回溯分析才有余地。3. 從 0 到 1 跑通一個(gè) IoT Central 應(yīng)用完整實(shí)操記錄3.1 創(chuàng)建應(yīng)用與選模板別小看這一步公開(kāi)預(yù)覽階段創(chuàng)建應(yīng)用入口在 Azure 門(mén)戶的“IoT Central Applications”或直接訪問(wèn)官方 IoT Central 入口。創(chuàng)建時(shí)需要填應(yīng)用名稱、URL 前綴、區(qū)域和計(jì)費(fèi)計(jì)劃。我第一次創(chuàng)建時(shí)選模板很隨意想著后續(xù)都可以改結(jié)果發(fā)現(xiàn)應(yīng)用模板雖然可以遷移但初始數(shù)據(jù)模型和一些預(yù)置規(guī)則都要自己清理反而更麻煩。我的建議是先想清楚你當(dāng)前項(xiàng)目最接近哪個(gè)場(chǎng)景比如是設(shè)備監(jiān)控、物流跟蹤還是能耗管理直接選最貼近的那個(gè)模板。這樣一開(kāi)始就有可用的設(shè)備模板和儀表板省掉不少冷啟動(dòng)時(shí)間。另一個(gè)需要注意的點(diǎn)是計(jì)費(fèi)計(jì)劃。公開(kāi)預(yù)覽階段一般有免費(fèi)試用和標(biāo)準(zhǔn)計(jì)劃之分。我用的是試用計(jì)劃設(shè)備數(shù)量和消息量都有限制對(duì) PoC 完全夠用。但如果你要給客戶做演示最好提前確認(rèn)演示設(shè)備數(shù)量和演示時(shí)長(zhǎng)不會(huì)撞到免費(fèi)額度上限否則數(shù)據(jù)突然被截?cái)鄷?huì)很尷尬。3.2 定義設(shè)備模板用模擬設(shè)備先跑通閉環(huán)創(chuàng)建完應(yīng)用后我到“Device templates”里新建了一個(gè)“環(huán)境監(jiān)測(cè)箱”模板。這個(gè)模板我定義了Telemetrytemperaturedouble單位 °C、humiditydouble單位 %、co2integer單位 ppm。PropertiesfirmwareVersion只讀字符串、samplingRate可寫(xiě)整數(shù)表示上報(bào)周期。Commandsreboot()用于遠(yuǎn)程重啟檢測(cè)箱。字段定義完成以后點(diǎn)擊“Add simulated device”添加一個(gè)模擬設(shè)備平臺(tái)就會(huì)自動(dòng)生成符合模板定義的時(shí)間序列數(shù)據(jù)。這個(gè)功能在聯(lián)調(diào)階段非常好用因?yàn)槟憧床坏秸鎸?shí)設(shè)備也能先把看板、規(guī)則、導(dǎo)出全部驗(yàn)證一遍。有一個(gè)細(xì)節(jié)容易被忽略模擬設(shè)備數(shù)據(jù)的生成頻率是可以調(diào)的。默認(rèn)可能是一分鐘一次如果你要測(cè)試規(guī)則觸發(fā)最好把模擬頻率調(diào)高一點(diǎn)比如 10 秒一次。否則你要等將近一分鐘才有新數(shù)據(jù)來(lái)確認(rèn)看板刷新是否正常會(huì)非常折磨人。3.3 配置規(guī)則與觸發(fā)動(dòng)作閾值告警的完整配置過(guò)程在“Rules”模塊中添加一條規(guī)則我當(dāng)時(shí)的條件是當(dāng)“環(huán)境監(jiān)測(cè)箱”模板下的設(shè)備 temperature 大于 45并且過(guò)去 5 分鐘的平均值也大于 45則觸發(fā)告警。要點(diǎn)是選對(duì)“設(shè)備模板”范圍。你可以讓規(guī)則只對(duì)某個(gè)模板生效也可以對(duì)某個(gè)設(shè)備組生效。公開(kāi)預(yù)覽階段我建議先按模板配置等設(shè)備多了再按設(shè)備組細(xì)化這樣新設(shè)備加入時(shí)自動(dòng)納入規(guī)則范圍不用手動(dòng)一個(gè)個(gè)加。動(dòng)作我配置的是一個(gè) Webhook。Webhook URL 指向我本地起的一個(gè)測(cè)試接口后來(lái)又接入了企業(yè)微信機(jī)器人。你也可以把動(dòng)作接到 Azure Functions 里做更復(fù)雜的處理比如查天氣、查設(shè)備位置、轉(zhuǎn)人工工單等等。配置完成后我在模擬設(shè)備上手動(dòng)把 temperature 改為 60 度。因?yàn)樵O(shè)置了 5 分鐘聚合窗口所以不是立刻觸發(fā)等了約一分鐘后規(guī)則狀態(tài)變成“Fired”Webhook 也收到了消息。測(cè)試通過(guò)后我把閾值調(diào)回 45保持規(guī)則一直啟用。3.4 用 SDK 接入真實(shí)設(shè)備代碼層面怎么做模擬設(shè)備跑通后我開(kāi)始嘗試接入真實(shí)設(shè)備。IoT Central 的設(shè)備接入走的是 Azure Device Provisioning Service (DPS)設(shè)備拿到一組連接憑證后先通過(guò) DPS 注冊(cè)DPS 會(huì)動(dòng)態(tài)分配 IoT Hub 地址然后再用 MQTT 或 AMQP 連接。我當(dāng)時(shí)用 C# 寫(xiě)了一個(gè)簡(jiǎn)單的模擬器核心邏輯是using Microsoft.Azure.Devices.Client; using Microsoft.Azure.Devices.Provisioning.Client; using Microsoft.Azure.Devices.Provisioning.Client.Transport; using Microsoft.Azure.Devices.Shared; var scopeId 0ne00000000; var registrationId env-sensor-001; var primaryKey 設(shè)備主密鑰; var security new SecurityProviderSymmetricKey(registrationId, primaryKey, null); var provisioningClient ProvisioningDeviceClient.Create( global.azure-devices-provisioning.net, scopeId, security, new ProvisioningTransportHandlerMqtt(TransportFallbackType.TcpWithWebSocket)); var result await provisioningClient.RegisterAsync(); var deviceClient DeviceClient.Create( result.AssignedHub, new DeviceAuthenticationWithRegistrySymmetricKey(result.DeviceId, result.DeviceKey), TransportType.Mqtt); var telemetryJson {\temperature\:25.6,\humidity\:60,\co2\:800}; var message new Message(Encoding.UTF8.GetBytes(telemetryJson)); await deviceClient.SendEventAsync(message);這段代碼的關(guān)鍵點(diǎn)就是先通過(guò) DPS 注冊(cè)拿到 AssignedHub 地址再用設(shè)備密鑰連接 Hub。Scope ID 在 IoT Central 應(yīng)用的“Administration Device connection”頁(yè)面可以找到設(shè)備密鑰可以在設(shè)備詳情頁(yè)生成或重置。實(shí)際運(yùn)行中我發(fā)現(xiàn)設(shè)備注冊(cè) ID 一定要和 IoT Central 里的設(shè)備 ID 一致。如果你在平臺(tái)里新建的設(shè)備 ID 是“env-sensor-001”那么代碼里的 registrationId 也必須填這個(gè)值否則會(huì)報(bào)錯(cuò)。對(duì)稱密鑰模式下DPS 就是靠注冊(cè) ID 加預(yù)置密鑰來(lái)確定設(shè)備歸屬的。3.5 真實(shí)場(chǎng)景里的發(fā)布流程模板版本化與設(shè)備分組有了真實(shí)設(shè)備之后我開(kāi)始體會(huì)到設(shè)備模板版本化的必要性。當(dāng)時(shí)我想給“環(huán)境監(jiān)測(cè)箱”模板增加一個(gè)電量的只讀屬性但現(xiàn)場(chǎng)已經(jīng)有 20 臺(tái)舊設(shè)備在跑了。如果我直接改模板并發(fā)布舊設(shè)備上報(bào)的數(shù)據(jù)流里沒(méi)有電量字段新設(shè)備有電量字段數(shù)據(jù)模型會(huì)變得很混亂。正確的做法是在模板的草稿版本里添加電量字段然后創(chuàng)建新版本并發(fā)布。已連接的舊設(shè)備繼續(xù)保持舊版本新設(shè)備在首次連接時(shí)會(huì)匹配到最新版本。你可以在“Device Explorer”里選擇一批設(shè)備批量遷移到新版本遷移后再驗(yàn)證設(shè)備上報(bào)是否正常。設(shè)備分組也是真實(shí)場(chǎng)景里的剛需。我當(dāng)時(shí)建了兩個(gè)組一組是“華東地區(qū)”一組是“華南地區(qū)”。分組條件可以基于設(shè)備屬性比如設(shè)備名稱包含“east”或者自定義屬性 locationeast。規(guī)則和儀表板都可以綁定到具體設(shè)備組這樣華南的溫度異常不會(huì)導(dǎo)致華北的運(yùn)維群收到告警告警噪音小很多。4. 設(shè)備連不上、數(shù)據(jù)不顯示、規(guī)則不觸發(fā)排查實(shí)錄4.1 連接層面的三類(lèi)高頻問(wèn)題我在實(shí)際接入和幫朋友排查過(guò)程中發(fā)現(xiàn)設(shè)備連不上幾乎都是這三類(lèi)問(wèn)題第一Scope ID 或注冊(cè) ID 填錯(cuò)。Scope ID 是一串以“0ne”開(kāi)頭的字符串很多人會(huì)把它和 IoT Hub 的 Hostname 搞混。注冊(cè) ID 大小寫(xiě)敏感如果你在平臺(tái)上創(chuàng)建設(shè)備時(shí)用的 ID 是“Device-01”代碼里填“device-01”DPS 直接拒絕。第二設(shè)備密鑰或主密鑰不匹配。IoT Central 里設(shè)備頁(yè)面展示的設(shè)備主密鑰是設(shè)備級(jí)的用 SAS 分組密鑰時(shí)還要注意 SecurityProvider 的構(gòu)造參數(shù)是否正確。如果報(bào) 401 Unauthorized絕大多數(shù)情況就是密鑰不匹配。第三DPS 的 endpoint 無(wú)法訪問(wèn)。global.azure-devices-provisioning.net 需要設(shè)備能通過(guò) 443 端口訪問(wèn)。在工廠現(xiàn)場(chǎng)測(cè)試時(shí)如果防火墻只放開(kāi)了 MQTT 1883 端口而沒(méi)放 443 端口DPS 注冊(cè)就會(huì)超時(shí)。我建議現(xiàn)場(chǎng)聯(lián)調(diào)前先檢查網(wǎng)絡(luò)連通性最穩(wěn)妥的辦法是設(shè)備端先配 MQTT 直連到 DPS 的 8883 端口不行再走 WebSocket。我自己排查時(shí)習(xí)慣先做一個(gè)最小化測(cè)試用平臺(tái)自帶的 CLI 工具比如 Azure CLI 的 az iot central device 命令嘗試手動(dòng)注冊(cè)該設(shè)備如果 CLI 能注冊(cè)、設(shè)備代碼不能那就是代碼或網(wǎng)絡(luò)問(wèn)題如果 CLI 都報(bào)錯(cuò)那就先檢查設(shè)備憑證和網(wǎng)絡(luò)環(huán)境。4.2 數(shù)據(jù)層的問(wèn)題字段映射、時(shí)區(qū)和精度設(shè)備顯示“已連接”但儀表板沒(méi)有數(shù)據(jù)這類(lèi)問(wèn)題在真實(shí)設(shè)備接入后特別常見(jiàn)。深挖原因大多數(shù)是字段映射和時(shí)區(qū)問(wèn)題。字段映射常見(jiàn)的坑是模板里定義的 telemetry 字段名是“temperature”但設(shè)備端代碼上報(bào)的 JSON 字段是“temp”。IoT Central 默認(rèn)按字段名匹配匹配不上就直接丟棄或忽略你幾乎不會(huì)看到明顯的報(bào)錯(cuò)。后果就是設(shè)備狀態(tài)正常、消息也發(fā)了但看板上一片空白。我排查這類(lèi)問(wèn)題時(shí)會(huì)先在設(shè)備調(diào)試頁(yè)面查看原始消息 JSON再和模板定義逐字段比對(duì)一眼就能看出問(wèn)題。時(shí)區(qū)問(wèn)題則是設(shè)備端的采樣時(shí)間戳。如果設(shè)備上報(bào)的時(shí)間不是 UTC平臺(tái)展示歷史曲線時(shí)就會(huì)出現(xiàn)“時(shí)間線偏移幾小時(shí)”的奇怪現(xiàn)象。大多數(shù)傳感器模塊的默認(rèn)時(shí)間是本地時(shí)間連接 IoT Central 時(shí)最好統(tǒng)一在設(shè)備端把時(shí)間戳轉(zhuǎn)成 UTC或者至少在代碼里做時(shí)區(qū)轉(zhuǎn)換后再拼 JSON。還有一個(gè)容易被忽略的點(diǎn)單位。模板里 temperature 定義成“°C”但設(shè)備端如果上報(bào)的是華氏度數(shù)值展示層不會(huì)自動(dòng)換算。你在看板看到“溫度飆到 90”的時(shí)候先別急著懷疑極端環(huán)境大概率是單位不一致。4.3 規(guī)則不觸發(fā)的隱蔽原因規(guī)則不觸發(fā)我總結(jié)了幾個(gè)排查思路按優(yōu)先級(jí)排列檢查規(guī)則范圍里是否包含目標(biāo)設(shè)備。規(guī)則綁定的是設(shè)備模板或者設(shè)備組如果設(shè)備是新加入的沒(méi)被分到規(guī)則范圍內(nèi)的組里自然不會(huì)觸發(fā)。檢查聚合窗口。前面提到過(guò)窗口聚合需要時(shí)間模擬數(shù)據(jù)頻率太低會(huì)導(dǎo)致永遠(yuǎn)滿足不了窗口條件。檢查動(dòng)作配置。Webhook 如果配置了 IP 白名單IoT Central 出口 IP 變更后 Webhook 會(huì)被拒絕。這個(gè)問(wèn)題公開(kāi)預(yù)覽階段遇到過(guò)最好通過(guò) DNS 解析把出口 IP 的變化盡量規(guī)避或者不要做太嚴(yán)格的 IP 白名單。檢查規(guī)則是否被手動(dòng)禁用。平臺(tái)里規(guī)則有啟用/停用狀態(tài)很容易誤觸。我把這些場(chǎng)景整理成一張速查表方便常用現(xiàn)象可能原因處理方法設(shè)備一直顯示未連接Scope ID/設(shè)備 ID/密鑰錯(cuò)誤核對(duì)連接頁(yè)和代碼參數(shù)設(shè)備已連接但無(wú)數(shù)據(jù)字段名不匹配對(duì)比設(shè)備調(diào)試頁(yè)面原始 JSON看板曲線時(shí)間偏移設(shè)備時(shí)間戳不是 UTC設(shè)備端轉(zhuǎn) UTC規(guī)則遲遲不觸發(fā)聚合窗口未結(jié)束縮短窗口或改為任意采樣值Webhook 收不到通知出口 IP 變化/IOT Central 規(guī)則禁用檢查動(dòng)作配置與規(guī)則狀態(tài)模板升級(jí)后圖表空白儀表板綁定舊模板版本在儀表板組件中重新選擇數(shù)據(jù)源4.4 本地環(huán)境問(wèn)題怎么辦SDK 與運(yùn)行時(shí)依賴接入 SDK 的過(guò)程中不少人也遇到過(guò)和 IoT 平臺(tái)無(wú)關(guān)的本地環(huán)境坑比如裝 Azure IoT Device SDK 時(shí) Win 系統(tǒng)本身就拋出 Visual C Redistributable 安裝失敗或者 VS 組件缺失導(dǎo)致 build 不過(guò)。這個(gè)現(xiàn)象和裝很多 Windows 原生依賴一樣不是云端服務(wù)的問(wèn)題而是本機(jī)環(huán)境被之前的舊版本搞亂了。建議先把舊的 Redistributable 卸載干凈再以管理員權(quán)限重新安裝之后再裝 SDK。別把這類(lèi)問(wèn)題一股腦歸結(jié)到 IoT Central 上否則排查方向就跑偏了。5. 用了一年之后我對(duì) IoT Central 適用邊界的重新思考5.1 什么人適合用什么人建議繞道經(jīng)過(guò)一段時(shí)間的實(shí)際使用我對(duì) IoT Central 的適用邊界有了還算清晰的判斷。適合用它的人主要有三類(lèi)需要快速交付 PoC 給客戶看的團(tuán)隊(duì)時(shí)間比什么都寶貴。中小團(tuán)隊(duì)、初創(chuàng)公司沒(méi)有太多資源去專門(mén)維護(hù)一套物聯(lián)網(wǎng)后臺(tái)。SI 集成商需要在多個(gè)客戶項(xiàng)目里做標(biāo)準(zhǔn)化交付用模板復(fù)制應(yīng)用能明顯提升人效。不太適合的場(chǎng)景也明確存在。如果你有非常復(fù)雜的邊緣計(jì)算邏輯設(shè)備側(cè)需要大量本地決策和規(guī)則鏈IoT Central 的設(shè)備命令和屬性能力會(huì)顯得單薄如果你的數(shù)據(jù)模型高度非結(jié)構(gòu)化設(shè)備上報(bào)每天都不一樣IoT Central 的物模型約束會(huì)讓你改模板改到崩潰如果你有私有化部署的合規(guī)需求SaaS 形態(tài)從一開(kāi)始就不合適。5.2 和團(tuán)隊(duì)協(xié)作、交付有關(guān)的幾條經(jīng)驗(yàn)從團(tuán)隊(duì)協(xié)作角度我學(xué)到幾個(gè)比較實(shí)在的經(jīng)驗(yàn)第一環(huán)境隔離要提前做。IoT Central 的應(yīng)用實(shí)例之間是完全隔離的。開(kāi)發(fā)、測(cè)試、生產(chǎn)環(huán)境最好各建一個(gè)應(yīng)用不要在一個(gè)應(yīng)用里又改模板又盯生產(chǎn)數(shù)據(jù)。公開(kāi)預(yù)覽階段應(yīng)用創(chuàng)建成本低多建幾個(gè)不心疼但要注意配額和計(jì)費(fèi)。第二模板的命名規(guī)范要統(tǒng)一。設(shè)備模板、儀表板、規(guī)則的命名最好帶上項(xiàng)目或客戶前綴否則應(yīng)用多了之后你會(huì)在列表里看到一堆“環(huán)境監(jiān)測(cè)箱1”“環(huán)境監(jiān)測(cè)箱2”根本分不清哪個(gè)是哪個(gè)。第三給客戶交付時(shí)盡量把儀表板權(quán)限收到最細(xì)。操作員賬號(hào)不要給設(shè)備模板編輯權(quán)限否則客戶手滑改了模板發(fā)布可能導(dǎo)致現(xiàn)場(chǎng)設(shè)備數(shù)據(jù)解析全亂。5.3 成本、數(shù)據(jù)歸屬、后續(xù)擴(kuò)展要提前想清楚成本方面IoT Central 的計(jì)費(fèi)是按設(shè)備數(shù)和消息量來(lái)算的和 IoTHub 的按消息量計(jì)費(fèi)邏輯類(lèi)似但多了托管應(yīng)用平臺(tái)的費(fèi)用。公開(kāi)預(yù)覽階段的試用計(jì)劃不花錢(qián)但正式商用前一定要根據(jù)設(shè)備數(shù)量和消息頻率做個(gè)估算。我記得當(dāng)時(shí)一個(gè)小型項(xiàng)目500 臺(tái)設(shè)備每 10 秒上報(bào)一次消息量立刻漲到很可觀的數(shù)字如果不做成本評(píng)估月底賬單會(huì)讓人措手不及。數(shù)據(jù)歸屬方面平臺(tái)本身會(huì)留存運(yùn)行數(shù)據(jù)但更穩(wěn)妥的做法還是盡早啟用數(shù)據(jù)導(dǎo)出把設(shè)備原始數(shù)據(jù)和屬性變更事件持續(xù)導(dǎo)入到自己的存儲(chǔ)里。這樣即使以后從 IoT Central 遷移到其他平臺(tái)歷史數(shù)據(jù)資產(chǎn)也不會(huì)丟。后續(xù)擴(kuò)展方面IoT Central 提供了一套 REST API 和 SDK可以做設(shè)備批量導(dǎo)入、遙測(cè)查詢、管理操作。如果你發(fā)現(xiàn)平臺(tái)內(nèi)置能力不夠用可以用 API 把設(shè)備模板、規(guī)則、儀表板數(shù)據(jù)同步到你自己的系統(tǒng)里。這意味著它并不是一個(gè)封閉的“黑盒”而是一個(gè)可以漸進(jìn)式替換掉部分自定義代碼的基座。這也正是我后來(lái)對(duì)它的評(píng)價(jià)它不是 IoT 領(lǐng)域的終點(diǎn)但絕對(duì)是大多數(shù)人起步的最佳捷徑。說(shuō)實(shí)話IoT Central 對(duì)我最大的啟發(fā)不是省了多少開(kāi)發(fā)時(shí)間而是把“應(yīng)用”和“平臺(tái)”分開(kāi)思考。當(dāng)年那種拿 IoTHub 硬造管理后臺(tái)的笨辦法也許在某些極復(fù)雜場(chǎng)景仍是必要的但對(duì)大部分物聯(lián)網(wǎng)項(xiàng)目來(lái)說(shuō)先從一個(gè)托管應(yīng)用起步把更多精力花在業(yè)務(wù)驗(yàn)證上才是真正劃算的選擇。如果你手頭正好有一個(gè)設(shè)備接入和監(jiān)控類(lèi)的需求我建議你花一個(gè)下午把官方模板跑一遍再?zèng)Q定要不要自己造輪子。