SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

.NET nanoFrameworkとESP32でIoTプログラミング

Bluetoothで気温などの環境データをモニタリング! .NET nanoFrameworkとESP32でIoTプログラミング

.NET nanoFrameworkとESP32でIoTプログラミング 第6回

  • X ポスト
  • このエントリーをはてなブックマークに追加

Bluetooth Low Energy通信(2)

基本のプログラム

 まず基本的なサンプルから作成してみます。最初に、次のパッケージをインストールしておきます。

  • nanoFramework.Device.Bluetooth

 またサービスとキャラクタリスティックのUUIDは、あらかじめ上記サービスなど作成しておきます。コードは、次のようになります。これはセントラルに対して、固定の文字列の送信と定期的に通知を行うものです。

[リスト2]Program.csの一部
public static void Main()
{
    // UUIDの定義(1)
    Guid serviceUuid = new("A6C00538-6373-4FC2-65B3-F43EAA9F9887");
    Guid charUuid = new("6CB42289-2139-A2A9-960D-C9E6960E5988");

    // BLEオブエジェクトの生成(シングルトン)(2)
    BluetoothLEServer server = BluetoothLEServer.Instance;

    // デバイス名の設定(3)
    server.DeviceName = "ESP32 BLE No.1";

    // サービスオブジェクトの生成(4)
    var result = GattServiceProvider.Create(serviceUuid);
    if (result.Error != BluetoothError.Success)
    {
        return;
    }

    // キャラクタリスティックオブジェクトの生成(5)
    var characteristicResult =
        result.ServiceProvider.Service.CreateCharacteristic(
            charUuid,
            new GattLocalCharacteristicParameters()
        {
           // プロパティに読み取りと通知を設定する(6)
           CharacteristicProperties =
               GattCharacteristicProperties.Read |
               GattCharacteristicProperties.Notify,
           UserDescription = "ESP Read Characteristic"
        });

    if (characteristicResult.Error != BluetoothError.Success)
    {
        return;
    }

    // 読み取り時のイベントハンドラ追加(7)
    characteristicResult.Characteristic.ReadRequested += 
        (sender, ReadRequestEventArgs) => {
            var request = ReadRequestEventArgs.GetRequest();
            DataWriter writer = new();
            writer.WriteString("1.23"); // 固定値
            request.RespondWithValue(writer.DetachBuffer());
        };

    // 通知のイベント作成(8)
    Timer notifyTimer = new((state) => {
        if (characteristicResult.Characteristic.SubscribedClients.Length > 0)
        {
            DataWriter writer = new();
            writer.WriteBytes(new byte[] { 0, 1, 2 }); // 固定値
            characteristicResult.Characteristic.NotifyValue(
                writer.DetachBuffer()
            );
        }
    }, null, 3000, 5000); // 3秒後に5秒間隔で実行する

    // アドバタイズの開始(9)
    result.ServiceProvider.StartAdvertising(
        new GattServiceProviderAdvertisingParameters()
        {
            IsConnectable = true,
            IsDiscoverable = true
        }
    );
    Thread.Sleep(Timeout.Infinite);
}

 まず使用するUUIDを定義します(1)。次に、BLE通信のメインオブジェクトとなるBluetoothLEServerオブジェクトを生成します(2)。このオブジェクトはシングルトンで、BluetoothLEServer.Instanceプロパティの最初の呼び出し時に、実際のインスタンスが生成されます。

 設定したデバイス名は(3)、セントラルでのスキャン時に表示される名称となります。定義したUUIDを使ってサービスを生成し(4)、キャラクタリスティックのオブジェクトを生成します(5)。ここでのキャラクタリスティックのプロパティとして、読み取りと通知を設定しています(6)。

 セントラルからの読み取り要求のイベントハンドラとして、固定の文字列を送信する処理をラムダ式で定義しています(7)。送信するデータは、バイト列を操作するためのBufferオブジェクトにする必要があります。ここでは、nanoFramework.Device.Bluetooth.DataWriterクラスを利用しています。DataWriterクラスは、文字列や数値などをBufferオブジェクトに変換するのに便利なクラスです。

 セントラルへの通知は、ここではTimerクラスを利用して、定期的に実行されるようにしています(8)。ここでも実行される処理は、ラムダ式で記述しています。なお、ペリフェラルからの通知は、セントラルが受け取る許可(サブスクライブ)が必要です。サブスクライブしている場合のみ、通知するようにしています。

 なお通知の場合は、送信できるデータの最大サイズが20バイト以下に制限されています。大きなサイズのデータを設定しても、20バイトしか送信できません。

 最後に、アドバタイズを開始します(9)。IsDiscoverableは、デバイスを検出できるようにする、IsConnectableは、ペリフェラルとして接続可能とするプロパティです。

BLE通知の確認

 サンプルコードを実行して実際の通信を試すには、セントラルとなるデバイスが必要です。このとき、PCよりもスマートフォンのアプリを利用するほうが手軽です。「LightBlue」「nRF Connect for Mobile」といったモバイルアプリが有名です。ここでは、Android版の「nRF Connect for Mobile」を利用しました。アプリを起動すると、アドバタイズしているペリフェラルの一覧が表示されます。設定した、「ESP32 BLE No.1」があるはずです。

ペリファラルリスト
ペリファラルリスト

 CONNECTボタンをタップすると接続します。

接続後の情報
接続後の情報

 接続の画面で、サービスのUUIDが表示されているはずです。そのUUIDをタップします。すると、サービス内のキャラクタリスティックの情報が表示されます。

nRF Connect for Mobileでのキャラクタリスティック情報
nRF Connect for Mobileでのキャラクタリスティック情報

 データを受信するアイコンをタップすると、受信したデータが、16進数と文字列で表示されます。Subscribeのアイコンをタップすると、通知を受け入れて、通知のデータが5秒おきに表示されます。

データの受信
データの受信

ブロードキャスト通信

 ペリフェラルがアドバタイズするだけのブロードキャスト通信では、もっとシンプルなコードとなります。例えば、ランダムの値を含むアドバタイズ信号を送信するコードは、次のようになります。

[リスト3]Program.csの一部
public static void Main()
{
    var rnd = new Random();
    while (true)
    {
        BluetoothLEAdvertisement advertisement = new()
        {
            LocalName = "ESP32Adv"
        };

        DataWriter writer = new();

        // ランダム値を設定する(1)
        writer.WriteInt32(rnd.Next());
        writer.WriteInt32(rnd.Next());
        writer.WriteInt32(rnd.Next());

        // 識別子を不明として設定(2)
        advertisement.ManufacturerData.Add(
            new BluetoothLEManufacturerData(0xfffe, writer.DetachBuffer()));

        BluetoothLEAdvertisementPublisher publisher = new(advertisement);
        publisher.Start();

        Thread.Sleep(1000);

        publisher.Stop();
    }
}

 アドバタイズでの送信パケットのデータサイズは31バイトです。ただし、既定のデータが含まれるため、任意に設定できるのは21バイトになります。アドバタイズデータの識別子は、Bluetooth SIGが企業に発行した識別子で、特定の用途では有効な値を設定する必要がありますが、今回のような用途では、未定義(0xfffe)のままで問題ありません(2)。

 実行すると、1秒ごとにアドバタイズ信号を送信します。

アドバタイズの受信
アドバタイズの受信

 アドバタイズ信号には、ランダムのint型(4バイト)の3つの値12バイトが含まれています(1)。「nRF Connect for Mobile」を使うと、データの変化をリアルタイムで画面で確認することができます。

環境センサーの値の送信

 最初のセンサーの値を取得する処理と組み合わせれば、BLE通信でデータを送信するプログラムは難しくはありません。例えば、BME680の測定値をJSON文字列にして送信すれば、受信側アプリでのデータ処理も簡単に行えます。

JSON文字列の受信
JSON文字列の受信

 実際のソースコードは、次回に解説することにします。

最後に

 環境データをモニタリングするプログラムの解説の前編となる今回は、センサーの計測処理の作成、そしてデータ送信処理としてBLE通信の基本プログラムを作成しました。後編では、環境データをモニタリングするAndroidアプリと、センサーデータをWi-Fi経由でAmbient(IoTデーター可視化サービス)に送信し、グラフ化するところまで解説する予定です。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
.NET nanoFrameworkとESP32でIoTプログラミング連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 高江 賢(タカエ ケン)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/20513 2024/12/04 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング