From 75ffd2eeb79788d1a9445c147c70ff677fa086e0 Mon Sep 17 00:00:00 2001 From: Emeric Date: Wed, 12 Oct 2022 15:37:55 +0200 Subject: [PATCH] Update sensor catalog --- assets/devices/devices_sensors.json | 249 +++++++++++++++++++++++++++- src/device_infos.cpp | 139 +++++++++++++++- src/device_infos.h | 20 ++- src/device_plantsensor.cpp | 8 +- 4 files changed, 404 insertions(+), 12 deletions(-) diff --git a/assets/devices/devices_sensors.json b/assets/devices/devices_sensors.json index 576a2ad..453152f 100644 --- a/assets/devices/devices_sensors.json +++ b/assets/devices/devices_sensors.json @@ -1,9 +1,10 @@ { "devices": [ { + "name_ble": "Flower care", "model": "Flower Care", "manufacturer": "HHCC Plant Technology", - "ID": ["HHCCJCY01", "HHCCJCY10"], + "ID": ["HHCCJCY01"], "year": 2016, "battery": "1 x CR2032", "ipx": "IPX5", @@ -20,11 +21,32 @@ ] }, { + "name_ble": "TY", + "model": "Flower Care (Tuya variant)", + "manufacturer": "HHCC Plant Technology", + "ID": ["HHCCJCY10"], + "year": 2022, + "battery": "1 x CR2032", + "ipx": "IPX5", + "sensors": [ + ["Soil moisture", "0 → 100%"], + ["Soil conductivity", ""], + ["Temperature", "-15 → 50 °C (± 0.5 °C)"], + ["Luminosity", "0 → 100k lux (± 100 lux)"] + ], + "capabilities": [ + ["led_status", "unsupported"], + ["realtime", ""], + ["history", "unsupported"] + ] + }, + { + "name_ble": "Grow care garden", "model": "Flower Care Max", "manufacturer": "HHCC Plant Technology", "ID": ["HHCCJCY09", "GCLS002"], "year": 2018, - "battery": "Lithium Polymer (embedded)", + "battery": "Lithium Polymer (internal)", "ipx": "IPX6", "sensors": [ ["Soil moisture", "0 → 100%"], @@ -39,11 +61,12 @@ ] }, { + "name_ble": "ropot", "model": "RoPot", "manufacturer": "HHCC Plant Technology", "ID": ["HHCCPOT002"], "year": 2016, - "battery": "Lithium Polymer (embedded)", + "battery": "Lithium Polymer (internal)", "ipx": "IPX6", "sensors": [ ["Soil moisture", "0 → 100%"], @@ -57,6 +80,7 @@ ] }, { + "name_ble": "Flower power XXXX", "model": "Flower Power", "manufacturer": "Parrot", "ID": ["RKXHAWAII"], @@ -78,6 +102,7 @@ ] }, { + "name_ble": "Parrot pot XXXX", "model": "Parrot Pot", "manufacturer": "Parrot", "ID": ["2AG61POT"], @@ -99,6 +124,224 @@ ["last_move", "unsupported"], ["water_tank", "manual trigger supported"] ] + }, + + { + "name_ble": "MJ_HT_V1", + "model": "Bluetooth Hygrometer (?)", + "manufacturer": "Miaomiaoce", + "ID": ["LYWSDCGQ/01ZM"], + "year": "2017", + "battery": "1 x AAA", + "screen": "LCD", + "sensors": [ + ["Temperature", "-9.9 → 60 °C"], + ["Humidity", "0 → 99% RH"] + ], + "capabilities": [ + ["realtime", ""], + ["history", "unsupported"] + ] + }, + { + "name_ble": "LYWSD02", + "model": "Digital Hygrometer Clock (?)", + "manufacturer": "Miaomiaoce", + "ID": ["LYWSD02"], + "year": "2018", + "battery": "2 x CR2032", + "screen": "EInk", + "sensors": [ + ["Temperature", "0 → 60 °C"], + ["Humidity", "0 → 99% RH"] + ], + "capabilities": [ + ["realtime", ""], + ["history", "unsupported"] + ] + }, + { + "name_ble": "MHO-C303", + "model": "Digital Hygrometer Alarm (?)", + "manufacturer": "Miaomiaoce", + "ID": ["MHO-C303"], + "year": "2019", + "battery": "2 x AAA", + "screen": "EInk", + "sensors": [ + ["Temperature", "0 → 60 °C"], + ["Humidity", "0 → 99% RH"] + ], + "capabilities": [ + ["realtime", ""], + ["history", "unsupported"] + ] + }, + { + "name_ble": "MHO-C401", + "model": "Digital Hygrometer (?)", + "manufacturer": "Miaomiaoce", + "ID": ["MHO-C401"], + "year": "2019", + "battery": "1 x CR2032", + "screen": "EInk", + "sensors": [ + ["Temperature", "0 → 60 °C (± 0.3 °C)"], + ["Humidity", "0 → 99% RH (± 3% RH)"] + ], + "capabilities": [ + ["realtime", "unsupported"], + ["history", "unsupported"] + ] + }, + { + "name_ble": "LYWSD03MMC", + "model": "Thermo-Hygrometer (?)", + "manufacturer": "Miaomiaoce", + "ID": ["LYWSD03MMC"], + "year": "2019", + "battery": "1 x CR2032", + "screen": "LCD", + "sensors": [ + ["Temperature", "-9.9 → 60 °C (± 0.1 °C)"], + ["Humidity", "0 → 99% RH (± 1% RH)"] + ], + "capabilities": [ + ["realtime", "unsupported"], + ["history", "unsupported"] + ] + }, + { + "name_ble": "XMWSDJO4MMC", + "model": "Thermo-Hygrometer (?)", + "manufacturer": "Miaomiaoce", + "ID": ["XMWSDJO4MMC"], + "year": "2021", + "battery": "1 x CR2450", + "screen": "EInk", + "sensors": [ + ["Temperature", "0 → 60 °C"], + ["Humidity", "0 → 99% RH"] + ], + "capabilities": [ + ["realtime", "unsupported"], + ["history", "unsupported"] + ] + }, + { + "name_ble": "Qingping Alarm Clock", + "model": "Bluetooth Alarm Clock", + "manufacturer": "Qinping", + "ID": ["CGD1"], + "year": "2018", + "battery": "2 x AAA", + "screen": "LCD", + "sensors": [ + ["Temperature", "-9.9 → 49.9 °C"], + ["Humidity", "0 → 100% RH"] + ], + "capabilities": [ + ["realtime", "unsupported"], + ["history", "unsupported"] + ] + }, + { + "name_ble": "Qingping Temp RH Barometer", + "model": "Temp & RH Barometer Pro S", + "manufacturer": "Qinping", + "ID": ["CGP1W"], + "year": "2019", + "battery": "1 x 18650 (internal)", + "screen": "EInk", + "sensors": [ + ["Temperature", "-30 → 55 °C (± 0.2 °C)"], + ["Humidity", "0 → 100% RH (± 2% RH)"], + ["Air pressure", "300 → 1250 hPa (±0.5 hPa)"] + ], + "capabilities": [ + ["realtime", "unsupported"], + ["history", "unsupported"] + ] + }, + { + "name_ble": "CGG1", + "model": "Temp & RH Monitor", + "manufacturer": "Qinping", + "ID": ["CGG1"], + "year": "?", + "battery": "1 x CR2430", + "screen": "EInk", + "sensors": [ + ["Temperature", "-9.9 → 50 °C"], + ["Humidity", "0 → 99.9% RH"] + ], + "capabilities": [ + ["realtime", "unsupported"], + ["history", "unsupported"] + ] + }, + { + "name_ble": "CGDK2", + "model": "Temp & RH Monitor Lite", + "manufacturer": "Qinping", + "ID": ["CGDK2"], + "year": "?", + "battery": "1 x CR2450", + "screen": "LCD", + "sensors": [ + ["Temperature", "0 → 60 °C"], + ["Humidity", "0 → 99% RH"] + ], + "capabilities": [ + ["realtime", "unsupported"], + ["history", "unsupported"] + ] + }, + { + "name_ble": "ThermoBeacon", + "model": "ThermoBeacon", + "manufacturer": "SensorBlue", + "ID": ["2ACD3-WS02","2ACD3-WS07"], + "year": "?", + "battery": "1 x CR2477", + "screen": "", + "sensors": [ + ["Temperature", "-20 → 65 °C (± 0.5 °C)"], + ["Humidity", "0 → 99% RH (± 5% RH)"] + ], + "capabilities": [ + ["led_status", "some models"], + ["realtime", ""], + ["history", "30 days"] + ] + }, + + { + "name_ble": "6003#XXXXXXXXXXXX", + "model": "Air Box WP6003", + "manufacturer": "VSON technology", + "ID": ["WP6003"], + "year": "2020", + "sensors": [ + ["Temperature", "-10 → 50 °C"], + ["TVOC", "0 → 9.999 mg/m3 RH"], + ["HCHO", "0 → 1.999 mg/m3"], + ["CO2 (estimated)", "400 → 2000 ppm"] + ] + }, + { + "name_ble": "JQJCY01YM", + "model": "Formaldehyde HCHO Monitor", + "manufacturer": "Honeywell", + "ID": ["JQJCY01YM"], + "year": "2018", + "battery": "2 x AA", + "screen": "OLED", + "sensors": [ + ["Temperature", "0 → 50 °C"], + ["Humidity", "0 → 99% RH"], + ["HCHO", "0 → 1.500 mg/m3"] + ] } ] } diff --git a/src/device_infos.cpp b/src/device_infos.cpp index 15d5f85..00b8a80 100644 --- a/src/device_infos.cpp +++ b/src/device_infos.cpp @@ -34,11 +34,35 @@ DeviceInfosSensor::DeviceInfosSensor(const QString &sensor, const QString &strin else if (sensor == "Soil conductivity") m_sensor = DeviceUtils::SENSOR_SOIL_CONDUCTIVITY; else if (sensor == "Soil temperature") m_sensor = DeviceUtils::SENSOR_SOIL_TEMPERATURE; else if (sensor == "Soil PH") m_sensor = DeviceUtils::SENSOR_SOIL_PH; + else if (sensor == "Temperature") m_sensor = DeviceUtils::SENSOR_TEMPERATURE; else if (sensor == "Humidity") m_sensor = DeviceUtils::SENSOR_HUMIDITY; + else if (sensor == "Pressure") m_sensor = DeviceUtils::SENSOR_PRESSURE; else if (sensor == "Luminosity") m_sensor = DeviceUtils::SENSOR_LUMINOSITY; + else if (sensor == "UV") m_sensor = DeviceUtils::SENSOR_UV; + else if (sensor == "Sound") m_sensor = DeviceUtils::SENSOR_SOUND; + else if (sensor == "Water level") m_sensor = DeviceUtils::SENSOR_WATER_LEVEL; else if (sensor == "Water tank") m_sensor = DeviceUtils::SENSOR_WATER_LEVEL; + else if (sensor == "Wind speed") m_sensor = DeviceUtils::SENSOR_WIND_SPEED; + else if (sensor == "Wind direction") m_sensor = DeviceUtils::SENSOR_WIND_DIRECTION; + + else if (sensor == "PM1") m_sensor = DeviceUtils::SENSOR_PM1; + else if (sensor == "PM25") m_sensor = DeviceUtils::SENSOR_PM25; + else if (sensor == "PM10") m_sensor = DeviceUtils::SENSOR_PM10; + else if (sensor == "O2") m_sensor = DeviceUtils::SENSOR_O2; + else if (sensor == "O3") m_sensor = DeviceUtils::SENSOR_O3; + else if (sensor == "CO") m_sensor = DeviceUtils::SENSOR_CO; + else if (sensor == "CO2") m_sensor = DeviceUtils::SENSOR_CO2; + else if (sensor == "CO2 (estimated)") m_sensor = DeviceUtils::SENSOR_eCO2; + else if (sensor == "NO2") m_sensor = DeviceUtils::SENSOR_NO2; + else if (sensor == "SO2") m_sensor = DeviceUtils::SENSOR_SO2; + else if (sensor == "VOC") m_sensor = DeviceUtils::SENSOR_VOC; + else if (sensor == "TVOC") m_sensor = DeviceUtils::SENSOR_VOC; + else if (sensor == "HCHO") m_sensor = DeviceUtils::SENSOR_HCHO; + + else if (sensor == "Radiation") m_sensor = DeviceUtils::SENSOR_GEIGER; + else if (sensor == "Geiger counter") m_sensor = DeviceUtils::SENSOR_GEIGER; m_string = string; } @@ -89,9 +113,51 @@ DeviceInfos::~DeviceInfos() m_capabilities.clear(); } -void DeviceInfos::load(const QString &model) +void DeviceInfos::load(const QJsonObject &obj) +{ + //qDebug() << "DeviceInfos::load(" << obj << ")"; + + m_model = obj["model"].toString(); + m_manufacturer = obj["manufacturer"].toString(); + for (const auto &vv: obj["ID"].toArray()) + { + if (!m_id.isEmpty()) m_id += ", "; + m_id += vv.toString(); + } + + m_year = obj["year"].toInt(); + m_battery = obj["battery"].toString(); + m_screen = obj["screen"].toString(); + m_ipx = obj["ipx"].toString(); + + for (const auto &vv: obj["sensors"].toArray()) + { + QJsonArray vvv = vv.toArray(); + if (vvv.size() == 2) + { + DeviceInfosSensor *dis = new DeviceInfosSensor(vvv.at(0).toString(), + vvv.at(1).toString(), + this); + m_sensors.push_back(dis); + } + } + + for (const auto &vv: obj["capabilities"].toArray()) + { + QJsonArray vvv = vv.toArray(); + if (vvv.size() == 2) + { + DeviceInfosCapability *dic = new DeviceInfosCapability(vvv.at(0).toString(), + vvv.at(1).toString(), + this); + m_capabilities.push_back(dic); + } + } +} + +bool DeviceInfos::loadSlow(const QString &name, const QString &model, const QString &modelId) { - //qDebug() << "DeviceInfos::load(" << model << ")"; + //qDebug() << "DeviceInfos::loadSlow(" << name << model << modelId << ")"; QFile file(":/devices/devices_sensors.json"); @@ -105,7 +171,10 @@ void DeviceInfos::load(const QString &model) for (const auto &value: deviceArray) { QJsonObject obj = value.toObject(); - if (model.toLower() == obj["model"].toString().toLower()) + if (name == obj["name_ble"].toString() || + name.toLower() == obj["model"].toString().toLower() || + model.toLower() == obj["model"].toString().toLower() || + obj["ID"].toArray().contains(name)) { //qDebug() << "DeviceInfos::load(" << model << ") FOUND"; @@ -146,10 +215,72 @@ void DeviceInfos::load(const QString &model) } } - return; + return true; } } } + + return false; +} + +/* ************************************************************************** */ + +DeviceInfosLoader *DeviceInfosLoader::instance = nullptr; + +DeviceInfosLoader *DeviceInfosLoader::getInstance() +{ + if (instance == nullptr) + { + instance = new DeviceInfosLoader(); + } + + return instance; +} + +DeviceInfosLoader::DeviceInfosLoader() +{ + // +} + +DeviceInfosLoader::~DeviceInfosLoader() +{ + // +} + +DeviceInfos *DeviceInfosLoader::getDeviceInfos(const QString &name, const QString &model, const QString &modelId) +{ + //qDebug() << "DeviceInfosLoader::getDeviceInfos(" << name << model << modelId << ")"; + + DeviceInfos *dev = nullptr; + + if (deviceJsonArray.isEmpty()) + { + QFile jsonFile(":/devices/devices_sensors.json"); + if (jsonFile.open(QIODevice::ReadOnly)) + { + QJsonDocument jsonDoc = QJsonDocument().fromJson(jsonFile.readAll()); + QJsonObject jsonObj = jsonDoc.object(); + + deviceJsonArray = jsonObj["devices"].toArray(); + + jsonFile.close(); + } + } + + for (const auto &value: qAsConst(deviceJsonArray)) + { + QJsonObject obj = value.toObject(); + if (name == obj["name_ble"].toString() || + name.toLower() == obj["model"].toString().toLower() || + model.toLower() == obj["model"].toString().toLower() || + obj["ID"].toArray().contains(name)) + { + dev = new DeviceInfos(this); + dev->load(obj); + } + } + + return dev; } /* ************************************************************************** */ diff --git a/src/device_infos.h b/src/device_infos.h index cdd7638..7f19f99 100644 --- a/src/device_infos.h +++ b/src/device_infos.h @@ -24,6 +24,8 @@ #include #include +#include +#include /* ************************************************************************** */ @@ -109,7 +111,23 @@ class DeviceInfos: public QObject DeviceInfos(QObject *parent); ~DeviceInfos(); - void load(const QString &model); + void load(const QJsonObject &device); + bool loadSlow(const QString &name, const QString &model, const QString &modelId); +}; + +class DeviceInfosLoader: public QObject +{ + // Singleton + static DeviceInfosLoader *instance; + DeviceInfosLoader(); + ~DeviceInfosLoader(); + + QJsonArray deviceJsonArray; + +public: + static DeviceInfosLoader *getInstance(); + + DeviceInfos *getDeviceInfos(const QString &name, const QString &model, const QString &modelId); }; /* ************************************************************************** */ diff --git a/src/device_plantsensor.cpp b/src/device_plantsensor.cpp index a0a1f72..dfcf752 100644 --- a/src/device_plantsensor.cpp +++ b/src/device_plantsensor.cpp @@ -46,7 +46,7 @@ DevicePlantSensor::DevicePlantSensor(const QString &deviceAddr, const QString &d // Device infos m_deviceInfos = new DeviceInfos(this); - m_deviceInfos->load(m_deviceName); + m_deviceInfos->loadSlow(m_deviceName, m_deviceModel, m_deviceModelID); } DevicePlantSensor::DevicePlantSensor(const QBluetoothDeviceInfo &d, QObject *parent): @@ -69,7 +69,7 @@ DevicePlantSensor::DevicePlantSensor(const QBluetoothDeviceInfo &d, QObject *par // Device infos m_deviceInfos = new DeviceInfos(this); - m_deviceInfos->load(m_deviceName); + m_deviceInfos->loadSlow(m_deviceName, m_deviceModel, m_deviceModelID); } DevicePlantSensor::~DevicePlantSensor() @@ -151,7 +151,7 @@ bool DevicePlantSensor::addDatabaseRecord(const int64_t timestamp, } else { - qWarning() << "> addData(" << m_deviceName << ") ERROR" + qWarning() << "> addDatabaseRecord_plants(" << m_deviceName << ") ERROR" << addData.lastError().type() << ":" << addData.lastError().text(); } } @@ -226,7 +226,7 @@ void DevicePlantSensor::resetPlant() void DevicePlantSensor::resetLimits() { - // + // not for Theengs } /* ************************************************************************** */