//========== 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 readSensors() { uint8_t ds18Count = sensor.getDeviceCount(); float tempC[ds18Count]; float temperature[ds18Count]; DeviceAddress addr; String deviceAddress[ds18Count]; int savedTemperatures = 0; for (uint8_t i = 0; i < ds18Count; i++) { sensor.getAddress(addr, i); deviceAddress[savedTemperatures] == ""; for (uint8_t n = 0; n < 8; n++) { if (addr[n] < 16) { deviceAddress[savedTemperatures] += String(0, HEX); } deviceAddress[savedTemperatures] += String(addr[n], HEX); } tempC[savedTemperatures] = sensor.getTempCByIndex(i); if (tempC[savedTemperatures] != DEVICE_DISCONNECTED_C) { if (savedTemperatures == 0) { avgTemperature = 0; } temperature[savedTemperatures] = tempC[savedTemperatures] + correction[i]; avgTemperature += temperature[savedTemperatures]; savedTemperatures++; } } if (savedTemperatures != 0) { avgTemperature = avgTemperature / savedTemperatures; } setMetricsVar(ds18Count, temperature, tempC, deviceAddress); } void setMetricsVar(uint8_t ds18Count, float temperature[], float tempC[], String deviceAddress[]) { metrics = ""; for (uint8_t i = 0; i < ds18Count; i++) { metrics += "\ntemp{device=\""; metrics += i; metrics += "\",address=\""; metrics += deviceAddress[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; } } void startConversion() { // start temperature conversion (does not block) sensor.requestTemperatures(); // schedule reading the actual temperature in 750 milliseconds tasker.setTimeout(readSensors, 750); } void ledBlink() { digitalWrite(LED_PIN, LOW); delay(200); digitalWrite(LED_PIN, HIGH); }