CTBot icon indicating copy to clipboard operation
CTBot copied to clipboard

kernel panic with getNewMessage()

Open SimonESchiller opened this issue 2 years ago • 2 comments

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;
}

SimonESchiller avatar Nov 12 '22 23:11 SimonESchiller