Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * An ESP32 BLE client to retrieve data from the Weight Measurement characteristic
- * of a Xiaomi Mi Smart weight scale
- * Author Pangodream
- * Date 2020.05.31
- */
- #include "BLEDevice.h"
- //Base UUIDs
- //Weight Scale service
- static BLEUUID srvUUID("0000181d-0000-1000-8000-00805f9b34fb");
- //Weight Measurement characteristic
- static BLEUUID chrUUID("00002a9d-0000-1000-8000-00805f9b34fb");
- static BLEAdvertisedDevice* scale;
- static BLERemoteCharacteristic* remoteChr;
- static boolean doConnect = false;
- static boolean connected = false;
- static int year = 0;
- /**
- * Callback function for characteristic notify / indication
- */
- static void chrCB(BLERemoteCharacteristic* remoteChr, uint8_t* pData, size_t length, bool isNotify) {
- //Console debugging
- Serial.print("Received data. Length = ");
- Serial.print(length);
- Serial.print(". - Data bytes: ");
- for(int i =0; i< length; i++){
- Serial.print(pData[i]);
- Serial.print(" ");
- }
- Serial.println(" ");
- //End of console debugging
- //Parsing the received data and calculate weight
- boolean temporary = true;
- int rcvdYear = pData[3];
- //If we received a year for the first time, store it in the year variable
- //The first year we receive indicates a temporary measurement
- if(year == 0){
- year = rcvdYear;
- }else{
- //If year has been previously defined and the year we have received is
- //greater than it, then the measurement is not temporary, is the final one
- if(rcvdYear > year){
- temporary = false;
- }
- }
- double weight = 0;
- weight = (pData[1] + pData[2] * 256) * 0.005;
- Serial.print("Weight: ");
- Serial.print(weight);
- Serial.print(" Kg - ");
- if(temporary){
- Serial.println(" (Provisional)");
- }else{
- Serial.println(" (Definitive)");
- }
- }
- /**
- * Callback class for each advertised device during scan
- */
- class deviceCB: public BLEAdvertisedDeviceCallbacks {
- //Called on each advertised device
- void onResult(BLEAdvertisedDevice advertisedDevice) {
- // We have found a device, let us now see if it contains the service we are looking for.
- if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(srvUUID)) {
- if(advertisedDevice.getName() != "MI_SCALE"){
- Serial.print(".");
- } else {
- Serial.println(" Found!");
- BLEDevice::getScan()->stop();
- Serial.println("Stopping scan and connecting to scale");
- scale = new BLEAdvertisedDevice(advertisedDevice);
- doConnect = true;
- }
- } else {
- Serial.print(".");
- }
- }
- };
- /**
- * Callback class for device events
- */
- class ClientCB : public BLEClientCallbacks {
- void onConnect(BLEClient* pclient) {
- }
- void onDisconnect(BLEClient* pclient) {
- Serial.println("Disconnected. Reconnecting...");
- connected = false;
- }
- };
- bool connectToScale() {
- Serial.println("Stablishing communications with scale:");
- BLEClient* pClient = BLEDevice::createClient();
- Serial.println(" BLE client created");
- pClient->setClientCallbacks(new ClientCB());
- // Connect to the remove BLE Server.
- pClient->connect(scale);
- Serial.println(" Connected to scale");
- // Obtain a reference to the service we are after in the remote BLE server.
- BLERemoteService* pRemoteService = pClient->getService(srvUUID);
- if (pRemoteService == nullptr) {
- Serial.println(" Error: Failed to find service");
- pClient->disconnect();
- return false;
- }
- Serial.println(" Service found");
- remoteChr = pRemoteService->getCharacteristic(chrUUID);
- if (remoteChr == nullptr) {
- Serial.print(" Failed to find characteristic");
- pClient->disconnect();
- return false;
- }
- Serial.println(" Characteristic found");
- Serial.println(" Setting callback for notify / indicate");
- remoteChr->registerForNotify(chrCB);
- return true;
- }
- void setup() {
- Serial.begin(115200);
- Serial.println("Searching for MI_SCALE device");
- BLEDevice::init("");
- BLEScan* pBLEScan = BLEDevice::getScan();
- pBLEScan->setAdvertisedDeviceCallbacks(new deviceCB());
- pBLEScan->setInterval(1349);
- pBLEScan->setWindow(449);
- //Set active scan
- pBLEScan->setActiveScan(true);
- //Scan during 5 seconds
- pBLEScan->start(5, false);
- }
- void loop() {
- if(doConnect && !connected){
- connected = connectToScale();
- }
- delay(1000);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement