CoreBluetoothForUnity サンプル Debug

## 本記事について

この記事は [CoreBluetoothForUnity Advent Calendar 2023](https://qiita.com/advent-calendar/2023/core-bluetooth-for-unity) の6日目の記事です。

Debug サンプルと Read の実装について解説します。

![pm_debug_sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/df95c281-c9ad-f3e2-f35b-45d4cec33943.png)

## 環境

- CoreBluetoothForUnity 0.4.3

## Debug サンプルとは

各イベントの発生をログに出力するサンプルです。
Peripheral, Central のどちらかを開発する際に、もう片方をこの Debug サンプルと通信することで、ちゃんと実装できているか、どんな値が送受信されているかを用意に確認できるかなと思います。

![debug.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/8bab044d-2b9d-db6a-674e-3f2cc193738e.png)

3つのシーンから構成されています。

|シーン名|画面|
|:--:|:--:|
|Home|![debug_home.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/82bc4af5-9103-a10b-9d4e-a1a63483c7ba.png)|
|Central|![debug_central.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/acf1fbf9-692b-892a-fb17-b6ea2fde213d.png)|
|Peripheral|![debug_peripheral.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113504/56af1cbd-cd64-87c6-9d82-7943c9fd333c.png)|

Home から Central と Peripheral のシーンに遷移でき、左上の HOME を押すことで Home に戻ることができます。

Home があることで、1アプリで Central, Peripheral の両方のテストが可能です。

## Read

Debug サンプルでは、01_LightControl, 02_ButtonInformation でやっていなかった Central から Peripheral への Read を実装しています。
CoreBluetooth の Read は Characteristic のデータを直接読む**わけではない**点がポイントです。実際にコードを追います。

## Read の Central の実装

https://github.com/teach310/CoreBluetoothForUnity/blob/0.4.3/Assets/CoreBluetooth/Samples/12_Debug/SampleDebug_Central.cs

```SampleDebug_Central.cs
public void OnClickRead()
{
    if (_peripheral == null)
    {
        Debug.Log("peripheral is null.");
        return;
    }

    if (_remoteCharacteristic == null)
    {
        Debug.Log("remoteCharacteristic is null.");
        return;
    }

    _peripheral.ReadValue(_remoteCharacteristic);
}
```

[ReadValue](https://developer.apple.com/documentation/corebluetooth/cbperipheral/1518759-readvalue)

Central からの読み込みリクエストは ReadValue で行います。
そして、その結果が Notify と同様に DidUpdateValueForCharacteristic で受け取れます。

ここではやっていませんが、以下のように Read 可能かどうかを確認することもできます。

```.cs
if (characteristic.Properties.HasFlag(CBCharacteristicProperties.Read))
{
    peripheral.ReadValue(characteristic);
}
```

### Read の Peripheral の実装

癖があるのはこちらです。

https://github.com/teach310/CoreBluetoothForUnity/blob/0.4.3/Assets/CoreBluetooth/Samples/12_Debug/SampleDebug_Peripheral.cs

```SampleDebug_Peripheral.cs
void ICBPeripheralManagerDelegate.DidReceiveReadRequest(CBPeripheralManager peripheral, CBATTRequest request)
{
    if (request.Characteristic.UUID != _characteristicUUID)
    {
        peripheral.RespondToRequest(request, CBATTError.AttributeNotFound);
        return;
    }

    int valueLength = _value?.Length ?? 0;
    if (request.Offset > valueLength)
    {
        peripheral.RespondToRequest(request, CBATTError.InvalidOffset);
        return;
    }

    request.Value = _value ?? new byte[0];
    peripheral.RespondToRequest(request, CBATTError.Success);
    Debug.Log($"[DidReceiveReadRequest] {System.Text.Encoding.UTF8.GetString(request.Value)}");
}
```

Read のリクエストを受け取るには、`ICBPeripheralManagerDelegate.DidReceiveReadRequest` を実装します。

request.Value に値を設定、RespondToRequest で返答することで Central に値を返すことができます。

で、この時 request.Value に値を設定するというプロセスで Characteristic の値を参照しなくても構いません。

本サンプルではメンバ変数の _value をセットしています。

## おわりに

本記事では CoreBluetoothForUnity のサンプル Debug と Read の実装について解説しました。

Debug サンプルは新しく機能を追加するたびに更新していく予定です。