一起幫忙解決難題,拯救IT 人的一天 - IT 邦幫忙- IThome

藍芽硬體連結

上一篇我們介紹硬體的藍芽開發介紹,今天介紹與其他藍芽做資料讀取。

ESP32 藍芽 scan

直接上代碼,各位可以看到並不會太多複雜的。

#include <Arduino.h> #include <BLEDevice.h> #include <BLEUtils.h> #include <BLEScan.h> #include <BLEAdvertisedDevice.h> int scanTime = 30; //In seconds class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) { Serial.printf("Advertised Device: %s \n", advertisedDevice.toString().c_str()); } }; void setup() { Serial.begin(115200); Serial.println("Scanning..."); BLEDevice::init(""); BLEScan *pBLEScan = BLEDevice::getScan(); //create new scan pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster BLEScanResults foundDevices = pBLEScan->start(scanTime); Serial.print("Devices found: "); Serial.println(foundDevices.getCount()); Serial.println("Scan done!"); } void loop() { // put your main code here, to run repeatedly: delay(2000); }

這邊是執行結果可以看到掃描到的裝置。

ets Jun 8 2016 00:22:57 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:2 load:0x3fff0018,len:4 load:0x3fff001c,len:1044 load:0x40078000,len:8896 load:0x40080400,len:5828 entry 0x400806ac Scanning... Advertised Device: Name: LYWSD02, Address: 3f:5b:7d:80:b0:d1, serviceUUID: 0000181a-0000-1000-8000-00805f9b34fb Advertised Device: Name: MJ_HT_V1, Address: 4c:65:a8:da:1f:cc, serviceUUID: 0000180f-0000-1000-8000-00805f9b34fb Devices found: 2 Scan done!

ESP32 藍芽讀取廣播資料 溫濕度

我們這邊依樣示範讀取小米的藍芽溫濕度。

#include <Arduino.h> #include <sstream> #include <BLEDevice.h> #include <BLEUtils.h> #include <BLEScan.h> #include <BLEAdvertisedDevice.h> int scanTime = 5; //In seconds BLEScan *pBLEScan; class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks { void onResult(BLEAdvertisedDevice advertisedDevice) { if (advertisedDevice.haveName() && advertisedDevice.haveServiceData() && !advertisedDevice.getName().compare("LYWSD02")) { std::string strServiceData = advertisedDevice.getServiceData(); Serial.printf("\n\nAdvertised Device: %s\n", advertisedDevice.toString().c_str()); std::string uuid = advertisedDevice.getServiceDataUUID().toString(); Serial.println(uuid.c_str()); if (uuid.compare("0000fe95-0000-1000-8000-00805f9b34fb")) { return; } uint8_t cServiceData[100]; char charServiceData[100]; strServiceData.copy((char *)cServiceData, strServiceData.length(), 0); for (int i = 0; i < strServiceData.length(); i++) { sprintf(&charServiceData[i * 2], "%02x", cServiceData[i]); } bool is_mijia = (cServiceData[1] & 0x20) == 0x20 && cServiceData[2] == 0xAA && cServiceData[3] == 0x01; bool is_lywsd02 = (cServiceData[1] & 0x20) == 0x20 && cServiceData[2] == 0x5b && cServiceData[3] == 0x04; if (is_mijia) { Serial.println("is_mijia!"); } if (is_lywsd02) { uint8_t raw_offset = is_mijia ? 11 : 12; const uint8_t raw_type = cServiceData[raw_offset]; const uint8_t data_length = cServiceData[raw_offset + 2]; const uint8_t *data = &cServiceData[raw_offset + 3]; const uint8_t expected_length = data_length + raw_offset + 3; const uint8_t actual_length = advertisedDevice.getServiceData().size(); if (expected_length != actual_length) { return; } // Serial.println("is_lywsd02!"); switch (raw_type) { case 0x0D: { // temperature+humidity, 4 bytes, 16-bit signed integer (LE) each, 0.1 °C, 0.1 % if (data_length != 4) return; const int16_t temperature = uint16_t(data[0]) | (uint16_t(data[1]) << 8); const int16_t humidity = uint16_t(data[2]) | (uint16_t(data[3]) << 8); Serial.print("temperature="); Serial.println(temperature / 10.0f); Serial.print("humidity="); Serial.println(humidity / 10.0f); return; } case 0x06: { // humidity, 2 bytes, 16-bit signed integer (LE), 0.1 % if (data_length != 2) return; const int16_t humidity = uint16_t(data[0]) | (uint16_t(data[1]) << 8); Serial.print("humidity="); Serial.println(humidity / 10.0f); return; } case 0x04: { // temperature, 2 bytes, 16-bit signed integer (LE), 0.1 °C if (data_length != 2) return; const int16_t temperature = uint16_t(data[0]) | (uint16_t(data[1]) << 8); Serial.print("temperature="); Serial.println(temperature / 10.0f); return; } default: return; } } } } }; void setup() { Serial.begin(115200); Serial.println("Scanning..."); BLEDevice::init(""); pBLEScan = BLEDevice::getScan(); //create new scan pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks()); pBLEScan->setActiveScan(true); //active scan uses more power, but get results faster pBLEScan->setInterval(100); pBLEScan->setWindow(99); } void loop() { BLEScanResults foundDevices = pBLEScan->start(scanTime); delay(2000); }

這邊是執行結果可以看到溫度濕度資訊。

Advertised Device: Name: LYWSD02, Address: 3f:5b:7d:80:b0:d1, serviceUUID: 0000181a-0000-1000-8000-00805f9b34fb 0000fe95-0000-1000-8000-00805f9b34fb humidity=56.00 Advertised Device: Name: LYWSD02, Address: 3f:5b:7d:80:b0:d1, serviceUUID: 0000181a-0000-1000-8000-00805f9b34fb 0000fe95-0000-1000-8000-00805f9b34fb temperature=27.80 Advertised Device: Name: LYWSD02, Address: 3f:5b:7d:80:b0:d1, serviceUUID: 0000181a-0000-1000-8000-00805f9b34fb 0000fe95-0000-1000-8000-00805f9b34fb humidity=56.00 Advertised Device: Name: LYWSD02, Address: 3f:5b:7d:80:b0:d1, serviceUUID: 0000181a-0000-1000-8000-00805f9b34fb 0000fe95-0000-1000-8000-00805f9b34fb temperature=27.80 Advertised Device: Name: LYWSD02, Address: 3f:5b:7d:80:b0:d1, serviceUUID: 0000181a-0000-1000-8000-00805f9b34fb 0000fe95-0000-1000-8000-00805f9b34fb humidity=56.00

這邊有踩到坑浪費我好幾小時,藍芽掃描廣播資訊時。這個程式庫會複寫得到的裝置 serviceUUID(依該説它只會存一筆單個 service)...所以要調整掃描區間給他縮短讓他收集到不同資料。

結語

今天介紹直接開發藍芽裝置去讀取其他藍芽的溫濕度!如果你還想延伸可以再將資料透過 MQTT 發送到主機。

Blog 同步刊登

Tag » Arduino Ble Device.h