C# TLMForwarder のバースト対応
Back
Alt+HOME
Burst Data をそのまま転送処理すると連続データが1パケットとして処理され正しいテレメトリーとならないためバッチ処理ですべて受信後に分解転送する仕様に変更してみた。
図中上半分が、幾つかのフレームが連なった、バーストデータである。1ファイル分読み込みと分割が終了すると・・・・
それぞれのフレームを通常転送する
FORWARD PROCESSルーティンで個別に
SatNOGS へ送信する。
Span<T>, Memory<T> (.NET 6.0以降) を使用してバイナリーを分割
// バースト受信が有効になっている時
if (ChkBurst.Checked == true)
{
// BurstとForwardingのラジオボタンが両方とも有効な場合
if (ChkForwarding.Checked == true)
{
// ファイルが存在するか確認
if (File.Exists(バイナリーデータのパス))
{
// ファイルからすべての行を読み込む
byte[] recvData = File.ReadAllBytes(バイナリーデータのパス);
// recvDataをseparatorで区切って分割 (SplitBinaryData関数へ)
List<byte[]> chunks = SplitBinaryData(recvData);
// 分割結果を転送(確認 Debug.WriteLine)
for (int i = 0; i < chunks.Count; i++)
{
// Debug.WriteLine($"{i + 1}: {BitConverter.ToString(chunks[i])}"); // Debug用出力
通常の転送処理(chunks[i]);
}
// 1ファイルすべて転送終了したらバースト処理を終了する
UpdateCheckBox(ChkBurst, false);
UpdateCheckBox(ChkForwarding, false);
UpdateTextBox($"\r\nDone the FORWARD PROCESS.\r\n");
}
}
// recvDataをスペース区切りの16進数テキストに変換
string hexString = string.Join(" ", data.Select(b => b.ToString("X2"))).ToLower();
// Telemetry Tabに表示
UpdateTextBox(hexString);
}
else
// 通常の1パケットごとに受信する時
{
通常の転送処理(recvData);
}
=MEMO= 運用操作としては、ラジオボタンの組み合わせで受信待機(Burst:ON = 自動的にForward:OFF)と受信後バッチ送信(Bust:ON + Forwarding:ON)となる。
// Burst DATA をセパレータで分割して個々ののフレームにする
static List<byte[]> SplitBinaryData(byte[] recvData)
{
List<byte[]> result = [];
ReadOnlySpan<byte> dataSpan = recvData;
ReadOnlySpan<byte> separatorSpan = [0xC0, 0x00];
int startIndex = 0; // statIndexの初期化
// 最初のセパレータをチェック
if (dataSpan.StartsWith(separatorSpan))
{
// 先頭セパレータをスキップ
startIndex = separatorSpan.Length;
}
while (startIndex < dataSpan.Length)
{
int separatorIndex = dataSpan[startIndex..].IndexOf(separatorSpan);
if (separatorIndex == -1)
{
// セパレーターが見つからなければ最後までを追加
result.Add(dataSpan[(startIndex - separatorSpan.Length)..].ToArray());
break;
}
// セパレーターを含めた範囲を取得
int endIndex = startIndex + separatorIndex;
result.Add(dataSpan[(startIndex - separatorSpan.Length)..endIndex].ToArray());
startIndex = endIndex + separatorSpan.Length; // セパレーターの次から開始
}
return result;
}
上段のコードにある Debug.WriteLine を有効にして出力すると下のように分割されているのが分かる。
1: C0-00-4A-47-36-59-42-57-30-4A-47-36-59-4D-58-30-3E-F0-FF-F0-FF-00-00-3B-33-33-22-39-02-00-06-AA-AA-AA-03-68-06-14-06-32-06-57-06-97-05-62-06-41-0C-D5-0D-5D-0D-46-0D-49-0C-C9-01-17-06-07-01-B3-A4-08-40-A4-0D-C4-01-85-00-00-BB-A0-06-00-04-00-00-F7-E0-CC-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-44-44-44-44-44-C0
2: C0-00-4A-47-36-59-42-57-30-4A-47-36-59-4D-58-30-3E-F0-FF-F0-FF-00-00-3C-33-33-03-3B-02-00-06-AA-AA-AA-03-9F-06-12-06-26-06-46-06-92-05-76-06-39-0D-5F-0D-54-0D-0C-0D-44-0D-5B-0E-09-01-02-0A-B3-A4-08-48-A4-0D-C4-01-8C-00-00-BB-A0-06-00-05-00-00-F7-E0-CC-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-44-44-44-44-44-C0
3: C0-00-4A-47-36-59-42-57-30-4A-47-36-59-4D-58-30-3E-F0-FF-F0-FF-00-00-49-33-33-21-12-03-00-06-AA-AA-AA-04-0D-05-EB-06-05-05-F9-05-F4-06-30-06-19-0D-79-0D-A5-0B-4E-0D-A0-0C-1E-02-13-00-0B-01-AF-A4-08-3A-A4-0D-C9-01-7F-00-00-BB-A0-06-00-0D-00-00-F7-E0-CC-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-FF-44-44-44-44-44-C0
:
:
これらのフレームを一つずつ、転送に対する応答の 201 を確認しながら、最後まで繰り返す事になる。
別スレッドからUIスレッドのコントロールを変更する
UpdateTextBox() は、UI要素であるテキストボックスが作成されたスレッド以外から、安全に書き込める様にするために Invoke を使用して、別途作成した関数である。
// UI要素(TxtTelemetry)が作成されたスレッド以外から安全に書き込める様にする
private void UpdateTextBox(string text)
{
if (TxtTelemetry.InvokeRequired)
{
TxtTelemetry.Invoke(new Action<string>(UpdateTextBox), text);
}
else
{
if (!TxtTelemetry.IsDisposed)
{
TxtTelemetry.AppendText(text);
}
}
}
次に示す同様のUIスレッドに対する変更は、目的のコントロールと変更内容を指定して呼び出すことで、使い回しが出来るようにしたものである。
// UIスレッドのChkBurstを変更する
private static void UpdateCheckBox(CheckBox chkBox, bool isChecked)
{
if (chkBox.InvokeRequired)
{
// UIスレッドにデリゲートを送る
chkBox.BeginInvoke((System.Windows.Forms.MethodInvoker)delegate {
chkBox.Checked = isChecked; // 無効にする
});
}
else
{
// UIスレッドにいる場合はそのまま実行
ChkBox.Checked = isChecked;
}
}
呼び出す時は UpdateCheckBox(ChkBoxName, true) のようになる。
Back
Alt+HOME
この 作品 は
クリエイティブ・コモンズ 表示 - 非営利 - 改変禁止 4.0 国際 ライセンス
の下に提供されています。
English
Powered by