DIY“物聯(lián)網(wǎng)”——自己動手處理傳感器數(shù)據(jù)
點擊:1129
A+ A-
所屬頻道:新聞中心
傳感器已經(jīng)大量部署于實際生產(chǎn)中,涉及航空、電力、醫(yī)療、教育各個行業(yè)的傳感器形成大規(guī)模的工業(yè)物聯(lián)網(wǎng),各式各樣的傳感器產(chǎn)生了大量的數(shù)據(jù),如何去分析這些數(shù)據(jù),作者用RaspberryPi和四個Tinkerforge傳感器DIY了一個辦公室“物聯(lián)網(wǎng)”,模擬了現(xiàn)實生產(chǎn)中傳感器應(yīng)用,為我們帶來了一些有益的借鑒,下面是作者的精彩分析。
以下為譯文:
當(dāng)前的一個客戶項目和一般工業(yè)大數(shù)據(jù)項目的有趣性質(zhì)(數(shù)據(jù)產(chǎn)生于傳感器)給了我啟發(fā),我決定自己動手處理傳感器數(shù)據(jù),我想通過這個小實驗,了解具體如何處理、存儲和分析這些數(shù)據(jù),以及在這一過程中會遇到哪些挑戰(zhàn)?
為了獲取傳感器數(shù)據(jù),我們決定把傳感器安裝到我們的辦公室里,生成我們自己的傳感器數(shù)據(jù),我們發(fā)現(xiàn)Tinkerforge的bricks和bricklets系統(tǒng)非常友好,易于上手,于是我們選擇采用Tinkerforge系統(tǒng)。
我們得到了以下四個傳感器bricklet:
·聲音強度傳感器(實際上是個小麥克風(fēng))
·溫度傳感器
·多點觸摸bricklet(12個自制的可連接鋁箔墊)
·運動探測器
四個bricklet都連接到主bricklet上,然后將主bricklet連接到RaspberryPi。
我們把溫度傳感器放在辦公室的中央,將運動探測器安裝在廚房和浴室之間的走廊里,把聲音強度傳感器放在廚房門邊,而觸摸傳感器則放在咖啡機、冰箱門和廁所的門把上。
雖然這樣的設(shè)備很難跟實際生產(chǎn)中的情形相比(而且為了獲取足夠多的數(shù)據(jù),你需要等很長時間),在這次小小的實驗中,我們還是很快遇到了那些現(xiàn)實傳感器應(yīng)用過程中的一些關(guān)鍵問題。
我們選擇了MongoDB作為存儲解決方案,主要是因為我們的那個客戶項目也使用了MongoDB。
四個傳感器產(chǎn)生的數(shù)據(jù)可以分為兩類:溫度和聲音強度傳感器輸出連續(xù)的數(shù)據(jù)流,運動探測器和多點觸摸傳感器往往是由非固定頻率的事件觸發(fā)。
這就形成了MongoDB中兩種不同的文檔模式。對于第一類(流),我們使用MongoDB推薦的模式,實際上也是這種情況下的最佳實踐,即“時間序列模式”,由一個內(nèi)部的嵌套文檔集合組成。嵌套的層數(shù)和每個級別子文檔的數(shù)量取決于數(shù)據(jù)的時間粒度。在我們的實驗中,Tinkerforge傳感器的最高時間分辨率為100ms,產(chǎn)生了下面的文檔結(jié)構(gòu):
·每小時一篇文檔
·字段:小時時間戳、傳感器類型、值
·值:嵌套的子文檔(subdocument)集,每分鐘60個子文檔(subdocument),每一秒60個子文檔(subdoc),每1/10秒10個子文檔(subdoc)
MongoDB中文檔是預(yù)先分配的,預(yù)先對所有的字段進行初始化,保證初始值大于傳感器的數(shù)據(jù)范圍,這樣做是為了避免由于MongoDB數(shù)據(jù)庫中文檔持續(xù)增多造成的麻煩。
第二個類型的數(shù)據(jù)(事件驅(qū)動/觸發(fā))以類“bucket”文檔模式存儲。針對每個傳感器的類型,需要預(yù)先為值分配固定數(shù)量的條目(一bucket分配100個)。當(dāng)事件發(fā)生時,將其寫入這些文件中,每個事件對應(yīng)100個條目組的一個子文檔,子文檔貫穿著事件的始終。當(dāng)記錄/事件第一次被寫入到文檔中時,全部文件獲取與開始日期對應(yīng)的時間戳。每次寫入到數(shù)據(jù)庫時,應(yīng)用程序都會檢查當(dāng)前記錄是否已經(jīng)寫入到當(dāng)前文檔,如果寫入已經(jīng)完成,它會設(shè)置文檔的結(jié)束日期/時間并啟動引導(dǎo)到下一文檔的寫入。
這兩個文檔模式表示權(quán)衡的邊界情況,在傳感器數(shù)據(jù)中比較常見。
MongoDB推薦的“時間序列”模式很適合高效寫入,而且兼具良好、一致性架構(gòu)的優(yōu)勢:每個文檔都對應(yīng)著一個時間單位(在我們的實驗中,時間單位為一個小時),這使得管理和檢索數(shù)據(jù)非常方便。此外,還可以很容易從當(dāng)前的時間推斷出要寫入的“當(dāng)前”文檔,所以應(yīng)用程序不需要一直對文檔進行追蹤。
嵌套結(jié)構(gòu)實現(xiàn)了對不同粒度級數(shù)據(jù)的整合——雖然應(yīng)用中這些整合不得不手動執(zhí)行。由于這樣一個事實,在該文檔模式中,“分鐘”、“秒”和“毫秒”不再有單一的鍵,相反,每一分鐘、每一秒、每一毫秒都有各自的鍵。
一旦數(shù)據(jù)變得稀疏、不連續(xù),這個模式就會出現(xiàn)問題。實驗中,這些數(shù)據(jù)顯然是由運動探測器和多點觸摸傳感器產(chǎn)生:由于事件是隨機發(fā)生的,所以數(shù)據(jù)也沒有固定的頻率。對于時間序列文檔模式,這就意味著文檔的某些字段永遠用不到,這顯然是對磁盤空間的一種浪費。
如果傳感器數(shù)據(jù)開始時不是通過事件驅(qū)動的話,也會產(chǎn)生稀疏數(shù)據(jù)。換句話說,許多傳感器,雖然它們以一個固定的頻率測量數(shù)據(jù),但是只會自動輸出相對于上一次測量改變的值,這個問題已經(jīng)被解決了,如果你想要堅持時間序列文檔模式,就需要經(jīng)常檢查是否有值被傳感器省去,以傳感器發(fā)出的最新值更新數(shù)據(jù)庫。當(dāng)然,這有可能會在數(shù)據(jù)庫中引入大量的冗余。
Bucket模式中用實際已記錄的數(shù)據(jù)填充文檔,避免了這一問題,但它也有自身的缺點:
·應(yīng)用程序需要處理有可能出現(xiàn)的全部數(shù)據(jù)重建問題(包括尚未保存的冗余數(shù)據(jù))
·“bucket”文件沒有一致的開始和結(jié)束時間——如果你對特定時間范圍感興趣,你就必須查找該范圍內(nèi)的所有文件
·“bucket”的管理(跟蹤當(dāng)前的bucket,檢查bucket是否為滿)需要應(yīng)用程序解決
Tinkerforge傳感器帶有多語言版本的API,我們決定使用Python,在連接傳感器的RaspberryPi上運行腳本,數(shù)據(jù)則寫入到MongoSoup托管的MongoDB實例中,MongoSoup是我們的MongoDB即服務(wù)解決方案。通過API注冊例如聲音強度和溫度bricklet,你需要執(zhí)行下列操作:
TinkerforgeAPI支持通過回調(diào)函數(shù)從傳感器中自動地讀取數(shù)據(jù)。若要使用此功能,你需要注冊你想要通過bricklet觸發(fā)的功能:
它將以每100ms的速度自動查詢傳感器的新數(shù)據(jù)并分別調(diào)用stream_handler.cb_intensity_SI和stream_handler.cb_temperature函數(shù)。
為了節(jié)省網(wǎng)絡(luò)帶寬,只在上一次傳感器的測量值發(fā)生改變時,你提供的功能才會被觸發(fā)——也產(chǎn)生了上文討論的稀疏數(shù)據(jù)。
可以通過直接自定義代碼的方式,以一個固定的頻率查詢傳感器來避免這種現(xiàn)象。但是,就如上文所說的那樣,這會導(dǎo)致數(shù)據(jù)庫中充滿了冗余數(shù)據(jù)。此外,它增加了從傳感器到應(yīng)用程序的網(wǎng)絡(luò)開銷。
最后,其中一個將必須決定哪種模式更適合用例。關(guān)于數(shù)據(jù)模式,MongoDB提供了大量元數(shù)據(jù)模式,你的選擇應(yīng)完全由用例(比如你最有可能遇到的讀/寫模式)來決定。
一個好方法是在決定一個文檔模型之前,問以下幾個問題:
·從整體的角度考慮(考慮到帳戶數(shù)據(jù)庫和應(yīng)用程序性能),是數(shù)據(jù)庫中的稀疏/冗余代價高?還是之后重建應(yīng)用程序中的冗余數(shù)據(jù)代價高?
·數(shù)據(jù)實際上有多大變化?如果周期性的持續(xù)測量比較少,那最好留有一定量的冗余。
·從一個更大的時間尺度看,有恒定的頻率嗎?例如,你的數(shù)據(jù)主要是以幾秒鐘為周期的分段常數(shù),而這些周期的長度相同,那你可能需要考慮粗?;瘯r間尺度,丟掉小尺度內(nèi)的冗余信息。
·假如出現(xiàn)另一種情況,常數(shù)的長度變化太快,事件隨機發(fā)生,那你最好還是選擇用bucket模式。
在我們的實驗中,最初的假設(shè)是溫度數(shù)據(jù)和聲音強度數(shù)據(jù)會有很大變化,我們需要將它們存儲在“時間序列”數(shù)據(jù)模式中,而運動探測器和觸摸傳感器數(shù)據(jù)適合用bucket模式,實際上我們也是這么做的。
在完成安裝并執(zhí)行處理傳感器數(shù)據(jù)的Python腳本后,我們開始收集數(shù)據(jù)。
我們使用matplotlib和Flaskweb服務(wù)器框架,搭建起一個小型的web服務(wù),直觀顯示最近收集的數(shù)據(jù)以用于檢查,并將該web服務(wù)部署到Heroku。
我們生成三個plot,第一個隨著時間變化分別顯示觸摸傳感器和運動探測器的事件,其他兩個顯示隨著時間的推移聲音強度和溫度水平,plot中的每個數(shù)據(jù)點平均一秒鐘計算一次。
一眼就能看出辦公室中人員活動產(chǎn)生的不同傳感器數(shù)據(jù)之間存在明顯相關(guān)性。
你可以確定選擇使用bucket模型是正確的,因為經(jīng)常會有在長達20分鐘的時間里,傳感器沒有記錄下任何東西。
看一下溫度數(shù)據(jù),雖然它會有波動,但很明顯這種波動保持在1攝氏度的范圍內(nèi)。如果用例是監(jiān)測全球白天溫度的變化,那很可能需要在時間上采用粗粒度數(shù)據(jù)寫入或者切換到bucket模式。
聲音強度數(shù)據(jù)表現(xiàn)為:長時間的安靜(測量值很小)之后大聲事件突然、短時間爆發(fā)。這樣短時間的數(shù)據(jù)肯定不容許被遺漏,所以上述的粗粒度辦法行不通,不過可以考慮切換到bucket模型,僅向數(shù)據(jù)庫中寫入變化的數(shù)據(jù)測量值。
(審核編輯: 小王子)
分享