この記事はM5Stack Advent Calendar 2018の5日目の記事です。
概要
M5StackからBluetooth Low Energy(BLE)を使うサンプルを作ったのでその紹介です。
BLE通信できた! #M5Stack pic.twitter.com/SM0ynKv8i5
— さわ/Naoki Sawada (@sawachyon) August 8, 2018
ソースコードはこちらから。
M5Stackの準備
M5Stackにソースコードを書き込む
M5Stackに次のBLEのソースコードを書き込みます。
#include <M5Stack.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <BLE2902.h>
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
BLEServer* pServer = NULL;
BLECharacteristic* pCharacteristic = NULL;
bool deviceConnected = false;
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
M5.Lcd.println("connect");
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) {
M5.Lcd.println("disconnect");
deviceConnected = false;
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onRead(BLECharacteristic *pCharacteristic) {
M5.Lcd.println("read");
pCharacteristic->setValue("Hello World!");
}
void onWrite(BLECharacteristic *pCharacteristic) {
M5.Lcd.println("write");
std::string value = pCharacteristic->getValue();
M5.Lcd.println(value.c_str());
}
};
void setup() {
Serial.begin(115200);
M5.begin();
M5.setWakeupButton(BUTTON_A_PIN);
M5.Lcd.println("BLE start.");
m5.Speaker.mute();
BLEDevice::init("m5-stack");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
pCharacteristic->setCallbacks(new MyCallbacks());
pCharacteristic->addDescriptor(new BLE2902());
pService->start();
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
void loop() {
if(M5.BtnA.wasPressed()) {
M5.powerOFF();
}
if (deviceConnected) {
if(M5.BtnB.wasPressed()) {
M5.Lcd.println("Button B pressed!");
pCharacteristic->setValue("Button B pressed!");
pCharacteristic->notify();
}
}
M5.update();
}
Clientの準備
次に、BLE Clientを準備します。
今回は、Pythonを使ったBLE Clientを作成します。
Bleakのインストール
ここでは、BLEモジュールBleakを使います。
pip install bleak
Python Client
次のコードを保存して、BLE Clientを作成します。
#!/usr/bin/env python3
import asyncio
import logging
import uuid
from bleak import BleakScanner, BleakClient
DEVICE_NAME = "m5-stack"
SERVICE_UUID = uuid.UUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b")
CHAR_UUID = uuid.UUID("beb5483e-36e1-4688-b7f5-ea07361b26a8")
async def run(loop):
print("Searching devices...")
devices = await BleakScanner.discover()
device = list(filter(lambda d: d.name == DEVICE_NAME, devices))
if len(device) == 0:
raise RuntimeError(f"Failed to find a device name '{DEVICE_NAME}'")
address = device[0].address
print(f"Connecting to the device... (address: {address})")
async with BleakClient(address, loop=loop) as client:
print("Message from the device...")
value = await client.read_gatt_char(CHAR_UUID)
print(value.decode())
print("Sending message to the device...")
message = bytearray(b"hi!")
await client.write_gatt_char(CHAR_UUID, message, True)
def callback(sender, data):
print(f"Received: {data}")
print("Subscribing to characteristic changes...")
await client.start_notify(CHAR_UUID, callback)
print("Waiting 60 seconds to receive data from the device...")
await asyncio.sleep(60)
loop = asyncio.get_event_loop()
loop.run_until_complete(run(loop))
BLEを試す
Clientを起動します。 client.py
を実行します。
$ python3 client.py
Searching devices...
Connecting to the device... (address: 6B6ABA49-B0CA-4461-994E-A70A88E0E354)
Message from the device...
Hello World!
Sending message to the device...
Subscribing to characteristic changes...
Waiting 60 seconds to receive data from the device...
Received: b'Button B pressed!'
Received: b'Button B pressed!'
Received: b'Button B pressed!'
コネクションが確立できたら、M5StackのBボタンを押します。
Received: b'Button B pressed!'
が表示されれば、正常に動作しています。
まとめ
この記事ではM5Stackを使ったBLE通信について紹介しました。
M5StackはESP32を使っているので、BLEを手軽に使えるのが良いですね。
参考
BLEについて
BLEの技術的な内容については、こちらのページがとても参考になりました。
AdvertisingやServices, Characteristicsなど、BLEの基本的な要素についてまとまっていておすすめです。
BLE Clientについて
今回の記事ではPythonを使ったBLE Clientの紹介をしましたが、
Web Bluetooth APIを使ったサンプルや、Node.jsを使ったサンプルも作りました。よければ使ってみてください。