2016-11-15 56 views
2

我們的一個應用程序的接收由傳感器發送的數據。通過檢查消息的內容,應用程序必須找出它正在查看的消息類型以及傳感器運行的固件版本。較新的固件版本發送額外的數據,必須以不同的方式處理。模式用於從非結構化消息中提取數據

我提供以下示出的數據消息的不同版本以及使用不同結構的配置消息的例子。

你可以看到一些數據是逗號分隔的,而有些則通過新線分離。消息中還有標記可用於確定消息類型。

既然我們不能改變的消息結構和該消息並不表示他們的固件版本,我正在尋找的建議和解釋數據的清晰,可維護,可擴展的方法的例子。我們能做的最好的事情就是儘可能優雅地處理事情。

舊版本的普通消息的

[MSG] 
4 031116 080423 

543215432154321 
3711mV 
30 
1,0,0 

[READINGS] 
00451,00450,00402,06017 
00000,021116 083000 
00000 
00000 
00000 
00000,031116 080000 
[MSGEND] 

的新版普通消息的

[MSG] 
4 031116 080423 

543215432154321 
3711mV 
30 
1,0,0 
**0000006216** <- Extra data added on extra line 

[READINGS] 
00451,00450,00402,06017 
00000,021116 083000 
00000 
00000 
00000 
00000,031116 080000 
[MSGEND] 

配置報告

[MSG] 
2 050416 194503 

3913mV 
30 
1,1,0 
0000006216 

[CONFIG] 
543215432154321 
234,15,0037,01DE,-60,234,15,0037,42B0,-76 
[MSGEND] 
+0

消息是如何識別的?參數總數?每行參數?參數的順序? []標記?每個標記的參數?一旦清楚瞭解確定消息類型的條件,就可以檢查這些條件並從數據中創建更多可用的消息對象。 – EpicSam

+0

消息類型(閱讀/配置)可以由[CONFIG]標誌確定。 固件版本比較困難。這取決於在更新版本的固件中尋找額外的數據。 –

+0

然後先檢查標誌以確定消息類型。之後,計算[MSG]和[MESSAGETYPE]之間的參數數目以確定固件版本? – EpicSam

回答

1

看起來像你一般的消息格式爲:

[MSG] 
<one or more lines> 
blank line 
<one or more lines> 
blank line 
[SOME TEXT] // (i.e. [READINGS or CONFIG] 
<one or more lines> 
[MSGEND] 

至少,你們就有了三個消息有一般格式。

我會建議分階段進行。首先,收集數據,直到您在緩衝區中獲得完整的消息。也就是說,該消息以[MSG]開始並以[MSGEND]結束。我會忽略這裏溝通失敗或腐敗的可能性,因爲它並沒有從根本上改變基本的想法。 不知何故得到一個完整的消息到緩衝區。

現在您可以開始解析。它看起來像消息的第一行(在[MSG]之後)包含一些信息,您可以從中確定消息的類型。在您的示例中,正常消息以第一行中的'4'開頭,配置以第一行中的'2'開頭。

下一組行似乎給出了類型特定的信息。如果你知道消息類型是什麼,那麼你知道如何解釋這個。在舊的和新的正常消息的情況下,你可以通過第五行的存在來判斷它是什麼類型的消息。

而且,當然,在[CONFIG][READINGS]之後的行給出了具體的信息。

它應該是很簡單的創建一個消息處理的通用模板:如果你看到了那些數據線分成四個不同的列表

Read "[MSG]" 
Read identification information up to a blank line 
Read blank line 
Read more specific message information -- up to a blank line 
Read blank line 
Read line with "[CONFIG]" or "[READINGS]" 
Read data lines up to "[MSGEND]" 
Read "[MSGEND]" 

,那麼你就可以檢查數據,並確定它是什麼類型的消息。從那裏,分支到分析和處理特定消息類型的特定功能。

您最終會重複一些代碼,但您可以隨時抽象出一旦您確定了是否想要執行處理。

這當然清晰可維護。它是否可擴展取決於您的可擴展定義。使用此模型,只要消息都遵循相同的一般格式,就可以輕鬆添加新類型的消息及其相應的處理方法。

我會反對嘗試創建一個可以接收消息並將其拆分爲相關部分的正則表達式。有了足夠的困惑,你可以創建這樣一個正則表達式。某些情況下,正則表達式在大多數情況下幾乎不可讀,難以修改並證明是正確的,並且可能非常容易出現輕微的格式偏差。

0

我想如果你分析一個足夠大的消息樣本(比如100),你會發現一個模式。攜帶傳感器讀數的非結構化信息非常少見。

一旦確定,你會發現它最簡單,最乾淨的類型相匹配的信息(比如,數據信息和配置的基礎上,你的例子)。例如,這個正則表達式將匹配你的「舊/舊」或新消息,但不匹配配置消息。如果消息是「新的」,則會有2個捕獲組 - 第一個包含10位固件,第二個包含數據(傳感器讀數)。如果消息是「老/遺留」,正則表達式將只包含1捕獲組,與傳感器讀數:

^\[MSG\]\n[\d ]+\n{2}\d{15}\n\d{4}mV\n\d{2}\n\d,\d,\d\n?\*{0,2}(\d{10})?\*{0,2}\n{2}\[READINGS\]\n(?m:([\d\s,]*))\[MSGEND\]$ 

當然,我舉的例子就是這樣 - 一個例子 - 它需要驗證更多的數據,更多的捕獲組以確定傳感器類型等;但這是我如何處理您的問題。

正則表達式的資源:

這裏有一個link這個正則表達式的regex101.com。

我也喜歡regexper.com相當多的正則表達式的可視化(他們比閱讀更容易寫,恕我直言)這是相同的正則表達式visualized

注意,我去掉了多線標誌 - (?m: - 從可視化數據捕獲基團。這不是絕對必要的。