mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-07 16:29:51 +03:00
Merge pull request #442 from proddy/dev
fix changing masks for customizations
This commit is contained in:
@@ -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({
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
// see if the mask has changed
|
||||||
|
const old_mask = parseInt(dd.data[objIndex].n.slice(0, 2), 16)
|
||||||
|
if (old_mask !== new_mask) {
|
||||||
|
const mask_hex = entity.slice(0, 2)
|
||||||
|
console.log('Updating ' + dd.data[objIndex].n + ' -> ' + mask_hex + fullname)
|
||||||
dd.data[objIndex].n = mask_hex + fullname
|
dd.data[objIndex].n = mask_hex + fullname
|
||||||
console.log('Updating: ')
|
}
|
||||||
console.log(dd.data[objIndex])
|
|
||||||
} else {
|
|
||||||
console.log("can't locate record for " + 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)
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
uint8_t mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); // first character contains mask flags
|
||||||
|
if (Mqtt::ha_enabled() && (((dv.state >> 4) ^ mask) & (DeviceValueState::DV_READONLY >> 4))) {
|
||||||
// remove ha config on change of dv_readonly flag
|
// remove ha config on change of dv_readonly flag
|
||||||
if (Mqtt::ha_enabled() && ((dv.state ^ flag) & DeviceValueState::DV_READONLY)) {
|
|
||||||
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
|
||||||
|
|||||||
@@ -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>)>;
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "3.4.0b10"
|
#define EMSESP_APP_VERSION "3.4.0b11"
|
||||||
|
|||||||
@@ -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,17 +220,17 @@ 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
|
||||||
|
// if the value is different from the default (mask == 0)
|
||||||
|
if (emsdevice->mask_entity(entity_id)) {
|
||||||
entity_ids.push_back(entity_id);
|
entity_ids.push_back(entity_id);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Save the list to the customization file
|
// Save the list to the customization file
|
||||||
uint8_t product_id = emsdevice->product_id();
|
uint8_t product_id = emsdevice->product_id();
|
||||||
|
|||||||
Reference in New Issue
Block a user