ESP32を使用してBLEスキャンアプリを作成します。その後、アルプスのセンサネットワークモジュールから環境データ、CC2541 SensorTagから温度データを取得します。WindowsでC#により作成したプログラムは、「C# .NET Frameworkを使ってアルプスのセンサネットワークモジュールからモーションデータの取得」、「C# .NET Frameworkを使ってCC2541 SensorTagから温度データの取得」にそれぞれ示します。なお、各データの取得のプログラムは「BLE_client」を参考にして作成しました。
BLEスキャンアプリのコンパイル・実行
次のようにスケッチ例から「BLE_scan」を選択して実行します。
実行した結果を次に示します。アルプスのセンサネットワークモジュールは、「Advertised Device: Name: , Address: 28:a1:83:e1:58:96」で表示されました。名称が検出されず、アドレスだけ表示されます。
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:1216 ho 0 tail 12 room 4 load:0x40078000,len:9720 ho 0 tail 12 room 4 load:0x40080400,len:6352 entry 0x400806b8 Scanning... Advertised Device: Name: , Address: 28:a1:83:e1:58:96 Advertised Device: Name: , Address: 69:b9:db:d9:dc:e5, manufacturer data: 060001092002df9ca2d6b42bbd48463354bb4703b029d9ada2d70543a0 Advertised Device: Name: , Address: 4a:8e:f0:7d:43:75, manufacturer data: 4c00100521188399b5, txPower: 8 Devices found: 3 Scan done! Advertised Device: Name: , Address: 69:b9:db:d9:dc:e5, manufacturer data: 060001092002df9ca2d6b42bbd48463354bb4703b029d9ada2d70543a0 Advertised Device: Name: , Address: 4a:8e:f0:7d:43:75, manufacturer data: 4c00100521188399b5, txPower: 8 Advertised Device: Name: , Address: 28:a1:83:e1:58:96 Devices found: 3
CC2541 SensorTagからの温度データ取得
CC2541 SensorTagから温度データを取得するプログラムを次に示します。
- 4行目でSensorTagのアドレスを指定し、検出したBLE機器のアドレスと137行目で比較し、SensorTagを検出します。
- 103行目でのNotifyのDescriptorの指定は必要ありませんでした。
- 109-110行目で温度データの出力要求を指示します。
SensortagCentral.ino
#include "BLEDevice.h"
// sensor tab
#define BLEADDRESS "b4:99:4c:64:cd:df"
// The remote service we wish to connect to.
static BLEUUID serviceUUID("F000AA00-0451-4000-B000-000000000000");
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID("F000AA01-0451-4000-B000-000000000000");
static BLEUUID charcmdUUID("F000AA02-0451-4000-B000-000000000000");
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLERemoteCharacteristic* pRemoteCmdCharacteristic;
static BLEAdvertisedDevice* myDevice;
static boolean initflg = false;
const uint8_t notifyOn[] = {0x1, 0x0};
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
Serial.print("Notify callback for characteristic ");
Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
Serial.print(" of data length ");
Serial.println(length);
Serial.print("data: ");
for (int i = 0; i <= length - 1; i++) {
Serial.print(String(*(pData + i), HEX));
Serial.print(" ");
}
Serial.println("");
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
}
void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
}
};
bool connectToServer() {
Serial.print("Forming a connection to ");
Serial.println(myDevice->getAddress().toString().c_str());
BLEClient* pClient = BLEDevice::createClient();
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remove BLE Server.
pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
Serial.println(" - Connected to server");
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our service");
// Obtain a reference to the characteristic in the service of the remote BLE server.
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our characteristic");
pRemoteCmdCharacteristic = pRemoteService->getCharacteristic(charcmdUUID);
if (pRemoteCmdCharacteristic == nullptr) {
Serial.print("Failed to find our cmdcharacteristic UUID: ");
Serial.println(charcmdUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our cmdcharacteristic");
// Read the value of the characteristic.
if (pRemoteCharacteristic->canRead()) {
//std::string value = pRemoteCharacteristic->readValue();
//Serial.println(value.c_str());
Serial.print("The characteristic value was: ");
uint8_t value = pRemoteCharacteristic->readUInt8();
Serial.println(String(value, HEX));
}
if (pRemoteCharacteristic->canNotify()) {
// pRemoteCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notifyOn, 2, true);
pRemoteCharacteristic->registerForNotify(notifyCallback);
Serial.println("canNotify!!");
}
byte comm1[] = { 0x01 };
pRemoteCmdCharacteristic->writeValue(comm1, 1);
connected = true;
}
/**
Scan for BLE servers and find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/**
Called for each advertising BLE server.
*/
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice.toString().c_str());
//Serial.println(advertisedDevice.getName().c_str());
if (advertisedDevice.haveServiceUUID()) {
Serial.println(advertisedDevice.getServiceUUID().toString().c_str());
}
else {
Serial.println("No ServiceUUID ");
}
Serial.println(advertisedDevice.getAddress().toString().c_str());
// We have found a device, let us now see if it contains the service we are looking for.
//if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
if (advertisedDevice.getAddress().toString() == BLEADDRESS) {
Serial.println("Sensortag!! ");
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
void setup() {
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
} // End of setup.
// This is the Arduino main loop function.
void loop() {
// If the flag "doConnect" is true then we have scanned for and found the desired
// BLE Server with which we wish to connect. Now we connect to it. Once we are
// connected we set the connected flag to be true.
if (doConnect == true) {
if (connectToServer()) {
Serial.println("We are now connected to the BLE Server.");
} else {
Serial.println("We have failed to connect to the server; there is nothin more we will do.");
}
doConnect = false;
}
delay(1000); // Delay a second between loops.
} // End of loop
実行した結果を次に示します。名称は「SensorTag」と表示され、アドレスは「b4:99:4c:64:cd:df」となります。Notify callbackにより、温度データが表示されます。
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:1216 ho 0 tail 12 room 4 load:0x40078000,len:9720 ho 0 tail 12 room 4 load:0x40080400,len:6352 entry 0x400806b8 Starting Arduino BLE Client application... BLE Advertised Device found: Name: , Address: 52:18:13:48:eb:aa, manufacturer data: 4c0010052118944155, txPower: 8 No ServiceUUID 52:18:13:48:eb:aa BLE Advertised Device found: Name: SensorTag, Address: b4:99:4c:64:cd:df, txPower: 0 No ServiceUUID b4:99:4c:64:cd:df Sensortag!! Forming a connection to b4:99:4c:64:cd:df - Created client - Connected to server - Found our service - Found our characteristic - Found our cmdcharacteristic The characteristic value was: f0 canNotify!! We are now connected to the BLE Server. Notify callback for characteristic f000aa01-0451-4000-b000-000000000000 of data length 4 data: e1 fe b0 8 Notify callback for characteristic f000aa01-0451-4000-b000-000000000000 of data length 4 data: e3 fe b0 8
アルプスのセンサネットワークモジュールからの環境データ取得
アルプスのセンサネットワークモジュールからの環境データ(Pressure、Humidity、Temperature)を取得するプログラムを次に示します。
- 186-204行目で環境データの出力を要求します。「delay(100)」を設定する必要があります。設定しない場合、ステータス「0xE0」のみが出力されます。
AlpsCentral.ino
/**
A BLE client example that is rich in capabilities.
There is a lot new capabilities implemented.
author unknown
updated by chegewara
*/
#include "BLEDevice.h"
//#include "BLEScan.h"
// ALPS
#define BLEADDRESS "28:a1:83:e1:58:96"
// The remote service we wish to connect to.
static BLEUUID serviceUUID("47FE55D8-447F-43EF-9AD9-FE6325E17C47");
// The characteristic of the remote service we are interested in.
static BLEUUID charUUID("686A9A3B-4C2C-4231-B871-9CFE92CC6B1E");
//static BLEUUID charUUID("078FF5D6-3C93-47F5-A30C-05563B8D831E");
static BLEUUID charcmdUUID("B962BDD1-5A77-4797-93A1-EDE8D0FF74BD");
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;
static BLERemoteCharacteristic* pRemoteCmdCharacteristic;
static BLEAdvertisedDevice* myDevice;
static boolean initflg = false;
const uint8_t notifyOn[] = {0x1, 0x0};
void dataana(uint8_t* pData){
uint8_t test[20] = { 0xf3, 0x14, 0x79, 0xe3, 0x40, 0x16, 0x23, 0xc, 1, 0, 3, 0, 0, 0, 0, 0, 1, 0xa, 0xf, 0x74 };
//pData = test;
float Pressure = (float)((uint32_t)(*(pData + 3))<<8);
Pressure = Pressure + *(pData + 2);
float Humidity = (float)((uint32_t)(*(pData + 5))<<8);
Humidity = Humidity + *(pData + 4);
float Temperature = (float)((uint32_t)(*(pData + 7))<<8);
Temperature = Temperature + *(pData + 6);
Pressure = Pressure*860/65535+250;
Humidity = (Humidity- 896)/64;
Temperature = (Temperature-2096)/50;
Serial.print("Pressure: ");
Serial.println(String(Pressure));
Serial.print("Humidity: ");
Serial.println(String(Humidity));
Serial.print("Temperature: ");
Serial.println(String(Temperature));
}
static void notifyCallback(
BLERemoteCharacteristic* pBLERemoteCharacteristic,
uint8_t* pData,
size_t length,
bool isNotify) {
Serial.print("Notify callback for characteristic ");
Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
Serial.print(" of data length ");
Serial.println(length);
Serial.print("data: ");
for (int i = 0; i <= length - 1; i++) {
Serial.print(String(*(pData + i), HEX));
Serial.print(" ");
}
Serial.println("");
if(*(pData) == 0xf3){
dataana(pData);
}
}
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
}
void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
}
};
bool connectToServer() {
Serial.print("Forming a connection to ");
Serial.println(myDevice->getAddress().toString().c_str());
BLEClient* pClient = BLEDevice::createClient();
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remove BLE Server.
pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
Serial.println(" - Connected to server");
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our service");
// Obtain a reference to the characteristic in the service of the remote BLE server.
pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
if (pRemoteCharacteristic == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our characteristic");
pRemoteCmdCharacteristic = pRemoteService->getCharacteristic(charcmdUUID);
if (pRemoteCmdCharacteristic == nullptr) {
Serial.print("Failed to find our cmdcharacteristic UUID: ");
Serial.println(charcmdUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our cmdcharacteristic");
// Read the value of the characteristic.
if (pRemoteCharacteristic->canRead()) {
//std::string value = pRemoteCharacteristic->readValue();
//Serial.println(value.c_str());
Serial.print("The characteristic value was: ");
uint8_t value = pRemoteCharacteristic->readUInt8();
Serial.println(String(value, HEX));
}
if (pRemoteCharacteristic->canNotify()) {
//pRemoteCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notifyOn, 2, true);
pRemoteCharacteristic->registerForNotify(notifyCallback);
Serial.println("canNotify!!");
}
//setcommand();
connected = true;
}
/**
Scan for BLE servers and find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/**
Called for each advertising BLE server.
*/
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice.toString().c_str());
//Serial.println(advertisedDevice.getName().c_str());
if (advertisedDevice.haveServiceUUID()) {
Serial.println(advertisedDevice.getServiceUUID().toString().c_str());
}
else {
Serial.println("No ServiceUUID ");
}
Serial.println(advertisedDevice.getAddress().toString().c_str());
// We have found a device, let us now see if it contains the service we are looking for.
//if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
if (advertisedDevice.getAddress().toString() == BLEADDRESS) {
Serial.println("ALPS!! ");
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
void setcommand() {
byte comm1[3] = { 0x2F, 0x03, 0x03 };
pRemoteCmdCharacteristic->writeValue(comm1, 3);
delay(100);
byte comm2[3] = { 0x01, 0x03, 0x7c};
pRemoteCmdCharacteristic->writeValue(comm2, 3);
delay(100);
byte comm3[3] = { 0x04, 0x03, 0x00 };
pRemoteCmdCharacteristic->writeValue(comm3, 3);
delay(100);
byte comm4[4] = { 0x05, 0x04, 0x05, 0x00 };
pRemoteCmdCharacteristic->writeValue(comm4, 4);
delay(100);
byte comm5[3] = { 0x2F, 0x03, 0x01 };
pRemoteCmdCharacteristic->writeValue(comm5, 3);
delay(100);
byte comm6[3] = { 0x20, 0x03, 0x01 };
pRemoteCmdCharacteristic->writeValue(comm6, 3);
}
void setup() {
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
pBLEScan->setInterval(1349);
pBLEScan->setWindow(449);
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);
} // End of setup.
// This is the Arduino main loop function.
void loop() {
// If the flag "doConnect" is true then we have scanned for and found the desired
// BLE Server with which we wish to connect. Now we connect to it. Once we are
// connected we set the connected flag to be true.
if (doConnect == true) {
if (connectToServer()) {
Serial.println("We are now connected to the BLE Server.");
} else {
Serial.println("We have failed to connect to the server; there is nothin more we will do.");
}
doConnect = false;
}
if (connected) {
setcommand();
connected = false;
}
delay(1000); // Delay a second between loops.
} // End of loop
実行した結果を次に示します。Notify callbackにより、「Pressure:」「Humidity:」「Temperature: 」として計測した環境データが表示されます。
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:1216 ho 0 tail 12 room 4 load:0x40078000,len:9720 ho 0 tail 12 room 4 load:0x40080400,len:6352 entry 0x400806b8 Starting Arduino BLE Client application... BLE Advertised Device found: Name: , Address: 28:a1:83:e1:58:96 No ServiceUUID 28:a1:83:e1:58:96 ALPS!! Forming a connection to 28:a1:83:e1:58:96 - Created client - Connected to server - Found our service - Found our characteristic - Found our cmdcharacteristic The characteristic value was: f3 canNotify!! We are now connected to the BLE Server. Notify callback for characteristic 686a9a3b-4c2c-4231-b871-9cfe92cc6b1e of data length 20 data: f2 14 0 80 0 80 0 80 0 80 0 80 0 80 0 0 1c 1 0 d Notify callback for characteristic 686a9a3b-4c2c-4231-b871-9cfe92cc6b1e of data length 20 data: f3 14 b e3 28 18 fd b 0 0 3 0 0 0 0 0 1 a f d Pressure: 1012.73 Humidity: 82.62 Temperature: 19.46 Notify callback for characteristic 686a9a3b-4c2c-4231-b871-9cfe92cc6b1e of data length 20 data: e0 14 0 0 0 0 c7 b5 9 0 1 0 0 0 0 0 0 0 0 0 Notify callback for characteristic 686a9a3b-4c2c-4231-b871-9cfe92cc6b1e of data length 20 data: f2 14 0 80 0 80 0 80 0 80 0 80 0 80 0 0 24 1 0 0
