Skip to content

Commit b912779

Browse files
committed
fix max for ULONG values, save counters every hour, 3.6.1-dev0c
1 parent ced63a6 commit b912779

14 files changed

+103
-77
lines changed

lib/framework/RestartService.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ RestartService::RestartService(AsyncWebServer * server, SecurityManager * securi
1313
}
1414

1515
void RestartService::restart(AsyncWebServerRequest * request) {
16-
emsesp::EMSESP::system_.store_boiler_energy();
16+
emsesp::EMSESP::system_.store_nvs_values();
1717
request->onDisconnect(RestartService::restartNow);
1818
request->send(200);
1919
}
@@ -22,7 +22,7 @@ void RestartService::partition(AsyncWebServerRequest * request) {
2222
const esp_partition_t * factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
2323
if (factory_partition) {
2424
esp_ota_set_boot_partition(factory_partition);
25-
emsesp::EMSESP::system_.store_boiler_energy();
25+
emsesp::EMSESP::system_.store_nvs_values();
2626
request->onDisconnect(RestartService::restartNow);
2727
request->send(200);
2828
return;
@@ -39,7 +39,7 @@ void RestartService::partition(AsyncWebServerRequest * request) {
3939
return;
4040
}
4141
esp_ota_set_boot_partition(ota_partition);
42-
emsesp::EMSESP::system_.store_boiler_energy();
42+
emsesp::EMSESP::system_.store_nvs_values();
4343
request->onDisconnect(RestartService::restartNow);
4444
request->send(200);
4545
}

lib/framework/UploadFileService.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) {
114114
// did we complete uploading a json file?
115115
if (request->_tempFile) {
116116
request->_tempFile.close(); // close the file handle as the upload is now done
117-
emsesp::EMSESP::system_.store_boiler_energy();
117+
emsesp::EMSESP::system_.store_nvs_values();
118118
request->onDisconnect(RestartService::restartNow);
119119
AsyncWebServerResponse * response = request->beginResponse(200);
120120
request->send(response);
@@ -124,7 +124,7 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) {
124124
// check if it was a firmware upgrade
125125
// if no error, send the success response as a JSON
126126
if (is_firmware && !request->_tempObject) {
127-
emsesp::EMSESP::system_.store_boiler_energy();
127+
emsesp::EMSESP::system_.store_nvs_values();
128128
request->onDisconnect(RestartService::restartNow);
129129
AsyncWebServerResponse * response = request->beginResponse(200);
130130
request->send(response);

src/analogsensor.cpp

+21-2
Original file line numberDiff line numberDiff line change
@@ -277,8 +277,8 @@ void AnalogSensor::measure() {
277277
} else if (!sensor.poll_) { // falling edge
278278
if (sensor.type() == AnalogType::COUNTER) {
279279
sensor.set_value(old_value + sensor.factor());
280-
EMSESP::nvs_.putDouble(sensor.name().c_str(), sensor.value());
281-
} else if (sensor.type() == AnalogType::RATE) { // dafault uom: Hz (1/sec) with factor 1
280+
// EMSESP::nvs_.putDouble(sensor.name().c_str(), sensor.value());
281+
} else if (sensor.type() == AnalogType::RATE) { // default uom: Hz (1/sec) with factor 1
282282
sensor.set_value(sensor.factor() * 1000 / (sensor.polltime_ - sensor.last_polltime_));
283283
} else if (sensor.type() == AnalogType::TIMER) { // default seconds with factor 1
284284
sensor.set_value(sensor.factor() * (sensor.polltime_ - sensor.last_polltime_) / 1000);
@@ -294,6 +294,25 @@ void AnalogSensor::measure() {
294294
}
295295
}
296296
}
297+
// store counter-values only every hour to reduce flash wear
298+
static uint8_t lastSaveHour = 0;
299+
time_t now = time(nullptr);
300+
tm * tm_ = localtime(&now);
301+
if (tm_->tm_hour != lastSaveHour) {
302+
lastSaveHour = tm_->tm_hour;
303+
store_counters();
304+
}
305+
}
306+
307+
// store counters to NVS, called every hour, on restart and update
308+
void AnalogSensor::store_counters() {
309+
for (auto & sensor : sensors_) {
310+
if (sensor.type() == AnalogType::COUNTER) {
311+
if (sensor.value() != EMSESP::nvs_.getDouble(sensor.name().c_str())) {
312+
EMSESP::nvs_.putDouble(sensor.name().c_str(), sensor.value());
313+
}
314+
}
315+
}
297316
}
298317

299318
void AnalogSensor::loop() {

src/analogsensor.h

+1
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ class AnalogSensor {
158158

159159
bool update(uint8_t gpio, const std::string & name, double offset, double factor, uint8_t uom, int8_t type, bool deleted = false);
160160
bool get_value_info(JsonObject & output, const char * cmd, const int8_t id) const;
161+
void store_counters();
161162

162163
#if defined(EMSESP_TEST)
163164
void test();

src/devices/boiler.cpp

+41-36
Original file line numberDiff line numberDiff line change
@@ -850,18 +850,30 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
850850
EMSESP::send_read_request(0x1C, device_id); // read maintenance status on start (only published on change)
851851
EMSESP::send_read_request(0xC2, device_id); // read last errorcode on start (only published on errors)
852852

853-
register_telegram_type(0x04, "UBAFactory", true, MAKE_PF_CB(process_UBAFactory));
854-
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &nomPower_, DeviceValueType::UINT, FL_(nomPower), DeviceValueUOM::KW, MAKE_CF_CB(set_nomPower));
855853

856854
if (model() != EMS_DEVICE_FLAG_HEATPUMP) {
855+
register_telegram_type(0x04, "UBAFactory", true, MAKE_PF_CB(process_UBAFactory));
856+
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &nomPower_, DeviceValueType::UINT, FL_(nomPower), DeviceValueUOM::KW, MAKE_CF_CB(set_nomPower));
857857
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &nrgHeat_, DeviceValueType::ULONG, FL_(nrgHeat), DeviceValueUOM::KWH, MAKE_CF_CB(set_nrgHeat));
858858
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &nrgWw_, DeviceValueType::ULONG, FL_(nrgWw), DeviceValueUOM::KWH, MAKE_CF_CB(set_nrgWw));
859859

860860
nrgHeatF_ = EMSESP::nvs_.getDouble(FL_(nrgHeat)[0], 0);
861861
nrgWwF_ = EMSESP::nvs_.getDouble(FL_(nrgWw)[0], 0);
862+
nomPower_ = EMSESP::nvs_.getUChar(FL_(nomPower)[0], 0);
863+
if (nrgHeatF_ < 0 || nrgHeatF_ >= EMS_VALUE_ULONG_NOTSET) {
864+
nrgHeatF_ = 0;
865+
}
866+
if (nrgWwF_ < 0 || nrgWwF_ >= EMS_VALUE_ULONG_NOTSET) {
867+
nrgWwF_ = 0;
868+
}
869+
if (nomPower_ == EMS_VALUE_UINT_NOTSET) {
870+
nomPower_ = 0;
871+
}
872+
store_energy();
862873
// update/publish the values
863874
has_update(nrgHeat_, (uint32_t)nrgHeatF_);
864875
has_update(nrgWw_, (uint32_t)nrgWwF_);
876+
has_update(&nomPower_);
865877
}
866878
}
867879

@@ -927,13 +939,7 @@ void Boiler::check_active() {
927939
static uint8_t heatBurnPow = 0;
928940
static uint8_t wwBurnPow = 0;
929941
static uint8_t lastSaveHour = 0;
930-
if (nrgHeat_ > (uint32_t)nrgHeatF_) {
931-
nrgHeatF_ = nrgHeat_;
932-
}
933-
if (nrgWw_ > (uint32_t)nrgWwF_) {
934-
nrgWwF_ = nrgWw_;
935-
}
936-
// 0.01 Wh = 0.01 Ws / 3600 = (% * kW * ms) / 3600
942+
// resolution needed: 0.01 Wh = 0.01 Ws / 3600 = (% * kW * ms) / 3600
937943
nrgHeatF_ += (double_t)(((uint32_t)heatBurnPow * nomPower_ * (uuid::get_uptime() - powLastReadTime_)) / 3600) / 100000UL;
938944
nrgWwF_ += (double_t)(((uint32_t)wwBurnPow * nomPower_ * (uuid::get_uptime() - powLastReadTime_)) / 3600) / 100000UL;
939945
has_update(nrgHeat_, (uint32_t)(nrgHeatF_));
@@ -962,19 +968,10 @@ void Boiler::process_UBAFactory(std::shared_ptr<const Telegram> telegram) {
962968
if (!telegram->read_value(nomPower, 4)) {
963969
return;
964970
}
965-
if (nomPower == 0 || nomPower == 255) {
966-
nomPower = EMSESP::nvs_.getUChar(FL_(nomPower)[0], 0);
967-
}
968-
if (nomPower != nomPower_ || nomPower == 255) {
969-
if (nomPower == 255) {
970-
nomPower_ = nomPower = 0;
971-
store_energy();
972-
has_update(&nomPower_);
973-
}
971+
if (nomPower > 0) {
974972
has_update(nomPower_, nomPower);
975-
toggle_fetch(telegram->type_id, false); // only read once
976-
// LOG_DEBUG("nominal power set to %d", nomPower_);
977973
}
974+
toggle_fetch(telegram->type_id, false); // only read once
978975
}
979976

980977
// 0x18
@@ -2723,35 +2720,43 @@ bool Boiler::set_wwAltOpPrio(const char * value, const int8_t id) {
27232720
return false;
27242721
}
27252722

2723+
// energy counters. Setting an invalid value does not update, but trigger a store.
27262724
bool Boiler::set_nrgHeat(const char * value, const int8_t id) {
27272725
int v;
2728-
if (Helpers::value2number(value, v)) {
2729-
nrgHeatF_ = nrgHeat_ = v;
2730-
store_energy();
2731-
return true;
2726+
if (!Helpers::value2number(value, v)) {
2727+
return false;
27322728
}
2733-
return false;
2729+
if (v >= 0 && v < EMS_VALUE_ULONG_NOTSET) {
2730+
nrgHeatF_ = v;
2731+
has_update(nrgHeat_, (uint32_t)nrgHeatF_);
2732+
}
2733+
store_energy();
2734+
return true;
27342735
}
27352736

27362737
bool Boiler::set_nrgWw(const char * value, const int8_t id) {
27372738
int v;
2738-
if (Helpers::value2number(value, v)) {
2739-
nrgWwF_ = nrgWw_ = v;
2740-
store_energy();
2741-
return true;
2739+
if (!Helpers::value2number(value, v)) {
2740+
return false;
27422741
}
2743-
return false;
2742+
if (v >= 0 && v < EMS_VALUE_ULONG_NOTSET) {
2743+
nrgWwF_ = v;
2744+
has_update(nrgWw_, (uint32_t)nrgWwF_);
2745+
}
2746+
store_energy();
2747+
return true;
27442748
}
27452749

27462750
bool Boiler::set_nomPower(const char * value, const int8_t id) {
27472751
int v;
2748-
if (Helpers::value2number(value, v)) {
2749-
nomPower_ = v > 0 ? v : nomPower_;
2750-
store_energy();
2751-
has_update(&nomPower_);
2752-
return true;
2752+
if (!Helpers::value2number(value, v)) {
2753+
return false;
27532754
}
2754-
return false;
2755+
if (v > 0 && v < EMS_VALUE_UINT_NOTSET) {
2756+
has_update(nomPower_, (uint8_t)v);
2757+
}
2758+
store_energy();
2759+
return true;
27552760
}
27562761

27572762
} // namespace emsesp

src/emsdevice.cpp

+12-12
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ void EMSdevice::add_device_value(uint8_t tag, // to b
488488
uint8_t uom, // unit of measure from DeviceValueUOM
489489
const cmd_function_p f, // command function pointer
490490
int16_t min, // min allowed value
491-
uint16_t max // max allowed value
491+
uint32_t max // max allowed value
492492
) {
493493
// initialize the device value depending on it's type
494494
// ignoring DeviceValueType::CMD and DeviceValueType::TIME
@@ -605,7 +605,7 @@ void EMSdevice::register_device_value(uint8_t tag,
605605
uint8_t uom,
606606
const cmd_function_p f,
607607
int16_t min,
608-
uint16_t max) {
608+
uint32_t max) {
609609
// create a multi-list from the options
610610
add_device_value(tag, value_p, type, nullptr, options_single, 0, name, uom, f, min, max);
611611
};
@@ -628,7 +628,7 @@ void EMSdevice::register_device_value(uint8_t tag,
628628
uint8_t uom,
629629
const cmd_function_p f,
630630
int16_t min,
631-
uint16_t max) {
631+
uint32_t max) {
632632
add_device_value(tag, value_p, type, nullptr, nullptr, numeric_operator, name, uom, f, min, max);
633633
}
634634

@@ -645,7 +645,7 @@ void EMSdevice::register_device_value(uint8_t tag,
645645
uint8_t uom,
646646
const cmd_function_p f,
647647
int16_t min,
648-
uint16_t max) {
648+
uint32_t max) {
649649
add_device_value(tag, value_p, type, nullptr, nullptr, 0, name, uom, f, min, max);
650650
};
651651

@@ -660,7 +660,7 @@ void EMSdevice::register_device_value(uint8_t tag,
660660
uint8_t uom,
661661
const cmd_function_p f,
662662
int16_t min,
663-
uint16_t max) {
663+
uint32_t max) {
664664
add_device_value(tag, value_p, type, options, nullptr, 0, name, uom, f, min, max);
665665
}
666666

@@ -931,15 +931,15 @@ void EMSdevice::generate_values_web(JsonObject & output) {
931931
}
932932
// handle INTs
933933
// add min and max values and steps, as integer values
934-
else if (dv.type != DeviceValueType::ULONG) {
934+
else {
935935
if (dv.numeric_operator > 0) {
936936
obj["s"] = (float)1 / dv.numeric_operator;
937937
} else if (dv.numeric_operator < 0) {
938938
obj["s"] = (float)(-1) * dv.numeric_operator;
939939
}
940940

941941
int16_t dv_set_min;
942-
uint16_t dv_set_max;
942+
uint32_t dv_set_max;
943943
if (dv.get_min_max(dv_set_min, dv_set_max)) {
944944
obj["m"] = dv_set_min;
945945
obj["x"] = dv_set_max;
@@ -1030,10 +1030,10 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) {
10301030
obj["m"] = dv.state >> 4; // send back the mask state. We're only interested in the high nibble
10311031
obj["w"] = dv.has_cmd; // if writable
10321032

1033-
if (dv.has_cmd && dv.type != DeviceValueType::ULONG && (obj["v"].is<float>() || obj["v"].is<int>())) {
1033+
if (dv.has_cmd && (obj["v"].is<float>() || obj["v"].is<int>())) {
10341034
// set the min and max values if there are any and if entity has a value
10351035
int16_t dv_set_min;
1036-
uint16_t dv_set_max;
1036+
uint32_t dv_set_max;
10371037
if (dv.get_min_max(dv_set_min, dv_set_max)) {
10381038
obj["mi"] = dv_set_min;
10391039
obj["ma"] = dv_set_max;
@@ -1059,7 +1059,7 @@ void EMSdevice::generate_values_web_customization(JsonArray & output) {
10591059
});
10601060
}
10611061

1062-
void EMSdevice::set_climate_minmax(uint8_t tag, int16_t min, uint16_t max) {
1062+
void EMSdevice::set_climate_minmax(uint8_t tag, int16_t min, uint32_t max) {
10631063
for (auto & dv : devicevalues_) {
10641064
if (dv.tag == tag && (strcmp(dv.short_name, FL_(haclimate[0])) == 0)) {
10651065
if (dv.min != min || dv.max != max) {
@@ -1236,7 +1236,7 @@ void EMSdevice::dump_value_info() {
12361236

12371237
// min/max range
12381238
int16_t dv_set_min;
1239-
uint16_t dv_set_max;
1239+
uint32_t dv_set_max;
12401240
if (dv.get_min_max(dv_set_min, dv_set_max)) {
12411241
Serial.print(" (>=");
12421242
Serial.print(dv_set_min);
@@ -1473,7 +1473,7 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
14731473
// set the min and max only for commands
14741474
if (dv.has_cmd) {
14751475
int16_t dv_set_min;
1476-
uint16_t dv_set_max;
1476+
uint32_t dv_set_max;
14771477
if (dv.get_min_max(dv_set_min, dv_set_max)) {
14781478
json["min"] = dv_set_min;
14791479
json["max"] = dv_set_max;

src/emsdevice.h

+6-6
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ class EMSdevice {
206206
void list_device_entries(JsonObject & output) const;
207207
void add_handlers_ignored(const uint16_t handler);
208208

209-
void set_climate_minmax(uint8_t tag, int16_t min, uint16_t max);
209+
void set_climate_minmax(uint8_t tag, int16_t min, uint32_t max);
210210
void setCustomEntity(const std::string & entity_id);
211211
void getCustomEntities(std::vector<std::string> & entity_ids);
212212

@@ -232,7 +232,7 @@ class EMSdevice {
232232
uint8_t uom,
233233
const cmd_function_p f,
234234
int16_t min,
235-
uint16_t max);
235+
uint32_t max);
236236

237237
void register_device_value(uint8_t tag,
238238
void * value_p,
@@ -242,7 +242,7 @@ class EMSdevice {
242242
uint8_t uom,
243243
const cmd_function_p f,
244244
int16_t min,
245-
uint16_t max);
245+
uint32_t max);
246246

247247
void
248248
register_device_value(uint8_t tag, void * value_p, uint8_t type, const char * const ** options, const char * const * name, uint8_t uom, const cmd_function_p f);
@@ -265,7 +265,7 @@ class EMSdevice {
265265
uint8_t uom,
266266
const cmd_function_p f,
267267
int16_t min,
268-
uint16_t max);
268+
uint32_t max);
269269

270270
// single list of options
271271
void register_device_value(uint8_t tag,
@@ -285,14 +285,14 @@ class EMSdevice {
285285
uint8_t uom,
286286
const cmd_function_p f,
287287
int16_t min,
288-
uint16_t max);
288+
uint32_t max);
289289

290290
// no options, optional function f
291291
void register_device_value(uint8_t tag, void * value_p, uint8_t type, const char * const * name, uint8_t uom, const cmd_function_p f = nullptr);
292292

293293
// no options, with min/max
294294
void
295-
register_device_value(uint8_t tag, void * value_p, uint8_t type, const char * const * name, uint8_t uom, const cmd_function_p f, int16_t min, uint16_t max);
295+
register_device_value(uint8_t tag, void * value_p, uint8_t type, const char * const * name, uint8_t uom, const cmd_function_p f, int16_t min, uint32_t max);
296296

297297
void write_command(const uint16_t type_id, const uint8_t offset, uint8_t * message_data, const uint8_t message_length, const uint16_t validate_typeid) const;
298298
void write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid) const;

0 commit comments

Comments
 (0)