MRが楽しい

MRやVRについて学習したことを書き残す

HoloLensの3DアプリでBlueToothAdvertisementを送信する

本日は HoloLens の技術調査枠です。
前回とは逆に、HoloLensの3DアプリでBlueToothAdvertisementを送信する方法を記事にします。
以下の記事の続きです。
bluebirdofoz.hatenablog.com

プロジェクトとシーンの準備

以下の記事を元にHoloLens(WindowsMR)プロジェクトを作成します。
bluebirdofoz.hatenablog.com

2019/5/3現在、MRTK 2017 の最新バージョンは 2017.4.3.0 です。
f:id:bluebirdofoz:20190505222845j:plain

BluetoothAdvertisementを参考に作成したサンプルコード

BluetoothAdvertisement のパブリッシャクラスのコードを参考に、Advertisement を送信するクラスを作成しました。
・BluetoothAdvertisePublisher.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

#if WINDOWS_UWP
using System;
using Windows.Storage.Streams;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
#endif

public class BluetoothAdvertisePublisher : MonoBehaviour
{
    /// <summary>
    /// テキストオブジェクトの参照
    /// </summary>
    public UnityEngine.UI.Text MessageText;
    string showmessage;

    /// <summary>
    /// 起動時処理
    /// </summary>
    void Start()
    {
        App_Message("Start");
#if WINDOWS_UWP
        // 初期化
        Awake_BluetoothLEAdvertisementPublisher();

        // ハンドラ登録
        OnEnable_BluetoothLEAdvertisementPublisher();

        // パブリッシャ起動
        Run_BluetoothLEAdvertisementPublisher();
#endif
    }

    /// <summary>
    /// 定期実行
    /// </summary>
    private void Update()
    {
        if (showmessage.Length != 0)
        {
            MessageText.text = showmessage;
            showmessage = "";
        }
    }

    /// <summary>
    /// テキスト更新
    /// </summary>
    /// <param name="message">メッセージ</param>
    void App_Message(string message)
    {
        showmessage = message;
    }

    /// <summary>
    /// 終了時処理
    /// </summary>
    void OnApplicationQuit()
    {
#if WINDOWS_UWP
        // 終了
        OnDisable_BluetoothLEAdvertisementPublisher();
#endif
    }

#if WINDOWS_UWP
    /// <summary>
    /// Bluetooth LE advertisement の制御とカスタマイズに使用するBluetoothLEAdvertisementPublisher
    /// </summary>
    private BluetoothLEAdvertisementPublisher publisher;

    /// <summary>
    /// BluetoothLEAdvertisementPublisher初期化(Awake)
    /// </summary>
    public void Awake_BluetoothLEAdvertisementPublisher()
    {
        // 新しいパブリッシャインスタンスを作成して初期化します。
        publisher = new BluetoothLEAdvertisementPublisher();

        // advertisement にペイロードを追加する必要があります。
        // ペイロードがない、または無効なパブリッシャーは起動できません。
        // ペイロードを設定する必要があるのは、どのパブリッシャに対しても1回だけです。

        // manufacturer-specific セクションを追加します。
        // まず、製造元データセクションを作成します。
        var manufacturerData = new BluetoothLEManufacturerData();

        // 製造元データのIDを設定します。ここでは 0xFFFE の値を指定します。
        manufacturerData.CompanyId = 0xFFFE;

        // manufacturer-specific セクション内にデータペイロードを設定します
        // ここでは以下の16ビットのUUIDを使用します。
        // 0x1234 - > { 0x34、0x12}(リトルエンディアン)
        var writer = new DataWriter();
        UInt16 uuidData = 0x1234;
        writer.WriteUInt16(uuidData);

        // 書き込みデータのバッファ長はアドバタイズペイロードに収まる必要があります。
        // 収まらない場合は例外が発生します。
        manufacturerData.Data = writer.DetachBuffer();

        // 製造元データを advertisement パブリッシャに追加します。
        publisher.Advertisement.ManufacturerData.Add(manufacturerData);
    }

    /// <summary>
    /// BluetoothLEAdvertisementPublisher初期化(OnEnable)
    /// </summary>
    public void OnEnable_BluetoothLEAdvertisementPublisher()
    {
        // パブリッシャのステータスを監視するためのイベントハンドラを登録します。
        // これにより、advertisement が提供されたかどうか、がわかります。
        // また、Bluetooth がユーザーによってオフになっているなどの予期しないエラーについても通知します。
        publisher.StatusChanged += OnStatusChanged_AdvertisementPublisher;
    }

    /// <summary>
    /// BluetoothLEAdvertisementPublisher終了(OnDisable)
    /// </summary>
    public void OnDisable_BluetoothLEAdvertisementPublisher()
    {
        // コンテキストを離れるときは、パブリッシャを停止します。
        // パブリッシャが停止されていなくても、パブリッシャが破棄されるとスキャンは自動的に停止します。
        publisher.Stop();
        // リークを防ぐためにリソースを解放する場合、ハンドラの登録を解除します。
        publisher.StatusChanged -= OnStatusChanged_AdvertisementPublisher;
    }

    /// <summary>
    /// BluetoothLEAdvertisementPublisherサスペンド時処理
    /// </summary>
    public void Suspending_BluetoothLEAdvertisementPublisher()
    {
        // 中断時にはパブリッシャを停止します。
        publisher.Stop();
        // リークを防ぐためにリソースを解放する場合、ハンドラの登録を解除します。
        publisher.StatusChanged -= OnStatusChanged_AdvertisementPublisher;
    }

    /// <summary>
    /// BluetoothLEAdvertisementPublisher再開時処理
    /// </summary>
    public void Resuming_BluetoothLEAdvertisementPublisher()
    {
        // ハンドラを登録してパブリッシャを再開します。
        publisher.StatusChanged += OnStatusChanged_AdvertisementPublisher;
        // 再開時にパブリッシャを開始します。
        publisher.Start();
    }

    /// <summary>
    /// BluetoothLEAdvertisementPublisher実行処理(Run)
    /// </summary>
    public void Run_BluetoothLEAdvertisementPublisher()
    {
        // パブリッシャの Start() を呼び出すと advertisement が開始されます。
        publisher.Start();
    }

    /// <summary>
    /// BluetoothLEAdvertisementPublisher停止処理(Stop)
    /// </summary>
    public void Stop_BluetoothLEAdvertisementPublisher()
    {
        // パブリッシャの Stop() を呼び出すと advertisement が停止します。
        publisher.Stop();
    }

    /// <summary>
    /// パブリッシャのステータスが変更されたときにイベントハンドラとして呼び出されます。
    /// </summary>
    /// <param name="publisher">イベントをトリガーした発行者のインスタンス</param>
    /// <param name="eventArgs">発行者ステータス変更イベントに関する情報を含むイベントデータ</param>
    private async void OnStatusChanged_AdvertisementPublisher(
        BluetoothLEAdvertisementPublisher publisher,
        BluetoothLEAdvertisementPublisherStatusChangedEventArgs eventArgs)
    {
        // このイベントハンドラを使用して、発行者のステータスを監視できます。
        // パブリッシャーがシステムによって中止された場合、エラーを検出できます。
        BluetoothLEAdvertisementPublisherStatus status = eventArgs.Status;
        BluetoothError error = eventArgs.Error;

        // 変更イベント処理を行う
        // 変更イベントメッセージをテキストオブジェクトに表示する
        App_Message("StatusChange Event");
    }
#endif
}

Empty オブジェクトを作成し、本スクリプトをアタッチしました。
f:id:bluebirdofoz:20190505222905j:plain

スクリプトの MessageText にテキストオブジェクトの参照を追加します。
f:id:bluebirdofoz:20190505222915j:plain

Capabilityの追加

UWPアプリで Bluetooth を利用する場合、Capability の設定が必要です。
メニューから Edit -> Project Settings - Player を開きます。
f:id:bluebirdofoz:20190505222926j:plain

Inspector ビューから Publishing Setttings を開きます。
[Capabilities]欄の[Bluetooth]にチェックを入れます。
f:id:bluebirdofoz:20190505222938j:plain

後は HoloLens 向けにプロジェクトをビルドしてインストールします。
UnityプロジェクトのビルドとHoloLensへのインストール手順については以下を参照してください。
bluebirdofoz.hatenablog.com

HoloLensでの動作確認

この状態で HoloLens 上で動作確認を行います。
HoloLens 上でアプリを起動すると、Bluetooth のアドバタイズが送信されます。
f:id:bluebirdofoz:20190505223008j:plain

受信側アプリの実行

PC側で前回ビルドした BluetoothAdvertisement アプリを起動します。
[Foreground watcher]のタブを開き、[Run]を実行して BlueTooth のアドバタイズを受信します。
HoloLens で送信されたアドバタイズを受信すると、IDとデータ値が表示されます。
f:id:bluebirdofoz:20190505223019j:plain