5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

スマートベッド nerum app を買ったので、レビューとハックする(ハック編)

Last updated at Posted at 2022-06-16

TL;DR

  • 電動スマートベッド nerum appを買った
    非常に良い。前編 レビュー編は こちらへ
  • BLE通信をスニッファでキャプチャしてプロトコル解析した。
  • スマホアプリでも出来ない、照明の状態と角度の表示、HEAD/FOOT同時操作までできるようになった。イエイ
  • サンプルコードは全部 C#

環境

  • Windows 11 Pro 21H2
  • Bluetoothドングル サンワサプライ MM-BTUD46
  • Bluetoothスニッファ Adafruit nRF51822搭載 Bluefruit LE Sniffer(v2) amazonで購入した
  • Wireshark v3.6.5
  • Python 3.10
  • VisualStudio 2022 17.2.3
  • スマホアプリ Google PlayApp Store

BLE

まずは、スニッファを使わず、PCから普通のBLEのデバイスとして様子を確認する。

アドバタイズ

サンプルコード C#

  • サンプルコード

  • ポイント

    • ターゲットフレームワーク
      csprojで、次のように指定する
      <TargetFramework>net6.0-windows10.0.22000.0</TargetFramework>
    • BluetoothLEAdvertisementWatcherクラスを使ってアドバタイズを受信する
    • 目的のServiceUuidが分かっていれば、あらかじめフィルタもかけられる
  • パッシブのアドバタイズ

AdvertisementType:ConnectableUndirected
Address:30E283XXXXXX Type:Public
LocalName:
Flags:GeneralDiscoverableMode, ClassicNotSupported
ManufacturerData
        CompanyId:0x0000(Ericsson Technology Licensing)
        Data:FF-FF-FF-FF-64-00-FF
ServiceUuids
        0000fff0-0000-1000-8000-00805f9b34fb
        0000ffb0-0000-1000-8000-00805f9b34fb
DataSections
        01(Flags):06
        02(Incomplete16bServices):F0-FF-B0-FF
        FF(Manufacturer):00-00-FF-FF-FF-FF-64-00-F
  • アクティブスキャンのレスポンス
AdvertisementType:ScanResponse
Address:30E283XXXXXX Type:Public
LocalName:OKIN-BLE0008XXXX
Flags:
ManufacturerData
ServiceUuids
DataSections
        09(CompleteLocalName):4F-4B-49-4E-2D-42-4C-45-30-30-30-38-XX-XX-XX-XX
        12(Unknown):08-00-10-00
        0A(TxPower):04

サービスとキャラクタリスティックの列挙

サンプルコード C#

サービスとキャラクタリスティックの一覧

サンプルコードで取得できた nerum appの一覧は以下の通り

サービスUUID キャラクタリスティックUUID Properties Descriptor DescriptorValue
0x1800
(GenericAccess)
0x2A00
(DeviceName)
Read "OKIN-BLE0008XXXX" - -
0x2A01
(Appearance)
Read 00-00 - -
0x2A02
(PeripheralPrivacyFlag)
Read, Write 00 - -
0x2A03
(ReconnectionAddress)
Write - - -
0x2A04
(PeripheralPreferred
ConnectionParameters)
Read 50-00-A0-00-00-00-E8-03 - -
0x1801
(GenericAttribute)
0x2A05
(ServiceChanged)
Indicate - ※2 02-00
0x180A
(DeviceInformation)
0x2A23
(SystemId)
Read D4-46-83-00-00-83-E2-30 - -
0x2A24
(ModelNumberString)
Read "GCBT40-1S" - -
0x2A28
(SoftwareRevisionString)
Read "V1.2.5" - -
0x2A29
(ManufacturerNameString)
Read "BLE-4.0 Module" - -
0xFFE0 0xFFE4 Notify - ※2 00-00
Notify - ※1 UART Channel
0xFFE5 0xFFE9 Write - ※1 BLE Channel
0xFF20 0xFF21 Write - ※1 Link Interval
0xFF22 Write - ※1 Modify Name
0xFF23 Write - ※1 Modify Uart Rate
0xFF24 Write - ※1 Modify RF Power
0xFF25 Write - ※1 Sleep Enable
0xFF26 Write - ※1 Modify Advert Time
0xFF2F Notify - ※2 00-00
Notify - ※1 Config Notify
0xFF30 0xFF31 Read, Write "00000" ※1 PWM0
0xFF32 Read, Write "00000" ※1 PWM1
0xFF33 Read, Write "00000" ※1 PWM2
0xFF34 Read, Write "00000" ※1 PWM3
0xFF35 Write - ※1 PHASE
0xFF36 Read, Write "65534" ※1 FREQUECY
0xFF37 WriteWithoutResponse - ※1 PWM
0xFF3F Notify - ※2 00-00
Notify - ※1 PWM Status
0xFF40 0xFF41 Read 01-62 ※1 ADC0
0xFF42 Read 01-62 ※1 ADC1
0xFF50 0xFF51 Write - ※1 GIPO Setting
0xFF52 Write - ※1 GPIO Mode Setting
0xFF53 Read "111111" ※1 Read GPIO Status
0xFF54 Read, Write FF-FF-FF-FF-FF-FF-FF-FF-FF-
FF-FF-FF-FF-FF-FF-FF-FF-FF
※1 Data Backup
0xFF5F Notify - ※2 00-00
Notify - ※1 GPIO Notify

Descriptor
※1 0x2901(CharacteristicUserDescription)
※2 0x2902(ClientCharacteristicConfiguration)

GCBT40というモジュールを使っているらしい
マニュアルっぽいのを見つけて、DeepLで翻訳してみたが、
一部サービスUUIDが異なるなど、リビジョンが違う模様。

BLEスニッファ

GATTキャラクタリスティックだけではどうやって操作するかわからないので、
実際のスマホアプリとベッドの通信を覗き見て、理解を進める。

セットアップ

公式のセットアップだけ見ておけばOK

キャプチャ

  1. WireSharkを起動し、nRF Sniffer for Bluetooth LEを選択する
    WireShark1
  2. アドバタイズが表示される
    WireShark1
  3. 目的のデバイスを選択する
    WireShark1
  4. スマホアプリからBLEデバイスに接続を開始し、 Master/Slaveの組み合わせが出るのを待機する
    出てこない場合、スマホアプリで切断⇒接続を繰り返すこと
    (アドバタイジングは3つの周波数で行われるので、2/3の確率で別のチャンネルを見ているタイミングで接続を開始したことによるもの。)
    WireShark1
  5. ここまで来たら後は 各GATTとどういうやり取りをしているか、
    アプリを動作させつつ観察していくだけです。
    WireShark1
    フィルタにbtattを指定するとGATT通信のみに絞れます
    他には、btatt.opcode == 0x12で送った値だけに絞れたり
    btatt.opcode == 0x1bで通知された値だけに絞れたり

nerum appのプロトコル解析

通知

スマホアプリでは、以下のキャラクタリスティックからのみ、通知を受けている
サービスUUID:0xFFE0、キャラクタリスティックUUID:0xFFE4(Description:UART Channel)

ServiceUuid 0000ffe0-0000-1000-8000-00805f9b34fb
CharacteristicsUuid 0000ffe4-0000-1000-8000-00805f9b34fb

アプリには大きく2画面ある(操作とタイマー設定)
image.png

  • 操作側を表示中、次のようなNotificationが1秒毎に送信されている
    image.png

    いろいろと操作・観察した結果以下のような構成であることが分かった

    • ペイロードは19または20バイト区切りで2つの通知に分割されている
      (大抵は合わせて23バイト たまに分割の境界が1バイト分消えることがあった よくわからん)
    長さ 意味 値の例 説明
    3 マジックワード F4FE16
    2 HEAD MOTORの開度 0000 0x0000~0x3338の間
    最大値多少の変動あり
    2 FOOT MOTORの開度 0000 0x0000~0x242Eの間
    最大値多少の変動あり
    12 不明(固定) 0000000010000000000000
    1 照明 40 ON:0x40
    OFF:0x00
    3 不明(固定) FF0001
    1 チェックサム A7 全バイトの合計の下位1バイトをビット反転した値
    例:合計 10進数856=0x0358
    0x58(0b0101100)のビット反転が0xA7(0b10100111)
  • タイマー設定側を表示中、次のようなNotificationが1秒毎に送信されている
    image.png
    いろいろと操作・観察した結果以下のような構成であることが分かった

    長さ 意味 値の例 説明
    3 マジックワード ED8003
    1 アラーム時間(HH) 0F 0x00~0x18の24h
    1 アラーム分(MM) 32 0x00~0x3bの60m
    1 繰返(曜日) 82 最上位ビットから順に
    ON/OFF,土曜日,金曜日,木曜日,水曜日,火曜日,月曜日,日曜日
    ONかつ土曜日のみ場合 0b11000000⇒0xC0
    1 モード 12 なし = 0x00
    M1 = 0x11
    M2 = 0x13
    灯り = 0x12
    8 不明(固定) 0000000000000000
    1 チェックサム BA (操作側と同じ)

操作

スマホアプリでは、以下のキャラクタリスティックにのみ、書き込みを行っている
サービスUUID:0xFFE5、キャラクタリスティックUUID:0xFFE9(Description:BLE Channel)

ServiceUuid 0000ffe5-0000-1000-8000-00805f9b34fb
CharacteristicsUuid 0000ffe9-0000-1000-8000-00805f9b34fb

ベッドの操作

いろいろと操作・観察した結果以下のような構成であることが分かった

長さ 意味 値の例 説明
3 マジックワード E6FE16
5 コマンド 01000000 詳細は次の表へ
1 チェックサム 04 (通知と同じ)
操作 マジック コマンド部 チェックサム メモ
HEAD-UP E6FE16 0100000000 04
HEAD-DOWN E6FE16 0200000000 03
FOOT-UP E6FE16 0400000000 01
FOOT-DOWN E6FE16 0800000000 FD
HEAD+FOOT-UP E6FE16 0500000000 00 (おそらく、1バイト目の下位4ビットの組み合わせ)
HEAD+FOOT-DOWN E6FE16 0A00000000 FB 同上
メモリ(FLAT) E6FE16 0000000800 FD
メモリ(ANTISNORE) E6FE16 0080000000 85
メモリ(不明) E6FE16 0040000000 C5 試しにやってみたら、特定の姿勢になった
メモリ(READING) E6FE16 0020000000 E5
メモリ(ZG) E6FE16 0010000000 F5
メモリ(M1) E6FE16 0000010000 04
照明ON|OFF E6FE16 0000020000 03
メモリ(M2) E6FE16 0000040000 01
停止コマンド? E6FE16 0000000000 05 FLAT等メモリの状態へ姿勢変化中に送信すると、姿勢変化が停止する
状態通知開始コマンド? E6FE16 0300000000 02 タイマー画面から操作画面へ切り替えた際に、このコマンド送信している。
このコマンド後、F4FE16のNotificationが飛ぶようになる模様(ほかのE6FE16でも同様)
1バイト目の0x03の意味は分かっていない

タイマー設定

  • タイマー画面に切り替えたタイミング
    以下のコマンドを送信している
    E28003009A
    このコマンド後、ED8003のNotificationが飛ぶようになる

  • ON/OFF操作時に以下2個のコマンドを送信している
    1.タイマー設定側を表示中のNotificationと同じコマンド
    2.時間で変化するコマンド(タイマーの起点となるシステム時刻設定をしている?)

    長さ 意味 値の例 説明
    3 マジックワード E78001
    1 7A 1900年を0とする値
    例:7a=122=2022年
    1 05 1月を0とする値
    例:05=6月
    1 07 1日は1とする値
    例:07=7日
    1 00 例:0時
    1 0D 例:13分
    1 38 例:56秒
    1 チェックサム CC (通知と同じ)

試作アプリの実装

解析したコマンド類の読み書きで実際に操作できるかアプリを試作した。

  • サンプルコード
  • 試作アプリ
    • 指定したBluetoothAddressに接続
      image.png
    • 任意の操作と状態の表示
      image.pngimage.png
    • Debug用 Notification/Writeを出力
      image.png

今後

  • 操作プロトコルをもっと理解したい(何か隠された機能とかないかな とか
    • GooglePlayストアのアプリを逆コンパイルすればいろいろ分かりそう
  • スケジュールのダイナミックな操作、オートメーション化
    • パラマウントベッド ActiveSleepBedのような入眠補助
    • 土日と平日で別スケジュールの実現
  • BLEのスタック周りWindowsから脱出したい、RasPi(Linux上)で動かしたい
5
1
1

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
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?