Improve MQTT (#2091)

* moved functions

* use hostname as default MQTT maintopic if parameter is not set

* use hostname as default MQTT client ID

* Only send Homassistant Discovery and Static Topics on the first connect. Retry in next round if any topic failed

* .

* add missing return code usage

* send maintopic/connection on every round like the system topics

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>
This commit is contained in:
CaCO3
2023-02-27 18:26:46 +01:00
committed by GitHub
parent c5b20f3680
commit a1a77ae5d9
7 changed files with 209 additions and 150 deletions

View File

@@ -37,7 +37,7 @@ void ClassFlowMQTT::SetInitialParameter(void)
topicUptime = ""; topicUptime = "";
topicFreeMem = ""; topicFreeMem = "";
clientname = "AIOTED-" + getMac(); clientname = wlan_config.hostname;
OldValue = ""; OldValue = "";
flowpostprocessing = NULL; flowpostprocessing = NULL;
@@ -166,7 +166,6 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
if (((toUpper(splitted[0]) == "TOPIC") || (toUpper(splitted[0]) == "MAINTOPIC")) && (splitted.size() > 1)) if (((toUpper(splitted[0]) == "TOPIC") || (toUpper(splitted[0]) == "MAINTOPIC")) && (splitted.size() > 1))
{ {
maintopic = splitted[1]; maintopic = splitted[1];
mqttServer_setMainTopic(maintopic);
} }
} }
@@ -175,6 +174,8 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
* How ever we need the interval parameter from the ClassFlowControll, but that only gets started later. * How ever we need the interval parameter from the ClassFlowControll, but that only gets started later.
* To work around this, we delay the start and trigger it from ClassFlowControll::ReadParameter() */ * To work around this, we delay the start and trigger it from ClassFlowControll::ReadParameter() */
mqttServer_setMainTopic(maintopic);
return true; return true;
} }
@@ -210,6 +211,7 @@ bool ClassFlowMQTT::Start(float AutoInterval)
bool ClassFlowMQTT::doFlow(string zwtime) bool ClassFlowMQTT::doFlow(string zwtime)
{ {
bool success;
std::string result; std::string result;
std::string resulterror = ""; std::string resulterror = "";
std::string resultraw = ""; std::string resultraw = "";
@@ -221,7 +223,7 @@ bool ClassFlowMQTT::doFlow(string zwtime)
string zw = ""; string zw = "";
string namenumber = ""; string namenumber = "";
publishSystemData(); success = publishSystemData();
if (flowpostprocessing && getMQTTisConnected()) if (flowpostprocessing && getMQTTisConnected())
{ {
@@ -247,13 +249,13 @@ bool ClassFlowMQTT::doFlow(string zwtime)
if (result.length() > 0) if (result.length() > 0)
MQTTPublish(namenumber + "value", result, SetRetainFlag); success |= MQTTPublish(namenumber + "value", result, SetRetainFlag);
if (resulterror.length() > 0) if (resulterror.length() > 0)
MQTTPublish(namenumber + "error", resulterror, SetRetainFlag); success |= MQTTPublish(namenumber + "error", resulterror, SetRetainFlag);
if (resultrate.length() > 0) { if (resultrate.length() > 0) {
MQTTPublish(namenumber + "rate", resultrate, SetRetainFlag); success |= MQTTPublish(namenumber + "rate", resultrate, SetRetainFlag);
std::string resultRatePerTimeUnit; std::string resultRatePerTimeUnit;
if (getTimeUnit() == "h") { // Need conversion to be per hour if (getTimeUnit() == "h") { // Need conversion to be per hour
@@ -262,22 +264,22 @@ bool ClassFlowMQTT::doFlow(string zwtime)
else { // Keep per minute else { // Keep per minute
resultRatePerTimeUnit = resultrate; resultRatePerTimeUnit = resultrate;
} }
MQTTPublish(namenumber + "rate_per_time_unit", resultRatePerTimeUnit, SetRetainFlag); success |= MQTTPublish(namenumber + "rate_per_time_unit", resultRatePerTimeUnit, SetRetainFlag);
} }
if (resultchangabs.length() > 0) { if (resultchangabs.length() > 0) {
MQTTPublish(namenumber + "changeabsolut", resultchangabs, SetRetainFlag); // Legacy API success |= MQTTPublish(namenumber + "changeabsolut", resultchangabs, SetRetainFlag); // Legacy API
MQTTPublish(namenumber + "rate_per_digitalization_round", resultchangabs, SetRetainFlag); success |= MQTTPublish(namenumber + "rate_per_digitalization_round", resultchangabs, SetRetainFlag);
} }
if (resultraw.length() > 0) if (resultraw.length() > 0)
MQTTPublish(namenumber + "raw", resultraw, SetRetainFlag); success |= MQTTPublish(namenumber + "raw", resultraw, SetRetainFlag);
if (resulttimestamp.length() > 0) if (resulttimestamp.length() > 0)
MQTTPublish(namenumber + "timestamp", resulttimestamp, SetRetainFlag); success |= MQTTPublish(namenumber + "timestamp", resulttimestamp, SetRetainFlag);
std::string json = flowpostprocessing->getJsonFromNumber(i, "\n"); std::string json = flowpostprocessing->getJsonFromNumber(i, "\n");
MQTTPublish(namenumber + "json", json, SetRetainFlag); success |= MQTTPublish(namenumber + "json", json, SetRetainFlag);
} }
} }
@@ -295,10 +297,14 @@ bool ClassFlowMQTT::doFlow(string zwtime)
// result = result + "\t" + zw; // result = result + "\t" + zw;
// } // }
// } // }
// MQTTPublish(topic, result, SetRetainFlag); // success |= MQTTPublish(topic, result, SetRetainFlag);
// } // }
OldValue = result; OldValue = result;
if (!success) {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "One or more MQTT topics failed to be published!");
}
return true; return true;
} }

View File

@@ -963,3 +963,34 @@ std::string UrlDecode(const std::string& value)
return result; return result;
} }
bool replaceString(std::string& s, std::string const& toReplace, std::string const& replaceWith) {
return replaceString(s, toReplace, replaceWith, true);
}
bool replaceString(std::string& s, std::string const& toReplace, std::string const& replaceWith, bool logIt) {
std::size_t pos = s.find(toReplace);
if (pos == std::string::npos) { // Not found
return false;
}
std::string old = s;
s.replace(pos, toReplace.length(), replaceWith);
if (logIt) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Migrated Configfile line '" + old + "' to '" + s + "'");
}
return true;
}
bool isInString(std::string& s, std::string const& toFind) {
std::size_t pos = s.find(toFind);
if (pos == std::string::npos) { // Not found
return false;
}
return true;
}

View File

@@ -95,4 +95,8 @@ const char* get404(void);
std::string UrlDecode(const std::string& value); std::string UrlDecode(const std::string& value);
bool replaceString(std::string& s, std::string const& toReplace, std::string const& replaceWith);
bool replaceString(std::string& s, std::string const& toReplace, std::string const& replaceWith, bool logIt);
bool isInString(std::string& s, std::string const& toFind);
#endif //HELPER_H #endif //HELPER_H

View File

@@ -326,8 +326,7 @@ bool mqtt_handler_flow_start(std::string _topic, char* _data, int _data_len) {
void MQTTconnected(){ void MQTTconnected(){
if (mqtt_connected) { if (mqtt_connected) {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Connected to broker"); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Connected to broker");
MQTTPublish(lwt_topic, lwt_connected, true); // Publish "connected" to maintopic/connection
if (connectFunktionMap != NULL) { if (connectFunktionMap != NULL) {
for(std::map<std::string, std::function<void()>>::iterator it = connectFunktionMap->begin(); it != connectFunktionMap->end(); ++it) { for(std::map<std::string, std::function<void()>>::iterator it = connectFunktionMap->begin(); it != connectFunktionMap->end(); ++it) {
it->second(); it->second();

View File

@@ -47,7 +47,7 @@ void mqttServer_setMeterType(std::string _meterType, std::string _valueUnit, std
rateUnit = _rateUnit; rateUnit = _rateUnit;
} }
void sendHomeAssistantDiscoveryTopic(std::string group, std::string field, bool sendHomeAssistantDiscoveryTopic(std::string group, std::string field,
std::string name, std::string icon, std::string unit, std::string deviceClass, std::string stateClass, std::string entityCategory) { std::string name, std::string icon, std::string unit, std::string deviceClass, std::string stateClass, std::string entityCategory) {
std::string version = std::string(libfive_git_version()); std::string version = std::string(libfive_git_version());
@@ -131,26 +131,29 @@ void sendHomeAssistantDiscoveryTopic(std::string group, std::string field,
"}" + "}" +
"}"; "}";
MQTTPublish(topicFull, payload, true); return MQTTPublish(topicFull, payload, true);
} }
void MQTThomeassistantDiscovery() { bool MQTThomeassistantDiscovery() {
if (!getMQTTisConnected()) bool allSendsSuccessed = false;
return;
if (!getMQTTisConnected()) {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Unable to send Homeassistant Discovery Topics, we are not connected to the MQTT broker!");
return false;
}
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "MQTT - Sending Homeassistant Discovery Topics (Meter Type: " + meterType + ", Value Unit: " + valueUnit + " , Rate Unit: " + rateUnit + ")..."); LogFile.WriteToFile(ESP_LOG_INFO, TAG, "MQTT - Sending Homeassistant Discovery Topics (Meter Type: " + meterType + ", Value Unit: " + valueUnit + " , Rate Unit: " + rateUnit + ")...");
// Group | Field | User Friendly Name | Icon | Unit | Device Class | State Class | Entity Category // Group | Field | User Friendly Name | Icon | Unit | Device Class | State Class | Entity Category
sendHomeAssistantDiscoveryTopic("", "uptime", "Uptime", "clock-time-eight-outline", "s", "", "", "diagnostic"); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "uptime", "Uptime", "clock-time-eight-outline", "s", "", "", "diagnostic");
sendHomeAssistantDiscoveryTopic("", "MAC", "MAC Address", "network-outline", "", "", "", "diagnostic"); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "MAC", "MAC Address", "network-outline", "", "", "", "diagnostic");
sendHomeAssistantDiscoveryTopic("", "hostname", "Hostname", "network-outline", "", "", "", "diagnostic"); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "hostname", "Hostname", "network-outline", "", "", "", "diagnostic");
sendHomeAssistantDiscoveryTopic("", "freeMem", "Free Memory", "memory", "B", "", "measurement", "diagnostic"); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "freeMem", "Free Memory", "memory", "B", "", "measurement", "diagnostic");
sendHomeAssistantDiscoveryTopic("", "wifiRSSI", "Wi-Fi RSSI", "wifi", "dBm", "signal_strength", "", "diagnostic"); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "wifiRSSI", "Wi-Fi RSSI", "wifi", "dBm", "signal_strength", "", "diagnostic");
sendHomeAssistantDiscoveryTopic("", "CPUtemp", "CPU Temperature", "thermometer", "°C", "temperature", "measurement", "diagnostic"); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "CPUtemp", "CPU Temperature", "thermometer", "°C", "temperature", "measurement", "diagnostic");
sendHomeAssistantDiscoveryTopic("", "interval", "Interval", "clock-time-eight-outline", "min", "" , "measurement", "diagnostic"); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "interval", "Interval", "clock-time-eight-outline", "min", "" , "measurement", "diagnostic");
sendHomeAssistantDiscoveryTopic("", "IP", "IP", "network-outline", "", "", "", "diagnostic"); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "IP", "IP", "network-outline", "", "", "", "diagnostic");
sendHomeAssistantDiscoveryTopic("", "status", "Status", "list-status", "", "", "", "diagnostic"); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "status", "Status", "list-status", "", "", "", "diagnostic");
for (int i = 0; i < (*NUMBERS).size(); ++i) { for (int i = 0; i < (*NUMBERS).size(); ++i) {
@@ -159,76 +162,126 @@ void MQTThomeassistantDiscovery() {
group = ""; group = "";
} }
// Group | Field | User Friendly Name | Icon | Unit | Device Class | State Class | Entity Category // Group | Field | User Friendly Name | Icon | Unit | Device Class | State Class | Entity Category
sendHomeAssistantDiscoveryTopic(group, "value", "Value", "gauge", valueUnit, meterType, "total_increasing", ""); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "value", "Value", "gauge", valueUnit, meterType, "total_increasing", "");
sendHomeAssistantDiscoveryTopic(group, "raw", "Raw Value", "raw", valueUnit, "", "total_increasing", "diagnostic"); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "raw", "Raw Value", "raw", valueUnit, "", "total_increasing", "diagnostic");
sendHomeAssistantDiscoveryTopic(group, "error", "Error", "alert-circle-outline", "", "", "", "diagnostic"); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "error", "Error", "alert-circle-outline", "", "", "", "diagnostic");
/* Not announcing "rate" as it is better to use rate_per_time_unit resp. rate_per_digitalization_round */ /* Not announcing "rate" as it is better to use rate_per_time_unit resp. rate_per_digitalization_round */
// sendHomeAssistantDiscoveryTopic(group, "rate", "Rate (Unit/Minute)", "swap-vertical", "", "", "", ""); // Legacy, always Unit per Minute // allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate", "Rate (Unit/Minute)", "swap-vertical", "", "", "", ""); // Legacy, always Unit per Minute
sendHomeAssistantDiscoveryTopic(group, "rate_per_time_unit", "Rate (" + rateUnit + ")", "swap-vertical", rateUnit, "", "", ""); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate_per_time_unit", "Rate (" + rateUnit + ")", "swap-vertical", rateUnit, "", "", "");
sendHomeAssistantDiscoveryTopic(group, "rate_per_digitalization_round", "Change since last digitalization round", "arrow-expand-vertical", valueUnit, "", "measurement", ""); // correctly the Unit is Uint/Interval! allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate_per_digitalization_round", "Change since last digitalization round", "arrow-expand-vertical", valueUnit, "", "measurement", ""); // correctly the Unit is Uint/Interval!
sendHomeAssistantDiscoveryTopic(group, "timestamp", "Timestamp", "clock-time-eight-outline", "", "timestamp", "", "diagnostic"); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "timestamp", "Timestamp", "clock-time-eight-outline", "", "timestamp", "", "diagnostic");
sendHomeAssistantDiscoveryTopic(group, "json", "JSON", "code-json", "", "", "", "diagnostic"); allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "json", "JSON", "code-json", "", "", "", "diagnostic");
sendHomeAssistantDiscoveryTopic(group, "problem", "Problem", "alert-outline", "", "problem", "", ""); // Special binary sensor which is based on error topic allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "problem", "Problem", "alert-outline", "", "problem", "", ""); // Special binary sensor which is based on error topic
} }
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Successfully published all Homeassistant Discovery MQTT topics");
return allSendsSuccessed;
} }
void publishSystemData() { bool publishSystemData() {
if (!getMQTTisConnected()) bool allSendsSuccessed = false;
return;
if (!getMQTTisConnected()) {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Unable to send System Topics, we are not connected to the MQTT broker!");
return false;
}
char tmp_char[50]; char tmp_char[50];
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Publishing system MQTT topics..."); LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Publishing system MQTT topics...");
allSendsSuccessed |= MQTTPublish(maintopic + "/" + std::string(LWT_TOPIC), LWT_CONNECTED, retainFlag); // Publish "connected" to maintopic/connection
sprintf(tmp_char, "%ld", (long)getUpTime()); sprintf(tmp_char, "%ld", (long)getUpTime());
MQTTPublish(maintopic + "/" + "uptime", std::string(tmp_char), retainFlag); allSendsSuccessed |= MQTTPublish(maintopic + "/" + "uptime", std::string(tmp_char), retainFlag);
sprintf(tmp_char, "%lu", (long) getESPHeapSize()); sprintf(tmp_char, "%lu", (long) getESPHeapSize());
MQTTPublish(maintopic + "/" + "freeMem", std::string(tmp_char), retainFlag); allSendsSuccessed |= MQTTPublish(maintopic + "/" + "freeMem", std::string(tmp_char), retainFlag);
sprintf(tmp_char, "%d", get_WIFI_RSSI()); sprintf(tmp_char, "%d", get_WIFI_RSSI());
MQTTPublish(maintopic + "/" + "wifiRSSI", std::string(tmp_char), retainFlag); allSendsSuccessed |= MQTTPublish(maintopic + "/" + "wifiRSSI", std::string(tmp_char), retainFlag);
sprintf(tmp_char, "%d", (int)temperatureRead()); sprintf(tmp_char, "%d", (int)temperatureRead());
MQTTPublish(maintopic + "/" + "CPUtemp", std::string(tmp_char), retainFlag); allSendsSuccessed |= MQTTPublish(maintopic + "/" + "CPUtemp", std::string(tmp_char), retainFlag);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Successfully published all System MQTT topics");
return allSendsSuccessed;
} }
void publishStaticData() { bool publishStaticData() {
if (!getMQTTisConnected()) bool allSendsSuccessed = false;
return;
if (!getMQTTisConnected()) {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Unable to send Static Topics, we are not connected to the MQTT broker!");
return false;
}
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Publishing static MQTT topics..."); LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Publishing static MQTT topics...");
MQTTPublish(maintopic + "/" + "MAC", getMac(), retainFlag); allSendsSuccessed |= MQTTPublish(maintopic + "/" + "MAC", getMac(), retainFlag);
MQTTPublish(maintopic + "/" + "IP", *getIPAddress(), retainFlag); allSendsSuccessed |= MQTTPublish(maintopic + "/" + "IP", *getIPAddress(), retainFlag);
MQTTPublish(maintopic + "/" + "hostname", wlan_config.hostname, retainFlag); allSendsSuccessed |= MQTTPublish(maintopic + "/" + "hostname", wlan_config.hostname, retainFlag);
std::stringstream stream; std::stringstream stream;
stream << std::fixed << std::setprecision(1) << roundInterval; // minutes stream << std::fixed << std::setprecision(1) << roundInterval; // minutes
MQTTPublish(maintopic + "/" + "interval", stream.str(), retainFlag); allSendsSuccessed |= MQTTPublish(maintopic + "/" + "interval", stream.str(), retainFlag);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Successfully published all Static MQTT topics");
return allSendsSuccessed;
} }
esp_err_t sendDiscovery_and_static_Topics(httpd_req_t *req) { esp_err_t sendDiscovery_and_static_Topics(httpd_req_t *req) {
bool success = false;
if (HomeassistantDiscovery) { if (HomeassistantDiscovery) {
MQTThomeassistantDiscovery(); success = MQTThomeassistantDiscovery();
} }
publishStaticData(); success |= publishStaticData();
const char* resp_str = (const char*) req->user_ctx; if (success) {
httpd_resp_send(req, resp_str, strlen(resp_str)); char msg[] = "MQTT Homeassistant Discovery and Static Topics sent!";
httpd_resp_send(req, msg, strlen(msg));
return ESP_OK; return ESP_OK;
}
else {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "One or more MQTT topics failed to be published!");
char msg[] = "Failed to send MQTT topics!";
httpd_resp_send(req, msg, strlen(msg));
return ESP_FAIL;
}
} }
void GotConnected(std::string maintopic, bool retainFlag) { void GotConnected(std::string maintopic, bool retainFlag) {
if (HomeassistantDiscovery) { static bool initialStaticOrHomeassistantDiscoveryTopicsGotSent = false;
MQTThomeassistantDiscovery(); bool success = false;
/* Only send Homeassistant Discovery and Static topics on the first time connecting */
if (!initialStaticOrHomeassistantDiscoveryTopicsGotSent) {
if (HomeassistantDiscovery) {
success = MQTThomeassistantDiscovery();
}
success |= publishStaticData();
if (success) {
/* Sending of all Homeassistant Discovery and Static Topics was successfull.
* Will no no longer send it on a re-connect!
* (But it is still possible to trigger sending through the REST API). */
initialStaticOrHomeassistantDiscoveryTopicsGotSent = true;
}
else {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "One or more static or Homeassistant Discovery MQTT topics failed to be published! Will try again on the next round.");
}
} }
publishStaticData(); /* The System Data changes at runtime, therefore we always send it after a re-connect */
publishSystemData(); success |= publishSystemData();
if (!success) {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "One or more MQTT topics failed to be published!");
}
} }
void register_server_mqtt_uri(httpd_handle_t server) { void register_server_mqtt_uri(httpd_handle_t server) {
@@ -237,7 +290,7 @@ void register_server_mqtt_uri(httpd_handle_t server) {
uri.uri = "/mqtt_publish_discovery"; uri.uri = "/mqtt_publish_discovery";
uri.handler = sendDiscovery_and_static_Topics; uri.handler = sendDiscovery_and_static_Topics;
uri.user_ctx = (void*) "MQTT Discovery and Static Topics sent"; uri.user_ctx = (void*) "";
httpd_register_uri_handler(server, &uri); httpd_register_uri_handler(server, &uri);
} }

View File

@@ -16,7 +16,7 @@ std::string mqttServer_getMainTopic();
void register_server_mqtt_uri(httpd_handle_t server); void register_server_mqtt_uri(httpd_handle_t server);
void publishSystemData(); bool publishSystemData();
std::string getTimeUnit(void); std::string getTimeUnit(void);
void GotConnected(std::string maintopic, bool SetRetainFlag); void GotConnected(std::string maintopic, bool SetRetainFlag);

View File

@@ -86,10 +86,6 @@ extern std::string getHTMLversion(void);
extern std::string getHTMLcommit(void); extern std::string getHTMLcommit(void);
std::vector<std::string> splitString(const std::string& str); std::vector<std::string> splitString(const std::string& str);
bool replace(std::string& s, std::string const& toReplace, std::string const& replaceWith);
bool replace(std::string& s, std::string const& toReplace, std::string const& replaceWith, bool logIt);
//bool replace_all(std::string& s, std::string const& toReplace, std::string const& replaceWith);
bool isInString(std::string& s, std::string const& toFind);
void migrateConfiguration(void); void migrateConfiguration(void);
static const char *TAG = "MAIN"; static const char *TAG = "MAIN";
@@ -495,7 +491,7 @@ void migrateConfiguration(void) {
if (configLines[i].find("[") != std::string::npos) { // Start of new section if (configLines[i].find("[") != std::string::npos) { // Start of new section
section = configLines[i]; section = configLines[i];
replace(section, ";", "", false); // Remove possible semicolon (just for the string comparison) replaceString(section, ";", "", false); // Remove possible semicolon (just for the string comparison)
//ESP_LOGI(TAG, "New section: %s", section.c_str()); //ESP_LOGI(TAG, "New section: %s", section.c_str());
} }
@@ -510,79 +506,79 @@ void migrateConfiguration(void) {
* - Only one whitespace before/after the equal sign * - Only one whitespace before/after the equal sign
*/ */
if (section == "[MakeImage]") { if (section == "[MakeImage]") {
migrated = migrated | replace(configLines[i], "[MakeImage]", "[TakeImage]"); // Rename the section itself migrated = migrated | replaceString(configLines[i], "[MakeImage]", "[TakeImage]"); // Rename the section itself
} }
if (section == "[MakeImage]" || section == "[TakeImage]") { if (section == "[MakeImage]" || section == "[TakeImage]") {
migrated = migrated | replace(configLines[i], "LogImageLocation", "RawImagesLocation"); migrated = migrated | replaceString(configLines[i], "LogImageLocation", "RawImagesLocation");
migrated = migrated | replace(configLines[i], "LogfileRetentionInDays", "RawImagesRetention"); migrated = migrated | replaceString(configLines[i], "LogfileRetentionInDays", "RawImagesRetention");
migrated = migrated | replace(configLines[i], ";Demo = true", ";Demo = false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";Demo = true", ";Demo = false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";Demo", "Demo"); // Enable it migrated = migrated | replaceString(configLines[i], ";Demo", "Demo"); // Enable it
migrated = migrated | replace(configLines[i], ";FixedExposure = true", ";FixedExposure = false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";FixedExposure = true", ";FixedExposure = false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";FixedExposure", "FixedExposure"); // Enable it migrated = migrated | replaceString(configLines[i], ";FixedExposure", "FixedExposure"); // Enable it
} }
if (section == "[Alignment]") { if (section == "[Alignment]") {
migrated = migrated | replace(configLines[i], ";InitialMirror = true", ";InitialMirror = false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";InitialMirror = true", ";InitialMirror = false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";InitialMirror", "InitialMirror"); // Enable it migrated = migrated | replaceString(configLines[i], ";InitialMirror", "InitialMirror"); // Enable it
migrated = migrated | replace(configLines[i], ";FlipImageSize = true", ";FlipImageSize = false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";FlipImageSize = true", ";FlipImageSize = false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";FlipImageSize", "FlipImageSize"); // Enable it migrated = migrated | replaceString(configLines[i], ";FlipImageSize", "FlipImageSize"); // Enable it
} }
if (section == "[Digits]") { if (section == "[Digits]") {
migrated = migrated | replace(configLines[i], "LogImageLocation", "ROIImagesLocation"); migrated = migrated | replaceString(configLines[i], "LogImageLocation", "ROIImagesLocation");
migrated = migrated | replace(configLines[i], "LogfileRetentionInDays", "ROIImagesRetention"); migrated = migrated | replaceString(configLines[i], "LogfileRetentionInDays", "ROIImagesRetention");
} }
if (section == "[Analog]") { if (section == "[Analog]") {
migrated = migrated | replace(configLines[i], "LogImageLocation", "ROIImagesLocation"); migrated = migrated | replaceString(configLines[i], "LogImageLocation", "ROIImagesLocation");
migrated = migrated | replace(configLines[i], "LogfileRetentionInDays", "ROIImagesRetention"); migrated = migrated | replaceString(configLines[i], "LogfileRetentionInDays", "ROIImagesRetention");
migrated = migrated | replace(configLines[i], "ExtendedResolution", ";UNUSED_PARAMETER"); // This parameter is no longer used migrated = migrated | replaceString(configLines[i], "ExtendedResolution", ";UNUSED_PARAMETER"); // This parameter is no longer used
} }
if (section == "[PostProcessing]") { if (section == "[PostProcessing]") {
migrated = migrated | replace(configLines[i], ";PreValueUse = true", ";PreValueUse = false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";PreValueUse = true", ";PreValueUse = false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";PreValueUse", "PreValueUse"); // Enable it migrated = migrated | replaceString(configLines[i], ";PreValueUse", "PreValueUse"); // Enable it
/* AllowNegativeRates has a <NUMBER> as prefix! */ /* AllowNegativeRates has a <NUMBER> as prefix! */
if (isInString(configLines[i], "AllowNegativeRates") && isInString(configLines[i], ";")) { // It is the parameter "AllowNegativeRates" and it is commented out if (isInString(configLines[i], "AllowNegativeRates") && isInString(configLines[i], ";")) { // It is the parameter "AllowNegativeRates" and it is commented out
migrated = migrated | replace(configLines[i], "true", "false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], "true", "false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";", ""); // Enable it migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it
} }
/* IgnoreLeadingNaN has a <NUMBER> as prefix! */ /* IgnoreLeadingNaN has a <NUMBER> as prefix! */
if (isInString(configLines[i], "IgnoreLeadingNaN") && isInString(configLines[i], ";")) { // It is the parameter "IgnoreLeadingNaN" and it is commented out if (isInString(configLines[i], "IgnoreLeadingNaN") && isInString(configLines[i], ";")) { // It is the parameter "IgnoreLeadingNaN" and it is commented out
migrated = migrated | replace(configLines[i], "true", "false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], "true", "false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";", ""); // Enable it migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it
} }
/* ExtendedResolution has a <NUMBER> as prefix! */ /* ExtendedResolution has a <NUMBER> as prefix! */
if (isInString(configLines[i], "ExtendedResolution") && isInString(configLines[i], ";")) { // It is the parameter "ExtendedResolution" and it is commented out if (isInString(configLines[i], "ExtendedResolution") && isInString(configLines[i], ";")) { // It is the parameter "ExtendedResolution" and it is commented out
migrated = migrated | replace(configLines[i], "true", "false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], "true", "false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";", ""); // Enable it migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it
} }
migrated = migrated | replace(configLines[i], ";ErrorMessage = true", ";ErrorMessage = false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";ErrorMessage = true", ";ErrorMessage = false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";ErrorMessage", "ErrorMessage"); // Enable it migrated = migrated | replaceString(configLines[i], ";ErrorMessage", "ErrorMessage"); // Enable it
migrated = migrated | replace(configLines[i], ";CheckDigitIncreaseConsistency = true", ";CheckDigitIncreaseConsistency = false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";CheckDigitIncreaseConsistency = true", ";CheckDigitIncreaseConsistency = false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";CheckDigitIncreaseConsistency", "CheckDigitIncreaseConsistency"); // Enable it migrated = migrated | replaceString(configLines[i], ";CheckDigitIncreaseConsistency", "CheckDigitIncreaseConsistency"); // Enable it
} }
if (section == "[MQTT]") { if (section == "[MQTT]") {
migrated = migrated | replace(configLines[i], "SetRetainFlag", "RetainMessages"); // First rename it, enable it with its default value migrated = migrated | replaceString(configLines[i], "SetRetainFlag", "RetainMessages"); // First rename it, enable it with its default value
migrated = migrated | replace(configLines[i], ";RetainMessages = true", ";RetainMessages = false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";RetainMessages = true", ";RetainMessages = false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";RetainMessages", "RetainMessages"); // Enable it migrated = migrated | replaceString(configLines[i], ";RetainMessages", "RetainMessages"); // Enable it
migrated = migrated | replace(configLines[i], ";HomeassistantDiscovery = true", ";HomeassistantDiscovery = false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";HomeassistantDiscovery = true", ";HomeassistantDiscovery = false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";HomeassistantDiscovery", "HomeassistantDiscovery"); // Enable it migrated = migrated | replaceString(configLines[i], ";HomeassistantDiscovery", "HomeassistantDiscovery"); // Enable it
if (configLines[i].rfind("Topic", 0) != std::string::npos) // only if string starts with "Topic" (Was the naming in very old version) if (configLines[i].rfind("Topic", 0) != std::string::npos) // only if string starts with "Topic" (Was the naming in very old version)
{ {
migrated = migrated | replace(configLines[i], "Topic", "MainTopic"); migrated = migrated | replaceString(configLines[i], "Topic", "MainTopic");
} }
} }
@@ -595,34 +591,34 @@ void migrateConfiguration(void) {
} }
if (section == "[DataLogging]") { if (section == "[DataLogging]") {
migrated = migrated | replace(configLines[i], "DataLogRetentionInDays", "DataFilesRetention"); migrated = migrated | replaceString(configLines[i], "DataLogRetentionInDays", "DataFilesRetention");
/* DataLogActive is true by default! */ /* DataLogActive is true by default! */
migrated = migrated | replace(configLines[i], ";DataLogActive = false", ";DataLogActive = true"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";DataLogActive = false", ";DataLogActive = true"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";DataLogActive", "DataLogActive"); // Enable it migrated = migrated | replaceString(configLines[i], ";DataLogActive", "DataLogActive"); // Enable it
} }
if (section == "[AutoTimer]") { if (section == "[AutoTimer]") {
migrated = migrated | replace(configLines[i], "Intervall", "Interval"); migrated = migrated | replaceString(configLines[i], "Intervall", "Interval");
migrated = migrated | replace(configLines[i], ";AutoStart = true", ";AutoStart = false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";AutoStart = true", ";AutoStart = false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";AutoStart", "AutoStart"); // Enable it migrated = migrated | replaceString(configLines[i], ";AutoStart", "AutoStart"); // Enable it
} }
if (section == "[Debug]") { if (section == "[Debug]") {
migrated = migrated | replace(configLines[i], "Logfile ", "LogLevel "); // Whitespace needed so it does not match `LogfileRetentionInDays` migrated = migrated | replaceString(configLines[i], "Logfile ", "LogLevel "); // Whitespace needed so it does not match `LogfileRetentionInDays`
/* LogLevel (resp. LogFile) was originally a boolean, but we switched it to an int /* LogLevel (resp. LogFile) was originally a boolean, but we switched it to an int
* For both cases (true/false), we set it to level 2 (WARNING) */ * For both cases (true/false), we set it to level 2 (WARNING) */
migrated = migrated | replace(configLines[i], "LogLevel = true", "LogLevel = 2"); migrated = migrated | replaceString(configLines[i], "LogLevel = true", "LogLevel = 2");
migrated = migrated | replace(configLines[i], "LogLevel = false", "LogLevel = 2"); migrated = migrated | replaceString(configLines[i], "LogLevel = false", "LogLevel = 2");
migrated = migrated | replace(configLines[i], "LogfileRetentionInDays", "LogfilesRetention"); migrated = migrated | replaceString(configLines[i], "LogfileRetentionInDays", "LogfilesRetention");
} }
if (section == "[System]") { if (section == "[System]") {
migrated = migrated | replace(configLines[i], "RSSIThreashold", "RSSIThreshold"); migrated = migrated | replaceString(configLines[i], "RSSIThreashold", "RSSIThreshold");
migrated = migrated | replace(configLines[i], "AutoAdjustSummertime", ";UNUSED_PARAMETER"); // This parameter is no longer used migrated = migrated | replaceString(configLines[i], "AutoAdjustSummertime", ";UNUSED_PARAMETER"); // This parameter is no longer used
migrated = migrated | replace(configLines[i], ";SetupMode = true", ";SetupMode = false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";SetupMode = true", ";SetupMode = false"); // Set it to its default value
migrated = migrated | replace(configLines[i], ";SetupMode", "SetupMode"); // Enable it migrated = migrated | replaceString(configLines[i], ";SetupMode", "SetupMode"); // Enable it
} }
} }
@@ -683,33 +679,3 @@ std::vector<std::string> splitString(const std::string& str) {
return found; return found;
}*/ }*/
bool replace(std::string& s, std::string const& toReplace, std::string const& replaceWith) {
return replace(s, toReplace, replaceWith, true);
}
bool replace(std::string& s, std::string const& toReplace, std::string const& replaceWith, bool logIt) {
std::size_t pos = s.find(toReplace);
if (pos == std::string::npos) { // Not found
return false;
}
std::string old = s;
s.replace(pos, toReplace.length(), replaceWith);
if (logIt) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Migrated Configfile line '" + old + "' to '" + s + "'");
}
return true;
}
bool isInString(std::string& s, std::string const& toFind) {
std::size_t pos = s.find(toFind);
if (pos == std::string::npos) { // Not found
return false;
}
return true;
}