2023-12-07 23:51:43 +03:00
|
|
|
#include "MiFloraHandler.h"
|
2023-12-10 10:29:34 +03:00
|
|
|
#include "NimBLEAttValue.h"
|
2023-12-07 23:51:43 +03:00
|
|
|
|
|
|
|
namespace MiFloraHandler {
|
|
|
|
|
|
|
|
std::vector<std::string> 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) {
|
2023-12-10 09:39:19 +03:00
|
|
|
ESP_LOGD(TAG, "-- Can't read characteristics");
|
2023-12-07 23:51:43 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// read characteristic value
|
|
|
|
NimBLEAttValue value;
|
|
|
|
|
|
|
|
value = floraCharacteristic->readValue();
|
|
|
|
|
|
|
|
if (value.size() == 0) {
|
2023-12-10 09:39:19 +03:00
|
|
|
ESP_LOGD(TAG, "Reading Value failed");
|
2023-12-07 23:51:43 +03:00
|
|
|
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;
|
|
|
|
|
2023-12-10 09:08:23 +03:00
|
|
|
(*doc)["temperature"] = temperature;
|
|
|
|
(*doc)["moisture"] = moisture;
|
|
|
|
(*doc)["light"] = brightness;
|
|
|
|
(*doc)["conductivity"] = conductivity;
|
2023-12-07 23:51:43 +03:00
|
|
|
|
|
|
|
floraService->deleteCharacteristics();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool readBatteryData(BLERemoteService* floraService, DynamicJsonDocument* doc) {
|
|
|
|
BLERemoteCharacteristic* floraCharacteristic = nullptr;
|
|
|
|
|
|
|
|
floraCharacteristic = floraService->getCharacteristic(uuid_version_battery);
|
|
|
|
|
|
|
|
if (floraCharacteristic == nullptr) {
|
2023-12-10 09:39:19 +03:00
|
|
|
ESP_LOGD(TAG, "-- Can't read characteristics");
|
2023-12-07 23:51:43 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
NimBLEAttValue val;
|
|
|
|
|
|
|
|
val = floraCharacteristic->readValue();
|
|
|
|
|
|
|
|
if (val.size() == 0) {
|
2023-12-10 09:39:19 +03:00
|
|
|
ESP_LOGD(TAG, "Reading Value failed");
|
2023-12-07 23:51:43 +03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int8_t battery = val.c_str()[0];
|
2023-12-10 09:08:23 +03:00
|
|
|
(*doc)["battery"] = battery;
|
2023-12-07 23:51:43 +03:00
|
|
|
|
|
|
|
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);
|
|
|
|
|
2023-12-10 09:08:23 +03:00
|
|
|
esphome::delay(500);
|
2023-12-07 23:51:43 +03:00
|
|
|
floraService->deleteCharacteristics();
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void fillDeviceData(DynamicJsonDocument* doc, BleFingerprint* f) {
|
2023-12-10 09:08:23 +03:00
|
|
|
(*doc)["id"] = f->getId();
|
|
|
|
(*doc)["mac"] = f->getMac();
|
|
|
|
(*doc)["rssi"] = f->getRssi();
|
2023-12-07 23:51:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool getFloraData(DynamicJsonDocument* doc, BLERemoteService* floraService, BleFingerprint* f) {
|
|
|
|
// Force miFlora to data mode
|
|
|
|
|
|
|
|
fillDeviceData(doc, f);
|
|
|
|
|
|
|
|
if (!MiFloraHandler::readBatteryData(floraService, doc))
|
2023-12-10 09:39:19 +03:00
|
|
|
ESP_LOGD(TAG, "Failed reading battery data");
|
2023-12-07 23:51:43 +03:00
|
|
|
|
|
|
|
if (MiFloraHandler::forceFloraServiceDataMode(floraService)) {
|
|
|
|
} else {
|
2023-12-10 09:39:19 +03:00
|
|
|
ESP_LOGD(TAG, "Failed to force data reading mode");
|
2023-12-07 23:51:43 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!MiFloraHandler::readSensorData(floraService, doc))
|
2023-12-10 09:39:19 +03:00
|
|
|
ESP_LOGD(TAG, "Failed reading sensor data");
|
2023-12-07 23:51:43 +03:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool requestData(NimBLEClient* pClient, BleFingerprint* fingerprint) // Getting mi flora data
|
|
|
|
{
|
|
|
|
DynamicJsonDocument document(256);
|
|
|
|
|
|
|
|
NimBLERemoteService* floraService = pClient->getService(serviceUUID);
|
|
|
|
|
|
|
|
if (floraService == nullptr) {
|
2023-12-10 09:39:19 +03:00
|
|
|
ESP_LOGD(TAG, "Getting MiFlora service failed");
|
2023-12-07 23:51:43 +03:00
|
|
|
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
|