custom min/max values

This commit is contained in:
MichaelDvP
2022-09-28 16:08:08 +02:00
parent 732aaffbb6
commit a0339f5ae2
5 changed files with 124 additions and 13 deletions

View File

@@ -472,6 +472,7 @@ void EMSdevice::add_device_value(uint8_t tag,
// add the device entity
devicevalues_.emplace_back(
device_type_, tag, value_p, type, options, options_single, numeric_operator, short_name, fullname, custom_fullname, uom, has_cmd, min, max, state);
devicevalues_.back().set_custom_minmax();
// add a new command if it has a function attached
if (!has_cmd) {
@@ -873,7 +874,7 @@ void EMSdevice::generate_values_web(JsonObject & output) {
// as generate_values_web() but stripped down to only show all entities and their state
// this is used only for WebCustomizationService::device_entities()
void EMSdevice::generate_values_web_customization(JsonArray & output) {
for (const auto & dv : devicevalues_) {
for (auto & dv : devicevalues_) {
// also show commands and entities that have an empty full name
JsonObject obj = output.createNestedObject();
@@ -958,8 +959,9 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) {
}
// add the custom name, is optional
if (!dv.custom_fullname.empty()) {
obj["cn"] = dv.custom_fullname;
std::string custom_fullname = dv.get_custom_fullname();
if (!custom_fullname.empty()) {
obj["cn"] = custom_fullname;
}
} else {
// it's a command
@@ -968,6 +970,16 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) {
obj["m"] = dv.state >> 4; // send back the mask state. We're only interested in the high nibble
obj["w"] = dv.has_cmd; // if writable
// set the custom min and max values if there are any
int16_t dv_set_min;
uint16_t dv_set_max;
if (dv.get_custom_min(dv_set_min)) {
obj["mi"] = dv_set_min;
}
if (dv.get_custom_max(dv_set_max)) {
obj["ma"] = dv_set_max;
}
}
}
@@ -1009,7 +1021,7 @@ void EMSdevice::setCustomEntity(const std::string & entity_id) {
} else {
dv.custom_fullname = "";
}
dv.set_custom_minmax();
return;
}
}
@@ -1405,6 +1417,24 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
// else if (dv.type == DeviceValueType::CMD && output_target != EMSdevice::OUTPUT_TARGET::MQTT) {
// json[name] = "";
// }
// check for value outside min/max range and adapt the limits to avoid HA complains
// Should this also check for api output?
if ((output_target == OUTPUT_TARGET::MQTT) && (dv.min != 0 || dv.max != 0)) {
if (json[name].is<float>() || json[name].is<int>()) {
int v = json[name];
if (fahrenheit) {
v = (v - (32 * (fahrenheit - 1))) / 1.8; // reset to °C
}
if (v < dv.min) {
dv.min = v;
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
} else if (v > dv.max) {
dv.max = v;
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
}
}
}
}
}
}

View File

@@ -326,13 +326,58 @@ bool DeviceValue::get_min_max(int16_t & dv_set_min, int16_t & dv_set_max) {
return false; // nothing changed, not supported
}
// returns the translated fullname or the custom fullname (if provided)
// always returns a std::string
std::string DeviceValue::get_fullname() const {
if (custom_fullname.empty()) {
return Helpers::translated_word(fullname);
// extract custom min from custom_fullname
bool DeviceValue::get_custom_min(int16_t & v) {
auto min_pos = custom_fullname.find('>');
bool has_min = (min_pos != std::string::npos);
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (uom == DeviceValueUOM::DEGREES) ? 2 : (uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
if (has_min) {
v = Helpers::atoint(custom_fullname.substr(min_pos + 1).c_str());
if (fahrenheit) {
v = (v - (32 * (fahrenheit - 1))) / 1.8; // reset to °C
}
}
return has_min;
}
// extract custom max from custom_fullname
bool DeviceValue::get_custom_max(uint16_t & v) {
auto max_pos = custom_fullname.find('<');
bool has_max = (max_pos != std::string::npos);
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (uom == DeviceValueUOM::DEGREES) ? 2 : (uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
if (has_max) {
v = Helpers::atoint(custom_fullname.substr(max_pos + 1).c_str());
if (fahrenheit) {
v = (v - (32 * (fahrenheit - 1))) / 1.8; // reset to °C
}
}
return has_max;
}
// sets min max to stored custom values (if set)
void DeviceValue::set_custom_minmax() {
get_custom_min(min);
get_custom_max(max);
}
std::string DeviceValue::get_custom_fullname() const {
auto min_pos = custom_fullname.find('>');
auto max_pos = custom_fullname.find('<');
auto minmax_pos = min_pos < max_pos ? min_pos : max_pos;
if (minmax_pos != std::string::npos) {
return custom_fullname.substr(0, minmax_pos);
}
return custom_fullname;
}
// returns the translated fullname or the custom fullname (if provided)
// always returns a std::string
std::string DeviceValue::get_fullname() const {
std::string customname = get_custom_fullname();
if (customname.empty()) {
return Helpers::translated_word(fullname);
}
return customname;
}
} // namespace emsesp

View File

@@ -179,6 +179,10 @@ class DeviceValue {
bool hasValue() const;
bool get_min_max(int16_t & dv_set_min, int16_t & dv_set_max);
void set_custom_minmax();
bool get_custom_min(int16_t & v);
bool get_custom_max(uint16_t & v);
std::string get_custom_fullname() const;
std::string get_fullname() const;
// dv state flags