本文是如何用jxTMS進行數據采集的第二部分,整個系列的文章請查看:docker版jxTMS使用指南:4.4版升級內容
docker版本的使用,請查看:docker版jxTMS使用指南
4.0版jxTMS的說明,請查看:4.0版升級內容
4.2版jxTMS的說明,請查看:4.2版升級內容
設備對數據的處理
設備接收到站點遞交的消息后,會依次完成如下的工作:
1、根據配置用相應的策略來解析所接收到的消息
不同的設備有自己獨特的編碼方式,所以相應的解碼工作單獨抽離出來由該設備的策略來實現。當然,有的解碼工作已經由站點在提取設備標識時就已經完成了,如使用自定義協議包傳送數據的站點。
解析策略一般單獨編寫,然后注冊到系統中。代碼文件應放到app的相應目錄中,并依次在各目錄的__init.py__文件中引用。
main.py文件的加載順序是先import app和module,然后再執行站點的初始化【加載站點和設備】,這就可以在站點加載時正確引用到相應的策略了。
2、觸發數據接收事件來對數據做需要的處理
這里所說的處理主要指數據的轉換、修正等針對數據本身的處理,如潮位儀收到測得的潮位數據后,要根據潮位儀安裝點的標高換算成潮水的實時水位。
在業務上,很多時候我們還需要利用設備數據來啟動業務處理。但筆者認為,為了提高系統的穩定性,最好將業務處理與此處所說的數據處理分隔開來,以最大化的降低代碼的耦合度。
那么,不在此處啟動業務處理,那在什么時候呢?!請參考之前的【本地數據總線】一文,筆者就是基于此種考慮,才增加了數據總線機制。
在需要執行業務處理時,通過向數據總線注冊一個興趣點來抄收設備接收并處理好的數據,然后完成需要的業務操作,從而將業務處理代碼從整個設備數據處理流中分離出來,不會對設備的數據處理與保存過程產生任何干擾與影響。
尤其是在業務頻繁變動的場景中,此種方案更具穩定性與可靠性。
3、設備數據的保存
接收并處理完畢的設備數據會被保存到數據庫中,而這就需要完成兩個動作:
-
根據配置將處理后的設備數據保存到數據庫中的哪個數據表中
-
由于設備數據的采集頻率可能會很高,如果數據的短期變化又不太重要,可以必要綜合考慮是實時保存所有設備數據,還是周期性保存最新的設備數據
當給出了設備數據的保存間隔【saveDataInterval】參數時,該設備的數據將以saveDataInterval【單位:分鐘】為間隔進行保存,如果該參數為0,則實時保存每一個新數據。
此外,由于設備的數據采集頻次一般都很高,所以大多數情況下,都需要進行分表。如果需要分表的話,對于啟動了jxTMS主系統的主站來說,只要在data文件中相應的數據類定義時指定rename屬性即可。
注:如果是不啟動jxTMS主系統的從站,如用于現場modbus設備采集,這些數據如果也需要保存到現場的數據庫中,并同樣需要分表,也很簡單,一是【app/data/DieselGenerator.py】中展示的,提供一個_sql_createTable建表語句【通過查詢主站所創建的該表的建表語句獲得】;二是將此建表語句注冊到jxTMS中:
ORM.registerSQL_createTable('DieselGenerator',_sql_createTable,renameType='day')
最后,在main.py中調用:
#啟動創建需要分表的調度器
ORM.startRenameTableScheduler()
從站即會同樣完成所有注冊建表語句時指定了renameType的分表工作。
原則上,我們建議盡可能的使用jxTMS主系統來完成分表工作,原因很簡單,風險有點高。python側來執行分表工作,就意味著,真有需要調整data中的數據類定義的時候,必須同時完成:
-
修改data文件中的數據類定義,否則java的jxTMS主系統在管理時會出錯
-
修改mysql中該數據庫表的定義【新的表會自動更新】
-
修改python側的建表語句,并重啟python側的代碼
前兩者都比較簡單,尤其是mysql比較熟悉的情況下;但后者,必須進行相關的全業務測試,尤其是還需要重啟服務器,所以風險高了很多。
分表數據的查詢,可以利用前面文章中講解過的query對象【參考:數據查詢】,非常的簡便。
4、站點綜合
一般情況下,站點都是管理方面的作用大于數據處理方面的作用,如開通、停運、對設備的管理/配置等。但有時也確實需要站點綜合下屬所有設備的數據以提供業務上的支撐。
如,配電系統的告警處理,管理方關心的是母線電壓、儲電系統的SOC等配電系統的綜合性健康指標。但這些指標卻是分別采集自下屬的各個設備的某幾個數據點。
這種情況下,以站點來統一過濾并綜合這些關鍵指標就是必然的選擇了。
因此,站點在接收并提取出設備信息后,調用distribute函數來將接收到的數據分發給相應的設備:
def distribute(self, d, data):
其使用一般是在站點的receive中,如site_multiDev_push類型的站點:
def receive(self, bsMsg):s = str(bsMsg,"utf8")js = json.loads(s)dn = js.get('dn')if not dn is None:d = self.getDev(dn)if not d is None:self.distribute(d,js)
distribute在向下屬設備分發數據后,會將設備回傳的數據回傳給站點內部的receiveData函數,以完成站點的數據綜合處理框架。該框架完成:
-
設備對站點的通知,目前主要是跟蹤狀態改變以完成相應的告警處理
-
站點觸發onReceive事件來對設備回送的數據進行必要的綜合
-
如果必要【重載newOrmData函數并返回站點數據對象】,保存【實時或周期性】站點綜合后的數據
5、數據聯動
數據處理完畢,設備會通過數據總線發送自己接收并處理完畢的數據,所有對該設備的數據感興趣者,都可以注冊到數據總線上,接收到此新收數據事件并執行自己的處理。
前文說過,jxTMS以此種方式實現數據處理與業務處理的隔離,以提供更好的靈活性、彈性。比如,不停機重啟的動態升級業務功能。
所以,使用jxTMS時應盡可能的將數據方面的處理與業務方面的處理區分出來,在設備與站點的onReceive事件【需要的話】中只完成數據轉換、調整、綜合、加工等工作。和業務相關的處理則通過監聽數據總線的方式放到另外的代碼模塊中完成。
這種方式雖然看起來比較繁瑣,而且效率有些低,但由于充分的隔離了數據處理與業務處理,所以業務的變動不會干擾到數據處理框架的正常工作,使得不管什么樣情況下,總能穩定而可靠的接收、處理并保存正確的數據。
目前,數據總線還只是本地的數據總線,有需要的話,數據總線可以基于MQ實現異機聯動,就如jxTMS的java側管控平臺那樣,從而進一步的提高數據處理的穩定性與可靠性。
6、告警
目前主要是針對超時未接收到設備數據發出告警。
現版本是將告警放到了設備處,考慮到收不到數據一是設備故障、二是線路故障,所以新版本會將告警收到站點處進行,以兼顧這二者。
新版本的故障告警機制是:
-
某站點處于正常狀態時【剛開機或當下屬所有設備都正常工作時】第一次收到失聯,則發送故障告警
-
當出現失聯后,每半個小時發送一次當前的故障綜述,即當前失聯設備的列表與第一次故障的時間點
-
當所有失聯設備都恢復正常后,發送一個全站恢復的通知
目前,jxTMS只有一個默認的釘釘告警策略,但如果服務器網絡中斷,則依然無法發出告警,所以如果對告警非常敏感,還應增加一個網絡之外的告警通道或機制。
參考資料:
jxTMS設計思想
jxTMS編程手冊
下面的系列文章講述了如何用jxTMS開發一個實用的業務功能:
如何用jxTMS開發一個功能
下面的系列文章講述了jxTMS的一些基本開發能力:
jxTMS的HelloWorld