//========== Preprocesor ========== //---- Required ---- #include #include //------------------ #include #include #include "Tasker.h" #include "OneWire.h" #include "DallasTemperature.h" #include "config.h" //========== Create objects ========== AsyncWebServer server(80); Tasker tasker; OneWire oneWire(DS18B20_PIN); DallasTemperature sensor(&oneWire); //========== Init variables ========== float avgTemperature; String metrics; bool heating; float reqTemp = 21.5; float offset = 0.25; float correction[6] = {CORRECTION1, CORRECTION2, CORRECTION3, CORRECTION4, CORRECTION5, CORRECTION6}; //================================= void setup() { //========== Wi-Fi setup ========== WiFi.mode(WIFI_STA); WiFi.begin(STASSID, STAPSK); while (WiFi.waitForConnectResult() != WL_CONNECTED) { //Connection Failed! Rebooting... delay(5000); ESP.restart(); } //========== OTA setup ========== // Port defaults to 8266 // ArduinoOTA.setPort(8266); // Hostname defaults to esp8266-[ChipID] // ArduinoOTA.setHostname("myesp8266"); // No authentication by default // ArduinoOTA.setPassword("admin"); // Password can be set with it's md5 value as well // MD5(admin) = 21232f297a57a5a743894a0e4a801fc3 // ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3"); ArduinoOTA.begin(); SPIFFS.begin(); //========== Pin setup ========== pinMode(RELAY_PIN, OUTPUT); pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); //========== Sensor setup ========== sensor.begin(); // do not block during temperature conversion sensor.setWaitForConversion(false); //========== Tasks init ========== startConversion(); // First temp read tasker.setInterval(startConversion, 15000); // read temperature every 15 seconds tasker.setInterval(otaHandle, 1000); if (THERMOSTAT) { tasker.setInterval(thermostatCheck, 1000); } //========== Web server setup ========== if (METRICS_EXPORT || API) { if (METRICS_EXPORT) { server.on("/metrics", HTTP_GET, [](AsyncWebServerRequest * request) { tasker.setTimeout(ledBlink, 10); request->send(200, "text/plain; charset=utf-8", metrics); }); } if (API) { server.on("/set", HTTP_GET, [](AsyncWebServerRequest * request) { //nutno nastavit maxima a minima String repply; if (THERMOSTAT) { if (request->hasParam("increasereqtemp")) { reqTemp += request->getParam("increasereqtemp")->value().toFloat(); repply = String(reqTemp); } else if (request->hasParam("decreasereqtemp")) { reqTemp -= request->getParam("decreasereqtemp")->value().toFloat(); repply = String(reqTemp); } else if (request->hasParam("increaseoffset")) { offset += request->getParam("increaseoffset")->value().toFloat(); repply = String(offset); } else if (request->hasParam("decreaseoffset")) { offset -= request->getParam("decreaseoffset")->value().toFloat(); repply = String(offset); } else { repply = "unknown parameter"; } } else { if (request->hasParam("relay")) { boolean state = request->getParam("relay")->value() == "0"; digitalWrite(RELAY_PIN, state); repply = "success"; } else { repply = "unknown parameter"; } } request->send(200, "text/plain; charset=utf-8", repply); }); server.on("/get", HTTP_GET, [](AsyncWebServerRequest * request) { //nutno vyřešit dotazy na více parametrů najednou String repply; if (request->hasParam("temp")) { repply = String(avgTemperature); } else if (request->hasParam("relay")) { repply = String(heating); } else if (THERMOSTAT && request->hasParam("reqtemp")) { repply = String(reqTemp); } else if (THERMOSTAT && request->hasParam("offset")) { repply = String(offset); } else { repply = "unknown parameter"; } request->send(200, "text/plain; charset=utf-8", repply); }); } if (API && WEBAPP) { server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html"); } server.onNotFound(notFound); server.begin(); } //================================= } void loop() { tasker.loop(); } void otaHandle() { ArduinoOTA.handle(); } void notFound(AsyncWebServerRequest *request) { request->send(404, "text/plain", "Not found"); } void thermostatCheck() { if (avgTemperature <= (reqTemp - offset)) { heating = 1; digitalWrite(RELAY_PIN, !heating); } else if (avgTemperature >= (reqTemp + offset)) { heating = 0; digitalWrite(RELAY_PIN, !heating); } } void readSensor() { uint8_t ds18Count = sensor.getDS18Count(); float tempC[ds18Count]; float temperature[ds18Count]; int savedTemperatures = 0; avgTemperature = 0; for (int i = 0; i < ds18Count; i++) { tempC[i] = sensor.getTempCByIndex(i); if (tempC[i] != DEVICE_DISCONNECTED_C) { temperature[i] = tempC[i] + correction[i]; avgTemperature += temperature[i]; savedTemperatures++; } } avgTemperature = avgTemperature / savedTemperatures; metrics = getMetricsVar(ds18Count, temperature, tempC); } String getMetricsVar(uint8_t ds18Count, float temperature[], float tempC[]) { metrics = "temp{device=\""; for (uint8_t i = 0; i < ds18Count; i++) { if (i != 0) { metrics += "\ntemp{device=\""; } metrics += i; metrics += "\"} "; metrics += temperature[i]; } for (uint8_t i = 0; i < ds18Count; i++) { metrics += "\nraw_temp{device=\""; metrics += i; metrics += "\"} "; metrics += tempC[i]; } if (THERMOSTAT) { metrics += "\nheating "; metrics += heating; metrics += "\nreqTemp "; metrics += reqTemp; metrics += "\noffset "; metrics += offset; } return metrics; } void startConversion() { // start temperature conversion (does not block) sensor.requestTemperatures(); // schedule reading the actual temperature in 750 milliseconds tasker.setTimeout(readSensor, 750); } void ledBlink() { digitalWrite(LED_PIN, LOW); delay(200); digitalWrite(LED_PIN, HIGH); }