ダイソーのBluetoothリモコンシャッターをESP32でハックする

はじめに
ダイソーで販売されている300円のBluetoothリモコンシャッター(Remote Shutter)を、ESP32と通信してボタンイベントを受信できるようにしてみました。この企画はすでに色々な方が挑戦されていて、情報も溢れています。ここでは下記の二つの記事を参考にさせてもらいながら、ESP32で実装してみました。
リモコンシャッターでLチカさせる
ESP32をつかって、リモコンシャッターのボタンが押されたらLEDの点灯状態を変化させてみました。
ソースコード
こちらがそのソースコードです:
#include <Arduino.h>
#include "BLEDevice.h"
#define LED_PIN 13
static uint16_t GATT_HID = 0x1812;
//static BLEUUID GATT_HID_REPORT((uint16_t) 0x2a4d);
static BLEAddress *pServerAddress = NULL;
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks {
void onResult(BLEAdvertisedDevice advertisedDevice) {
if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(GATT_HID)) {
.getScan()->stop();
advertisedDevice
= new BLEAddress(advertisedDevice.getAddress());
pServerAddress .print("found device:");
Serial.println(pServerAddress->toString().c_str()); // 2a:07:98:10:33:fa
Serial}
}
};
void updateLedState() {
static boolean ledState = true;
if (ledState == 0) {
(LED_PIN, LOW);
digitalWrite} else {
(LED_PIN, HIGH);
digitalWrite}
= !ledState;
ledState }
static void
(BLERemoteCharacteristic *pBLERemoteCharacteristic, uint8_t *pData, size_t length, bool isNotify) {
notifyCallback.println("notifyCallback");
Serialswitch (pData[0]) {
case 0x01: // Volume Up
.println("Volume Up");
Serial();
updateLedStatebreak;
case 0x02: // Volume Down
.println("Volume Down");
Serial();
updateLedStatebreak;
}
}
void setup() {
.begin(115200);
Serial
(LED_PIN, OUTPUT);
pinMode(LED_PIN, LOW);
digitalWrite
::init("");
BLEDevice*pBLEScan = BLEDevice::getScan();
BLEScan ->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setActiveScan(true);
pBLEScan->start(30);
pBLEScan}
void loop() {
static boolean connected = false;
if (pServerAddress != NULL && !connected) {
*pClient = BLEDevice::createClient();
BLEClient ->connect(*pServerAddress);
pClient
if(pClient->isConnected()) {
.println("connected");
Serial} else {
return;
}
//! arduino-esp32のバージョンによってはクラッシュするので注意
//! ver 2.0.2 だとここで落ちる → ver 2.0.14 または ver 3.20014.0 で動作確認済み
*pRemoteService = pClient->getService(GATT_HID);
BLERemoteService if (pRemoteService) {
// BLERemoteCharacteristic *pRemoteCharacteristic = pRemoteService->getCharacteristic(GATT_HID_REPORT);
// pRemoteCharacteristic->registerForNotify(notifyCallback);
std::map<uint16_t, BLERemoteCharacteristic*>* mapCharacteristics = pRemoteService->getCharacteristicsByHandle();
for (std::map<uint16_t, BLERemoteCharacteristic*>::iterator i = mapCharacteristics->begin(); i != mapCharacteristics->end(); ++i) {
.print("connected to:");
Serial.println(i->second->getUUID().toString().c_str());
Serialif (i->second->canNotify()) {
.println(" - Add Notify");
Serial->second->registerForNotify(notifyCallback);
i}
}
= true;
connected }
}
(10); // 高負荷防止
delay}
注意点
ソースコードをアップロードするにあたって、注意点があります。PlatformIOを使っていると思いますが、arduino-esp32のバージョンが古いとクラッシュします。ソースコード内のコメント注釈のとおり、version 2.0.2だとダメでした。version 2.0.14以降でしたら問題なさそうです。
[env]
platform = https://github.com/platformio/platform-espressif32.git
board = esp32dev
framework = arduino
monitor_speed = 115200
platform_packages =
; framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32#2.0.2
framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32#2.0.14
解説
BLE処理の流れ
BLE処理の流れは以下の通りです:
- デバイスのスキャン開始:
setup
関数でBLEスキャンが開始され、指定したサービスUUIDを持つデバイスが見つかるまで続けられます。 - デバイス発見時の処理:
MyAdvertisedDeviceCallbacks
のonResult
コールバックが呼び出され、条件に合致するデバイスが見つかった場合、スキャンは停止され、デバイスのアドレスが保存されます。 - デバイスへの接続試行:
loop
関数内で、保存されたデバイスアドレスに対して接続を試みます。接続に成功すると、次のステップに進みます。 - サービスの取得と通知の購読: 接続後、GATT
HIDサービスを取得し、そのサービス内の特性(Characteristic)に対して通知を購読します。このステップでは、すべての特性をループして、通知可能な特性に対して
notifyCallback
を登録します。 - 通知の受信と処理:
notifyCallback
が、購読した特性から通知を受け取るたびに呼び出され、受け取ったデータに基づいてLEDの状態を切り替えます。
このスケッチは、BLEデバイスのスキャン、接続、および通知の購読という、BLE通信の基本的なプロセスを実演しています。それぞれのステップは、BLEデバイスとのインタラクションを制御し、特定のサービスや特性にアクセスするために重要です。
関数やクラスの説明
このArduinoスケッチは、BLE(Bluetooth Low Energy)を使用して特定のサービスUUID(この場合はGATT HIDサービス)を持つデバイスをスキャンし、見つけたデバイスに接続して、通知を購読するプロセスを実行します。以下に、主要なBluetooth関連のロジックを中心に解説したテーブルを示します。
関数/クラス名 | 説明 |
---|---|
MyAdvertisedDeviceCallbacks |
BLEデバイスのスキャン中に呼び出されるコールバック。指定したUUIDを持つデバイスを見つけた場合、そのデバイスのアドレスを保存し、スキャンを停止します。 |
notifyCallback |
BLEデバイスからの通知を受け取ったときに呼び出されるコールバック。受け取ったデータに基づいて、特定のアクション(この例ではLEDの状態の切り替え)を実行します。 |
setup |
Arduinoスケッチの初期設定を行う関数。BLEデバイスの初期化、スキャンの設定、そしてスキャンの開始を行います。 |
loop |
Arduinoスケッチのメインループ。特定のデバイスが見つかり、まだ接続されていない場合、そのデバイスに接続し、GATT HIDサービスを取得して、通知を購読します。 |
UUID | UUIDを通じて、BLEデバイスは特定のサービスや特性を識別し、操作を行うことができます。これにより、互換性のあるデバイス間での正確なデータ交換が可能になります。 |
BLERemoteService | BLERemoteService は、BLEデバイス上で提供されるサービスを表します。サービスは、一連の特性(BLERemoteCharacteristic )をグルーピングしたもので、デバイスが提供する機能や情報のカテゴリを表します。たとえば、「バッテリーサービス」は、デバイスのバッテリーレベルに関する情報を提供する特性を含むことができます。 |
BLERemoteCharacteristic | BLERemoteCharacteristic は、BLEサービスの下で定義されるデータポイントです。特性は、サービスが提供する具体的な情報や操作を表し、データの読み取り、書き込み、通知(データの変更があったときに自動的に送信される)をサポートできます。 |
関連記事
- ダイソーのリモコンシャッターをESP32で通信するためのヘルパー関数
- ESP32でBluetooth Classicを使ってAndroidと通信する
- はじめてのBLE通信、iOSからESP32のLチカ
- ESP32 で SigFox をはじめる
- ESP32でBLE通信、ESP32からiOSでデータ受信