You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

239 lines
6.2 KiB
C++

//========== Preprocesor ==========
//---- Required ----
#include <ESP8266WiFi.h>
#include <ArduinoOTA.h>
//------------------
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#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);
}