POSTS
制霸 IoT 30Day! Day 21 藍芽硬體連結
藍芽硬體連結
上一篇我們介紹硬體的藍芽開發介紹,今天介紹與其他藍芽做資料讀取。
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 發送到主機。