UDP 用に Wi-Fi と LoRa 間のゲートウェイを作成する

私には子供の頃からの夢がありました。「WiFi のない」すべての家庭にネットワーク チケット、つまり IP アドレスとポートを発行することです。しばらくして、延期しても意味がないと気づきました。私たちはそれを受け入れて実行しなければなりません。
参照条件
LoRa モジュールがインストールされた M5Stack ゲートウェイにします (図 1)。ゲートウェイは Wi-Fi ネットワークに接続され、DHCP 経由でローカル IP アドレスを受け取ります。ゲートウェイは、その名前 (Wi-Fi の SSID に似たもの) と有効なポートの範囲を特定の周波数で LoRa ブロードキャストにブロードキャストします。これにより、他のデバイスは、接続できるネットワークがあり、その範囲内にあることを認識できます。空いているポートを選択できます。今回はプロトタイプになりますので認証は必要ありません。新しいクライアント デバイスは、利用可能な LoRa ネットワークを見つけて、選択したポートをそこに送信します。ゲートウェイは、新しいクライアントからポートを受信すると、そのポートが空いているかどうかを確認し、空いている場合は、新しいクライアントを登録し、独自の非同期 UDP サーバーでこのポートのリッスンを開始します。登録後、クライアントは宣言されたポートの使用に対する同意または拒否を受け取ります。操作手順を表 1 に示します。

図1
表1
側
方向性とデータ
側
セッション
[ クライアント ]
←ビーコン信号—
[ゲートウェイ]
0xA1
[ クライアント ]
— 選択されたポート —>
[ゲートウェイ]
0×B1
[ クライアント ]
←同意または拒否—
[ゲートウェイ]
0xA2
[ クライアント ]
— UPDパッケージ —>
[ゲートウェイ]
0×B2
[ クライアント ]
← UPDパッケージ —
[ゲートウェイ]
0xA3
[ネット]
← UPDパッケージ —
[ゲートウェイ]
0xC1
目の前のテーブルの上に M5Stack 用のあらゆる種類のモジュールが転がっていて、退屈です。 LoR を楽しんでみましょう。モジュール自体のコンセプトが素晴らしいですね!何て言えばいいでしょうか?しかし、私が所有している最初のリビジョン モジュールには、最もひどい内蔵アンテナがあり、フレキシブル プリント基板上に作られ、ケースの側壁に接着されています。私はかつてそのようなモジュールのフィールドテストを実施しました(YouTubeのロシア語チャンネルで見ることができます)。

当然のことながら、これらの基礎を取り外して、Ra-01 に付属する標準のヘリカル アンテナをはんだ付けする必要がありました。このようなカスタマイズの後、通信範囲は著しく改善されましたが、アンテナの直径がモジュール間の許容距離よりも大きいという副次的な問題が発生しました。プロジェクトの期間中、最終モジュールを放棄する必要がありました。
同期のタイトさによる最初の困難
どうやら図書館に行ってみよう WiFiUdp.h、UDP サーバーが快適に存在するためにすべてが存在する場合、これは当てはまりません。このライブラリは同期サーバーを起動するように設計されていますが、残念ながら、1 つのスレッドで複数の接続を同時に処理することはできません。このようなライブラリは現在のタスクには適していません。私はお茶を何杯も飲みながら、同時に多くの接続をサポートできる非同期 UDP サーバーを構築できるライブラリを探す必要がありました。そんなライブラリが見つかりました - 非同期UDP.h。同期サーバーと非同期サーバーの違いは何ですか?図 2 の XNUMX つのエピソードを見てみましょう。ソケットがどのように機能するかを簡単に示しています。

図2
出演:
人間 役割で ソケット;
ピジョン 役割で 接続;
ピズモ 役割で Даныхх.
エピソード A. タイムアウトなしの同期ソケット
男は鳩が手紙を持ってくるまで立ち続けるだろう。
エピソード B. タイムアウトのある同期ソケット
男は鳩と合意した時間を待ち、時間通りに到着しない場合は立ち去ります。
エピソード C. マルチスレッドを使用した同期ソケット
男は座って、ハトが自分たちで手紙を届けるのを眺めています。
エピソード D. 非同期ソケット (他に受信するものがない場合)
人は自分の好きなことをしますが、ハトのことを忘れません。
エピソード E. 非同期ソケット (何か得がある場合)
その男は鳩からの手紙を受け取るために仕事を少し休んだ。
エピソード F. マルチスレッドを使用した非同期ソケット
男は仕事をしながら、ハトが自分たちで手紙を届けるのを眺めている。
注意していれば、おそらく各エピソードのハトの首輪に特定の色があることに気づいたはずです。これには理由がないわけではありません。エピソード A と B では、サーバー上で動作しているソケットは 2 つだけで、それだけです。エピソード C では、3 つのソケットがすでに動作しています。エピソード D、E、F にはすでに 2 つのソケットがあります。 「なぜあそこには20人、ここには200人いるのですか?」 -あなたは尋ねます。これらは条件付きで XNUMX と XNUMX ですが、実際、XNUMX の代わりに XNUMX、XNUMX つの代わりに XNUMX も可能です。目的は、非同期ソケットが同期ソケットほどアイロンを加熱しないことを示すことです。
どこにどのくらいのものが収まりますか?
UDP パケットの構造を示す表 1 を見て、それを使って何ができるかを考えてみましょう。
表 1. UDP パケットの構造
ビット
0 - 15
16 - 31
0-31
送信元ポート
宛先ポート
32-63
データグラム長 (Length)
チェックサム
64-..。
データ
このテーブルの先頭に別のフィールドを追加してみましょう。 セッション (1バイト)。このプロジェクトにはこれで十分です。セッションに基づいて、デバイスはパケットに対して次に何を行うべきかを認識します。次に、セッション用のコードを考え出し、表 2 に書き留めてみましょう。
表 2. セッションの説明
コード
名前
明確化
0xA1
Маяк
ゲートウェイは、LoRa ネットワークの名前と有効なポートの範囲を特定の頻度でブロードキャストします。これは、新しいクライアントが利用可能なネットワークを認識し、送信がないときに現在のクライアントが信号レベルを判断できるようにするために必要です。
0×B1
リクエスト
クライアントはネットワークを検出すると、優先ポートを送信します。
0xA2
同意または拒否
クライアントが要求したポートが空いている場合、サーバーは同意で応答し、そうでない場合は拒否で応答します。
0×B2
アップリンク
クライアントが UDP パケットをゲートウェイに送信するとき。
0xA3
ダウンリンク
ゲートウェイが UDP パケットをクライアントに送信するとき。
0xC1
アップリンクの継続
ゲートウェイが UDP パケットをローカル ネットワークに送信するとき。
大丈夫。次に、表 3 のセッションの構成について説明します。
表 3. セッション
セッション名
構造
Маяк
セッションコード (1 バイト) + LoRa ネットワーク名 (4 バイト) + 開始ポート (2 バイト) + 終了ポート (2 バイト)
リクエスト
伝送コード(1バイト) + LoRaネットワーク名(4バイト) + 優先ポート(2バイト)
同意または拒否
送信コード (1 バイト) + LoRa ネットワーク名 (4 バイト) + 優先ポート (2 バイト) + 結果 (1 バイト)
アップリンク
伝送コード (1 バイト) + LoRa ネットワーク名 (4 バイト) + リモート IP アドレス (4 バイト) + リモート ポート (2 バイト) + ローカル IP アドレス (4 バイト) + ローカル ポート (2 バイト) + データ サイズ (2 バイト) ) + データ
ダウンリンク
伝送コード (1 バイト) + LoRa ネットワーク名 (4 バイト) + リモート IP アドレス (4 バイト) + リモート ポート (2 バイト) + ローカル IP アドレス (4 バイト) + ローカル ポート (2 バイト) + データ サイズ (2 バイト) ) + データ
アップリンクの継続
リモートIPアドレス(4バイト) + リモートポート(2バイト) + データサイズ(2バイト) + データ
私は Arduino 用と M5Stack 用の XNUMX つのクライアントを作成しました。の上 それがどのように機能するかを見ることができます。アパート内には問題はありませんが、まだフィールドテストは行っていません。
ソース コードは GitHub で入手できます。
M5Stack Base Device の詳細については、こちらから購入できます。
ベースデバイス用に LoRa ワイヤレスモジュールを選択できます
このプロジェクトがお役に立てば幸いです。お時間をいただきまして誠にありがとうございました!
参考文献および(または)出典のリスト:
出所: habr.com
