2016-11-15 6 views
2

私たちのアプリケーションの1つはセンサーによって送信されたデータを受信します。メッセージの内容を調べることによって、アプリケーションは、どのタイプのメッセージを見ているのか、センサーが動作しているファームウェアのバージョンを把握しなければなりません。新しいバージョンのファームウェアは余分なデータを送信するため、別の方法で処理する必要があります。構造化されていないメッセージからデータを抽出するためのパターン

以下の例では、異なるバージョンのデータメッセージと、異なる構造を使用する構成メッセージを示しています。

一部のデータはコンマ区切りで、一部は新しい行で区切られています。メッセージには、メッセージタイプを決定するのに役立つマーカーもあります。

私たちはメッセージの構造を変更することができず、メッセージにファームウェアのバージョンが示されていないことを前提に、データを解釈する明確かつ維持可能で拡張可能な方法の提案と例を探しています。私たちができる最善のことは、私たちの目的のためにできるだけ優雅に物事を処理することです。

通常のメッセージの旧バージョン

[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] 

、あなたが示した3つのメッセージは、その一般的なフォーマットを持っています。

これを段階的に行うことをおすすめします。まず、バッファ内に完全なメッセージが得られるまでデータを収集します。つまり、メッセージは[MSG]で始まり、[MSGEND]で終わります。基本的な考え方を根本的に変えないので、ここでは通信の失敗や腐敗の可能性を無視するつもりです。 何とかバッファに完全なメッセージを取得します。

これで解析を開始できます。メッセージの最初の行([MSG]の後)には、メッセージの種類を判別できる情報が含まれているようです。あなたのサンプルでは、​​通常のメッセージは最初の行で '4'で始まり、最初の行で '2'で始まります。

次のグループの行は、タイプ固有の情報を示すようです。メッセージタイプが何であるか知っていれば、これをどのように解釈するのか知っています。古いメッセージと新しい通常のメッセージの場合は、その5行目の存在によってメッセージのタイプを知ることができます。

そしてもちろん、[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]" 

あなたは、4つの異なるリストにそれらのデータラインを読めば、あなたは、データを調べて、それがメッセージの種類を決定することができます。そこから、その特定のメッセージタイプを解析して処理するための特定の関数に分岐します。

あなたはいくつかのコードを繰り返すことになりますが、処理の仕方がわかると、いつでもそのコードを抽象化できます。

これは確かに明確で維持可能です。拡張可能かどうかは、拡張可能な定義に依存します。このモデルでは、すべてのメッセージが同じ一般形式に従う限り、新しいタイプのメッセージとそれに対応する処理メソッドを簡単に追加できます。

メッセージを受け取り、関連する部分に分割できる正規表現を作成しようとしないように注意します。十分な困惑で、おそらくそのような正規表現を作成することができます。確かに、その正規表現は、大部分がほとんど読めなくなり、修正が難しく、正しいと証明され、おそらくわずかなフォーマットの偏差が許されなくなります。

0

十分な大きさのメッセージ(たとえば100)を分析すると、パターンに気づくでしょう。センサーの読み取り値を持つ非構造化メッセージは非常にまれです。

一度識別されると、メッセージをタイプ(たとえば、あなたの例に基づいてデータメッセージや設定など)ごとに一致させるのが最も簡単でクリーンです。たとえば、この正規表現はあなたの "古い/レガシー"または新しいメッセージと一致しますが、設定メッセージは一致しません。メッセージが「新規」の場合、2つのキャプチャグループがあります。最初は10桁のファームウェアで、もう1つはデータ(センサーの読み取り値)付きです。メッセージは、「古い/レガシー」であれば、正規表現は、センサーの測定値で、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\]$ 

を、私の例はまさにそれである - 例 - それは、より多くの、検証のために、より多くのデータを必要としますセンサータイプなどを決定するためにグループを捕捉する。しかし、これが私があなたの問題に近づく方法です。

正規表現の資源:

ここregex101.comに、この正規表現にlinkです。

私は正規表現の視覚化のためにかなりregexper.comが好きです(読んでいるよりも書く方が簡単です、imho)。ここには同じ正規表現visualizedがあります。

注意、私は、データキャプチャグループの可視化からマルチラインフラグ-(?m:を削除しました。厳密には必要ではありません。あなたの一般的なメッセージフォーマットがあるよう

関連する問題