Merge branch 'dev_' into dev_no_master_thermostat

This commit is contained in:
MichaelDvP
2022-04-14 07:27:07 +02:00
55 changed files with 3607 additions and 2542 deletions

View File

@@ -31,9 +31,9 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
securityManager,
AuthenticationPredicates::IS_AUTHENTICATED)
, _fsPersistence(WebCustomization::read, WebCustomization::update, this, fs, EMSESP_CUSTOMIZATION_FILE)
, _exclude_entities_handler(EXCLUDE_ENTITIES_PATH,
securityManager->wrapCallback(std::bind(&WebCustomizationService::exclude_entities, this, _1, _2),
AuthenticationPredicates::IS_AUTHENTICATED))
, _masked_entities_handler(MASKED_ENTITIES_PATH,
securityManager->wrapCallback(std::bind(&WebCustomizationService::masked_entities, this, _1, _2),
AuthenticationPredicates::IS_AUTHENTICATED))
, _device_entities_handler(DEVICE_ENTITIES_PATH,
securityManager->wrapCallback(std::bind(&WebCustomizationService::device_entities, this, _1, _2),
AuthenticationPredicates::IS_AUTHENTICATED)) {
@@ -45,16 +45,17 @@ WebCustomizationService::WebCustomizationService(AsyncWebServer * server, FS * f
HTTP_POST,
securityManager->wrapRequest(std::bind(&WebCustomizationService::reset_customization, this, _1), AuthenticationPredicates::IS_ADMIN));
_exclude_entities_handler.setMethod(HTTP_POST);
_exclude_entities_handler.setMaxContentLength(1024);
server->addHandler(&_exclude_entities_handler);
_masked_entities_handler.setMethod(HTTP_POST);
_masked_entities_handler.setMaxContentLength(4096);
_masked_entities_handler.setMaxJsonBufferSize(4096);
server->addHandler(&_masked_entities_handler);
_device_entities_handler.setMethod(HTTP_POST);
_device_entities_handler.setMaxContentLength(256);
server->addHandler(&_device_entities_handler);
}
// this creates the customization file, saving to the FS
// this creates the customization file, saving it to the FS
void WebCustomization::read(WebCustomization & settings, JsonObject & root) {
// Dallas Sensor customization
JsonArray sensorsJson = root.createNestedArray("sensors");
@@ -77,21 +78,21 @@ void WebCustomization::read(WebCustomization & settings, JsonObject & root) {
sensorJson["type"] = sensor.type; // t
}
// Exclude entities customization
JsonArray exclude_entitiesJson = root.createNestedArray("exclude_entities");
// Masked entities customization
JsonArray masked_entitiesJson = root.createNestedArray("masked_entities");
for (const EntityCustomization & entityCustomization : settings.entityCustomizations) {
JsonObject entityJson = exclude_entitiesJson.createNestedObject();
JsonObject entityJson = masked_entitiesJson.createNestedObject();
entityJson["product_id"] = entityCustomization.product_id;
entityJson["device_id"] = entityCustomization.device_id;
JsonArray exclude_entityJson = entityJson.createNestedArray("entity_ids");
for (uint8_t entity_id : entityCustomization.entity_ids) {
exclude_entityJson.add(entity_id);
JsonArray masked_entityJson = entityJson.createNestedArray("entity_ids");
for (std::string entity_id : entityCustomization.entity_ids) {
masked_entityJson.add(entity_id);
}
}
}
// call on initialization and also when the page is saved via web
// call on initialization and also when the page is saved via web UI
// this loads the data into the internal class
StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization & settings) {
// Dallas Sensor customization
@@ -123,17 +124,20 @@ StateUpdateResult WebCustomization::update(JsonObject & root, WebCustomization &
}
}
// load array of entities id's to exclude, building up the object class
// load array of entities id's with masks, building up the object class
settings.entityCustomizations.clear();
if (root["exclude_entities"].is<JsonArray>()) {
for (const JsonObject exclude_entities : root["exclude_entities"].as<JsonArray>()) {
if (root["masked_entities"].is<JsonArray>()) {
for (const JsonObject masked_entities : root["masked_entities"].as<JsonArray>()) {
auto new_entry = EntityCustomization();
new_entry.product_id = exclude_entities["product_id"];
new_entry.device_id = exclude_entities["device_id"];
new_entry.product_id = masked_entities["product_id"];
new_entry.device_id = masked_entities["device_id"];
for (const JsonVariant exclude_entity_id : exclude_entities["entity_ids"].as<JsonArray>()) {
new_entry.entity_ids.push_back(exclude_entity_id.as<uint8_t>()); // add entity list
for (const JsonVariant masked_entity_id : masked_entities["entity_ids"].as<JsonArray>()) {
if (masked_entity_id.is<std::string>()) {
new_entry.entity_ids.push_back(masked_entity_id.as<std::string>()); // add entity list
}
}
settings.entityCustomizations.push_back(new_entry); // save the new object
}
}
@@ -156,7 +160,7 @@ void WebCustomizationService::reset_customization(AsyncWebServerRequest * reques
#endif
}
// send back a short list devices used in the customization page
// send back a list of devices used to the customization web page
void WebCustomizationService::devices(AsyncWebServerRequest * request) {
auto * response = new AsyncJsonResponse(false, EMSESP_JSON_SIZE_LARGE_DYN);
JsonObject root = response->getRoot();
@@ -167,14 +171,16 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) {
JsonObject obj = devices.createNestedObject();
obj["i"] = emsdevice->unique_id(); // a unique id
// shortname - we prefix the count to make it unique
/*
uint8_t device_index = EMSESP::device_index(emsdevice->device_type(), emsdevice->unique_id());
if (device_index) {
char s[10];
obj["s"] = emsdevice->device_type_name() + Helpers::smallitoa(s, device_index);
obj["s"] = emsdevice->device_type_name() + Helpers::smallitoa(s, device_index) + " (" + emsdevice->name() + ")"; // shortname - we prefix the count to make it unique
} else {
obj["s"] = emsdevice->device_type_name();
obj["s"] = emsdevice->device_type_name() + " (" + emsdevice->name() + ")";
}
*/
obj["s"] = emsdevice->device_type_name() + " (" + emsdevice->name() + ")";
}
}
@@ -182,10 +188,10 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) {
request->send(response);
}
// send back list device entities
// send back list of device entities
void WebCustomizationService::device_entities(AsyncWebServerRequest * request, JsonVariant & json) {
if (json.is<JsonObject>()) {
auto * response = new MsgpackAsyncJsonResponse(true, EMSESP_JSON_SIZE_XXLARGE_DYN);
auto * response = new MsgpackAsyncJsonResponse(true, EMSESP_JSON_SIZE_XXXLARGE_DYN);
for (const auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice->unique_id() == json["id"]) {
#ifndef EMSESP_STANDALONE
@@ -204,52 +210,53 @@ void WebCustomizationService::device_entities(AsyncWebServerRequest * request, J
request->send(response);
}
// takes a list of excluded ids send from the webUI
// takes a list of updated entities with new masks from the web UI
// saves it in the customization service
// and updates the entity list real-time
void WebCustomizationService::exclude_entities(AsyncWebServerRequest * request, JsonVariant & json) {
void WebCustomizationService::masked_entities(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"];
if (emsdevice->unique_id() == unique_device_id) {
// first reset all the entity ids
emsdevice->reset_exclude_entities();
// build a list of entities to exclude and then set the flag to non-visible
JsonArray entity_ids_json = json["entity_ids"];
std::vector<uint8_t> entity_ids;
for (JsonVariant id : entity_ids_json) {
uint8_t entity_id = id.as<int>();
emsdevice->exclude_entity(entity_id); // this will have immediate affect
entity_ids.push_back(entity_id);
}
// Save the list to the customization file
uint8_t product_id = emsdevice->product_id();
uint8_t device_id = emsdevice->device_id();
// and set the mask immediately for the changed entities
JsonArray entity_ids_json = json["entity_ids"];
for (const JsonVariant id : entity_ids_json) {
emsdevice->mask_entity(id.as<std::string>());
}
// Save the list to the customization file
EMSESP::webCustomizationService.update(
[&](WebCustomization & settings) {
// if it exists (productid and deviceid match) overwrite it
for (auto & entityCustomization : settings.entityCustomizations) {
if ((entityCustomization.product_id == product_id) && (entityCustomization.device_id == device_id)) {
// already exists, clear the list and add the new values
entityCustomization.entity_ids.clear();
for (uint8_t i = 0; i < entity_ids.size(); i++) {
entityCustomization.entity_ids.push_back(entity_ids[i]);
}
return StateUpdateResult::CHANGED;
// see if we already have a mask list for this device, if so remove it
for (auto it = settings.entityCustomizations.begin(); it != settings.entityCustomizations.end();) {
if ((*it).product_id == product_id && (*it).device_id == device_id) {
it = settings.entityCustomizations.erase(it);
break;
} else {
++it;
}
}
// create a new entry in the list
if (!entity_ids_json.size()) {
return StateUpdateResult::UNCHANGED; // nothing to add
}
// create a new entry for this device if there are values
EntityCustomization new_entry;
new_entry.product_id = product_id;
new_entry.device_id = device_id;
for (uint8_t i = 0; i < entity_ids.size(); i++) {
new_entry.entity_ids.push_back(entity_ids[i]);
}
// get list of entities that have masks
std::vector<std::string> entity_ids;
emsdevice->getMaskedEntities(entity_ids);
new_entry.entity_ids = entity_ids;
// add the record and save
settings.entityCustomizations.push_back(new_entry);
return StateUpdateResult::CHANGED;
},

View File

@@ -27,7 +27,7 @@
// POST
#define DEVICE_ENTITIES_PATH "/rest/deviceEntities"
#define EXCLUDE_ENTITIES_PATH "/rest/excludeEntities"
#define MASKED_ENTITIES_PATH "/rest/maskedEntities"
#define RESET_CUSTOMIZATION_SERVICE_PATH "/rest/resetCustomizations"
namespace emsesp {
@@ -61,19 +61,18 @@ class AnalogCustomization {
// we use product_id and device_id to make the device unique
class EntityCustomization {
public:
uint8_t product_id; // device's product id
uint8_t device_id; // device's device id
std::vector<uint8_t> entity_ids; // array of entity ids to exclude
uint8_t product_id; // device's product id
uint8_t device_id; // device's device id
std::vector<std::string> entity_ids; // array of entity ids with masks
};
class WebCustomization {
public:
std::list<SensorCustomization> sensorCustomizations; // for sensor names and offsets
std::list<AnalogCustomization> analogCustomizations; // for analog sensors
std::list<EntityCustomization> entityCustomizations; // for a list of entities that should be excluded from the device list
static void read(WebCustomization & settings, JsonObject & root);
static StateUpdateResult update(JsonObject & root, WebCustomization & settings);
std::list<EntityCustomization> entityCustomizations; // for a list of entities that have a special mask set
static void read(WebCustomization & settings, JsonObject & root);
static StateUpdateResult update(JsonObject & root, WebCustomization & settings);
};
class WebCustomizationService : public StatefulService<WebCustomization> {
@@ -94,11 +93,11 @@ class WebCustomizationService : public StatefulService<WebCustomization> {
void devices(AsyncWebServerRequest * request);
// POST
void exclude_entities(AsyncWebServerRequest * request, JsonVariant & json);
void masked_entities(AsyncWebServerRequest * request, JsonVariant & json);
void device_entities(AsyncWebServerRequest * request, JsonVariant & json);
void reset_customization(AsyncWebServerRequest * request);
AsyncCallbackJsonWebHandler _exclude_entities_handler, _device_entities_handler;
AsyncCallbackJsonWebHandler _masked_entities_handler, _device_entities_handler;
};
} // namespace emsesp

View File

@@ -77,7 +77,7 @@ void WebDataService::core_data(AsyncWebServerRequest * request) {
// Ignore Contoller
JsonArray devices = root.createNestedArray("devices");
for (const auto & emsdevice : EMSESP::emsdevices) {
if (emsdevice && emsdevice->device_type() != EMSdevice::DeviceType::CONTROLLER) {
if (emsdevice && (emsdevice->device_type() != EMSdevice::DeviceType::CONTROLLER || emsdevice->count_entities() > 0)) {
JsonObject obj = devices.createNestedObject();
obj["i"] = emsdevice->unique_id(); // a unique id
obj["t"] = emsdevice->device_type_name(); // type