CTBot
CTBot copied to clipboard
kernel panic with getNewMessage()
Hello Guys I want to recive messages from CTBot and use the input to control my water boiler. I use a ESP8266 The program runs as expected, but unfrequently the kernel panics when the getNewMessage() is called. Do you know how fix it? Thanks in advance! Simon
#include <ArduinoJson.h> // Arduino JSON (6.19.4)
#include <ESP8266WiFi.h> // ESP8266 WiFi
#include <WiFiClient.h> // ESP8266 Wifi-Client
#include <ESP8266HTTPClient.h> // ESP8266 HTTP-Client
#include <NTPClient.h> // TIme
#include <WiFiUdp.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "CTBot.h"
#include <SPI.h>
#include <SD.h>
#include <TimeLib.h>
//Pin configuration for power controll (now GPIO15 / D8)
#define GPIO_PIN_PWM_CONTROL 15
CTBot myBot;
//SD card
const int chipSelect = 5;
// GPIO where the DS18B20(themperature probe) is connected to
const int oneWireBus = 4;
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);
// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);
//Telegram token
String token = "xxxxxx:xxxxxxxx_xxxxxxxxxxxxxxxx";
// WiFi SSID und PSK
const char *ssid = "xxxxxxxx";
const char *password = "xxxxx";
const char *host_name = "xxxxxxx";
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
WiFiClient wifiClient;
//Inverter IP adress
const String inverterHostname = "xxxxxxxxxx";
// Fronius Solar API URL "Flow Data"
String urlFlow = "http://" + inverterHostname + "/solar_api/v1/GetPowerFlowRealtimeData.fcgi";
//global variables:
int value = 0; //1024= 100% power ; 0= 0% power
bool heating = false; //if boiler heats at 100%
float temperatureC; //actual temperature
float targetTemperature = 50; //target temperatur for the nightheating
bool temperatureReachedOnThisDay = false;
bool hollidayModus = false;
bool sdAvailable = false;
//Size calculated by https://arduinojson.org/v6/assistant/
size_t capacityFlow = 768;
void setup() {
//1s wait
delay(1000);
// serial begin, 115200/8/N/1
Serial.begin(115200);
// Start the DS18B20(temperature) sensor
sensors.begin();
// WiFi aus
WiFi.mode(WIFI_OFF);
// 1s warten
delay(1000);
// WiFi Client-Modus, AP-Modus aus
WiFi.mode(WIFI_STA);
WiFi.hostname(host_name);
// WiFi verbinden
WiFi.begin(ssid, password);
Serial.println();
Serial.println("ESP8266 WiFi-Client für Fronius Solar Api V1");
Serial.println("https://www.onderka.com/hausautomation-technik-und-elektronik/nodemcu-json-daten-von-fronius-wechselrichter-einlesen/");
Serial.println();
Serial.print("Verbinde ");
// Auf Verbindung warten
while (WiFi.status() != WL_CONNECTED) {
// Alle 0.5s einen Punkt
delay(500);
Serial.print(".");
}
Serial.println(" Verbunden.");
// set the telegram bot token
myBot.setTelegramToken(token);
// check if all things are ok
if (myBot.testConnection())
Serial.println("\ntestConnection OK");
else
Serial.println("\ntestConnection NOK");
// Verbindungs-Informationen
Serial.println();
Serial.print("SSID: ");
Serial.println(ssid);
Serial.print("Kanal: ");
Serial.println(WiFi.channel());
Serial.print("Signal (RX): ");
Serial.print(WiFi.RSSI());
Serial.println(" dBm");
Serial.print("IP-Adresse: ");
Serial.println(WiFi.localIP());
Serial.print("MAC-Adresse: ");
Serial.println(WiFi.macAddress());
Serial.println();
Serial.print("Initializing SD card...");
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
// don't do anything more:
sdAvailable = false;
} else {
sdAvailable = true;
Serial.println("card initialized.");
}
// Initialize a NTPClient to get time
timeClient.begin();
// Set offset time in seconds to adjust for your timezone, for example:
// GMT +1 = 3600
// GMT +8 = 28800
// GMT -1 = -3600
// GMT 0 = 0
timeClient.setTimeOffset(7200);
delay(2000);
}
//end setup
//loop()
void loop() {
timeClient.update();
sensors.requestTemperatures();
temperatureC = sensors.getTempCByIndex(0);
// HTTP-Clients initialisieren
HTTPClient http;
//Jason buffer
DynamicJsonDocument jsonBufferFlow(capacityFlow);
// URL - Flow Data
http.begin(wifiClient, urlFlow); // get the result (**the error code**)
//http.begin(urlFlow);
int httpCodeFlow = http.GET();
// JSON-Antwort
String httpResponseFlow = http.getString();
// HTTP-Client beenden
http.end();
auto jsonFlowError = deserializeJson(jsonBufferFlow, httpResponseFlow);
if (jsonFlowError) {
// JSON nicht erfolgreich geparst
Serial.print("JSON-Parser: ");
Serial.println(jsonFlowError.c_str());
} else {
//Serial.println("JSON-Parser: OK");
}
Serial.println();
// Timestamp Daten Power Flow
String ts_flow = (jsonBufferFlow["Head"]["Timestamp"] | "Leer");
// Einspeisung / Bezug: Negativ Einspeisung, positiv Bezug
auto in_out = jsonBufferFlow["Body"]["Data"]["Site"]["P_Grid"].as<float>();
// Ausgabe seriell
Serial.print("Timestamp Flow: ");
Serial.println(ts_flow);
Serial.println();
// Negativ Einspeisung, positiv Bezug
if (in_out >= 0) {
// Bezug
Serial.print("Strom Bezug: ");
Serial.print(in_out);
Serial.println(" W");
Serial.println("Strom Einspeisung: 0.00 W");
} else {
// Einspeisung
Serial.println("Strom Bezug: 0.00 W");
Serial.print("Strom Einspeisung: ");
Serial.print(in_out * -1);
Serial.println(" W");
}
Serial.print("Temperatur Boiler: ");
Serial.print(temperatureC);
Serial.println(" C");
//check if heating to target temperature is necessary
int currentHour = timeClient.getHours();
if (currentHour == 0 && temperatureReachedOnThisDay) { //reset the heating to target temperature
temperatureReachedOnThisDay = false;
}
if (currentHour >= 5 && temperatureReachedOnThisDay == false) {
Serial.println("Debug 1");
Serial.print(currentHour);
HeatingToTargetTemperature(temperatureC, targetTemperature);
Serial.println("Debug 8");
}
Serial.println("Debug 9");
//control loop!
if (!heating) {
if (in_out <= -10 && value < 1024) {
value = value + 4;
}
if (in_out >= 0 && value > 0) {
value = value - 4;
}
}
Serial.println("Debug 10");
//write the value to the output
analogWrite(GPIO_PIN_PWM_CONTROL, value);
Serial.print("Power value that the heater is heating (1024=100% (1600W) ) power): ");
Serial.println(value);
TBMessage msg;
Serial.println("Debug 11");
//TelegramBot
if (CTBotMessageText == myBot.getNewMessage(msg)){
// ...forward it to the sender
Serial.println("Case Telegramm bot");
Serial.println("Debug 11 receive nöööö");
String responseTextBot;
if (msg.text == "/help") {
String tempOut = " /temp -- gibt die aktuelle Temperatur aus \n ";
String settempOut = "/settemp --setzt die Temperatur, die auf die er in der Nacht heizt zwischen 40 und 65 \n";
String urlaubOnOut = "/urlaubOn -- Urlaubsmodus gesetzt. Es wird nur noch mit Überschussstrom geheizt \n";
String urlaubOffOut = "/urlaubOff -- Urlaubsmodus aus. Es wird in der Nacht auf " + String(targetTemperature) + " Grad C geheitzt. \n";
String valueOut = "/value -- Wert der Phasenanschnittsterung und die aktuell entsprechende Leistung in Watt \n/heizen --Heizt bis auf " + String(targetTemperature) + " Grad C. \n";
String heizenOffOut = "/heizenOff --Stoppt das heizen auf " + String(targetTemperature) + " Grad C.\n";
String verbrauchOut = "/verbrauch -- Gibt den aktuellen Stromverbrauch in Watt zurück.\n/status --Gibt alle Werte des Programmes aus";
responseTextBot = tempOut + settempOut + urlaubOnOut + urlaubOffOut + valueOut + heizenOffOut + verbrauchOut;
} else if (msg.text == "/status") {
responseTextBot = "" + String(temperatureC) + " Grad Celsius des Wassers \n" + String(value) +
" Value vom Phasenanschnitt; entspricht " + String(value * 1600 / 1024) + " Watt Leistung\nHat heute schon geheizt: " + temperatureReachedOnThisDay +
"\nEs werden gerade " + String(in_out) + " Watt Verbraucht.\nEs wird in der Nacht auf " + String(targetTemperature) + " Grad C geheizt.\nUrlaubsmodus: " + hollidayModus + "";
} else if (msg.text == "/temp") {
responseTextBot = String(temperatureC) + " Grad Celsius";
} else if (msg.text == "/urlaubOn") {
hollidayModus = true;
responseTextBot = "Urlaubsmodus gesetzt. Es wird nur noch mit Überschussstrom geheitzt.";
} else if (msg.text == "/urlaubOff") {
hollidayModus = false;
responseTextBot = "Urlaubsmodus aus. Es wird in der Nacht auf " + String(targetTemperature) + " Grad C geheizt.";
} else if (msg.text == "/verbrauch") {
responseTextBot = "Es wird gerade " + String(in_out) + " Watt Verbraucht.";
} else if (msg.text == "/heizen") {
temperatureReachedOnThisDay = false;
responseTextBot = "Heitz bis auf " + String(targetTemperature) + " Grad C.";
} else if (msg.text == "/heizenOff") {
temperatureReachedOnThisDay = true;
responseTextBot = "Stoppt das heizen auf" + String(targetTemperature) + " Grad C.";
} else if (msg.text == "/value") {
responseTextBot = String(value) + " Value vom Phasenanschnitt; entspricht " + String(value * 1600 / 1024) + " Watt Leistung";
} else if (msg.text.substring(0, 8) == "/settemp") {
if (IsNumber(msg.text.substring(9, 11))) {
float newTargetTemperature = msg.text.substring(9, 11).toFloat();
if (newTargetTemperature >= 40 && newTargetTemperature <= 65) {
targetTemperature = newTargetTemperature;
responseTextBot = String(targetTemperature) + " Grad C wurde als neue Target Temperatur gesezt.";
} else {
responseTextBot = msg.text.substring(9, 11) + " <-- außerhalb der Grenzen min 40 max 65";
}
}
} else {
Serial.println("Debug 11 wäää");
responseTextBot = "Versteh ich nicht";
}
Serial.println("Debug 12");
myBot.sendMessage(msg.sender.id, responseTextBot);
}
Serial.println("Debug 13");
//if SD card is available --> log data
if (sdAvailable) {
Serial.println("Log Data");
// 5s warten
//Daten sichern auf SD Kart
String logData = String(timeClient.getEpochTime()) + ";" + String(value) + ";" + String(in_out) + ";" + String(temperatureC);
File dataFile = SD.open("log.txt", FILE_WRITE);
if (dataFile) {
dataFile.println(logData);
dataFile.close();
// print to the serial port too:
Serial.println(logData);
}
// if the file isn't open, pop up an error:
else {
Serial.println("error opening datalog.txt");
}
}
delay(1000);
// Ende loop()
}
//heats the boiler to the set target temperatre
void HeatingToTargetTemperature(float currentTemperature, float targetTemperature) {
Serial.println("Debug 2");
// Overnight heating
int currentHour = timeClient.getHours();
Serial.println(currentHour);
Serial.println("Debug 3");
if (currentTemperature > targetTemperature) {
//ausschalten
heating = false;
Serial.println("Debug 4");
value = 0;
temperatureReachedOnThisDay = true;
Serial.println(currentTemperature);
Serial.println("Debug 5");
} else if (!heating && !hollidayModus) {
value = 1024; //MAX Leistung
heating = true;
} else if (hollidayModus) {
value = 0;
heating = false;
}
Serial.print("Zeit in h: ");
Serial.println(currentHour);
Serial.println(value);
Serial.println("Debug 13");
Serial.println(heating);
}
bool IsNumber(String input) {
for (int i = 1; i < 2; i++) /* Überprüfe Ziffern bzw Zahl */
{
if (input[i] < '0' || input[i] > '9')
return 0;
}
return 1;
}