LoginSignup
1

More than 3 years have passed since last update.

ETロボコン Bluetoothログ受信②

Posted at

こちらの記事はケーシーエスキャロット Advent Calendar 2019の8日目の記事です。
昨日…、ではなく一昨日はaookiさんの自作キーボードを作りましたでした、自作キーボード、興味はあるのですが、手が出せていません。

さて、1年ほど前、VB.Net で Bluetooth を経由してロボットからログを取得・表示するツールを作成する記事を記載しました。

その記事の最後

  • 受信したログをファイルに保存
  • ログにキーワードを紐付けて、絞り込みを行う

等を追加すると利便性が高まると記載したのですが、その部分を1年越しに追加してみたいと思います!

前提条件

VB.Net で Bluetooth を経由してロボットからログを取得・表示するツールの内容に沿って、既にロボットとbluetooth通信が行えていること。

フォームの配置

前回から新たに追加するコンポーネントは以下の通り。

cap2.png

コード(VB.Net)

コンポーネントを配置したら、コードを記載していきます。

データセットの追加

プロジェクト内に、新規にデータセットを追加します。

追加方法は以下の通りです。

  1. ソリューションエクスプローラー内のプロジェクト名を右クリック
  2. コンテキストメニューで追加 -> 新しい項目を選択
  3. 新しい項目の追加ダイアログでデータセットを選択

また、追加したデータセットへ、下図のような名称で DataTable を追加、その DataTable 内に列(DataColumn)を2つ追加します。

プロパティ.png

更に、コードとして以下のクラス・メソッドを追加します。

EtRoboData.vb
Partial Class EtRoboData

    Public Function AddBtRecvLogRow(ByVal recv As String) As String

        Const DELIMITER As String = ")]"

        Dim row As BtRecvLogRow = Me.BtRecvLog.NewBtRecvLogRow()

        Dim index As Integer = recv.IndexOf(DELIMITER)

        If index < 0 Then

            row.Tag = "notag"
            row.Log = recv

        Else

            row.Tag = recv.Substring(0, index)
            row.Log = recv.Substring(index + DELIMITER.Length)

        End If

        Me.BtRecvLog.AddBtRecvLogRow(row)

        Return row.Tag

    End Function

End Class

追加したデータセットをフレーム内にメンバ変数として追加。

frmMain.vb(追加)
    Private m_EtRoboData As New EtRoboData() '追加
    Private Delegate Sub addRecvLogDataDelegate(recv As String)

前回追加したaddRecvLogDataメソッドを以下のように変更。

frmMain.vb(更新)
    Private Sub addRecvLogData(recv As String)

        Dim lines() As String = Split(recv.Replace(vbCr, String.Empty), vbLf)

        If lines.Length <= 1 Then

            Return

        End If

        For Each line As String In lines

            If String.IsNullOrEmpty(line) Then

                Continue For

            End If

            Console.WriteLine(line)

            addCmbTag(m_EtRoboData.AddBtRecvLogRow(line))
            Me.lstLog.SelectedIndex = Me.lstLog.Items.Count - 1

        Next

    End Sub

今回追加したコンポーネント群の初期化処理。

frmMain.vb(追加)
    Private Sub initDataTable()

        Me.lstLog.DataSource = m_EtRoboData.BtRecvLog
        Me.lstLog.DisplayMember = m_EtRoboData.BtRecvLog.Columns(1).ColumnName

    End Sub

    Private Sub clearCmbTag()

        Me.cmbTag.Items.Clear()
        Me.cmbTag.Items.Add(String.Empty)

    End Sub

    Private Sub addCmbTag(ByVal tag As String)

        If Me.cmbTag.Items.Contains(tag) Then

            Return

        End If

        Me.cmbTag.Items.Add(tag)

    End Sub

イベントハンドラ

追加した各初期化処理をロード部分へ追加、さらに新しく追加したコンポーネントのイベントハンドラを追加します。

frmMain.vb(更新)
    Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        initPortName()
        initDataTable() '追加
        clearCmbTag()   '追加

    End Sub
frmMain.vb(追加)
    Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click

        Dim dialog As New SaveFileDialog()

        With dialog

            'ダイアログボックスで表示するファイル名
            .FileName = DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".log"

            'ファイル種類
            .Filter = "ログファイル(*.log)|*.log|すべてのファイル(*.*)|*.*"

            'タイトル
            .Title = "ログ保存先"

            '前回保存先フォルダの保持
            .RestoreDirectory = True

            '既存ファイルのチェック
            .OverwritePrompt = True

            If .ShowDialog() = DialogResult.OK Then

                Using sr As New StreamWriter(.FileName, False, System.Text.Encoding.UTF8)

                    For Each row As EtRoboData.BtRecvLogRow In m_EtRoboData.BtRecvLog.Rows()

                        sr.WriteLine(row.Tag + "," + row.Log)

                    Next

                End Using

            End If

        End With

    End Sub
frmMain.vb(追加)
    Private Sub cmbTag_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cmbTag.SelectedIndexChanged

        Dim search As String = Me.cmbTag.Text.TrimEnd()

        If String.IsNullOrEmpty(search) Then

            Me.lstLog.DataSource = m_EtRoboData.BtRecvLog

        Else

            Dim query = From row As EtRoboData.BtRecvLogRow In m_EtRoboData.BtRecvLog.AsEnumerable
                        Where row.Tag = search

            Me.lstLog.DataSource = query.AsDataView()

        End If

    End Sub

コード (C)

続いて、ロボット側のログ送信部分を以下のように変更します。

    const char *pTag1 = "hogehoge";
    const char *pTag2 = "test";
    const char *pMsg1 = "Hello EV3!";
    const char *pMsg2 = "Good Bye EV3!";

    FILE* sp;

    sp = ev3_serial_open_file(EV3_SERIAL_DEFAULT)

    fprintf(sp, "%s)],%s\r\n", pTag1, pMsg1);
    fprintf(sp, "%s)],%s\r\n", pTag2, pMsg2);

    fclose(sp);

動作確認

では、動作確認です。
ツールとロボットを起動すると、以下のようにログが表示されます。

test1.png

さらにログを受信した状態でコンボボックスをクリックすると、ログに紐付けたタグが表示されます。
補足ですが、タグの部分を未指定(空文字)にするとnotagとして紐づきます。

test2.png

試しにhogehogeを選択すると、Hello EV3!のみ絞り込まれて表示できます。
(この機能を使えば、PID部分だったり、難所部分のログといった感じで絞り込みが行えます)

test3.png

あとは、保存ボタンを押下すると、ログ保存先ダイアログが表示されて保存ができます。

ログ保存.png

保存したログを開くと、タグと一緒に保存できています。

log.png

最後に

今年もETロボコンに参加しましたが、昨年同様、大変な半年でした。
そんな中、リンク情報システムさんが開催して頂いた非公式試走会のおかげで、本番に近い環境で色々と試せたことは非常に助かりました。
改めまして、ありがとうございました!

因みに、今回動確をしていて思ったのですが、bluetoothの接続状態等を表示すると、もっと使いやすいかもしれませんね。
※ 来年度の記事への布石ではありません(笑)

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1