#include "MiFloraHandler.h" #include "NimBLEAttValue.h" namespace MiFloraHandler { std::vector addresses; bool readSensorData(BLERemoteService* floraService, DynamicJsonDocument* doc) { BLERemoteCharacteristic* floraCharacteristic = nullptr; // get the main device data characteristic floraCharacteristic = floraService->getCharacteristic(uuid_sensor_data); if (floraCharacteristic == nullptr) { ESP_LOGD(TAG, "-- Can't read characteristics"); return false; } // read characteristic value NimBLEAttValue value; value = floraCharacteristic->readValue(); if (value.size() == 0) { ESP_LOGD(TAG, "Reading Value failed"); return false; } const char* val = value.c_str(); float temperature = (val[0] + val[1] * 256) / ((float)10.0); uint8_t moisture = val[7]; uint32_t brightness = val[3] + val[4] * 256; float conductivity = val[8] + val[9] * 256; (*doc)["temperature"] = temperature; (*doc)["moisture"] = moisture; (*doc)["light"] = brightness; (*doc)["conductivity"] = conductivity; floraService->deleteCharacteristics(); return true; } bool readBatteryData(BLERemoteService* floraService, DynamicJsonDocument* doc) { BLERemoteCharacteristic* floraCharacteristic = nullptr; floraCharacteristic = floraService->getCharacteristic(uuid_version_battery); if (floraCharacteristic == nullptr) { ESP_LOGD(TAG, "-- Can't read characteristics"); return false; } NimBLEAttValue val; val = floraCharacteristic->readValue(); if (val.size() == 0) { ESP_LOGD(TAG, "Reading Value failed"); return false; } int8_t battery = val.c_str()[0]; (*doc)["battery"] = battery; floraService->deleteCharacteristics(); return true; } bool forceFloraServiceDataMode(BLERemoteService* floraService) { // Setting the mi flora to data reading mode BLERemoteCharacteristic* floraCharacteristic; // get device mode characteristic, needs to be changed to read data // Serial.println("- Force device in data mode"); floraCharacteristic = nullptr; floraCharacteristic = floraService->getCharacteristic(uuid_write_mode); if (floraCharacteristic == nullptr) { // Serial.println("-- Failed, skipping device"); return false; } uint8_t buf[2] = {0xA0, 0x1F}; floraCharacteristic->writeValue(buf, 2, true); esphome::delay(500); floraService->deleteCharacteristics(); return true; } void fillDeviceData(DynamicJsonDocument* doc, BleFingerprint* f) { (*doc)["id"] = f->getId(); (*doc)["mac"] = f->getMac(); (*doc)["rssi"] = f->getRssi(); } bool getFloraData(DynamicJsonDocument* doc, BLERemoteService* floraService, BleFingerprint* f) { // Force miFlora to data mode fillDeviceData(doc, f); if (!MiFloraHandler::readBatteryData(floraService, doc)) ESP_LOGD(TAG, "Failed reading battery data"); if (MiFloraHandler::forceFloraServiceDataMode(floraService)) { } else { ESP_LOGD(TAG, "Failed to force data reading mode"); } if (!MiFloraHandler::readSensorData(floraService, doc)) ESP_LOGD(TAG, "Failed reading sensor data"); return true; } bool requestData(NimBLEClient* pClient, BleFingerprint* fingerprint) // Getting mi flora data { DynamicJsonDocument document(256); NimBLERemoteService* floraService = pClient->getService(serviceUUID); if (floraService == nullptr) { ESP_LOGD(TAG, "Getting MiFlora service failed"); return false; } // Retriving the actual data if (!getFloraData(&document, floraService, fingerprint)) // Getting flora data return false; std::string buf = std::string(); serializeJson(document, buf); // Sending buffer over mqtt fingerprint->setReport(QueryReport{"miflora", buf}); return true; } } // namespace MiFloraHandler