Ich habe folgende funktionen, mit denen ich einen HTML QueryString erstelle:
bool save_data(PubSubClient* mqttClient, WiFiClient* wifiClient, const char* data) {
if (WiFi.status() != WL_CONNECTED && wasConnected) {
delay(200);
ESP.restart();
}
digitalWrite(WIFI_LED, LOW);
const char* PimaticHost = HandleEeprom(pimhost_Address, EEPROM_READ).c_str();
uint16_t PimaticPort = EepromReadInt16(pimport_Address);
if (PimaticType == 1) {
#ifdef DEBUG
char query[33];
snprintf(query, sizeof(query), "%s", HandleEeprom(pimquery_Address, EEPROM_READ).c_str());
Serial.print(F("Sending data: http://"));
Serial.print(PimaticHost);
Serial.println((PimaticPort != 80 ? ":" + PimaticPort : "") + query + data);
#endif
// Use WiFiClient class to create TCP connections
if (!wifiClient->connect(PimaticHost, PimaticPort)) {
#ifdef DEBUG
Serial.println(F("Connection Error"));
#endif
digitalWrite(WIFI_LED, HIGH);
return false;
}
// This will send the request to the server
wifiClient->println("GET /" + HandleEeprom(pimquery_Address, EEPROM_READ, "", "/") + data + "\r\nHTTP/1.1");
wifiClient->print("Host: ");
wifiClient->println(PimaticHost);
wifiClient->println("Connection: close\r\n");
#ifdef DEBUG
delay(200);
// Read all the lines of the reply from server and print them to Serial
String response = "";
while (wifiClient->available()) {
response = wifiClient->readStringUntil('\r');
// only for debug
// Serial.print(response);
}
#endif
wifiClient->flush();
wifiClient->stop();
}
else if (PimaticType == 2) {
if (!mqttClient->connected()) {
MqttReconnect(mqttClient);
}
#ifdef DEBUG
Serial.print(F("Publish message: "));
Serial.println(data);
#endif
char topic[50] = {'\0'};
snprintf(topic, sizeof(topic), "%s/%s", HandleEeprom(pimquery_Address, EEPROM_READ).c_str(), DeviceName);
mqttClient->publish(topic, data);
}
delay(200);
digitalWrite(WIFI_LED, HIGH);
return true;
}
void addValue(String& queryString, const char* var, char value[], bool firstValue = false) {
queryString += (firstValue ? "\"" : ",\"");
queryString += var;
queryString += "\":";
queryString += value;
}
und im loop:
void loop() {
.
.
.
if (millis() - pimatic_lastInterval > pimatic_sendInterval && PimaticEnabled) {
String msg = "";
switch (PimaticType) {
case 1: //HTTP
msg = "?data={\"sensor\":\"" + String(DeviceName) + "\",";
break;
case 2: //MQTT
msg = "{";
break;
default: //Pimatic
msg = "";
break;
}
bool firstValue = true;
addValue(msg, "bv", LastBatteryVoltage, firstValue);
firstValue = false;
if (ADCEnabled) {
addValue(msg, HandleEeprom(adcvar_Address, EEPROM_READ, "" "value1").c_str(), LastAnalogValue, firstValue);
firstValue = false;
}
if (BME280Enabled) {
addValue(msg, HandleEeprom(bme280tempvar_Address, EEPROM_READ, "", "value2").c_str(), LastBmeTemperature, firstValue);
addValue(msg, HandleEeprom(bme280humvar_Address, EEPROM_READ, "", "value3").c_str(), LastBmeHumidity);
addValue(msg, HandleEeprom(bme280pressvar_Address, EEPROM_READ, "", "value4").c_str(), LastBmePressure);
firstValue = false;
}
if (BH1750Enabled) {
addValue(msg, HandleEeprom(bh1750var_Address, EEPROM_READ, "", "value5").c_str(), LastBrightness, firstValue);
firstValue = false;
}
if (MoistureEnabled) {
addValue(msg, HandleEeprom(moisturevar_Address, EEPROM_READ, "", "value6").c_str(), LastSoilMoisture, firstValue);
char buff[24];
snprintf(buff, sizeof(buff), "%lu", last_watering_time);
addValue(msg, "lw", buff);
firstValue = false;
}
if (RainGaugeEnabled) {
addValue(msg, "hr", HourlyRain, firstValue);
addValue(msg, "dr", DaylyRain);
firstValue = false;
}
if (PimaticType < 3 {
msg += "}";
}
save_data(&mqttClient, &wifiClient, msg.c_str());
pimatic_lastInterval = millis();
}
}
Jeder Aufbau der msg fragmentiert den Speicher und nach 8-12 Tagen bootet der ESP32 neu.
Nach send_data(...) gibt ESP.getFreeHeap(); bis zu 2kB weniger zurück.
Die gleiche Hardware, ohne die Daten an den Webserver zu senden, läuft schon seit über 30 Tagen stabil.
Wie kann ich die msg anders konstruieren, ohne immer bis zu 2 KB Speicher zu verlieren.
Gruß
Fred