測(cè)系統(tǒng)設(shè)計(jì)與部署實(shí)戰(zhàn):從選型到上線(xiàn))
前陣子接了一個(gè)不算特別前沿、但相當(dāng)磨人的項(xiàng)目給某座中型體育館設(shè)計(jì)并部署一套基于物聯(lián)網(wǎng)的人流量監(jiān)測(cè)系統(tǒng)。體育館的場(chǎng)地運(yùn)營(yíng)方最初的需求很簡(jiǎn)單就一句話(huà)我想知道現(xiàn)在館里有多少人別再靠保安掐著對(duì)講機(jī)報(bào)數(shù)了。但真實(shí)落地之后你會(huì)發(fā)現(xiàn)這句話(huà)背后牽扯出的問(wèn)題遠(yuǎn)比想象中復(fù)雜——傳感器選什么、裝在哪個(gè)位置、數(shù)據(jù)怎么傳、到了后臺(tái)怎么處理、報(bào)警閾值怎么定每一步都有坑。這篇文章不聊宏大的智慧場(chǎng)館概念主要把我在這套系統(tǒng)設(shè)計(jì)和實(shí)施過(guò)程中踩過(guò)的一些坑、比較系統(tǒng)的選型思路以及最終可復(fù)現(xiàn)的架構(gòu)方案整理出來(lái)完整復(fù)盤(pán)一個(gè)基于物聯(lián)網(wǎng)的體育館人流量監(jiān)測(cè)系統(tǒng)從需求到上線(xiàn)的全過(guò)程。如果你正準(zhǔn)備做場(chǎng)館人流統(tǒng)計(jì)、室內(nèi)空間密度監(jiān)測(cè)這一類(lèi)項(xiàng)目這篇文章值得收藏。1. 需求解剖先搞清楚人流量監(jiān)測(cè)到底要解決什么1.1 場(chǎng)館運(yùn)營(yíng)方的三個(gè)核心痛點(diǎn)做任何系統(tǒng)之前第一步都不是選硬件而是追問(wèn)需求方背后真正的痛點(diǎn)。這個(gè)項(xiàng)目里體育館運(yùn)營(yíng)團(tuán)隊(duì)列出的問(wèn)題大概能歸結(jié)為三類(lèi)。安全容量管理是第一優(yōu)先級(jí)。體育館平時(shí)承辦籃球賽、羽毛球活動(dòng)、企業(yè)團(tuán)建偶爾還有明星演出。運(yùn)營(yíng)方需要知道的在館人數(shù)不是一個(gè)大概數(shù)而是能夠和消防設(shè)計(jì)容量、場(chǎng)館安全規(guī)定掛鉤的可靠數(shù)字。按照相關(guān)要求當(dāng)館內(nèi)人數(shù)達(dá)到設(shè)計(jì)上限的一定比例時(shí)必須啟動(dòng)限流措施這個(gè)數(shù)字錯(cuò)幾千人沒(méi)問(wèn)題但關(guān)鍵拐點(diǎn)不能錯(cuò)。第二個(gè)痛點(diǎn)是分區(qū)域的人流密度分布。運(yùn)營(yíng)方不僅僅是想知道總?cè)藬?shù)還想知道羽毛球片區(qū)和器械片區(qū)各自忙不忙。如果能把人流量分區(qū)域呈現(xiàn)管理員就能在某個(gè)區(qū)域接近飽和時(shí)通過(guò)廣播、引導(dǎo)等手段分流人群同時(shí)保潔、通風(fēng)、空調(diào)也能按需調(diào)度。只統(tǒng)計(jì)進(jìn)出總?cè)藬?shù)解決不了這個(gè)問(wèn)題。第三個(gè)痛點(diǎn)是運(yùn)營(yíng)數(shù)據(jù)沉淀。場(chǎng)館的租賃定價(jià)、賽事排期、工作人員排班都依賴(lài)什么時(shí)間段人多、高峰持續(xù)多久這類(lèi)歷史數(shù)據(jù)。人工巡檢的方式?jīng)]法連續(xù)記錄也無(wú)法事后回溯。所以系統(tǒng)不僅要實(shí)時(shí)顯示數(shù)字還要在后臺(tái)保存完整的時(shí)間序列數(shù)據(jù)供月度、季度復(fù)盤(pán)使用。1.2 設(shè)計(jì)目標(biāo)與技術(shù)選型邊界明確了痛點(diǎn)之后我梳理出了以下幾項(xiàng)硬性指標(biāo)這些指標(biāo)直接影響后文的所有選型判斷指標(biāo)項(xiàng)目標(biāo)值說(shuō)明出入口監(jiān)測(cè)精度誤差不超過(guò)5%以人工計(jì)數(shù)抽樣作為基準(zhǔn)數(shù)據(jù)上報(bào)延遲10秒以?xún)?nèi)超過(guò)15秒時(shí)管理端需告警單監(jiān)測(cè)點(diǎn)覆蓋寬度2米至3米覆蓋常見(jiàn)雙開(kāi)大門(mén)寬度在場(chǎng)人數(shù)計(jì)算一致性斷電恢復(fù)后不丟數(shù)據(jù)網(wǎng)關(guān)需本地緩存支持?jǐn)嗑W(wǎng)續(xù)傳系統(tǒng)運(yùn)行成本單點(diǎn)硬件成本控制在合理區(qū)間場(chǎng)館預(yù)算有限不做高端視覺(jué)方案這里要強(qiáng)調(diào)一個(gè)經(jīng)驗(yàn)設(shè)計(jì)目標(biāo)必須在選型之前固定下來(lái)否則后面很容易被硬件廠(chǎng)商帶著走。我在溝通前期見(jiàn)過(guò)不止一個(gè)供應(yīng)商推薦幾十萬(wàn)一套的視覺(jué)分析方案需求方聽(tīng)完覺(jué)得很先進(jìn)但實(shí)際場(chǎng)景只有一個(gè)普通體育館入口預(yù)算和必要性都不匹配。所以我給自己定的邊界是能用低成本的傳感器解決絕不上豪華設(shè)備。2. 系統(tǒng)總體架構(gòu)與數(shù)據(jù)流向一條完整的鏈路2.1 分層架構(gòu)感知、傳輸、平臺(tái)、應(yīng)用整個(gè)系統(tǒng)的架構(gòu)我最終分成了四層每一層職責(zé)單一方便后期單獨(dú)替換和排障。感知層由部署在各個(gè)出入口的人流檢測(cè)節(jié)點(diǎn)組成每個(gè)節(jié)點(diǎn)包括傳感器模組和邊緣計(jì)算單元。邊緣計(jì)算單元負(fù)責(zé)在本地完成人流方向判斷和數(shù)據(jù)緩存它輸出的不是原始信號(hào)而是進(jìn)1、出-1這種已經(jīng)結(jié)構(gòu)化的事件這樣做的好處是不占用太多網(wǎng)絡(luò)帶寬。傳輸層負(fù)責(zé)把各節(jié)點(diǎn)的結(jié)構(gòu)化事件上送到平臺(tái)。這里我沒(méi)有搞復(fù)雜的組網(wǎng)而是統(tǒng)一通過(guò)無(wú)線(xiàn)方式匯聚到場(chǎng)館弱電間里的網(wǎng)關(guān)再由網(wǎng)關(guān)通過(guò)有線(xiàn)網(wǎng)絡(luò)上傳到服務(wù)器。無(wú)線(xiàn)方式主要解決了兩個(gè)問(wèn)題一是體育館出入口往往已經(jīng)裝修完畢拉網(wǎng)線(xiàn)會(huì)破壞地面和墻面二是后期增加監(jiān)測(cè)點(diǎn)時(shí)不需要重新布線(xiàn)。平臺(tái)層部署在體育館本地的服務(wù)器上運(yùn)行消息中間件、數(shù)據(jù)存儲(chǔ)服務(wù)和告警引擎??紤]到場(chǎng)館的網(wǎng)絡(luò)環(huán)境并不總是穩(wěn)定我沒(méi)有把平臺(tái)完全放到外網(wǎng)云服務(wù)器而是采用本地優(yōu)先、云端可選的部署模式。本地部署保證了數(shù)據(jù)在主網(wǎng)絡(luò)中斷時(shí)依然可用給運(yùn)營(yíng)方留下了充足的應(yīng)急窗口。應(yīng)用層就是管理員端和前臺(tái)展示大屏。管理員端承擔(dān)實(shí)時(shí)人數(shù)查看、歷史數(shù)據(jù)查詢(xún)、閾值設(shè)置等操作展示大屏放在場(chǎng)館值班室紅色、黃色、綠色三色狀態(tài)一目了然。2.2 數(shù)據(jù)鏈路的關(guān)鍵細(xì)節(jié)一條數(shù)據(jù)從產(chǎn)生到展示在真實(shí)系統(tǒng)里要經(jīng)過(guò)以下環(huán)節(jié)傳感器原始信號(hào) → 邊緣節(jié)點(diǎn)本地濾波與方向判定 → 生成進(jìn)出事件 → MQTT消息發(fā)布 → 網(wǎng)關(guān)匯聚轉(zhuǎn)發(fā) → 服務(wù)器消息中間件接收 → 實(shí)時(shí)計(jì)算引擎更新在場(chǎng)人數(shù) → 寫(xiě)入時(shí)序數(shù)據(jù)庫(kù) → 前端通過(guò)WebSocket訂閱最新數(shù)據(jù) → 大屏刷新很多人做這類(lèi)系統(tǒng)時(shí)容易忽略的一個(gè)點(diǎn)是實(shí)時(shí)通道和歷史通道要分開(kāi)。實(shí)時(shí)顯示要求低延遲歷史統(tǒng)計(jì)要求高吞吐如果都走同一條鏈路歷史數(shù)據(jù)回放時(shí)可能會(huì)拖慢實(shí)時(shí)通道。我的做法是消息中間件把數(shù)據(jù)同時(shí)推給實(shí)時(shí)計(jì)算模塊和持久化模塊兩個(gè)模塊各自消費(fèi)互不阻塞。這算是一個(gè)很基礎(chǔ)但很有效的設(shè)計(jì)決策。3. 硬件選型與部署位置規(guī)劃數(shù)據(jù)質(zhì)量的前置決定因素3.1 傳感器方案橫向?qū)Ρ扔布x型是這套系統(tǒng)里最容易被低估的一環(huán)。體育館入口的光線(xiàn)、人員密集程度、攜帶物品的形態(tài)都會(huì)影響傳感器判斷。我對(duì)比了四類(lèi)主流方案紅外對(duì)射傳感器成本最低兩個(gè)對(duì)射探頭跨門(mén)安裝人員穿過(guò)時(shí)遮擋光線(xiàn)產(chǎn)生脈沖。優(yōu)點(diǎn)是便宜、穩(wěn)定不受光線(xiàn)影響缺點(diǎn)是只能判斷有沒(méi)有人穿過(guò)無(wú)法可靠區(qū)分進(jìn)出方向需要成對(duì)安裝配合邏輯推斷對(duì)并列而行的人流容易誤判。ToF測(cè)距傳感器通過(guò)測(cè)量光飛行時(shí)間獲取目標(biāo)距離可以形成低分辨率的深度信息。它比紅外對(duì)射強(qiáng)的地方在于能夠做簡(jiǎn)單的軌跡判斷兩個(gè)ToF模塊一前一后通過(guò)觸發(fā)順序判斷進(jìn)出方向也可以統(tǒng)計(jì)一定寬度內(nèi)的人流。缺點(diǎn)是測(cè)量范圍有限通常適合2米左右的通道。熱成像傳感器通過(guò)捕捉人體熱輻射識(shí)別目標(biāo)隱私保護(hù)很好不會(huì)采集人臉細(xì)節(jié)。在中型場(chǎng)館入口這種場(chǎng)景熱成像能夠比較好地解決多人并列和遮擋問(wèn)題。但成本明顯高而且環(huán)境溫度接近人體溫度時(shí)誤報(bào)率會(huì)上來(lái)比如夏天出入口冷氣外泄門(mén)內(nèi)門(mén)外溫差大時(shí)目標(biāo)邊緣識(shí)別會(huì)抖。毫米波雷達(dá)通過(guò)發(fā)射和接收毫米波頻段電磁波檢測(cè)運(yùn)動(dòng)目標(biāo)能輸出目標(biāo)距離、速度和方位角。它在雨霧、光線(xiàn)變化、非金屬遮擋等場(chǎng)景下表現(xiàn)比較穩(wěn)定能實(shí)現(xiàn)多目標(biāo)追蹤而且完全不受隱私問(wèn)題影響。缺點(diǎn)是對(duì)靜止或緩慢移動(dòng)的目標(biāo)不敏感如果有人在門(mén)口長(zhǎng)時(shí)間停留雷達(dá)計(jì)數(shù)可能漏掉后續(xù)目標(biāo)。綜合對(duì)比之后我選擇了ToF測(cè)距傳感器為主、紅外對(duì)射為輔的組合方案。兩個(gè)ToF模塊間隔0.8米安裝通過(guò)目標(biāo)的觸發(fā)時(shí)序判斷進(jìn)出方向同時(shí)在門(mén)側(cè)部署一組紅外對(duì)射做交叉校驗(yàn)。這樣單監(jiān)測(cè)點(diǎn)的硬件成本控制在合理范圍內(nèi)精度也能滿(mǎn)足設(shè)計(jì)目標(biāo)。3.2 部署位置與安裝細(xì)節(jié)傳感器裝在哪、裝在什么高度比選型還要影響最終效果。這里直接說(shuō)結(jié)論和依據(jù)。第一安裝高度建議在2.2米左右略微向下傾斜。這個(gè)高度可以覆蓋大多數(shù)人的頭部和肩部區(qū)域同時(shí)降低兒童、輪椅使用者被漏檢的概率。要注意不能裝太高否則ToF的俯視角度過(guò)大會(huì)導(dǎo)致相鄰并排人員的深度值混在一起難以區(qū)分。第二傳感器要避開(kāi)金屬門(mén)框正上方。毫米波和ToF在貼近金屬反射表面時(shí)容易產(chǎn)生多徑效應(yīng)產(chǎn)生虛假目標(biāo)。如果門(mén)框上方空間有限寧可采用側(cè)裝支架斜跨過(guò)門(mén)洞也不要貼著金屬框垂直向下安裝。第三進(jìn)出口要分開(kāi)檢測(cè)不要試圖用一個(gè)傳感器覆蓋雙向人流。場(chǎng)館入口在實(shí)際使用中經(jīng)常是出的人貼著左側(cè)進(jìn)的人貼著右側(cè)一個(gè)傳感器無(wú)法同時(shí)準(zhǔn)確區(qū)分兩個(gè)方向。我的方案是在門(mén)洞左右兩側(cè)各部署一組檢測(cè)單元一側(cè)負(fù)責(zé)統(tǒng)計(jì)進(jìn)一側(cè)負(fù)責(zé)統(tǒng)計(jì)出邏輯上徹底分離。這個(gè)設(shè)計(jì)后來(lái)實(shí)測(cè)效果非常好雙向?qū)α鞯恼`判率比單點(diǎn)方案低了一個(gè)數(shù)量級(jí)。提示如果出入口寬度超過(guò)3米建議拆分成兩個(gè)監(jiān)測(cè)點(diǎn)。一個(gè)傳感器覆蓋3米以上寬度時(shí)邊緣區(qū)域的目標(biāo)信號(hào)質(zhì)量會(huì)明顯下降與其后期調(diào)算法不如前期拆硬件。4. 通信方案與數(shù)據(jù)協(xié)議傳輸層的工程取舍4.1 無(wú)線(xiàn)通信方式怎么選感知層和網(wǎng)關(guān)之間我評(píng)估了三種常見(jiàn)無(wú)線(xiàn)方式LoRa是長(zhǎng)距離低功耗的代表單節(jié)點(diǎn)通信距離在空曠環(huán)境能達(dá)到幾百米穿墻能力也不錯(cuò)非常適合園區(qū)級(jí)廣覆蓋。但LoRa的帶寬很低如果每個(gè)監(jiān)測(cè)點(diǎn)每次上報(bào)的數(shù)據(jù)量稍大實(shí)時(shí)刷新會(huì)有明顯延遲。我在體育館場(chǎng)地實(shí)測(cè)從傳感器觸發(fā)到數(shù)據(jù)到達(dá)網(wǎng)關(guān)LoRa路徑的端到端時(shí)延在1到3秒抖動(dòng)雖然勉強(qiáng)達(dá)標(biāo)但不夠理想。NB-IoT依托運(yùn)營(yíng)商網(wǎng)絡(luò)覆蓋廣、穿透強(qiáng)而且模組功耗控制得很好。但NB-IoT依賴(lài)運(yùn)營(yíng)商基站在信號(hào)覆蓋不佳的地下場(chǎng)館區(qū)域需要額外加裝增強(qiáng)設(shè)備而且單次通信會(huì)產(chǎn)生流量套餐成本。考慮到體育館弱電間本身具有有線(xiàn)網(wǎng)絡(luò)沒(méi)必要繞一圈走運(yùn)營(yíng)商網(wǎng)絡(luò)。Wi-Fi方案是我最終的選擇。理由很直接體育館內(nèi)已有商用無(wú)線(xiàn)網(wǎng)絡(luò)覆蓋每個(gè)出入口附近都有接入點(diǎn)傳感器數(shù)據(jù)量本身很小Wi-Fi的帶寬和時(shí)延完全夠用。Wi-Fi的功耗確實(shí)比前兩者高一些但監(jiān)測(cè)點(diǎn)可以直接用PoE供電不存在電池續(xù)航問(wèn)題功耗劣勢(shì)也就不存在了。實(shí)際工程中還考慮過(guò)用RS-485有線(xiàn)總線(xiàn)布線(xiàn)太長(zhǎng)、后期維護(hù)麻煩直接排除。4.2 數(shù)據(jù)協(xié)議與異常補(bǔ)償機(jī)制通信協(xié)議我采用輕量級(jí)的MQTT消息體使用JSON格式。為什么不用HTTP輪詢(xún)因?yàn)閷?shí)時(shí)人數(shù)變化需要秒級(jí)推送HTTP短連接輪詢(xún)費(fèi)流量、費(fèi)功耗且實(shí)現(xiàn)復(fù)雜。MQTT的發(fā)布-訂閱模式和長(zhǎng)連接機(jī)制天然適合這種傳感器上報(bào)場(chǎng)景。上行消息最簡(jiǎn)單的時(shí)候只有幾個(gè)字段{ node_id: gate_a_01, event: enter, ts: 1682312400, seq: 321 }node_id標(biāo)識(shí)監(jiān)測(cè)點(diǎn)event是事件類(lèi)型ts是事件發(fā)生時(shí)間戳seq是節(jié)點(diǎn)側(cè)消息序號(hào)。seq這個(gè)字段非常重要它是實(shí)現(xiàn)斷網(wǎng)續(xù)傳和消息去重的關(guān)鍵。邊緣節(jié)點(diǎn)本地維護(hù)一個(gè)自增序號(hào)網(wǎng)絡(luò)恢復(fù)后服務(wù)器可以根據(jù)序號(hào)發(fā)現(xiàn)中間是否有丟包。消息中間件的QoS我設(shè)置在1也就是至少一次投遞。為什么不用QoS 2的恰好一次?因?yàn)镼oS 2的多次握手確認(rèn)對(duì)傳感器這種資源受限設(shè)備來(lái)說(shuō)太重了而且我們靠消息序號(hào)去重完全能在應(yīng)用層解決重復(fù)問(wèn)題。下行消息主要用于遠(yuǎn)程配置和指令下發(fā)比如遠(yuǎn)程修改告警閾值、重啟節(jié)點(diǎn)同樣走M(jìn)QTT但單獨(dú)劃一個(gè)topic前綴隔離控制指令和數(shù)據(jù)流。5. 人流統(tǒng)計(jì)算法的精度與容錯(cuò)數(shù)據(jù)真正可用的關(guān)鍵5.1 邊緣節(jié)點(diǎn)的雙向計(jì)數(shù)邏輯每個(gè)入口的監(jiān)測(cè)點(diǎn)內(nèi)兩個(gè)ToF模塊在空間上前后安裝分別稱(chēng)為A點(diǎn)外側(cè)和B點(diǎn)內(nèi)側(cè)。當(dāng)人員通過(guò)時(shí)理想情況下會(huì)依次觸發(fā)A和B。通過(guò)觸發(fā)順序即可判斷方向先觸發(fā)A后觸發(fā)B判定為進(jìn)入先觸發(fā)B后觸發(fā)A判定為離開(kāi)。看起來(lái)非常簡(jiǎn)單但真實(shí)場(chǎng)景有太多看起來(lái)的問(wèn)題。人不是點(diǎn)是多幀連續(xù)運(yùn)動(dòng)軌跡。我用一個(gè)簡(jiǎn)單的滑動(dòng)窗口狀態(tài)機(jī)來(lái)處理狀態(tài)機(jī)包含四個(gè)狀態(tài)空閑、檢測(cè)到A目標(biāo)、檢測(cè)到B目標(biāo)、已計(jì)數(shù)。每個(gè)狀態(tài)有超時(shí)機(jī)制比如A點(diǎn)觸發(fā)后如果3秒內(nèi)沒(méi)有在B點(diǎn)檢測(cè)到對(duì)應(yīng)目標(biāo)就判定為無(wú)效觸發(fā)狀態(tài)回到空閑不產(chǎn)生任何事件。這樣可以過(guò)濾掉門(mén)口徘徊、彎腰系鞋帶、停下來(lái)看手機(jī)這類(lèi)行為觸發(fā)。多人并排通過(guò)是另一個(gè)棘手問(wèn)題。兩個(gè)ToF模塊測(cè)距數(shù)據(jù)里會(huì)出現(xiàn)兩個(gè)相近的目標(biāo)我在邊緣節(jié)點(diǎn)上維護(hù)一個(gè)目標(biāo)列表根據(jù)距離值做聚類(lèi)再對(duì)聚類(lèi)中心做前后關(guān)聯(lián)跟蹤。簡(jiǎn)單來(lái)說(shuō)就是不判斷這個(gè)點(diǎn)是張三還是李四只判斷前方目標(biāo)數(shù)量增加了還是減少了用通道內(nèi)目標(biāo)數(shù)量變化來(lái)推導(dǎo)通行事件。這個(gè)方法在2.5米以下寬度的出入口準(zhǔn)確率相當(dāng)高。5.2 干擾與異常場(chǎng)景的處理整個(gè)系統(tǒng)最容易出錯(cuò)的環(huán)節(jié)其實(shí)是人流量大的時(shí)候。首先是長(zhǎng)時(shí)間停留目標(biāo)。有人站在門(mén)口打電話(huà)、等人目標(biāo)在A點(diǎn)和B點(diǎn)之間長(zhǎng)時(shí)間駐留如果不做處理就會(huì)一直占用跟蹤資源導(dǎo)致后續(xù)人員無(wú)法被正確關(guān)聯(lián)。我的方案是設(shè)置駐留超時(shí)目標(biāo)在監(jiān)測(cè)區(qū)內(nèi)停留超過(guò)10秒后邊緣節(jié)點(diǎn)就不再將其納入進(jìn)出判斷邏輯只當(dāng)作靜態(tài)背景處理。這樣雖然會(huì)犧牲一部分這個(gè)人后來(lái)到底走沒(méi)走的統(tǒng)計(jì)但總?cè)藬?shù)計(jì)算反而更穩(wěn)。說(shuō)到底人流監(jiān)測(cè)關(guān)注的是流量脈沖不是長(zhǎng)期駐留個(gè)體的精確去向。其次是多人同向快速連續(xù)通過(guò)。在比賽散場(chǎng)時(shí)幾十人會(huì)在幾十秒內(nèi)連續(xù)涌出。這時(shí)候邊緣節(jié)點(diǎn)的處理能力會(huì)面臨壓力如果算法處理不過(guò)來(lái)丟幀就會(huì)導(dǎo)致漏統(tǒng)。我的應(yīng)對(duì)是兩級(jí)緩沖傳感器數(shù)據(jù)先寫(xiě)入邊緣節(jié)點(diǎn)的本地環(huán)形隊(duì)列業(yè)務(wù)算法按固定速率消費(fèi)處理隊(duì)列溢出時(shí)優(yōu)先丟棄舊幀而不是新幀。處理不過(guò)來(lái)的時(shí)候系統(tǒng)會(huì)主動(dòng)降級(jí)把單目標(biāo)檢測(cè)降級(jí)為檢測(cè)到通道有密集人流通過(guò)用經(jīng)驗(yàn)流量系數(shù)估算本次通行數(shù)量。降級(jí)估算的總誤差雖然比逐目標(biāo)檢測(cè)大但至少不會(huì)完全丟失事件。最后是重復(fù)計(jì)數(shù)問(wèn)題。場(chǎng)館出口和入口相距不遠(yuǎn)閘機(jī)附近存在大量折返人員。比如入場(chǎng)時(shí)發(fā)現(xiàn)走錯(cuò)了安檢口立刻折返出門(mén)再重新走進(jìn)來(lái)。這套系統(tǒng)記錄到的是一個(gè)進(jìn)入事件加上一個(gè)離開(kāi)事件兩者相抵總量實(shí)際上是正確且自洽的。5.3 與人工抽檢的數(shù)據(jù)校準(zhǔn)算法再穩(wěn)也需要真值基準(zhǔn)。我們上線(xiàn)第一周做了系統(tǒng)的數(shù)據(jù)校準(zhǔn)實(shí)驗(yàn)。安排兩名工作人員分別在主入口的人工計(jì)數(shù)點(diǎn)記錄真實(shí)通行數(shù)據(jù)每15分鐘與系統(tǒng)統(tǒng)計(jì)數(shù)比對(duì)一次。校準(zhǔn)過(guò)程中發(fā)現(xiàn)了一個(gè)非常典型的偏差系統(tǒng)計(jì)算的在場(chǎng)人數(shù)在閉館清場(chǎng)時(shí)和人工總數(shù)往往能對(duì)齊但中間的每個(gè)小時(shí)會(huì)出現(xiàn)幾十人的累計(jì)漂移。定位后發(fā)現(xiàn)漂移源主要集中在側(cè)門(mén)。側(cè)門(mén)平時(shí)用得少但保潔人員和商戶(hù)會(huì)頻繁通過(guò)而且側(cè)門(mén)通行方向無(wú)法固定區(qū)分導(dǎo)致?tīng)顟B(tài)機(jī)出現(xiàn)間歇性誤判。處理方式分兩步一是給保潔、商戶(hù)人員集中通行時(shí)段加了輔助判斷邏輯在固定時(shí)間段內(nèi)降低觸發(fā)靈敏度減少機(jī)械性的誤判二是開(kāi)發(fā)了一個(gè)日終自動(dòng)歸零功能在每天閉館后由管理員確認(rèn)清場(chǎng)系統(tǒng)自動(dòng)重置在場(chǎng)人數(shù)基準(zhǔn)切斷跨天累積誤差。這類(lèi)周期性校準(zhǔn)是低成本且非常實(shí)用的手段。6. 后臺(tái)服務(wù)、數(shù)據(jù)存儲(chǔ)與可視化從計(jì)數(shù)到管理決策6.1 后端服務(wù)邊界與數(shù)據(jù)存儲(chǔ)選擇后臺(tái)服務(wù)需要做的事情包括消息接入、實(shí)時(shí)人數(shù)計(jì)算、區(qū)域人數(shù)聚合、歷史數(shù)據(jù)存儲(chǔ)、告警引擎和權(quán)限管理。為了避免堆成一個(gè)大單體我按數(shù)據(jù)職責(zé)拆成了三個(gè)服務(wù)接入服務(wù)、計(jì)算服務(wù)、管理服務(wù)。接入服務(wù)負(fù)責(zé)完整接收邊緣節(jié)點(diǎn)上報(bào)的MQTT消息先做格式校驗(yàn)、冪等去重再寫(xiě)入消息隊(duì)列同時(shí)把原始數(shù)據(jù)歸檔到歷史庫(kù)。計(jì)算服務(wù)消費(fèi)消息隊(duì)列里的數(shù)據(jù)維護(hù)每個(gè)監(jiān)測(cè)點(diǎn)的最新計(jì)數(shù)狀態(tài)并周期性計(jì)算在場(chǎng)人數(shù)、各區(qū)域人數(shù)、單位時(shí)間內(nèi)進(jìn)出流量。計(jì)算服務(wù)不直接讀數(shù)據(jù)庫(kù)它的狀態(tài)全部保存在內(nèi)存中這樣性能會(huì)非常穩(wěn)定。管理服務(wù)處理管理后臺(tái)的API請(qǐng)求操作配置信息、查詢(xún)歷史趨勢(shì)、管理用戶(hù)權(quán)限。存儲(chǔ)方面我用了兩類(lèi)存儲(chǔ)搭配。關(guān)系型數(shù)據(jù)庫(kù)存設(shè)備信息、用戶(hù)、閾值配置這類(lèi)數(shù)據(jù)量小、變更少。時(shí)序數(shù)據(jù)庫(kù)存人流數(shù)據(jù)的時(shí)間序列數(shù)據(jù)量大、寫(xiě)入頻繁。時(shí)序數(shù)據(jù)庫(kù)在寫(xiě)放大和壓縮率上優(yōu)勢(shì)明顯接入1000個(gè)監(jiān)測(cè)點(diǎn)每天產(chǎn)生的數(shù)據(jù)量也只有幾十萬(wàn)條左右普通機(jī)器完全扛得住。6.2 大屏可視化與告警聯(lián)動(dòng)可視化層我沒(méi)有過(guò)度設(shè)計(jì)。室內(nèi)人流監(jiān)測(cè)系統(tǒng)的用戶(hù)是一個(gè)值班管理員他要看的核心信息只有四塊現(xiàn)在總?cè)藬?shù)多少、各區(qū)域人數(shù)多少、過(guò)去24小時(shí)趨勢(shì)曲線(xiàn)、當(dāng)前運(yùn)行狀態(tài)的設(shè)備數(shù)量。大屏的實(shí)時(shí)人數(shù)展示我用了WebSocket通道推送秒級(jí)刷新。區(qū)域熱度用簡(jiǎn)單的色塊來(lái)表示不需要復(fù)雜的3D場(chǎng)館模型。之所以特意克制展示形式是因?yàn)閷?shí)踐中發(fā)現(xiàn)過(guò)度動(dòng)畫(huà)化的可視化會(huì)讓值班人員失去對(duì)關(guān)鍵數(shù)字的敏感性。真正有用的告警不是花哨的彈窗而是清晰的分級(jí)狀態(tài)人數(shù)達(dá)到容量的80%顯示黃色提醒超過(guò)100%觸發(fā)紅色預(yù)警并通過(guò)廣播接口提示現(xiàn)場(chǎng)工作人員啟動(dòng)限流措施。告警聯(lián)動(dòng)還有一個(gè)容易忽視的細(xì)節(jié)告警要可確認(rèn)、可關(guān)閉。如果告警只能自動(dòng)觸發(fā)、無(wú)法被人工確認(rèn)那么管理員會(huì)在頻繁的誤報(bào)中產(chǎn)生疲勞最終變成看到紅點(diǎn)也當(dāng)作例行公事。我在告警接口上加了確認(rèn)和備注功能讓管理員能記錄已通知現(xiàn)場(chǎng)引導(dǎo)員疏散這樣后續(xù)復(fù)盤(pán)時(shí)也能弄清楚當(dāng)時(shí)的處置鏈條。7. 實(shí)測(cè)數(shù)據(jù)與踩坑記錄幾個(gè)值得寫(xiě)出來(lái)的真實(shí)問(wèn)題7.1 門(mén)口陰影滯留導(dǎo)致的重復(fù)計(jì)數(shù)上線(xiàn)第一周遇到的第一個(gè)怪問(wèn)題主入口的系統(tǒng)統(tǒng)計(jì)人數(shù)比人工計(jì)數(shù)多了不少而且多出來(lái)的數(shù)字主要集中在下午3點(diǎn)到5點(diǎn)。我?guī)еP記本去現(xiàn)場(chǎng)看日志發(fā)現(xiàn)某幾個(gè)ToF測(cè)距單元反復(fù)出現(xiàn)目標(biāo)進(jìn)入但長(zhǎng)時(shí)間未離開(kāi)的記錄而這個(gè)目標(biāo)的位置恰好是一根大理石門(mén)柱旁邊。排查后確認(rèn)是門(mén)柱形成了測(cè)距盲區(qū)的陰影滯留。目標(biāo)從柱邊走過(guò)時(shí)測(cè)距信號(hào)被柱子遮擋了一部分算法把單個(gè)人拆分成了兩個(gè)目標(biāo)其中一個(gè)目標(biāo)被錯(cuò)誤地判定為長(zhǎng)期駐留。這個(gè)問(wèn)題的修復(fù)不是調(diào)參能徹底解決的而是從根本上調(diào)整了柱邊那一路傳感器的朝向角度同時(shí)在算法中增加了一個(gè)檢測(cè)邏輯兩個(gè)目標(biāo)的空間位置在連續(xù)多幀內(nèi)非常接近則判定為同一目標(biāo)的不同徑向投影合并處理。這類(lèi)問(wèn)題很難通過(guò)實(shí)驗(yàn)室測(cè)試發(fā)現(xiàn)因?yàn)槭覂?nèi)測(cè)試環(huán)境不可能覆蓋場(chǎng)館門(mén)口的各種物理結(jié)構(gòu)。我能給的建議是在算法邊緣節(jié)點(diǎn)上保留足夠長(zhǎng)的原始調(diào)試日志第一周留下原始測(cè)距數(shù)據(jù)方便定位問(wèn)題根源。7.2 金屬安檢閘機(jī)帶來(lái)的多徑干擾第二輪問(wèn)題出現(xiàn)在貴賓通道。貴賓通道安裝有金屬安檢閘機(jī)閘機(jī)旁邊是金屬材質(zhì)的門(mén)框。部署完成后貴賓通道的離開(kāi)事件數(shù)明顯偏高于進(jìn)入事件數(shù)而且高頻出現(xiàn)在設(shè)備開(kāi)啟后的前30分鐘。用頻譜分析工具看了當(dāng)時(shí)的無(wú)線(xiàn)環(huán)境結(jié)合現(xiàn)場(chǎng)物理結(jié)構(gòu)推斷應(yīng)該是金屬閘機(jī)表面反射導(dǎo)致ToF測(cè)距信號(hào)出現(xiàn)多徑效應(yīng)產(chǎn)生了額外的虛假目標(biāo)。毫米波雷達(dá)方案在這種環(huán)境下的抗干擾能力會(huì)更強(qiáng)但我們已經(jīng)選了ToF方案調(diào)整手段是有限的。最終通過(guò)姿態(tài)調(diào)整和虛擬墻機(jī)制解決了問(wèn)題將傳感器盡量避開(kāi)閘機(jī)金屬面的正反射區(qū)同時(shí)在算法中把通道兩側(cè)的固定金屬結(jié)構(gòu)識(shí)別為背景點(diǎn)云建了一張?zhí)摂M屏蔽墻凡是落在屏蔽墻內(nèi)的測(cè)距點(diǎn)一律不參與目標(biāo)聚類(lèi)。這個(gè)方法比較笨但效果直接貴賓通道后續(xù)的誤差率降到了2%以?xún)?nèi)。這個(gè)經(jīng)驗(yàn)帶給我一個(gè)教訓(xùn)場(chǎng)館內(nèi)做傳感器部署時(shí)不能只看裝在哪合適還要觀(guān)察周?chē)欠翊嬖诖竺娣e固定金屬結(jié)構(gòu)。凡是存在這種結(jié)構(gòu)的區(qū)域都要提前規(guī)劃傳感器角度和算法屏蔽策略。7.3 網(wǎng)絡(luò)波動(dòng)導(dǎo)致的時(shí)序抖動(dòng)與補(bǔ)償機(jī)制最后一個(gè)值得分享的問(wèn)題是消息亂序。某天后臺(tái)運(yùn)維突然發(fā)現(xiàn)告警引擎頻繁彈出數(shù)據(jù)延遲但各監(jiān)測(cè)點(diǎn)狀態(tài)看起來(lái)卻都正常。排查后發(fā)現(xiàn)原因是核心交換機(jī)某端口出現(xiàn)了微小的流量擁塞部分MQTT消息在傳輸路徑上被重新排隊(duì)導(dǎo)致到達(dá)服務(wù)器的順序與節(jié)點(diǎn)發(fā)送順序不一致。消息亂序?qū)?shí)時(shí)人數(shù)計(jì)算是致命的。如果離開(kāi)事件先到、進(jìn)入事件后到服務(wù)器臨時(shí)計(jì)算出的在場(chǎng)人數(shù)就會(huì)短暫虛低雖然最終消息都到了數(shù)據(jù)會(huì)修正但告警引擎會(huì)基于錯(cuò)誤時(shí)間點(diǎn)的數(shù)據(jù)觸發(fā)誤報(bào)。解決辦法就是在協(xié)議中引入seq序號(hào)并增加一個(gè)緩沖隊(duì)列。服務(wù)器接收到消息后不按到達(dá)順序直接計(jì)算而是先進(jìn)入一個(gè)以seq排序的亂序緩沖隊(duì)列等待前序消息補(bǔ)齊后統(tǒng)一重放給計(jì)算服務(wù)。定時(shí)器兜底超過(guò)3秒未補(bǔ)齊的消息直接跳過(guò)避免阻塞后續(xù)消息。同時(shí)告警引擎接收到的人數(shù)變化數(shù)據(jù)增加了一個(gè)小時(shí)級(jí)別的平滑窗口避免單次抖動(dòng)直接觸發(fā)預(yù)警。def replay_messages(message_buf, next_seq): while next_seq in message_buf: process_event(message_buf.pop(next_seq)) next_seq 1這個(gè)邏輯本身不復(fù)雜但加與不加系統(tǒng)的穩(wěn)定性完全是兩個(gè)體驗(yàn)。后來(lái)遇到網(wǎng)絡(luò)波動(dòng)時(shí)告警引擎再也沒(méi)有因?yàn)閬y序產(chǎn)生誤報(bào)。寫(xiě)在最后整套系統(tǒng)從需求梳理到上線(xiàn)運(yùn)行前后花了接近兩個(gè)月。最直觀(guān)的心得是物聯(lián)網(wǎng)系統(tǒng)設(shè)計(jì)的難度從來(lái)不在單點(diǎn)技術(shù)上而在所有環(huán)節(jié)疊加后的可靠性。傳感器精度再高部署位置不對(duì)也白搭通信協(xié)議再快服務(wù)器消息處理邏輯有缺陷也白搭。如果你打算做類(lèi)似的場(chǎng)館人流量監(jiān)測(cè)項(xiàng)目我給三條建議。第一花足夠多的時(shí)間在現(xiàn)場(chǎng)觀(guān)察真實(shí)的人員流動(dòng)模式別急著畫(huà)架構(gòu)圖。第二所有設(shè)備上線(xiàn)前先部署一套小范圍試點(diǎn)把狀態(tài)機(jī)、異常處理邏輯的日志調(diào)出來(lái)逐幀核對(duì)試運(yùn)行至少一周再全面鋪開(kāi)。第三一定要設(shè)計(jì)一套人工抽樣校核機(jī)制沒(méi)有任何算法可以在缺乏真值基準(zhǔn)的情況下自我驗(yàn)證。這套系統(tǒng)的邊緣節(jié)點(diǎn)代碼和后臺(tái)服務(wù)骨架基本都是基于標(biāo)準(zhǔn)MQTT協(xié)議加通用狀態(tài)機(jī)邏輯寫(xiě)的技術(shù)棧沒(méi)有稀有組件任何有基礎(chǔ)物聯(lián)網(wǎng)開(kāi)發(fā)經(jīng)驗(yàn)的人都可以在類(lèi)似場(chǎng)景復(fù)現(xiàn)。希望這次復(fù)盤(pán)能幫你少走一些彎路。