BLE, рддрд╛рдкрдорд╛рди рдФрд░ Xiaomi рд╕реЗрдВрд╕рд░ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдлрд┐рд░ рд╕реЗ

рдЗрддрдирд╛ рд╕рдордп рдкрд╣рд▓реЗ рдирд╣реАрдВ, рдореИрдВ рдкреНрд░рд╕рд┐рджреНрдз Xiaomi рддрд╛рдкрдорд╛рди рдФрд░ рдЖрд░реНрджреНрд░рддрд╛ рд╕реЗрдВрд╕рд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛ред рдЗрди рд╕реЗрдВрд╕рд░реЛрдВ рдиреЗ рд╡реНрдпрд╛рдкрдХ рд░реВрдк рд╕реЗ рд╡реНрдпрд╛рдкрдХ рд▓реЛрдХрдкреНрд░рд┐рдпрддрд╛ рд╣рд╛рд╕рд┐рд▓ рдХреА рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдЙрдирдХреА рдХрд╛рдлреА рдХрдо рдХреАрдордд рдкрд░, рд╡реЗ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╛рдлреА рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИрдВ, рдФрд░ рд╡реЗ рдпрд╣ рднреА рдЬрд╛рдирддреЗ рд╣реИрдВ рдХрд┐ рдЕрдкрдиреЗ рд░реАрдбрд┐рдВрдЧ рдХреЛ BLE рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрд╕реА Mi рд╣реЛрдо рдореЗрдВ рдХреИрд╕реЗ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЗрди рд╕реЗрдВрд╕рд░реЛрдВ рдХреЛ рд╣реЛрдо рдЕрд╕рд┐рд╕реНрдЯреЗрдВрдЯ , рдореЗрдЬрд░рдбреЛрдореЛ рдФрд░ рдЕрдиреНрдп рдкреНрд░рдгрд╛рд▓рд┐рдпреЛрдВ рд╕реЗ рдЬреЛрдбрд╝рдиреЗ рдХреЗ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдХреЗ рд╕рд╛рде рдкреВрд░рд╛ рдЗрдВрдЯрд░рдиреЗрдЯ рдлрд┐рд╕рдбреНрдбреА рд╣реИ ред


рд▓реЗрдХрд┐рди рдпрд╣ рдореБрдЭреЗ рдкрд░реНрдпрд╛рдкреНрдд рдирд╣реАрдВ рд▓рдЧ рд░рд╣рд╛ рдерд╛ рдФрд░ рдореИрдВ рд╕рдм рдХреБрдЫ рдЕрдкрдиреЗ рддрд░реАрдХреЗ рд╕реЗ рдХрд░рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ (рдореБрдЭрд╕реЗ рдпрд╣ рдХреНрдпреЛрдВ рдФрд░ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдкреВрдЫрдирд╛, рдореИрдВ рдмрд╕ рдЪрд╛рд╣рддрд╛ рдерд╛)ред рдЕрд░реНрдерд╛рддреН, рдореИрдВ рдЙрди рд╕реЗрдВрд╕рд░реЛрдВ рдХреЗ рдбреЗрдЯрд╛ рдХреЛ рдкрдврд╝рдирд╛ рдЪрд╛рд╣рддрд╛ рдерд╛ рдЬреЛ рдШрд░ рдХреЗ рдЖрд╕рдкрд╛рд╕ рд▓рдЯрдХрд╛рдП рдЬрд╛рддреЗ рд╣реИрдВ рдФрд░ рдХрд┐рд╕реА рддрд░рд╣ рдЙрдирдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рджрд┐рд▓рдЪрд╕реНрдк рд╣реЛрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП, рдореИрдВрдиреЗ рдЕрдкрдиреЗ рдЗрд▓реЗрдХреНрдЯреНрд░реЙрдирд┐рдХ рдбрд┐рдмреНрдмреЗ рдореЗрдВ рд░рдо рдХрд┐рдпрд╛ рдФрд░ рд╡рд╣рд╛рдВ ESP32 рдореЙрдбреНрдпреВрд▓ рдкрд╛рдпрд╛ред



рдПрдХ рддреНрд╡рд░рд┐рдд Google рдиреЗ рджрд┐рдЦрд╛рдпрд╛: ESP32 рд╡рд╣ рд╣реИ рдЬреЛ рдореБрдЭреЗ рдЪрд╛рд╣рд┐рдПред рдпрд╣ рдЬрд╛рдирддрд╛ рд╣реИ рдХрд┐ рдХреИрд╕реЗ рдмреНрд▓реВрдЯреВрде рдФрд░ рд╡рд╛рдИрдлрд╛рдИ, Arduino IDE рд╕реЗ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдФрд░ рдореБрдЭреЗ рд╕реЗрдВрд╕рд░ рд╕реЗ рд░реАрдбрд┐рдВрдЧ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╡рд╛рдИрдлрд╛рдИ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рднреЗрдЬрдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ рдЬрд╣рд╛рдВ рдореБрдЭреЗ рдЬрд╝рд░реВрд░рдд рд╣реИ (рдХрдо рд╕реЗ рдХрдо рд╣реЛрдо рд╕рд░реНрд╡рд░, рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдХреНрд▓рд╛рдЙрдб рддрдХ)ред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдПрдХ рдмрд╣реБрдд рдЬрд▓реНрджреА рдФрд░ рд╕рд░рд▓ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдкрд╛рдпрд╛ рдЧрдпрд╛ рдХрд┐ рдмрд╕ рдореЗрд░реА рд╕рдорд╕реНрдпрд╛ рд╣рд▓ рд╣реЛ рдЧрдИред рд▓реЗрдХрд┐рди рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рдирд┐рдХрд▓рд╛, рд╕рдм рдХреБрдЫ рдЗрддрдирд╛ рд╕рд░рд▓ рдирд╣реАрдВ рд╣реИ ...


рдкрд╣рд▓реА рд╕рдорд╕реНрдпрд╛рдПрдВ


, . тАж , .


, ESP32, . ( , ) . , . , BLE . , , - .



BLE 2- . (discover mode) (connection mode). , Bluetooth . . - . , .


Xiaomi , . . . , .


- ?


. , (advertising ).


void initBluetooth()
{
    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(0x50);
    pBLEScan->setWindow(0x30);
}

:


 void onResult(BLEAdvertisedDevice advertisedDevice)
    {
        if (advertisedDevice.haveName() && advertisedDevice.haveServiceData() && !advertisedDevice.getName().compare("MJ_HT_V1")) {
            std::string strServiceData = advertisedDevice.getServiceData();
            uint8_t cServiceData[100];
            char charServiceData[100];

            strServiceData.copy((char *)cServiceData, strServiceData.length(), 0);

            Serial.printf("\n\nAdvertised Device: %s\n", advertisedDevice.toString().c_str());

            for (int i=0;i<strServiceData.length();i++) {
                sprintf(&charServiceData[i*2], "%02x", cServiceData[i]);
            }

            std::stringstream ss;
            ss << "fe95" << charServiceData;

            Serial.print("Payload:");
            Serial.println(ss.str().c_str());

            char eventLog[256];
            unsigned long value, value2;
            char charValue[5] = {0,};
            switch (cServiceData[11]) {
                case 0x04:
                    sprintf(charValue, "%02X%02X", cServiceData[15], cServiceData[14]);
                    value = strtol(charValue, 0, 16);
                    if(METRIC)
                    {
                      current_temperature = (float)value/10;
                    }else
                    {
                      current_temperature = CelciusToFahrenheit((float)value/10);
                    }
                    displayTemperature();  
                    break;
                case 0x06:
                    sprintf(charValue, "%02X%02X", cServiceData[15], cServiceData[14]);
                    value = strtol(charValue, 0, 16);  
                    current_humidity = (float)value/10;
                    displayHumidity();                      
                    Serial.printf("HUMIDITY_EVENT: %s, %d\n", charValue, value);
                    break;
                case 0x0A:
                    sprintf(charValue, "%02X", cServiceData[14]);
                    value = strtol(charValue, 0, 16);                    
                    Serial.printf("BATTERY_EVENT: %s, %d\n", charValue, value);
                    break;
                case 0x0D:
                    sprintf(charValue, "%02X%02X", cServiceData[15], cServiceData[14]);
                    value = strtol(charValue, 0, 16);      
                    if(METRIC)
                    {
                      current_temperature = (float)value/10;
                    }else
                    {
                      current_temperature = CelciusToFahrenheit((float)value/10);
                    }
                    displayTemperature();               
                    Serial.printf("TEMPERATURE_EVENT: %s, %d\n", charValue, value);                    
                    sprintf(charValue, "%02X%02X", cServiceData[17], cServiceData[16]);
                    value2 = strtol(charValue, 0, 16);
                    current_humidity = (float)value2/10;
                    displayHumidity();                                        
                    Serial.printf("HUMIDITY_EVENT: %s, %d\n", charValue, value2);
                    break;
            }
        }
    }

, - .


switch, 11 service data . , 11 . .


advertising (payload). , , . . payload ( ):


020106121695fe5020aa01ab9f0231342d580a10014309094d4a5f48545f563105030f180a180916ffffc8b33f8a48db

. ( 0x02) . , ( ). . ( ) .


0x16, service data, .. , . 2:


121695fe5020aa01ab9f0231342d580a100143
0916ffffc8b33f8a48db

, , 11 , , switch (0x0A). , , . . , , .


?


- , , , . ESP32 Arduino. , , getServiceData , . .. , payload service data. , . , ( 1.0.4). Arduino IDE ESP32 Boards Manager . getServiceData() service data. , . , .



. . , , . , payload service data ( findServiceData).


class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {

    uint8_t* findServiceData(uint8_t* data, size_t length, uint8_t* foundBlockLength) {
        //      [ ][ ][]
        //      0x16,     0x95 0xfe
        //   ,       
        //         
        uint8_t* rightBorder = data + length;
        while (data < rightBorder) {
            uint8_t blockLength = *data;
            if (blockLength < 5) { //      
                data += (blockLength+1);
                continue;
            }
            uint8_t blockType = *(data+1);
            uint16_t serviceType = *(uint16_t*)(data + 2);
            if (blockType == 0x16 && serviceType == 0xfe95) { //    
                *foundBlockLength = blockLength-3; //    
                return data+4; //     
            }
            data += (blockLength+1);
        }   
        return nullptr;
    }

    void onResult(BLEAdvertisedDevice advertisedDevice) {
        if (!advertisedDevice.haveName() || advertisedDevice.getName().compare("MJ_HT_V1"))
            return; //    ,     

        uint8_t* payload = advertisedDevice.getPayload();
        size_t payloadLength = advertisedDevice.getPayloadLength();
        Serial.printf("\n\nAdvertised Device: %s\n", advertisedDevice.toString().c_str());
        printBuffer(payload, payloadLength);
        uint8_t serviceDataLength=0;
        uint8_t* serviceData = findServiceData(payload, payloadLength, &serviceDataLength);

        if (serviceData == nullptr) {
            return; //      
        }

        Serial.printf("Found service data len: %d\n", serviceDataLength);
        printBuffer(serviceData, serviceDataLength);

        // 11      
        // 0x0D -   
        // 0x0A - 
        // 0x06 - 
        // 0x04 - 

        switch (serviceData[11])
        {
            case 0x0D:
            {
                float temp = *(uint16_t*)(serviceData + 11 + 3) / 10.0;
                float humidity = *(uint16_t*)(serviceData + 11 + 5) / 10.0;
                Serial.printf("Temp: %f Humidity: %f\n", temp, humidity);
            }
            break;
            case 0x04:
            {
                float temp = *(uint16_t*)(serviceData + 11 + 3) / 10.0;
                Serial.printf("Temp: %f\n", temp);
            }
            break;
            case 0x06:
            {
                float humidity = *(uint16_t*)(serviceData + 11 + 3) / 10.0;
                Serial.printf("Humidity: %f\n", humidity);
            }
            break;
            case 0x0A:
            {
                int battery = *(serviceData + 11 + 3);
                Serial.printf("Battery: %d\n", battery);
            }
            break;
        default:
            break;
        } 
    }
};


, . - ESP32 StackOverflow, . , . , -, , , . , .


- , , - . , , , .


.


UPD:


All Articles