[応用編]JavaScriptでバイナリデータを扱ってみる~Bluetoothの温度データ形式を理解する~(1/3)

[BRIGHT VIE Advent Calendar 2017 - Qiita](https://qiita.com/advent-calendar/2017/brightvie) 4日です。

昨日は、「[[基礎編]JavaScriptでバイナリデータを扱ってみる](https://qiita.com/megadreams14/items/dded3cf770010bb8ff08)」というタイトルで、JavaScriptでのバイナリデータの扱い方の基礎を記載しました。
本日からは、3回に分けて実際にBluetoothの仕様で定義されているデータ形式を元に実際の生データを扱ってみたいと思います。



# はじめに

いきなりですが、まずはこちらを御覧ください。

<img width="1076" alt="BLE_Temperature Measurement.png" src="https://qiita-image-store.s3.amazonaws.com/0/17346/d96b91bd-8698-07bd-fa3d-b4693990424b.png">

[引用元] [Temperature Measurement - Assigned Number: 0x2A1C Bluetooth ](https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.temperature_measurement.xml)

こちらは、Bluetoothで温度のやりとりをする際の共通フォーマットが上記のように定義されております。

# Bluetooth Temperature Measurementのフォーマットを読み解いてみる

## Flags
まず、1バイト目に記載されている「Flags」にて

### 1ビット目: 温度の設定
|  | 説明 | 形式 |
|:-:|:-:|:-:|
| 0の場合 | Celsius: 摂氏（°C）    | C1のフィールドを参照 |
| 1の場合 | Fahrenheit: 華氏（°F） | C2のフィールドを参照 |

### 2ビット目: 計測時間の記録有無
|  | 説明 | 形式 |
|:-:|:-:|:-:|
| 0の場合 | 設定なし | |
| 1の場合 | 設定あり | C3のフィールドを参照 |

### 3ビット目: 温度のタイプ設定の有無
|  | 説明 | 形式 |
|:-:|:-:|:-:|
| 0の場合 | 設定なし | |
| 1の場合 | 設定あり | C4のフィールドを参照 |

### 4~8ビット: 設定なし

現在は利用されていないが、今後仕様が追加されたときのための予約フィールドとして指定されている。

## C1: Temperature Measurement Value (Celsius)

Flagsの1ビット目が0の場合、「Celsius: 摂氏（°C）」での温度が設定されています。
保存されているデータのフォーマット形式が、「FLOAT」であるため、
下記記事の定義より「IEEE-11073 32-bit FLOAT」であることがわかります。

[引用元][Format Types - Bluetooth](https://www.bluetooth.com/specifications/assigned-numbers/format-types)


https://www.bluetooth.com/specifications/assigned-numbers/units

## C2: Temperature Measurement Value (Fahrenheit)

Flagsの1ビット目が1の場合、「Fahrenheit: 華氏（°F）」での温度が設定されています。
C1の摂氏（°C）の場合と同様にフォーマット形式が、「FLOAT」であるため、
こちらも「IEEE-11073 32-bit FLOAT」であることがわかります。

## C3: Time Stamp

Flagsの2ビット目が1の場合、このフィールドには「温度を計測したときの時間」が設定されています。
形式は、「org.bluetooth.characteristic.date_time」と記載されており、
引用元の定義より、下記のような7バイトのフォーマットで計測時間が記録されています。


<img width="925" alt="Day of Month is not known.png" src="https://qiita-image-store.s3.amazonaws.com/0/17346/90b43a10-294d-8a18-49e2-ac53577e973c.png">


[引用元]
[Date Time - Assigned Number: 0x2A08](https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.date_time.xml)


## C4: Temperature Type

最後にFlagsの3ビット目が1の場合、このフィールドには「温度のタイプ」（計測時の状況）が設定されています。
形式は、「org.bluetooth.characteristic.temperature_type」と記載されており、
引用元の定義より、下記のような1バイトのフォーマットで計測時間が記録されています。

<img width="860" alt="Name_Temperature_Type.png" src="https://qiita-image-store.s3.amazonaws.com/0/17346/9b44a70d-f55c-6ac8-bfd4-16aeb3257898.png">


[引用元][Temperature Type - Assigned Number: 0x2A1D](https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.temperature_type.xml)

# フローチャート

次にプログラムの処理を考えるため、フローチャートを記載してみます。

<img width="602" alt="Flagsのビットパターン別状態チェック.png" src="https://qiita-image-store.s3.amazonaws.com/0/17346/ced28144-70ab-7528-5e8b-fd7766e2c233.png">

このようにロジックを記載すれば解析可能です。
また、参考程度に1バイト目のFlagsのビットパターン別に、どのようにデータが保存されているか可視化してみました。

<img width="764" alt="Flagsのビットパターン別メモリ状態.png" src="https://qiita-image-store.s3.amazonaws.com/0/17346/1d1a5d61-1086-8709-a4a2-53e9bae38cf2.png">


結構簡単ですね！

# まとめ

ここまでBluetooth経由で温度データを受信する際の共通フォーマット及び処理フローが理解できたかと思います。
次の記事では、上記フローをもとに生データを扱ってみたいと思いますが、
ここで1つ疑問に思われていることがあるのではないでしょうか？

それは、
「摂氏（°C）」「華氏（°F）」ともにそうですが、「Temperature Measurement Value」がFLOATと定義されていますが、
「IEEE-11073 32-bit FLOAT」というところ...

FLOATとは、浮動小数点のことを指しており、小数点を扱うためのデータフォーマットです。
[昨日の記事](https://qiita.com/megadreams14/items/dded3cf770010bb8ff08)でも、JavaScriptで「32ビット浮動小数点数」を扱うときは
DataViewクラスの「getFloat32」や「setFloat32」を利用すれば良かったはずです。

よく資料を見てみると

|Format|short Name| Description |
|:-:|:-:|:-:|
| 0x14 | float32 | IEEE-754 32-bit floating point |
| 0x15 | float64 | IEEE-754 64-bit floating point |
| 0x16 | SFLOAT  | IEEE-11073 16-bit SFLOAT |
| 0x17 | FLOAT	 | IEEE-11073 32-bit FLOAT |
[引用元][Format Types - Bluetooth](https://www.bluetooth.com/specifications/assigned-numbers/format-types)

IEEE-754で定義されているfloatとIEEE-11073で定義されているFLOAT
どちらも小数点を扱うデータフォーマットですが何が違うのか...

明日の記事ではこのあたりの部分を明確にしていきたいと思います。