Skip to content

Commit

Permalink
fix max for ULONG values, save counters every hour, 3.6.1-dev0c
Browse files Browse the repository at this point in the history
  • Loading branch information
MichaelDvP committed Sep 4, 2023
1 parent ced63a6 commit b912779
Show file tree
Hide file tree
Showing 14 changed files with 103 additions and 77 deletions.
6 changes: 3 additions & 3 deletions lib/framework/RestartService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ RestartService::RestartService(AsyncWebServer * server, SecurityManager * securi
}

void RestartService::restart(AsyncWebServerRequest * request) {
emsesp::EMSESP::system_.store_boiler_energy();
emsesp::EMSESP::system_.store_nvs_values();
request->onDisconnect(RestartService::restartNow);
request->send(200);
}
Expand All @@ -22,7 +22,7 @@ void RestartService::partition(AsyncWebServerRequest * request) {
const esp_partition_t * factory_partition = esp_partition_find_first(ESP_PARTITION_TYPE_APP, ESP_PARTITION_SUBTYPE_APP_FACTORY, NULL);
if (factory_partition) {
esp_ota_set_boot_partition(factory_partition);
emsesp::EMSESP::system_.store_boiler_energy();
emsesp::EMSESP::system_.store_nvs_values();
request->onDisconnect(RestartService::restartNow);
request->send(200);
return;
Expand All @@ -39,7 +39,7 @@ void RestartService::partition(AsyncWebServerRequest * request) {
return;
}
esp_ota_set_boot_partition(ota_partition);
emsesp::EMSESP::system_.store_boiler_energy();
emsesp::EMSESP::system_.store_nvs_values();
request->onDisconnect(RestartService::restartNow);
request->send(200);
}
4 changes: 2 additions & 2 deletions lib/framework/UploadFileService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) {
// did we complete uploading a json file?
if (request->_tempFile) {
request->_tempFile.close(); // close the file handle as the upload is now done
emsesp::EMSESP::system_.store_boiler_energy();
emsesp::EMSESP::system_.store_nvs_values();
request->onDisconnect(RestartService::restartNow);
AsyncWebServerResponse * response = request->beginResponse(200);
request->send(response);
Expand All @@ -124,7 +124,7 @@ void UploadFileService::uploadComplete(AsyncWebServerRequest * request) {
// check if it was a firmware upgrade
// if no error, send the success response as a JSON
if (is_firmware && !request->_tempObject) {
emsesp::EMSESP::system_.store_boiler_energy();
emsesp::EMSESP::system_.store_nvs_values();
request->onDisconnect(RestartService::restartNow);
AsyncWebServerResponse * response = request->beginResponse(200);
request->send(response);
Expand Down
23 changes: 21 additions & 2 deletions src/analogsensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,8 +277,8 @@ void AnalogSensor::measure() {
} else if (!sensor.poll_) { // falling edge
if (sensor.type() == AnalogType::COUNTER) {
sensor.set_value(old_value + sensor.factor());
EMSESP::nvs_.putDouble(sensor.name().c_str(), sensor.value());
} else if (sensor.type() == AnalogType::RATE) { // dafault uom: Hz (1/sec) with factor 1
// EMSESP::nvs_.putDouble(sensor.name().c_str(), sensor.value());
} else if (sensor.type() == AnalogType::RATE) { // default uom: Hz (1/sec) with factor 1
sensor.set_value(sensor.factor() * 1000 / (sensor.polltime_ - sensor.last_polltime_));
} else if (sensor.type() == AnalogType::TIMER) { // default seconds with factor 1
sensor.set_value(sensor.factor() * (sensor.polltime_ - sensor.last_polltime_) / 1000);
Expand All @@ -294,6 +294,25 @@ void AnalogSensor::measure() {
}
}
}
// store counter-values only every hour to reduce flash wear
static uint8_t lastSaveHour = 0;
time_t now = time(nullptr);
tm * tm_ = localtime(&now);
if (tm_->tm_hour != lastSaveHour) {
lastSaveHour = tm_->tm_hour;
store_counters();
}
}

// store counters to NVS, called every hour, on restart and update
void AnalogSensor::store_counters() {
for (auto & sensor : sensors_) {
if (sensor.type() == AnalogType::COUNTER) {
if (sensor.value() != EMSESP::nvs_.getDouble(sensor.name().c_str())) {
EMSESP::nvs_.putDouble(sensor.name().c_str(), sensor.value());
}
}
}
}

void AnalogSensor::loop() {
Expand Down
1 change: 1 addition & 0 deletions src/analogsensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ class AnalogSensor {

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

#if defined(EMSESP_TEST)
void test();
Expand Down
77 changes: 41 additions & 36 deletions src/devices/boiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -850,18 +850,30 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
EMSESP::send_read_request(0x1C, device_id); // read maintenance status on start (only published on change)
EMSESP::send_read_request(0xC2, device_id); // read last errorcode on start (only published on errors)

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

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

nrgHeatF_ = EMSESP::nvs_.getDouble(FL_(nrgHeat)[0], 0);
nrgWwF_ = EMSESP::nvs_.getDouble(FL_(nrgWw)[0], 0);
nomPower_ = EMSESP::nvs_.getUChar(FL_(nomPower)[0], 0);
if (nrgHeatF_ < 0 || nrgHeatF_ >= EMS_VALUE_ULONG_NOTSET) {
nrgHeatF_ = 0;
}
if (nrgWwF_ < 0 || nrgWwF_ >= EMS_VALUE_ULONG_NOTSET) {
nrgWwF_ = 0;
}
if (nomPower_ == EMS_VALUE_UINT_NOTSET) {
nomPower_ = 0;
}
store_energy();
// update/publish the values
has_update(nrgHeat_, (uint32_t)nrgHeatF_);
has_update(nrgWw_, (uint32_t)nrgWwF_);
has_update(&nomPower_);
}
}

Expand Down Expand Up @@ -927,13 +939,7 @@ void Boiler::check_active() {
static uint8_t heatBurnPow = 0;
static uint8_t wwBurnPow = 0;
static uint8_t lastSaveHour = 0;
if (nrgHeat_ > (uint32_t)nrgHeatF_) {
nrgHeatF_ = nrgHeat_;
}
if (nrgWw_ > (uint32_t)nrgWwF_) {
nrgWwF_ = nrgWw_;
}
// 0.01 Wh = 0.01 Ws / 3600 = (% * kW * ms) / 3600
// resolution needed: 0.01 Wh = 0.01 Ws / 3600 = (% * kW * ms) / 3600
nrgHeatF_ += (double_t)(((uint32_t)heatBurnPow * nomPower_ * (uuid::get_uptime() - powLastReadTime_)) / 3600) / 100000UL;
nrgWwF_ += (double_t)(((uint32_t)wwBurnPow * nomPower_ * (uuid::get_uptime() - powLastReadTime_)) / 3600) / 100000UL;
has_update(nrgHeat_, (uint32_t)(nrgHeatF_));
Expand Down Expand Up @@ -962,19 +968,10 @@ void Boiler::process_UBAFactory(std::shared_ptr<const Telegram> telegram) {
if (!telegram->read_value(nomPower, 4)) {
return;
}
if (nomPower == 0 || nomPower == 255) {
nomPower = EMSESP::nvs_.getUChar(FL_(nomPower)[0], 0);
}
if (nomPower != nomPower_ || nomPower == 255) {
if (nomPower == 255) {
nomPower_ = nomPower = 0;
store_energy();
has_update(&nomPower_);
}
if (nomPower > 0) {
has_update(nomPower_, nomPower);
toggle_fetch(telegram->type_id, false); // only read once
// LOG_DEBUG("nominal power set to %d", nomPower_);
}
toggle_fetch(telegram->type_id, false); // only read once
}

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

// energy counters. Setting an invalid value does not update, but trigger a store.
bool Boiler::set_nrgHeat(const char * value, const int8_t id) {
int v;
if (Helpers::value2number(value, v)) {
nrgHeatF_ = nrgHeat_ = v;
store_energy();
return true;
if (!Helpers::value2number(value, v)) {
return false;
}
return false;
if (v >= 0 && v < EMS_VALUE_ULONG_NOTSET) {
nrgHeatF_ = v;
has_update(nrgHeat_, (uint32_t)nrgHeatF_);
}
store_energy();
return true;
}

bool Boiler::set_nrgWw(const char * value, const int8_t id) {
int v;
if (Helpers::value2number(value, v)) {
nrgWwF_ = nrgWw_ = v;
store_energy();
return true;
if (!Helpers::value2number(value, v)) {
return false;
}
return false;
if (v >= 0 && v < EMS_VALUE_ULONG_NOTSET) {
nrgWwF_ = v;
has_update(nrgWw_, (uint32_t)nrgWwF_);
}
store_energy();
return true;
}

bool Boiler::set_nomPower(const char * value, const int8_t id) {
int v;
if (Helpers::value2number(value, v)) {
nomPower_ = v > 0 ? v : nomPower_;
store_energy();
has_update(&nomPower_);
return true;
if (!Helpers::value2number(value, v)) {
return false;
}
return false;
if (v > 0 && v < EMS_VALUE_UINT_NOTSET) {
has_update(nomPower_, (uint8_t)v);
}
store_energy();
return true;
}

} // namespace emsesp
24 changes: 12 additions & 12 deletions src/emsdevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ void EMSdevice::add_device_value(uint8_t tag, // to b
uint8_t uom, // unit of measure from DeviceValueUOM
const cmd_function_p f, // command function pointer
int16_t min, // min allowed value
uint16_t max // max allowed value
uint32_t max // max allowed value
) {
// initialize the device value depending on it's type
// ignoring DeviceValueType::CMD and DeviceValueType::TIME
Expand Down Expand Up @@ -605,7 +605,7 @@ void EMSdevice::register_device_value(uint8_t tag,
uint8_t uom,
const cmd_function_p f,
int16_t min,
uint16_t max) {
uint32_t max) {
// create a multi-list from the options
add_device_value(tag, value_p, type, nullptr, options_single, 0, name, uom, f, min, max);
};
Expand All @@ -628,7 +628,7 @@ void EMSdevice::register_device_value(uint8_t tag,
uint8_t uom,
const cmd_function_p f,
int16_t min,
uint16_t max) {
uint32_t max) {
add_device_value(tag, value_p, type, nullptr, nullptr, numeric_operator, name, uom, f, min, max);
}

Expand All @@ -645,7 +645,7 @@ void EMSdevice::register_device_value(uint8_t tag,
uint8_t uom,
const cmd_function_p f,
int16_t min,
uint16_t max) {
uint32_t max) {
add_device_value(tag, value_p, type, nullptr, nullptr, 0, name, uom, f, min, max);
};

Expand All @@ -660,7 +660,7 @@ void EMSdevice::register_device_value(uint8_t tag,
uint8_t uom,
const cmd_function_p f,
int16_t min,
uint16_t max) {
uint32_t max) {
add_device_value(tag, value_p, type, options, nullptr, 0, name, uom, f, min, max);
}

Expand Down Expand Up @@ -931,15 +931,15 @@ void EMSdevice::generate_values_web(JsonObject & output) {
}
// handle INTs
// add min and max values and steps, as integer values
else if (dv.type != DeviceValueType::ULONG) {
else {
if (dv.numeric_operator > 0) {
obj["s"] = (float)1 / dv.numeric_operator;
} else if (dv.numeric_operator < 0) {
obj["s"] = (float)(-1) * dv.numeric_operator;
}

int16_t dv_set_min;
uint16_t dv_set_max;
uint32_t dv_set_max;
if (dv.get_min_max(dv_set_min, dv_set_max)) {
obj["m"] = dv_set_min;
obj["x"] = dv_set_max;
Expand Down Expand Up @@ -1030,10 +1030,10 @@ 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

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

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

// min/max range
int16_t dv_set_min;
uint16_t dv_set_max;
uint32_t dv_set_max;
if (dv.get_min_max(dv_set_min, dv_set_max)) {
Serial.print(" (>=");
Serial.print(dv_set_min);
Expand Down Expand Up @@ -1473,7 +1473,7 @@ bool EMSdevice::get_value_info(JsonObject & output, const char * cmd, const int8
// set the min and max only for commands
if (dv.has_cmd) {
int16_t dv_set_min;
uint16_t dv_set_max;
uint32_t dv_set_max;
if (dv.get_min_max(dv_set_min, dv_set_max)) {
json["min"] = dv_set_min;
json["max"] = dv_set_max;
Expand Down
12 changes: 6 additions & 6 deletions src/emsdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ class EMSdevice {
void list_device_entries(JsonObject & output) const;
void add_handlers_ignored(const uint16_t handler);

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

Expand All @@ -232,7 +232,7 @@ class EMSdevice {
uint8_t uom,
const cmd_function_p f,
int16_t min,
uint16_t max);
uint32_t max);

void register_device_value(uint8_t tag,
void * value_p,
Expand All @@ -242,7 +242,7 @@ class EMSdevice {
uint8_t uom,
const cmd_function_p f,
int16_t min,
uint16_t max);
uint32_t max);

void
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);
Expand All @@ -265,7 +265,7 @@ class EMSdevice {
uint8_t uom,
const cmd_function_p f,
int16_t min,
uint16_t max);
uint32_t max);

// single list of options
void register_device_value(uint8_t tag,
Expand All @@ -285,14 +285,14 @@ class EMSdevice {
uint8_t uom,
const cmd_function_p f,
int16_t min,
uint16_t max);
uint32_t max);

// no options, optional function f
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);

// no options, with min/max
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, int16_t min, uint16_t max);
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);

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;
void write_command(const uint16_t type_id, const uint8_t offset, const uint8_t value, const uint16_t validate_typeid) const;
Expand Down
Loading

0 comments on commit b912779

Please sign in to comment.