【FireBeetle 2 ESP32 C6开发板】-3- C6获取小米温湿度计2数据
[复制链接]
本帖最后由 慕容雪花 于 2024-5-2 12:36 编辑
小米温湿度计2 是从设备,同时也是BLE SERVER,部署了多个sevice,其中serviceUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6")里面的charUUID("ebe0ccc1-7a0a-4b0c-8a1a-6ff2997da3a6")就是温湿度数据。
esp32c6是主设备,同时也是BLE CLIENT,通过BLE的协议来访问Server上的Characteristic,从而获取到温湿度数据。
C6启动后,会开始扫描周围的BLE设备,此时进行一个判断,设备名称是否为XiaomiDeviceName = "LYWSD03MMC"
/**
* Called for each advertising BLE server.
*/
void onResult(BLEAdvertisedDevice advertisedDevice) {
Serial.println("*-------------------------------------------------------------------*");
Serial.print("BLE Advertised Device found: ");
Serial.println(advertisedDevice.toString().c_str());
// We have found a device, let us now see if it contains the service we are looking for.
Serial.println(advertisedDevice.getServiceUUID().toString().c_str());
Serial.println(advertisedDevice.getName().c_str());
if(0 == advertisedDevice.getName().compareTo(XiaomiDeviceName)){
Serial.println("Great, Found " + advertisedDevice.getName());
Serial.println("advertisedDevice.getServiceUUIDCount() = " + String(advertisedDevice.getServiceUUIDCount()));
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
}
} // onResult
找到小米设备后,进行连接:
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");
pClient->setMTU(517); //set client to request maximum MTU from server (default is 23 otherwise)
// 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");
// Read the value of the characteristic.
if(pRemoteCharacteristic->canRead()) {
String value = pRemoteCharacteristic->readValue();
Serial.print("The characteristic value was: ");
Serial.println(value.c_str());
}
if(pRemoteCharacteristic->canNotify())
pRemoteCharacteristic->registerForNotify(notifyCallback);
connected = true;
return true;
}
从小米设备获取到数据,共有5个字节。
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);
uint16_t TempVal = pData[1]*256 + pData[0];
Serial.println("Temperature is: "+ String(TempVal/100) + "." + String(TempVal%100) + " degree");
uint8_t HumidityVal = pData[2];
Serial.println("Humidity is: " + String(pData[2]) + "% ");
uint16_t BatteryVal = pData[4]*256 + pData[3];
Serial.println("Battery Voltage is: "+ String(BatteryVal/100) + "." + String(BatteryVal%100) + " mV");
Serial.println();
}
注意数据为小端模式存储。
-------------------------------------------------------------------------------------------------------------------
5.2日更新:
上文中BLE SERVER notify上来的数据是没有问题的,温湿度值跟实际设备对比也是OK的,但是仔细观察设备启动,首次连接小米设备成功后,直接读取Characteristic的值,竟然是4??
这个肯定是读取的姿势不对,我接下来一番笨丁解牛。
小米温湿度数据格式为:F2 07 4A C3 0A。也就是5个十六进制数据。仔细看当前的直接读取Characteristic值代码:
// Read the value of the characteristic.
if(pRemoteCharacteristic->canRead()) {
String value = pRemoteCharacteristic->readValue();
Serial.print("The characteristic value was: ");
Serial.println(value.c_str());
}
readValue()方法返回的是String类型变量,更合适的应该是:
uint8_t* test = pRemoteCharacteristic->readRawData();
计算一下使用直接读取数据所对应的温湿度:
代码:
uint8_t* test = pRemoteCharacteristic->readRawData();
uint8_t i;
uint8_t test_temp_val[5]={0};
for(i = 0; i < 5; i++){
if(test != nullptr){
Serial.print("The characteristic value using readRawData was: ");
Serial.println(*test);
test_temp_val = *test;
}else{
Serial.println("pRemoteCharacteristic->readRawData() returns NULL PTR");
}
test++;
}
static uint16_t Test_TempVal = test_temp_val[1]*256 + test_temp_val[0];
Serial.println("Test Temperature is: "+ String(Test_TempVal/100) + "." + String(Test_TempVal%100) + " degree");
static uint8_t Test_HumidityVal = test_temp_val[2];
Serial.println("Test Humidity is: " + String(test_temp_val[2]) + "% ");
static uint16_t Test_BatteryVal = test_temp_val[4]*256 + test_temp_val[3];
Serial.println("Test Battery Voltage is: "+ String(Test_BatteryVal/100) + "." + String(Test_BatteryVal%100) + " mV");
参考:
读取小米蓝牙温湿度计2数据 https://www.cnblogs.com/qsbye/p/15913753.html
|