This commit is contained in:
MichaelDvP
2022-04-03 18:35:00 +02:00
10 changed files with 56 additions and 59 deletions

View File

@@ -161,7 +161,7 @@ const SettingsCustomization: FC = () => {
const saveCustomization = async () => { const saveCustomization = async () => {
if (deviceEntities && selectedDevice) { if (deviceEntities && selectedDevice) {
const masked_entities = deviceEntities const masked_entities = deviceEntities
.filter((de) => de.m) // .filter((de) => de.m)
.map((new_de) => new_de.m.toString(16).padStart(2, '0') + new_de.s); .map((new_de) => new_de.m.toString(16).padStart(2, '0') + new_de.s);
try { try {
const response = await EMSESP.writeMaskedEntities({ const response = await EMSESP.writeMaskedEntities({

View File

@@ -131,10 +131,10 @@ export interface DeviceValue {
n: string; // name n: string; // name
c: string; // command c: string; // command
l: string[]; // list l: string[]; // list
h?: string; // help text h?: string; // help text, optional
s?: string; // steps for up/down s?: string; // steps for up/down, optional
m?: string; // min m?: string; // min, optional
x?: string; // max x?: string; // max, optional
} }
export interface DeviceData { export interface DeviceData {
@@ -147,7 +147,7 @@ export interface DeviceEntity {
n: string; // name n: string; // name
s: string; // shortname s: string; // shortname
m: number; // mask m: number; // mask
w?: boolean; // writeable w: boolean; // writeable
} }
export interface MaskedEntities { export interface MaskedEntities {

View File

@@ -634,14 +634,14 @@ const emsesp_deviceentities_2 = [
{ v: 5, n: 'selected flow temperature', s: 'selflowtemp', m: 0 }, { v: 5, n: 'selected flow temperature', s: 'selflowtemp', m: 0 },
{ v: 0, n: 'burner selected max power', s: 'selburnpow', m: 0 }, { v: 0, n: 'burner selected max power', s: 'selburnpow', m: 0 },
{ v: 0, n: 'heating pump modulation', s: 'heatingpumpmod', m: 0 }, { v: 0, n: 'heating pump modulation', s: 'heatingpumpmod', m: 0 },
{ n: 'heating pump 2 modulation', s: 'heatingpump2mod', m: 2 }, { n: 'heating pump 2 modulation', s: 'heatingpump2mod', m: 0 },
{ n: 'outside temperature', s: 'outdoortemp', m: 2 }, { n: 'outside temperature', s: 'outdoortemp', m: 0 },
{ v: 53, n: 'current flow temperature', s: 'curflowtemp', m: 0 }, { v: 53, n: 'current flow temperature', s: 'curflowtemp', m: 0 },
{ v: 51.8, n: 'return temperature', s: 'rettemp', m: 0 }, { v: 51.8, n: 'return temperature', s: 'rettemp', m: 0 },
{ n: 'mixing switch temperature', s: 'switchtemp', m: 2 }, { n: 'mixing switch temperature', s: 'switchtemp', m: 0 },
{ v: 1.3, n: 'system pressure', s: 'syspress', m: 0 }, { v: 1.3, n: 'system pressure', s: 'syspress', m: 0 },
{ v: 54.6, n: 'actual boiler temperature', s: 'boiltemp', m: 0 }, { v: 54.6, n: 'actual boiler temperature', s: 'boiltemp', m: 0 },
{ n: 'exhaust temperature', s: 'exhausttemp', m: 2 }, { n: 'exhaust temperature', s: 'exhausttemp', m: 0 },
{ v: false, n: 'gas', s: 'burngas', m: 0 }, { v: false, n: 'gas', s: 'burngas', m: 0 },
{ v: false, n: 'gas stage 2', s: 'burngas2', m: 0 }, { v: false, n: 'gas stage 2', s: 'burngas2', m: 0 },
{ v: 0, n: 'flame current', s: 'flamecurr', m: 0 }, { v: 0, n: 'flame current', s: 'flamecurr', m: 0 },
@@ -923,22 +923,23 @@ rest_server.post(EMSESP_DEVICEENTITIES_ENDPOINT, (req, res) => {
} }
}) })
function myF(entity, de, dd) { function updateMask(entity, de, dd) {
const name = entity.slice(2) const name = entity.slice(2)
const mask = parseInt(entity.slice(0, 2), 16) const new_mask = parseInt(entity.slice(0, 2), 16)
const mask_hex = entity.slice(0, 2)
objIndex = de.findIndex((obj) => obj.s == name) objIndex = de.findIndex((obj) => obj.s == name)
if (objIndex !== -1) { if (objIndex !== -1) {
de[objIndex].m = mask de[objIndex].m = new_mask
const fullname = de[objIndex].n const fullname = de[objIndex].n
objIndex = dd.data.findIndex((obj) => obj.n.slice(2) == fullname) objIndex = dd.data.findIndex((obj) => obj.n.slice(2) == fullname)
if (objIndex !== -1) { if (objIndex !== -1) {
dd.data[objIndex].n = mask_hex + fullname // see if the mask has changed
console.log('Updating: ') const old_mask = parseInt(dd.data[objIndex].n.slice(0, 2), 16)
console.log(dd.data[objIndex]) if (old_mask !== new_mask) {
} else { const mask_hex = entity.slice(0, 2)
console.log("can't locate record for " + fullname) console.log('Updating ' + dd.data[objIndex].n + ' -> ' + mask_hex + fullname)
dd.data[objIndex].n = mask_hex + fullname
}
} }
} else { } else {
console.log("can't locate record for id " + id) console.log("can't locate record for id " + id)
@@ -949,11 +950,11 @@ rest_server.post(EMSESP_MASKED_ENTITIES_ENDPOINT, (req, res) => {
const id = req.body.id const id = req.body.id
for (const entity of req.body.entity_ids) { for (const entity of req.body.entity_ids) {
if (id === 1) { if (id === 1) {
myF(entity, emsesp_deviceentities_1, emsesp_devicedata_1) updateMask(entity, emsesp_deviceentities_1, emsesp_devicedata_1)
} else if (id === 2) { } else if (id === 2) {
myF(entity, emsesp_deviceentities_2, emsesp_devicedata_2) updateMask(entity, emsesp_deviceentities_2, emsesp_devicedata_2)
} else if (id === 4) { } else if (id === 4) {
myF(entity, emsesp_deviceentities_4, emsesp_devicedata_4) updateMask(entity, emsesp_deviceentities_4, emsesp_devicedata_4)
} }
} }
res.sendStatus(200) res.sendStatus(200)

View File

@@ -404,9 +404,9 @@ void EMSdevice::register_device_value(uint8_t tag,
if ((entityCustomization.product_id == product_id()) && (entityCustomization.device_id == device_id())) { if ((entityCustomization.product_id == product_id()) && (entityCustomization.device_id == device_id())) {
std::string entity = tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(short_name) : tag_to_string(tag) + "/" + read_flash_string(short_name); std::string entity = tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(short_name) : tag_to_string(tag) + "/" + read_flash_string(short_name);
for (std::string entity_id : entityCustomization.entity_ids) { for (std::string entity_id : entityCustomization.entity_ids) {
uint8_t flag = Helpers::hextoint(entity_id.substr(0, 2).c_str());
if (entity_id.substr(2) == entity) { if (entity_id.substr(2) == entity) {
state = flag << 4; // set state high bits to flag, turn off active and ha flags uint8_t mask = Helpers::hextoint(entity_id.substr(0, 2).c_str());
state = mask << 4; // set state high bits to flag, turn off active and ha flags
break; break;
} }
} }
@@ -759,7 +759,7 @@ void EMSdevice::generate_values_web(JsonObject & output) {
// as generate_values_web() but stripped down to only show all entities and their state // as generate_values_web() but stripped down to only show all entities and their state
// this is used only for WebCustomizationService::device_entities() // this is used only for WebCustomizationService::device_entities()
void EMSdevice::generate_values_web_all(JsonArray & output) { void EMSdevice::generate_values_web_all(JsonArray & output) {
for (auto & dv : devicevalues_) { for (const auto & dv : devicevalues_) {
// also show commands and entities that have an empty full name // also show commands and entities that have an empty full name
JsonObject obj = output.createNestedObject(); JsonObject obj = output.createNestedObject();
@@ -847,30 +847,24 @@ void EMSdevice::generate_values_web_all(JsonArray & output) {
} }
} }
// reset all entities to being visible // set mask per device entity based on the id which is prefixed with the 2 char hex mask value
// this is called before loading in the exclude entities list from the customization service // returns true if the entity has a mask set
void EMSdevice::reset_entity_masks() { bool EMSdevice::mask_entity(const std::string & entity_id) {
for (auto & dv : devicevalues_) {
dv.state &= 0x0F; // clear high nibble
}
}
// disable/exclude/mask_out a device entity based on the id
void EMSdevice::mask_entity(const std::string & entity_id) {
// first character contains mask flags
uint8_t flag = (Helpers::hextoint(entity_id.substr(0, 2).c_str()) << 4);
for (auto & dv : devicevalues_) { for (auto & dv : devicevalues_) {
std::string entity = dv.tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(dv.short_name) : tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name); std::string entity = dv.tag < DeviceValueTAG::TAG_HC1 ? read_flash_string(dv.short_name) : tag_to_string(dv.tag) + "/" + read_flash_string(dv.short_name);
if (entity == entity_id.substr(2)) { if (entity == entity_id.substr(2)) {
// remove ha config on change of dv_readonly flag uint8_t mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); // first character contains mask flags
if (Mqtt::ha_enabled() && ((dv.state ^ flag) & DeviceValueState::DV_READONLY)) { if (Mqtt::ha_enabled() && (((dv.state >> 4) ^ mask) & (DeviceValueState::DV_READONLY >> 4))) {
// remove ha config on change of dv_readonly flag
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED); dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
Mqtt::publish_ha_sensor_config(dv, "", "", true); // delete topic (remove = true) Mqtt::publish_ha_sensor_config(dv, "", "", true); // delete topic (remove = true)
} }
dv.state = (dv.state & 0x0F) | flag; // set state high bits to flag dv.state = ((dv.state & 0x0F) | (mask << 4)); // set state high bits to flag
return; return mask; // true if entity mask is not the deafult 0
} }
} }
return false;
} }
// builds json for a specific device value / entity // builds json for a specific device value / entity

View File

@@ -183,8 +183,7 @@ class EMSdevice {
char * show_telegram_handlers(char * result, const size_t len, const uint8_t handlers); char * show_telegram_handlers(char * result, const size_t len, const uint8_t handlers);
void show_mqtt_handlers(uuid::console::Shell & shell) const; void show_mqtt_handlers(uuid::console::Shell & shell) const;
void list_device_entries(JsonObject & output) const; void list_device_entries(JsonObject & output) const;
void mask_entity(const std::string & entity_id); bool mask_entity(const std::string & entity_id);
void reset_entity_masks();
using process_function_p = std::function<void(std::shared_ptr<const Telegram>)>; using process_function_p = std::function<void(std::shared_ptr<const Telegram>)>;

View File

@@ -134,7 +134,7 @@ size_t DeviceValue::tag_count = sizeof(DeviceValue::DeviceValueTAG_s) / sizeof(_
// checks whether the device value has an actual value // checks whether the device value has an actual value
// returns true if its valid // returns true if its valid
// state is stored in the dv object // state is stored in the dv object
bool DeviceValue::hasValue() { bool DeviceValue::hasValue() const {
bool has_value = false; bool has_value = false;
switch (type) { switch (type) {
case DeviceValueType::BOOL: case DeviceValueType::BOOL:

View File

@@ -168,20 +168,20 @@ class DeviceValue {
, state(state) { , state(state) {
} }
bool hasValue(); bool hasValue() const;
bool get_min_max(int16_t & dv_set_min, int16_t & dv_set_max); bool get_min_max(int16_t & dv_set_min, int16_t & dv_set_max);
// state flags // state flags
inline void add_state(uint8_t s) { void add_state(uint8_t s) {
state |= s; state |= s;
} }
inline bool has_state(uint8_t s) const { bool has_state(uint8_t s) const {
return (state & s) == s; return (state & s) == s;
} }
inline void remove_state(uint8_t s) { void remove_state(uint8_t s) {
state &= ~s; state &= ~s;
} }
inline uint8_t get_state() const { uint8_t get_state() const {
return state; return state;
} }

View File

@@ -919,6 +919,10 @@ void Mqtt::publish_ha_sensor_config(DeviceValue & dv, const std::string & model,
int16_t dv_set_min, dv_set_max; int16_t dv_set_min, dv_set_max;
(void)dv.get_min_max(dv_set_min, dv_set_max); (void)dv.get_min_max(dv_set_min, dv_set_max);
// determine if we're creating the command topics which we use special HA configs
// unless the entity has been marked as read-only and so it'll default to using the sensor/ type
bool has_cmd = dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY);
publish_ha_sensor_config(dv.type, publish_ha_sensor_config(dv.type,
dv.tag, dv.tag,
dv.full_name, dv.full_name,
@@ -926,7 +930,7 @@ void Mqtt::publish_ha_sensor_config(DeviceValue & dv, const std::string & model,
dv.short_name, dv.short_name,
dv.uom, dv.uom,
remove, remove,
dv.has_cmd && !dv.has_state(DeviceValueState::DV_READONLY), has_cmd,
dv.options, dv.options,
dv.options_size, dv.options_size,
dv_set_min, dv_set_min,

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.4.0b10" #define EMSESP_APP_VERSION "3.4.0b11"

View File

@@ -172,11 +172,10 @@ void WebCustomizationService::devices(AsyncWebServerRequest * request) {
obj["i"] = emsdevice->unique_id(); // a unique id 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()); uint8_t device_index = EMSESP::device_index(emsdevice->device_type(), emsdevice->unique_id());
if (device_index) { if (device_index) {
char s[10]; char s[10];
obj["s"] = emsdevice->device_type_name() + Helpers::smallitoa(s, device_index) + " (" + emsdevice->name() + ")"; obj["s"] = emsdevice->device_type_name() + Helpers::smallitoa(s, device_index) + " (" + emsdevice->name() + ")"; // shortname - we prefix the count to make it unique
} else { } else {
obj["s"] = emsdevice->device_type_name() + " (" + emsdevice->name() + ")"; obj["s"] = emsdevice->device_type_name() + " (" + emsdevice->name() + ")";
} }
@@ -221,16 +220,16 @@ void WebCustomizationService::masked_entities(AsyncWebServerRequest * request, J
if (emsdevice) { if (emsdevice) {
uint8_t unique_device_id = json["id"]; uint8_t unique_device_id = json["id"];
if (emsdevice->unique_id() == unique_device_id) { if (emsdevice->unique_id() == unique_device_id) {
// first reset all the entity ids
emsdevice->reset_entity_masks();
// build a list of entities // build a list of entities
JsonArray entity_ids_json = json["entity_ids"]; JsonArray entity_ids_json = json["entity_ids"];
std::vector<std::string> entity_ids; std::vector<std::string> entity_ids;
for (JsonVariant id : entity_ids_json) { for (const JsonVariant id : entity_ids_json) {
std::string entity_id = id.as<std::string>(); std::string entity_id = id.as<std::string>();
emsdevice->mask_entity(entity_id); // this will have immediate affect // handle the mask change and add to the list of customized entities
entity_ids.push_back(entity_id); // if the value is different from the default (mask == 0)
if (emsdevice->mask_entity(entity_id)) {
entity_ids.push_back(entity_id);
}
} }
// Save the list to the customization file // Save the list to the customization file