mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
Feature: Allow device name to be customized #1174
This commit is contained in:
@@ -21,10 +21,11 @@
|
|||||||
- Added scripts for OTA (scripts/upload.py and upload_cli.py) [#1738](https://github.com/emsesp/EMS-ESP32/issues/1738)
|
- Added scripts for OTA (scripts/upload.py and upload_cli.py) [#1738](https://github.com/emsesp/EMS-ESP32/issues/1738)
|
||||||
- timeout for remote thermostat emulation [#1680](https://github.com/emsesp/EMS-ESP32/discussions/1680), [#1774](https://github.com/emsesp/EMS-ESP32/issues/1774)
|
- timeout for remote thermostat emulation [#1680](https://github.com/emsesp/EMS-ESP32/discussions/1680), [#1774](https://github.com/emsesp/EMS-ESP32/issues/1774)
|
||||||
- CR120 thermostat as own model() [#1779](https://github.com/emsesp/EMS-ESP32/discussions/1779)
|
- CR120 thermostat as own model() [#1779](https://github.com/emsesp/EMS-ESP32/discussions/1779)
|
||||||
- Modules - external linkable module library [#1778](https://github.com/emsesp/EMS-ESP32/issues/1778)
|
- modules - external linkable module library [#1778](https://github.com/emsesp/EMS-ESP32/issues/1778)
|
||||||
- Scheduler onChange and Conditions [#1806](https://github.com/emsesp/EMS-ESP32/issues/1806)
|
- scheduler onChange and Conditions [#1806](https://github.com/emsesp/EMS-ESP32/issues/1806)
|
||||||
- make remote control timeout editable [#1774](https://github.com/emsesp/EMS-ESP32/issues/1774)
|
- make remote control timeout editable [#1774](https://github.com/emsesp/EMS-ESP32/issues/1774)
|
||||||
- added extra pump characteristics (mode and pressure for EMS+) by @SLTKA [#1802](https://github.com/emsesp/EMS-ESP32/pull/1802)
|
- added extra pump characteristics (mode and pressure for EMS+) by @SLTKA [#1802](https://github.com/emsesp/EMS-ESP32/pull/1802)
|
||||||
|
- allow device name to be customized [#1174](https://github.com/emsesp/EMS-ESP32/issues/1174)
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
|
|||||||
@@ -34,14 +34,15 @@ class EMSdevice {
|
|||||||
using process_function_p = std::function<void(std::shared_ptr<const Telegram>)>;
|
using process_function_p = std::function<void(std::shared_ptr<const Telegram>)>;
|
||||||
|
|
||||||
// device_type defines which derived class to use, e.g. BOILER, THERMOSTAT etc..
|
// device_type defines which derived class to use, e.g. BOILER, THERMOSTAT etc..
|
||||||
EMSdevice(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
EMSdevice(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * default_name, uint8_t flags, uint8_t brand)
|
||||||
: device_type_(device_type)
|
: device_type_(device_type)
|
||||||
, device_id_(device_id)
|
, device_id_(device_id)
|
||||||
, product_id_(product_id)
|
, product_id_(product_id)
|
||||||
, name_(name)
|
, default_name_(default_name)
|
||||||
, flags_(flags)
|
, flags_(flags)
|
||||||
, brand_(brand) {
|
, brand_(brand) {
|
||||||
strlcpy(version_, version, sizeof(version_));
|
strlcpy(version_, version, sizeof(version_));
|
||||||
|
custom_name_ = ""; // init custom name to blank
|
||||||
}
|
}
|
||||||
|
|
||||||
// static functions, used outside the class like in console.cpp, command.cpp, emsesp.cpp, mqtt.cpp
|
// static functions, used outside the class like in console.cpp, command.cpp, emsesp.cpp, mqtt.cpp
|
||||||
@@ -111,12 +112,18 @@ class EMSdevice {
|
|||||||
return brand_;
|
return brand_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void name(const char * name) {
|
// set custom device name
|
||||||
name_ = name;
|
inline void custom_name(std::string & custom_name) {
|
||||||
|
custom_name_ = custom_name;
|
||||||
}
|
}
|
||||||
|
std::string name(); // returns either default or custom name if defined
|
||||||
|
|
||||||
inline const char * name() const {
|
// default name
|
||||||
return name_;
|
inline void default_name(const char * default_name) {
|
||||||
|
default_name_ = default_name;
|
||||||
|
}
|
||||||
|
inline const char * default_name() const {
|
||||||
|
return default_name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t unique_id() const {
|
inline uint8_t unique_id() const {
|
||||||
@@ -479,7 +486,8 @@ class EMSdevice {
|
|||||||
uint8_t device_id_ = 0;
|
uint8_t device_id_ = 0;
|
||||||
uint8_t product_id_ = 0;
|
uint8_t product_id_ = 0;
|
||||||
char version_[6];
|
char version_[6];
|
||||||
const char * name_; // the long name for the EMS model
|
const char * default_name_; // the fixed name the EMS model taken from the device library
|
||||||
|
std::string custom_name_; // custom name
|
||||||
uint8_t flags_ = 0;
|
uint8_t flags_ = 0;
|
||||||
uint8_t brand_ = Brand::NO_BRAND;
|
uint8_t brand_ = Brand::NO_BRAND;
|
||||||
|
|
||||||
|
|||||||
106
src/emsesp.cpp
106
src/emsesp.cpp
@@ -359,7 +359,7 @@ void EMSESP::dump_all_values(uuid::console::Shell & shell) {
|
|||||||
// add the device and print out all the entities
|
// add the device and print out all the entities
|
||||||
// for testing the mixer use ... if (device.product_id == 69) {
|
// for testing the mixer use ... if (device.product_id == 69) {
|
||||||
emsdevices.push_back(
|
emsdevices.push_back(
|
||||||
EMSFactory::add(device.device_type, device_id, device.product_id, "1.0", device.name, device.flags, EMSdevice::Brand::NO_BRAND));
|
EMSFactory::add(device.device_type, device_id, device.product_id, "1.0", device.default_name, device.flags, EMSdevice::Brand::NO_BRAND));
|
||||||
emsdevices.back()->dump_value_info();
|
emsdevices.back()->dump_value_info();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -400,7 +400,7 @@ void EMSESP::dump_all_telegrams(uuid::console::Shell & shell) {
|
|||||||
|
|
||||||
// add the device and print out all the entities
|
// add the device and print out all the entities
|
||||||
emsdevices.push_back(
|
emsdevices.push_back(
|
||||||
EMSFactory::add(device.device_type, device_id, device.product_id, "1.0", device.name, device.flags, EMSdevice::Brand::NO_BRAND));
|
EMSFactory::add(device.device_type, device_id, device.product_id, "1.0", device.default_name, device.flags, EMSdevice::Brand::NO_BRAND));
|
||||||
// add to our vector list
|
// add to our vector list
|
||||||
emsdevices.back()->dump_telegram_info(telegram_functions_dump);
|
emsdevices.back()->dump_telegram_info(telegram_functions_dump);
|
||||||
}
|
}
|
||||||
@@ -1167,17 +1167,20 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
if (product_id == 0 || emsdevice->product_id() != 0) { // update only with valid product_id
|
if (product_id == 0 || emsdevice->product_id() != 0) { // update only with valid product_id
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("Updating details for already active deviceID 0x%02X", device_id);
|
LOG_DEBUG("Updating details for already active deviceID 0x%02X", device_id);
|
||||||
emsdevice->product_id(product_id);
|
emsdevice->product_id(product_id);
|
||||||
emsdevice->version(version);
|
emsdevice->version(version);
|
||||||
|
|
||||||
// only set brand if it doesn't already exist
|
// only set brand if it doesn't already exist
|
||||||
if (emsdevice->brand() == EMSdevice::Brand::NO_BRAND) {
|
if (emsdevice->brand() == EMSdevice::Brand::NO_BRAND) {
|
||||||
emsdevice->brand(brand);
|
emsdevice->brand(brand);
|
||||||
}
|
}
|
||||||
// find the name and flags in our database
|
|
||||||
|
// find the name and flags in our device library database
|
||||||
for (const auto & device : device_library_) {
|
for (const auto & device : device_library_) {
|
||||||
if (device.product_id == product_id && device.device_type == emsdevice->device_type()) {
|
if (device.product_id == product_id && device.device_type == emsdevice->device_type()) {
|
||||||
emsdevice->name(device.name);
|
emsdevice->default_name(device.default_name); // custom name is set later
|
||||||
emsdevice->add_flags(device.flags);
|
emsdevice->add_flags(device.flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1192,7 +1195,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
if (device.product_id == product_id) {
|
if (device.product_id == product_id) {
|
||||||
// sometimes boilers share the same productID as controllers
|
// sometimes boilers share the same productID as controllers
|
||||||
// so only add boilers if the device_id is 0x08
|
// so only add boilers if the device_id is 0x08
|
||||||
// cascaded boilers with 0x70.., map to heatsources
|
// cascaded boilers with 0x70..., map to heatsources
|
||||||
if (device.device_type == DeviceType::BOILER) {
|
if (device.device_type == DeviceType::BOILER) {
|
||||||
if (device_id == EMSdevice::EMS_DEVICE_ID_BOILER) {
|
if (device_id == EMSdevice::EMS_DEVICE_ID_BOILER) {
|
||||||
device_p = &device;
|
device_p = &device;
|
||||||
@@ -1204,7 +1207,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// it's not a boiler, but we have a match
|
// it's not a boiler, but we still have a match
|
||||||
device_p = &device;
|
device_p = &device;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1219,84 +1222,99 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
return false; // not found
|
return false; // not found
|
||||||
}
|
}
|
||||||
|
|
||||||
auto name = device_p->name;
|
auto default_name = device_p->default_name;
|
||||||
auto device_type = device_p->device_type;
|
auto device_type = device_p->device_type;
|
||||||
auto flags = device_p->flags;
|
auto flags = device_p->flags;
|
||||||
|
|
||||||
// check for integrated modules with same product id, but different function (device_id)
|
// check for integrated modules with same product id, but different function (device_id)
|
||||||
|
// and force set the correct device type and hardcoded name
|
||||||
if (device_type == DeviceType::HEATPUMP) {
|
if (device_type == DeviceType::HEATPUMP) {
|
||||||
if (device_id == EMSdevice::EMS_DEVICE_ID_MODEM) {
|
if (device_id == EMSdevice::EMS_DEVICE_ID_MODEM) {
|
||||||
device_type = DeviceType::GATEWAY;
|
device_type = DeviceType::GATEWAY;
|
||||||
name = "WiFi module";
|
default_name = "WiFi module";
|
||||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_RFBASE) {
|
} else if (device_id == EMSdevice::EMS_DEVICE_ID_RFBASE) {
|
||||||
device_type = DeviceType::CONNECT;
|
device_type = DeviceType::CONNECT;
|
||||||
name = "Wireless sensor base";
|
default_name = "Wireless sensor base";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device_id >= EMSdevice::EMS_DEVICE_ID_DHW1 && device_id <= EMSdevice::EMS_DEVICE_ID_DHW8) {
|
if (device_id >= EMSdevice::EMS_DEVICE_ID_DHW1 && device_id <= EMSdevice::EMS_DEVICE_ID_DHW8) {
|
||||||
device_type = DeviceType::WATER;
|
device_type = DeviceType::WATER;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CR120 have version 22.xx, RC400/CW100 uses version 42.xx, see https://github.com/emsesp/EMS-ESP32/discussions/1779
|
// CR120 have version 22.xx, RC400/CW100 uses version 42.xx, see https://github.com/emsesp/EMS-ESP32/discussions/1779
|
||||||
if (product_id == 157 && version[0] == '2') {
|
if (product_id == 157 && version[0] == '2') {
|
||||||
flags = DeviceFlags::EMS_DEVICE_FLAG_CR120;
|
flags = DeviceFlags::EMS_DEVICE_FLAG_CR120;
|
||||||
name = "CR120";
|
default_name = "CR120";
|
||||||
}
|
}
|
||||||
|
|
||||||
// empty reply to version, read a generic device from database
|
// empty reply to version, read a generic device from database
|
||||||
if (product_id == 0) {
|
if (product_id == 0) {
|
||||||
// check for known device IDs
|
// check for known device IDs
|
||||||
if (device_id == EMSdevice::EMS_DEVICE_ID_RFSENSOR) {
|
if (device_id == EMSdevice::EMS_DEVICE_ID_RFSENSOR) {
|
||||||
// see: https://github.com/emsesp/EMS-ESP32/issues/103#issuecomment-911717342 and https://github.com/emsesp/EMS-ESP32/issues/624
|
// see: https://github.com/emsesp/EMS-ESP32/issues/103#issuecomment-911717342 and https://github.com/emsesp/EMS-ESP32/issues/624
|
||||||
name = "RF room temperature sensor";
|
default_name = "RF room temperature sensor";
|
||||||
device_type = DeviceType::THERMOSTAT;
|
device_type = DeviceType::THERMOSTAT;
|
||||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_ROOMTHERMOSTAT || device_id == EMSdevice::EMS_DEVICE_ID_TADO_OLD) {
|
} else if (device_id == EMSdevice::EMS_DEVICE_ID_ROOMTHERMOSTAT || device_id == EMSdevice::EMS_DEVICE_ID_TADO_OLD) {
|
||||||
// see https://github.com/emsesp/EMS-ESP32/issues/174
|
// see https://github.com/emsesp/EMS-ESP32/issues/174
|
||||||
name = "Generic thermostat";
|
default_name = "Generic Thermostat";
|
||||||
device_type = DeviceType::THERMOSTAT;
|
device_type = DeviceType::THERMOSTAT;
|
||||||
flags = DeviceFlags::EMS_DEVICE_FLAG_RC10 | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE;
|
flags = DeviceFlags::EMS_DEVICE_FLAG_RC10 | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE;
|
||||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_RS232) {
|
} else if (device_id == EMSdevice::EMS_DEVICE_ID_RS232) {
|
||||||
name = "RS232";
|
default_name = "RS232";
|
||||||
device_type = DeviceType::CONNECT;
|
device_type = DeviceType::CONNECT;
|
||||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_TERMINAL) {
|
} else if (device_id == EMSdevice::EMS_DEVICE_ID_TERMINAL) {
|
||||||
name = "Terminal";
|
default_name = "Terminal";
|
||||||
device_type = DeviceType::CONNECT;
|
device_type = DeviceType::CONNECT;
|
||||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_SERVICEKEY) {
|
} else if (device_id == EMSdevice::EMS_DEVICE_ID_SERVICEKEY) {
|
||||||
name = "Service Key";
|
default_name = "Service Key";
|
||||||
device_type = DeviceType::CONNECT;
|
device_type = DeviceType::CONNECT;
|
||||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CASCADE) {
|
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CASCADE) {
|
||||||
name = "Cascade";
|
default_name = "Cascade";
|
||||||
device_type = DeviceType::CONNECT;
|
device_type = DeviceType::CONNECT;
|
||||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_EASYCOM
|
} else if (device_id == EMSdevice::EMS_DEVICE_ID_EASYCOM
|
||||||
|| (device_id >= EMSdevice::EMS_DEVICE_ID_MODEM && device_id <= EMSdevice::EMS_DEVICE_ID_MODEM + 5)) {
|
|| (device_id >= EMSdevice::EMS_DEVICE_ID_MODEM && device_id <= EMSdevice::EMS_DEVICE_ID_MODEM + 5)) {
|
||||||
// see https://github.com/emsesp/EMS-ESP/issues/460#issuecomment-709553012
|
// see https://github.com/emsesp/EMS-ESP/issues/460#issuecomment-709553012
|
||||||
name = "Modem";
|
default_name = "Modem";
|
||||||
device_type = DeviceType::CONNECT;
|
device_type = DeviceType::CONNECT;
|
||||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CONVERTER) {
|
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CONVERTER) {
|
||||||
name = "Converter"; // generic
|
default_name = "Converter"; // generic
|
||||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CLOCK) {
|
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CLOCK) {
|
||||||
name = "Clock"; // generic
|
default_name = "Clock"; // generic
|
||||||
device_type = DeviceType::CONTROLLER;
|
device_type = DeviceType::CONTROLLER;
|
||||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CONTROLLER) {
|
} else if (device_id == EMSdevice::EMS_DEVICE_ID_CONTROLLER) {
|
||||||
name = "Generic Controller";
|
default_name = "Generic Controller";
|
||||||
device_type = DeviceType::CONTROLLER;
|
device_type = DeviceType::CONTROLLER;
|
||||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_BOILER) {
|
} else if (device_id == EMSdevice::EMS_DEVICE_ID_BOILER) {
|
||||||
name = "Generic Boiler";
|
default_name = "Generic Boiler";
|
||||||
device_type = DeviceType::BOILER;
|
device_type = DeviceType::BOILER;
|
||||||
flags = DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP;
|
flags = DeviceFlags::EMS_DEVICE_FLAG_HEATPUMP;
|
||||||
LOG_WARNING("Unknown EMS boiler. Using generic profile. Please report on GitHub.");
|
LOG_WARNING("Unknown EMS boiler. Using generic profile. Please report on GitHub.");
|
||||||
} else if (device_id >= 0x68 && device_id <= 0x6F) {
|
} else if (device_id >= 0x68 && device_id <= 0x6F) {
|
||||||
// test for https://github.com/emsesp/EMS-ESP32/issues/882
|
// test for https://github.com/emsesp/EMS-ESP32/issues/882
|
||||||
name = "Cascaded Controller";
|
default_name = "Cascaded Controller";
|
||||||
device_type = DeviceType::CONTROLLER;
|
device_type = DeviceType::CONTROLLER;
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING("Unrecognized EMS device (device ID 0x%02X, no product ID). Please report on GitHub.", device_id);
|
LOG_WARNING("Unrecognized EMS device (device ID 0x%02X, no product ID). Please report on GitHub.", device_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DEBUG("Adding new device %s (deviceID 0x%02X, productID %d, version %s)", name, device_id, product_id, version);
|
LOG_DEBUG("Adding new device %s (deviceID 0x%02X, productID %d, version %s)", default_name, device_id, product_id, version);
|
||||||
emsdevices.push_back(EMSFactory::add(device_type, device_id, product_id, version, name, flags, brand));
|
emsdevices.push_back(EMSFactory::add(device_type, device_id, product_id, version, default_name, flags, brand));
|
||||||
|
|
||||||
// assign a unique ID. Note that this is not actual unique after a restart as it's dependent on the order that devices are found
|
// see if we have a custom device name in our Customizations list, and if so set it
|
||||||
|
webCustomizationService.read([&](WebCustomization & settings) {
|
||||||
|
for (EntityCustomization e : settings.entityCustomizations) {
|
||||||
|
if ((e.device_id == device_id) && (e.product_id == product_id)) {
|
||||||
|
LOG_DEBUG("Have customizations for %s with deviceID 0x%02X productID %d", e.custom_name.c_str(), device_id, product_id);
|
||||||
|
emsdevices.back()->custom_name(e.custom_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// assign a unique ID. Note that this is not actual remain unique after a restart as it's dependent on the order that devices are found
|
||||||
// can't be 0 otherwise web won't work
|
// can't be 0 otherwise web won't work
|
||||||
emsdevices.back()->unique_id(++unique_id_count_);
|
emsdevices.back()->unique_id(++unique_id_count_);
|
||||||
|
|
||||||
@@ -1305,7 +1323,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
return a->device_type() < b->device_type();
|
return a->device_type() < b->device_type();
|
||||||
});
|
});
|
||||||
|
|
||||||
fetch_device_values(device_id); // go and fetch its data
|
fetch_device_values(device_id); // go and fetch its device entity data
|
||||||
|
|
||||||
// Print to LOG showing we've added a new device
|
// Print to LOG showing we've added a new device
|
||||||
LOG_INFO("Recognized new %s with deviceID 0x%02X", EMSdevice::device_type_2_device_name(device_type), device_id);
|
LOG_INFO("Recognized new %s with deviceID 0x%02X", EMSdevice::device_type_2_device_name(device_type), device_id);
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ class EMSESP {
|
|||||||
struct Device_record {
|
struct Device_record {
|
||||||
uint8_t product_id;
|
uint8_t product_id;
|
||||||
EMSdevice::DeviceType device_type;
|
EMSdevice::DeviceType device_type;
|
||||||
const char * name;
|
const char * default_name;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
};
|
};
|
||||||
static std::vector<Device_record> device_library_;
|
static std::vector<Device_record> device_library_;
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ class EMSFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Construct derived class returning an unique ptr
|
// Construct derived class returning an unique ptr
|
||||||
static auto add(const uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand)
|
static auto add(const uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * default_name, uint8_t flags, uint8_t brand)
|
||||||
-> std::unique_ptr<EMSdevice> {
|
-> std::unique_ptr<EMSdevice> {
|
||||||
return std::unique_ptr<EMSdevice>(EMSFactory::makeRaw(device_type, device_id, product_id, version, name, flags, brand));
|
return std::unique_ptr<EMSdevice>(EMSFactory::makeRaw(device_type, device_id, product_id, version, default_name, flags, brand));
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual auto construct(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand) const
|
virtual auto construct(uint8_t device_type, uint8_t device_id, uint8_t product_id, const char * version, const char * name, uint8_t flags, uint8_t brand) const
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ bool WebCustomization::_start = true;
|
|||||||
|
|
||||||
WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||||
: _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE) {
|
: _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE) {
|
||||||
|
// GET
|
||||||
server->on(DEVICE_ENTITIES_PATH,
|
server->on(DEVICE_ENTITIES_PATH,
|
||||||
HTTP_GET,
|
HTTP_GET,
|
||||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { device_entities(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
|
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { device_entities(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
|
||||||
@@ -32,10 +33,15 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
|
|||||||
HTTP_GET,
|
HTTP_GET,
|
||||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { devices(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
|
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { devices(request); }, AuthenticationPredicates::IS_AUTHENTICATED));
|
||||||
|
|
||||||
|
// POST
|
||||||
server->on(RESET_CUSTOMIZATION_SERVICE_PATH,
|
server->on(RESET_CUSTOMIZATION_SERVICE_PATH,
|
||||||
HTTP_POST,
|
HTTP_POST,
|
||||||
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { reset_customization(request); }, AuthenticationPredicates::IS_ADMIN));
|
securityManager->wrapRequest([this](AsyncWebServerRequest * request) { reset_customization(request); }, AuthenticationPredicates::IS_ADMIN));
|
||||||
|
|
||||||
|
server->on(WRITE_DEVICE_NAME_PATH,
|
||||||
|
securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { writeDeviceName(request, json); },
|
||||||
|
AuthenticationPredicates::IS_AUTHENTICATED));
|
||||||
|
|
||||||
server->on(CUSTOMIZATION_ENTITIES_PATH,
|
server->on(CUSTOMIZATION_ENTITIES_PATH,
|
||||||
securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { customization_entities(request, json); },
|
securityManager->wrapCallback([this](AsyncWebServerRequest * request, JsonVariant json) { customization_entities(request, json); },
|
||||||
AuthenticationPredicates::IS_AUTHENTICATED));
|
AuthenticationPredicates::IS_AUTHENTICATED));
|
||||||
@@ -65,12 +71,13 @@ void WebCustomization::read(WebCustomization & customizations, JsonObject root)
|
|||||||
sensorJson["type"] = sensor.type; // t
|
sensorJson["type"] = sensor.type; // t
|
||||||
}
|
}
|
||||||
|
|
||||||
// Masked entities customization
|
// Masked entities customization and custom device name (optional)
|
||||||
JsonArray masked_entitiesJson = root["masked_entities"].to<JsonArray>();
|
JsonArray masked_entitiesJson = root["masked_entities"].to<JsonArray>();
|
||||||
for (const EntityCustomization & entityCustomization : customizations.entityCustomizations) {
|
for (const EntityCustomization & entityCustomization : customizations.entityCustomizations) {
|
||||||
JsonObject entityJson = masked_entitiesJson.add<JsonObject>();
|
JsonObject entityJson = masked_entitiesJson.add<JsonObject>();
|
||||||
entityJson["product_id"] = entityCustomization.product_id;
|
entityJson["product_id"] = entityCustomization.product_id;
|
||||||
entityJson["device_id"] = entityCustomization.device_id;
|
entityJson["device_id"] = entityCustomization.device_id;
|
||||||
|
entityJson["custom_name"] = entityCustomization.custom_name;
|
||||||
|
|
||||||
// entries are in the form <XX><shortname>[optional customname] e.g "08heatingactive|heating is on"
|
// entries are in the form <XX><shortname>[optional customname] e.g "08heatingactive|heating is on"
|
||||||
JsonArray masked_entityJson = entityJson["entity_ids"].to<JsonArray>();
|
JsonArray masked_entityJson = entityJson["entity_ids"].to<JsonArray>();
|
||||||
@@ -120,9 +127,10 @@ StateUpdateResult WebCustomization::update(JsonObject root, WebCustomization & c
|
|||||||
customizations.entityCustomizations.clear();
|
customizations.entityCustomizations.clear();
|
||||||
if (root["masked_entities"].is<JsonArray>()) {
|
if (root["masked_entities"].is<JsonArray>()) {
|
||||||
for (const JsonObject masked_entities : root["masked_entities"].as<JsonArray>()) {
|
for (const JsonObject masked_entities : root["masked_entities"].as<JsonArray>()) {
|
||||||
auto emsEntity = EntityCustomization();
|
auto emsEntity = EntityCustomization();
|
||||||
emsEntity.product_id = masked_entities["product_id"];
|
emsEntity.product_id = masked_entities["product_id"];
|
||||||
emsEntity.device_id = masked_entities["device_id"];
|
emsEntity.device_id = masked_entities["device_id"];
|
||||||
|
emsEntity.custom_name = masked_entities["custom_name"].as<std::string>();
|
||||||
|
|
||||||
for (const JsonVariant masked_entity_id : masked_entities["entity_ids"].as<JsonArray>()) {
|
for (const JsonVariant masked_entity_id : masked_entities["entity_ids"].as<JsonArray>()) {
|
||||||
if (masked_entity_id.is<std::string>()) {
|
if (masked_entity_id.is<std::string>()) {
|
||||||
@@ -163,8 +171,8 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) {
|
|||||||
for (const auto & emsdevice : EMSESP::emsdevices) {
|
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||||
if (emsdevice->has_entities()) {
|
if (emsdevice->has_entities()) {
|
||||||
JsonObject obj = devices.add<JsonObject>();
|
JsonObject obj = devices.add<JsonObject>();
|
||||||
obj["i"] = emsdevice->unique_id(); // its unique id
|
obj["i"] = emsdevice->unique_id(); // its unique id
|
||||||
obj["s"] = emsdevice->name();
|
obj["s"] = emsdevice->name(); // custom name
|
||||||
obj["tn"] = emsdevice->device_type_name(); // non-translated, lower-case
|
obj["tn"] = emsdevice->device_type_name(); // non-translated, lower-case
|
||||||
obj["t"] = emsdevice->device_type(); // internal device type ID
|
obj["t"] = emsdevice->device_type(); // internal device type ID
|
||||||
}
|
}
|
||||||
@@ -211,6 +219,58 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request) {
|
|||||||
request->send(response);
|
request->send(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// renames a device
|
||||||
|
// takes the unique ID and the custom name
|
||||||
|
void WebCustomizationService::writeDeviceName(AsyncWebServerRequest * request, JsonVariant json) {
|
||||||
|
if (json.is<JsonObject>()) {
|
||||||
|
// find the device using the unique_id
|
||||||
|
for (const auto & emsdevice : EMSESP::emsdevices) {
|
||||||
|
if (emsdevice) {
|
||||||
|
uint8_t unique_device_id = json["id"];
|
||||||
|
// find product id and device id using the unique id
|
||||||
|
if (emsdevice->unique_id() == unique_device_id) {
|
||||||
|
uint8_t product_id = emsdevice->product_id();
|
||||||
|
uint8_t device_id = emsdevice->device_id();
|
||||||
|
auto custom_name = json["name"].as<std::string>();
|
||||||
|
|
||||||
|
// emsesp::EMSESP::logger().info("Found Device ID: %d, Product ID: %d", device_id, product_id);
|
||||||
|
|
||||||
|
// updates current record or creates a new one
|
||||||
|
bool entry_exists = false;
|
||||||
|
update([&](WebCustomization & settings) {
|
||||||
|
for (auto it = settings.entityCustomizations.begin(); it != settings.entityCustomizations.end();) {
|
||||||
|
if ((*it).product_id == product_id && (*it).device_id == device_id) {
|
||||||
|
(*it).custom_name = custom_name;
|
||||||
|
entry_exists = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if we don't have any customization for this device, create a new entry
|
||||||
|
if (!entry_exists) {
|
||||||
|
EntityCustomization new_entry;
|
||||||
|
new_entry.product_id = product_id;
|
||||||
|
new_entry.device_id = device_id;
|
||||||
|
new_entry.custom_name = custom_name;
|
||||||
|
settings.entityCustomizations.push_back(new_entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return StateUpdateResult::CHANGED;
|
||||||
|
});
|
||||||
|
|
||||||
|
// update the EMS Device record real-time
|
||||||
|
emsdevice->custom_name(custom_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncWebServerResponse * response = request->beginResponse(200);
|
||||||
|
request->send(response);
|
||||||
|
}
|
||||||
|
|
||||||
// takes a list of updated entities with new masks from the web UI
|
// takes a list of updated entities with new masks from the web UI
|
||||||
// saves it in the customization service
|
// saves it in the customization service
|
||||||
// and updates the entity list real-time
|
// and updates the entity list real-time
|
||||||
@@ -236,7 +296,6 @@ void WebCustomizationService::customization_entities(AsyncWebServerRequest * req
|
|||||||
} else {
|
} else {
|
||||||
emsdevice->setCustomizationEntity(id_s);
|
emsdevice->setCustomizationEntity(id_s);
|
||||||
}
|
}
|
||||||
// emsesp::EMSESP::logger().info(id.as<const char *>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// add deleted entities from file
|
// add deleted entities from file
|
||||||
@@ -271,7 +330,7 @@ void WebCustomizationService::customization_entities(AsyncWebServerRequest * req
|
|||||||
|
|
||||||
// Save the list to the customization file
|
// Save the list to the customization file
|
||||||
update([&](WebCustomization & settings) {
|
update([&](WebCustomization & settings) {
|
||||||
// see if we already have a mask list for this device, if so remove it
|
// see if we already have a mask list for this device, if so remove the entry
|
||||||
for (auto it = settings.entityCustomizations.begin(); it != settings.entityCustomizations.end();) {
|
for (auto it = settings.entityCustomizations.begin(); it != settings.entityCustomizations.end();) {
|
||||||
if ((*it).product_id == product_id && (*it).device_id == device_id) {
|
if ((*it).product_id == product_id && (*it).device_id == device_id) {
|
||||||
it = settings.entityCustomizations.erase(it);
|
it = settings.entityCustomizations.erase(it);
|
||||||
@@ -281,16 +340,14 @@ void WebCustomizationService::customization_entities(AsyncWebServerRequest * req
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a new entry for this device if there are values
|
// re-create a new entry
|
||||||
EntityCustomization new_entry;
|
EntityCustomization new_entry;
|
||||||
new_entry.product_id = product_id;
|
new_entry.product_id = product_id;
|
||||||
new_entry.device_id = device_id;
|
new_entry.device_id = device_id;
|
||||||
|
|
||||||
new_entry.entity_ids = entity_ids;
|
new_entry.entity_ids = entity_ids;
|
||||||
|
|
||||||
// add the record and save
|
|
||||||
settings.entityCustomizations.push_back(new_entry);
|
settings.entityCustomizations.push_back(new_entry);
|
||||||
return StateUpdateResult::CHANGED;
|
|
||||||
|
return StateUpdateResult::CHANGED; // save the changes
|
||||||
});
|
});
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -308,7 +365,6 @@ void WebCustomizationService::begin() {
|
|||||||
_fsPersistence.readFromFS();
|
_fsPersistence.readFromFS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// hard coded tests
|
// hard coded tests
|
||||||
#ifdef EMSESP_TEST
|
#ifdef EMSESP_TEST
|
||||||
void WebCustomizationService::test() {
|
void WebCustomizationService::test() {
|
||||||
@@ -321,11 +377,11 @@ void WebCustomizationService::test() {
|
|||||||
sensor.offset = 0;
|
sensor.offset = 0;
|
||||||
webCustomization.sensorCustomizations.push_back(sensor);
|
webCustomization.sensorCustomizations.push_back(sensor);
|
||||||
|
|
||||||
sensor = SensorCustomization();
|
auto sensor2 = SensorCustomization();
|
||||||
sensor.id = "0B-0C0D-0E0F-1011";
|
sensor2.id = "0B-0C0D-0E0F-1011";
|
||||||
sensor.name = "test_sensor2";
|
sensor2.name = "test_sensor2";
|
||||||
sensor.offset = 4;
|
sensor2.offset = 4;
|
||||||
webCustomization.sensorCustomizations.push_back(sensor);
|
webCustomization.sensorCustomizations.push_back(sensor2);
|
||||||
|
|
||||||
// Analog sensors
|
// Analog sensors
|
||||||
// This actually adds the sensors as we use customizations to store them
|
// This actually adds the sensors as we use customizations to store them
|
||||||
@@ -350,9 +406,10 @@ void WebCustomizationService::test() {
|
|||||||
|
|
||||||
// EMS entities
|
// EMS entities
|
||||||
webCustomization.entityCustomizations.clear();
|
webCustomization.entityCustomizations.clear();
|
||||||
auto emsEntity = EntityCustomization();
|
auto emsEntity = EntityCustomization();
|
||||||
emsEntity.product_id = 123;
|
emsEntity.product_id = 123;
|
||||||
emsEntity.device_id = 8;
|
emsEntity.device_id = 8;
|
||||||
|
emsEntity.custom_name = "Custom Name!!";
|
||||||
emsEntity.entity_ids.push_back("08heatingactive|is my heating on?");
|
emsEntity.entity_ids.push_back("08heatingactive|is my heating on?");
|
||||||
webCustomization.entityCustomizations.push_back(emsEntity);
|
webCustomization.entityCustomizations.push_back(emsEntity);
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
// POST
|
// POST
|
||||||
#define CUSTOMIZATION_ENTITIES_PATH "/rest/customizationEntities"
|
#define CUSTOMIZATION_ENTITIES_PATH "/rest/customizationEntities"
|
||||||
#define RESET_CUSTOMIZATION_SERVICE_PATH "/rest/resetCustomizations"
|
#define RESET_CUSTOMIZATION_SERVICE_PATH "/rest/resetCustomizations"
|
||||||
|
#define WRITE_DEVICE_NAME_PATH "/rest/writeDeviceName"
|
||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
@@ -60,9 +61,10 @@ class AnalogCustomization {
|
|||||||
// we use product_id and device_id to make the device unique
|
// we use product_id and device_id to make the device unique
|
||||||
class EntityCustomization {
|
class EntityCustomization {
|
||||||
public:
|
public:
|
||||||
uint8_t product_id; // device's product id
|
uint8_t product_id; // device's product id
|
||||||
uint8_t device_id; // device's device id
|
uint8_t device_id; // device's device id
|
||||||
std::vector<std::string> entity_ids; // array of entity ids with masks and optional custom fullname
|
std::string custom_name; // custom device name
|
||||||
|
std::vector<std::string> entity_ids; // array of entity ids with masks and optional custom fullname
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebCustomization {
|
class WebCustomization {
|
||||||
@@ -100,6 +102,7 @@ class WebCustomizationService : public StatefulService<WebCustomization> {
|
|||||||
|
|
||||||
// POST
|
// POST
|
||||||
void customization_entities(AsyncWebServerRequest * request, JsonVariant json);
|
void customization_entities(AsyncWebServerRequest * request, JsonVariant json);
|
||||||
|
void writeDeviceName(AsyncWebServerRequest * request, JsonVariant json);
|
||||||
void reset_customization(AsyncWebServerRequest * request); // command
|
void reset_customization(AsyncWebServerRequest * request); // command
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
|
|||||||
obj["tn"] = emsdevice->device_type_2_device_name_translated(); // translated device type name
|
obj["tn"] = emsdevice->device_type_2_device_name_translated(); // translated device type name
|
||||||
obj["t"] = emsdevice->device_type(); // device type number
|
obj["t"] = emsdevice->device_type(); // device type number
|
||||||
obj["b"] = emsdevice->brand_to_char(); // brand
|
obj["b"] = emsdevice->brand_to_char(); // brand
|
||||||
obj["n"] = emsdevice->name(); // name
|
obj["n"] = emsdevice->name(); // custom name
|
||||||
obj["d"] = emsdevice->device_id(); // deviceid
|
obj["d"] = emsdevice->device_id(); // deviceid
|
||||||
obj["p"] = emsdevice->product_id(); // productid
|
obj["p"] = emsdevice->product_id(); // productid
|
||||||
obj["v"] = emsdevice->version(); // version
|
obj["v"] = emsdevice->version(); // version
|
||||||
|
|||||||
Reference in New Issue
Block a user