show trailing zero for float values, #663

This commit is contained in:
MichaelDvP
2022-10-07 10:56:52 +02:00
parent 0a56ee7dbb
commit bace01e4f7
3 changed files with 44 additions and 101 deletions

View File

@@ -4,10 +4,11 @@
## Added ## Added
- Translations in Web UI and all device entity names to German. [#22](https://github.com/emsesp/EMS-ESP32/issues/22) - Translations in Web UI and all device entity names (DE, NL, SE, PL, NO, ...). [#22](https://github.com/emsesp/EMS-ESP32/issues/22)
- Add support for Lolin C3 mini [#620](https://github.com/emsesp/EMS-ESP32/pull/620) - Add support for Lolin C3 mini [#620](https://github.com/emsesp/EMS-ESP32/pull/620)
- Add Greenstar 30Ri boiler - Add devices: Greenstar 30Ri boiler, Junkers FW500 thermostat, Buderus BC30 controller
- Add program memory info - Add program memory info
- Add mqtt queue and connection infos
- Add min/max setting to customizations - Add min/max setting to customizations
- Adapt min/max if ems-value is not in this range - Adapt min/max if ems-value is not in this range
- Add heatpump settings for inputs and limits - Add heatpump settings for inputs and limits
@@ -20,6 +21,7 @@
- Discovery in HomeAssistant don't work with custom base topic. [#596](https://github.com/emsesp/EMS-ESP32/issues/596) Base topic containing `/` are changed to `_` - Discovery in HomeAssistant don't work with custom base topic. [#596](https://github.com/emsesp/EMS-ESP32/issues/596) Base topic containing `/` are changed to `_`
- RF room temperature sensor are shown as thermostat - RF room temperature sensor are shown as thermostat
- render mqtt float json values with trailing zero
## **BREAKING CHANGES:** ## **BREAKING CHANGES:**

View File

@@ -360,14 +360,15 @@ bool DallasSensor::command_info(const char * value, const int8_t id, JsonObject
} }
for (const auto & sensor : sensors_) { for (const auto & sensor : sensors_) {
char val[10];
if (id == -1) { // show number and id if (id == -1) { // show number and id
JsonObject dataSensor = output.createNestedObject(sensor.name()); JsonObject dataSensor = output.createNestedObject(sensor.name());
dataSensor["id"] = sensor.id(); dataSensor["id"] = sensor.id();
if (Helpers::hasValue(sensor.temperature_c)) { if (Helpers::hasValue(sensor.temperature_c)) {
dataSensor["temp"] = Helpers::transformNumFloat((float)(sensor.temperature_c), 10, EMSESP::system_.fahrenheit() ? 2 : 0); dataSensor["temp"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
} }
} else if (Helpers::hasValue(sensor.temperature_c)) { } else if (Helpers::hasValue(sensor.temperature_c)) {
output[sensor.name()] = Helpers::transformNumFloat((float)(sensor.temperature_c), 10, EMSESP::system_.fahrenheit() ? 2 : 0); output[sensor.name()] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
} }
} }
@@ -392,12 +393,13 @@ bool DallasSensor::get_value_info(JsonObject & output, const char * cmd, const i
if (strcmp(command_s, sensor.name().c_str()) == 0) { if (strcmp(command_s, sensor.name().c_str()) == 0) {
output["id"] = sensor.id(); output["id"] = sensor.id();
output["name"] = sensor.name(); output["name"] = sensor.name();
char val[10];
if (Helpers::hasValue(sensor.temperature_c)) { if (Helpers::hasValue(sensor.temperature_c)) {
output["value"] = Helpers::transformNumFloat((float)(sensor.temperature_c), 10, EMSESP::system_.fahrenheit() ? 2 : 0); output["value"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
} }
output["type"] = F_(number); output["type"] = F_(number);
output["min"] = Helpers::transformNumFloat(-55, 0, EMSESP::system_.fahrenheit() ? 2 : 0); output["min"] = serialized(Helpers::render_value(val, -55, 0, EMSESP::system_.fahrenheit() ? 2 : 0));
output["max"] = Helpers::transformNumFloat(125, 0, EMSESP::system_.fahrenheit() ? 2 : 0); output["max"] = serialized(Helpers::render_value(val, 125, 0, EMSESP::system_.fahrenheit() ? 2 : 0));
output["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES); output["uom"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES);
output["writeable"] = false; output["writeable"] = false;
// if we're filtering on an attribute, go find it // if we're filtering on an attribute, go find it
@@ -469,14 +471,15 @@ void DallasSensor::publish_values(const bool force) {
for (auto & sensor : sensors_) { for (auto & sensor : sensors_) {
bool has_value = Helpers::hasValue(sensor.temperature_c); bool has_value = Helpers::hasValue(sensor.temperature_c);
char val[10];
if (Mqtt::is_nested()) { if (Mqtt::is_nested()) {
JsonObject dataSensor = doc.createNestedObject(sensor.id()); JsonObject dataSensor = doc.createNestedObject(sensor.id());
dataSensor["name"] = sensor.name(); dataSensor["name"] = sensor.name();
if (has_value) { if (has_value) {
dataSensor["temp"] = Helpers::transformNumFloat((float)(sensor.temperature_c), 10, EMSESP::system_.fahrenheit() ? 2 : 0); dataSensor["temp"] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
} }
} else if (has_value) { } else if (has_value) {
doc[sensor.name()] = Helpers::transformNumFloat((float)(sensor.temperature_c), 10, EMSESP::system_.fahrenheit() ? 2 : 0); doc[sensor.name()] = serialized(Helpers::render_value(val, sensor.temperature_c, 10, EMSESP::system_.fahrenheit() ? 2 : 0));
} }
// create the HA MQTT config // create the HA MQTT config

View File

@@ -791,18 +791,19 @@ void EMSdevice::generate_values_web(JsonObject & output) {
// note, the nested if's is necessary due to the way the ArduinoJson templates are pre-processed by the compiler // note, the nested if's is necessary due to the way the ArduinoJson templates are pre-processed by the compiler
fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0; fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
char val[10];
if ((dv.type == DeviceValueType::INT) && Helpers::hasValue(*(int8_t *)(dv.value_p))) { if ((dv.type == DeviceValueType::INT) && Helpers::hasValue(*(int8_t *)(dv.value_p))) {
obj["v"] = Helpers::transformNumFloat(*(int8_t *)(dv.value_p), dv.numeric_operator, fahrenheit); obj["v"] = serialized(Helpers::render_value(val, *(int8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
} else if ((dv.type == DeviceValueType::UINT) && Helpers::hasValue(*(uint8_t *)(dv.value_p))) { } else if ((dv.type == DeviceValueType::UINT) && Helpers::hasValue(*(uint8_t *)(dv.value_p))) {
obj["v"] = Helpers::transformNumFloat(*(uint8_t *)(dv.value_p), dv.numeric_operator, fahrenheit); obj["v"] = serialized(Helpers::render_value(val, *(uint8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
} else if ((dv.type == DeviceValueType::SHORT) && Helpers::hasValue(*(int16_t *)(dv.value_p))) { } else if ((dv.type == DeviceValueType::SHORT) && Helpers::hasValue(*(int16_t *)(dv.value_p))) {
obj["v"] = Helpers::transformNumFloat(*(int16_t *)(dv.value_p), dv.numeric_operator, fahrenheit); obj["v"] = serialized(Helpers::render_value(val, *(int16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
} else if ((dv.type == DeviceValueType::USHORT) && Helpers::hasValue(*(uint16_t *)(dv.value_p))) { } else if ((dv.type == DeviceValueType::USHORT) && Helpers::hasValue(*(uint16_t *)(dv.value_p))) {
obj["v"] = Helpers::transformNumFloat(*(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit); obj["v"] = serialized(Helpers::render_value(val, *(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
} else if ((dv.type == DeviceValueType::ULONG) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) { } else if ((dv.type == DeviceValueType::ULONG) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
obj["v"] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), dv.numeric_operator, fahrenheit); obj["v"] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
} else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) { } else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
obj["v"] = dv.numeric_operator ? (*(uint32_t *)(dv.value_p) / dv.numeric_operator) : *(uint32_t *)(dv.value_p); obj["v"] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
} else { } else {
obj["v"] = ""; // must have a value for sorting to work obj["v"] = ""; // must have a value for sorting to work
} }
@@ -901,40 +902,20 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) {
// handle Integers and Floats // handle Integers and Floats
else { else {
int8_t num_op = dv.numeric_operator; char val[10];
bool make_float;
if (num_op == 0) {
// no changes to number
make_float = false;
num_op = 1; // so it gets *1
} else if (num_op < 0) {
// negative numbers, convert to a positive multiplier
make_float = false;
num_op *= -1;
} else {
// has a divider, make it a float
make_float = true;
}
// always convert temperatures to floats with 1 decimal place
if ((dv.uom == DeviceValueUOM::DEGREES) || (dv.uom == DeviceValueUOM::DEGREES_R)) {
make_float = true;
}
if (dv.type == DeviceValueType::INT) { if (dv.type == DeviceValueType::INT) {
obj["v"] = make_float ? Helpers::transformNumFloat(*(int8_t *)(dv.value_p), num_op, fahrenheit) : *(int8_t *)(dv.value_p) * num_op; obj["v"] = serialized(Helpers::render_value(val, *(int8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
} else if (dv.type == DeviceValueType::UINT) { } else if (dv.type == DeviceValueType::UINT) {
obj["v"] = make_float ? Helpers::transformNumFloat(*(uint8_t *)(dv.value_p), num_op, fahrenheit) : *(uint8_t *)(dv.value_p) * num_op; obj["v"] = serialized(Helpers::render_value(val, *(uint8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
} else if (dv.type == DeviceValueType::SHORT) { } else if (dv.type == DeviceValueType::SHORT) {
obj["v"] = make_float ? Helpers::transformNumFloat(*(int16_t *)(dv.value_p), num_op, fahrenheit) : *(int16_t *)(dv.value_p) * num_op; obj["v"] = serialized(Helpers::render_value(val, *(int16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
} else if (dv.type == DeviceValueType::USHORT) { } else if (dv.type == DeviceValueType::USHORT) {
obj["v"] = make_float ? Helpers::transformNumFloat(*(uint16_t *)(dv.value_p), num_op, fahrenheit) : *(uint16_t *)(dv.value_p) * num_op; obj["v"] = serialized(Helpers::render_value(val, *(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
} else if (dv.type == DeviceValueType::ULONG) { } else if (dv.type == DeviceValueType::ULONG) {
obj["v"] = make_float ? Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), num_op) : *(uint32_t *)(dv.value_p) * num_op; obj["v"] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
} else if (dv.type == DeviceValueType::TIME) { } else if (dv.type == DeviceValueType::TIME) {
// sometimes we need to divide by 60 // sometimes we need to divide by 60
obj["v"] = (num_op == DeviceValueNumOp::DV_NUMOP_DIV60) ? (uint32_t)Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), num_op) obj["v"] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
: *(uint32_t *)(dv.value_p);
} }
} }
} }
@@ -1095,8 +1076,6 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
// search device value with this tag // search device value with this tag
for (auto & dv : devicevalues_) { for (auto & dv : devicevalues_) {
if (strcmp(command_s, Helpers::toLower(read_flash_string(dv.short_name)).c_str()) == 0 && (tag <= 0 || tag == dv.tag)) { if (strcmp(command_s, Helpers::toLower(read_flash_string(dv.short_name)).c_str()) == 0 && (tag <= 0 || tag == dv.tag)) {
int8_t num_op = dv.numeric_operator;
uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0; uint8_t fahrenheit = !EMSESP::system_.fahrenheit() ? 0 : (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : 0;
const char * type = "type"; const char * type = "type";
@@ -1117,6 +1096,7 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
json["circuit"] = tag_to_mqtt(dv.tag); json["circuit"] = tag_to_mqtt(dv.tag);
} }
char val[10];
switch (dv.type) { switch (dv.type) {
case DeviceValueType::ENUM: { case DeviceValueType::ENUM: {
if (*(uint8_t *)(dv.value_p) < dv.options_size) { if (*(uint8_t *)(dv.value_p) < dv.options_size) {
@@ -1136,35 +1116,35 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
case DeviceValueType::USHORT: case DeviceValueType::USHORT:
if (Helpers::hasValue(*(uint16_t *)(dv.value_p))) { if (Helpers::hasValue(*(uint16_t *)(dv.value_p))) {
json[value] = Helpers::transformNumFloat(*(uint16_t *)(dv.value_p), num_op, fahrenheit); json[value] = serialized(Helpers::render_value(val, *(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
} }
json[type] = F_(number); json[type] = F_(number);
break; break;
case DeviceValueType::UINT: case DeviceValueType::UINT:
if (Helpers::hasValue(*(uint8_t *)(dv.value_p))) { if (Helpers::hasValue(*(uint8_t *)(dv.value_p))) {
json[value] = Helpers::transformNumFloat(*(uint8_t *)(dv.value_p), num_op, fahrenheit); json[value] = serialized(Helpers::render_value(val, *(uint8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
} }
json[type] = F_(number); json[type] = F_(number);
break; break;
case DeviceValueType::SHORT: case DeviceValueType::SHORT:
if (Helpers::hasValue(*(int16_t *)(dv.value_p))) { if (Helpers::hasValue(*(int16_t *)(dv.value_p))) {
json[value] = Helpers::transformNumFloat(*(int16_t *)(dv.value_p), num_op, fahrenheit); json[value] = serialized(Helpers::render_value(val, *(int16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
} }
json[type] = F_(number); json[type] = F_(number);
break; break;
case DeviceValueType::INT: case DeviceValueType::INT:
if (Helpers::hasValue(*(int8_t *)(dv.value_p))) { if (Helpers::hasValue(*(int8_t *)(dv.value_p))) {
json[value] = Helpers::transformNumFloat(*(int8_t *)(dv.value_p), num_op, fahrenheit); json[value] = serialized(Helpers::render_value(val, *(int8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
} }
json[type] = F_(number); json[type] = F_(number);
break; break;
case DeviceValueType::ULONG: case DeviceValueType::ULONG:
if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) { if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
json[value] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), num_op); json[value] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
} }
json[type] = F_(number); json[type] = F_(number);
break; break;
@@ -1186,7 +1166,7 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
case DeviceValueType::TIME: case DeviceValueType::TIME:
if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) { if (Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
json[value] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), num_op); json[value] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
} }
json[type] = F_(number); json[type] = F_(number);
break; break;
@@ -1368,64 +1348,22 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
: (dv.uom == DeviceValueUOM::DEGREES) ? 2 : (dv.uom == DeviceValueUOM::DEGREES) ? 2
: (dv.uom == DeviceValueUOM::DEGREES_R) ? 1 : (dv.uom == DeviceValueUOM::DEGREES_R) ? 1
: 0; : 0;
char val[10];
int8_t num_op = dv.numeric_operator;
bool make_float;
if (num_op == 0) {
// no changes to number
make_float = false;
num_op = 1; // so it gets *1
} else if (num_op < 0) {
// negative numbers, convert to a positive multiplier
make_float = false;
num_op *= -1;
} else {
// has a divider, make it a float
make_float = true;
}
// always convert temperatures to floats with 1 decimal place
if ((dv.uom == DeviceValueUOM::DEGREES) || (dv.uom == DeviceValueUOM::DEGREES_R)) {
make_float = true;
}
if (dv.type == DeviceValueType::INT) { if (dv.type == DeviceValueType::INT) {
if (make_float) { json[name] = serialized(Helpers::render_value(val, *(int8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
json[name] = Helpers::transformNumFloat(*(int8_t *)(dv.value_p), num_op, fahrenheit);
} else {
json[name] = *(int8_t *)(dv.value_p) * num_op;
}
} else if (dv.type == DeviceValueType::UINT) { } else if (dv.type == DeviceValueType::UINT) {
if (make_float) { json[name] = serialized(Helpers::render_value(val, *(uint8_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
json[name] = Helpers::transformNumFloat(*(uint8_t *)(dv.value_p), num_op, fahrenheit);
} else {
json[name] = *(uint8_t *)(dv.value_p) * num_op;
}
} else if (dv.type == DeviceValueType::SHORT) { } else if (dv.type == DeviceValueType::SHORT) {
if (make_float) { json[name] = serialized(Helpers::render_value(val, *(int16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
json[name] = Helpers::transformNumFloat(*(int16_t *)(dv.value_p), num_op, fahrenheit);
} else {
json[name] = *(int16_t *)(dv.value_p) * num_op;
}
} else if (dv.type == DeviceValueType::USHORT) { } else if (dv.type == DeviceValueType::USHORT) {
if (make_float) { json[name] = serialized(Helpers::render_value(val, *(uint16_t *)(dv.value_p), dv.numeric_operator, fahrenheit));
json[name] = Helpers::transformNumFloat(*(uint16_t *)(dv.value_p), num_op, fahrenheit);
} else {
json[name] = *(uint16_t *)(dv.value_p) * num_op;
}
} else if (dv.type == DeviceValueType::ULONG) { } else if (dv.type == DeviceValueType::ULONG) {
if (make_float) { json[name] = serialized(Helpers::render_value(val, *(uint32_t *)(dv.value_p), dv.numeric_operator));
json[name] = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), num_op, fahrenheit);
} else {
json[name] = *(uint32_t *)(dv.value_p) * num_op;
}
} else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) { } else if ((dv.type == DeviceValueType::TIME) && Helpers::hasValue(*(uint32_t *)(dv.value_p))) {
uint32_t time_value; uint32_t time_value = *(uint32_t *)(dv.value_p);
if (num_op == DeviceValueNumOp::DV_NUMOP_DIV60) { if (dv.numeric_operator == DeviceValueNumOp::DV_NUMOP_DIV60) {
// sometimes we need to divide by 60 // sometimes we need to divide by 60
time_value = Helpers::transformNumFloat(*(uint32_t *)(dv.value_p), num_op); time_value /= 60;
} else {
time_value = *(uint32_t *)(dv.value_p);
} }
if (output_target == OUTPUT_TARGET::API_VERBOSE || output_target == OUTPUT_TARGET::CONSOLE) { if (output_target == OUTPUT_TARGET::API_VERBOSE || output_target == OUTPUT_TARGET::CONSOLE) {
char time_s[60]; char time_s[60];