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