LoginSignup
0
0

CoreBluetoothForUnity サンプル 02_ButtonInformation

Last updated at Posted at 2023-12-02

本記事について

この記事は CoreBluetoothForUnity Advent Calendar 2023 の3日目の記事です。

02_ButtonInformation サンプルの解説をします。

前提

  • 前回の記事
  • 02_ButtonInformation サンプルを動かすことができること。

環境

  • CoreBluetoothForUnity 0.4.3

02_ButtonInformation の概要

02_ButtonInformation は、Peripheral に配置されたボタンの状態を Central に送信するサンプルです。

SampleButtonInformation_PeripheralScene

button_information_peripheral

ボタンが6つ配置されており、それぞれのボタンが以下のように登録されています。

buttons.png

それぞれのボタンのインデックス + 1 が id となるような仕様にしています。

例: A のインデックスは4なため、id は5。

SampleButtonInformation_CentralScene

mov_button_information

送られてきたデータによって画面中央の Cube..(1)と右下のテキスト..(2)を更新しています。

screen_button_central.png

上下左右 -> Cube が上下移動
AB -> Cube の拡大・縮小

01_LightControl との違い

サンプル データの読み書きの方向 名称
01_LightControl Central -> Peripheral Write
02_ButtonInformation Peripheral -> Central Notify

Write と Notify は書き方が全然違います。
本記事では Notify の書き方を解説します。

Service, Characteristic の作成 (Peripheral)

SampleButtonInformation_Peripheral.cs
var service = new CBMutableService(SampleButtonInformation_Data.ServiceUUID, true);
_buttonInformationCharacteristic = new CBMutableCharacteristic(
    SampleButtonInformation_Data.ButtonInformationCharacteristicUUID,
    CBCharacteristicProperties.Read | CBCharacteristicProperties.Notify,
    null,
    CBAttributePermissions.Readable
);

Service の作成は特に変わりません。
Peripheral -> Central とデータを送信するために、今回は Characteristic の権限に Notify を追加しています。

(Read については権限追加していますが、本記事では使いません。)

Notify できるように設定

SetNotifyValue (Central)

SampleButtonInformation_Central.cs
void ICBPeripheralDelegate.DidDiscoverCharacteristics(CBPeripheral peripheral, CBService service, CBError error)
{
...
    foreach (var characteristic in service.Characteristics)
    {
        if (characteristic.UUID.Equals(SampleButtonInformation_Data.ButtonInformationCharacteristicUUID))
        {
            if (characteristic.Properties.HasFlag(CBCharacteristicProperties.Notify))
            {
                peripheral.SetNotifyValue(true, characteristic);
            }
        }
    }
}

Characteristic に Notify 権限がある場合、SetNotifyValue の引数 enabled に true を渡すことで Notify が有効になります。

SetNotifyValue

この処理を 「Characteristic のデータを購読する」(Subscribe)と言います。

Characteristic のデータが購読されたことを検知 (Peripheral)

Central がデータを購読すると Peripheral 側では以下の処理が呼ばれます。

SampleButtonInformation_Peripheral.cs
void ICBPeripheralManagerDelegate.DidSubscribeToCharacteristic(CBPeripheralManager peripheral, CBCentral central, CBCharacteristic characteristic)
{
    if (_peripheralManager.IsAdvertising)
    {
        peripheral.StopAdvertising();
    }
    _stateLabel.text = "Connected";
    _central = central;
}

これによってどの Central が Peripheral を購読しているかを検知することができます。
Peripheral では Central から接続されることで呼び出されるイベントはないため、DidSubscribeToCharacteristic は接続されたことを把握する方法でもあります。

サンプルでは電池の消費を抑えるために、Peripheral が Central に接続されたらアドバタイズを停止しています。

Peripheral から Central へデータを送信 (Peripheral)

SampleButtonInformation_Peripheral.cs
        void OnButtonDown(int buttonID)
        {
            if (_central == null)
            {
                return;
            }

            var data = SampleButtonInformation_Data.GetButtonInformation(buttonID, true);
            _peripheralManager.UpdateValue(data, _buttonInformationCharacteristic, new CBCentral[] { _central });
        }
SampleButtonInformation_Data.cs
        /// <summary>
        /// Convert button information to byte array.
        /// This data format is same as toio button information.
        /// https://toio.github.io/toio-spec/en/docs/ble_button#read-operations
        /// </summary>
        /// <param name="isPressed"></param>
        /// <returns></returns>
        public static byte[] GetButtonInformation(int buttonId, bool isPressed)
        {
            byte[] buff = new byte[2];
            buff[0] = BitConverter.GetBytes(Mathf.Clamp(buttonId, 0, 255))[0];
            buff[1] = (byte)(isPressed ? 0x80 : 0x00);
            return buff;
        }

Peripheral から Central へデータを送信するには、UpdateValue を使います。
送信対象を指定するために、第3引数に CBCentral[] を渡します。

UpdateValue

Central でデータを受信

DidUpdateValueForCharacteristic でデータを受信します。

SampleButtonInformation_Central.cs
        void ICBPeripheralDelegate.DidUpdateValueForCharacteristic(CBPeripheral peripheral, CBCharacteristic characteristic, CBError error)
        {
            if (error != null)
            {
                Debug.LogError($"[DidUpdateValue] error: {error}");
                return;
            }

            if (SampleButtonInformation_Data.ParseButtonInformation(characteristic.Value, out int buttonId, out bool isPressed))
            {
                _log.AppendLog(buttonId, isPressed);
                _cube.Action(buttonId, isPressed);
            }
        }

Notify は Peripheral -> Central の一方通行なため、返答する必要はありません。

おわりに

本記事では、02_ButtonInformation サンプルを通して Notify の使い方を解説しました。
Write よりも Notify のほうが使う機会多いと思いますので、ぜひ参考にしてください!

0
0
0

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
0
0