/* Система контроля температуры для управления котлом * СЕРВЕР * = vlapa = 20221127 - 20231130 v.017 */ #include #include #include #include #define ONE_WIRE_BUS 2 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); #include // #include // #include #include //----------------------------------- // const char *ssid = "TP-Link_77C4"; // const char *pass = "14697272"; // const char *mqtt_client = "GasBoilerServer_Maxx"; // const char *mqtt_client2 = "GasBoiler_Maxx"; const char *ssid = "MikroTik-2"; const char *pass = "dkfgf#*12091997"; const char *mqtt_client = "mqtt_client-esp32-c3_001"; const char *mqtt_client2 = "GasBoiler_Villa"; // const char *ssid = "link"; // const char *pass = "dkfgf#*12091997"; // const char *mqtt_client = "mqtt_client-011"; // const char *mqtt_client2 = "GasBoiler_TEST"; const char *mqtt_user = "mqtt"; const char *mqtt_pass = "qwe#*1243"; const char *mqtt_server = "178.20.46.157"; const uint16_t mqtt_port = 1883; const char *inTopicTempRoom = "/Temp_Room"; const char *inTopicTempDS18b20 = "/Room_ds18b20"; const char *inTopicTempDHT11_1 = "/Room_dht11_1"; const char *inTopicTempDHT11_2 = "/Room_dht11_2"; const char *inTopicReboot = "/Reboot"; const char *outTopicIP = "/IP_Boiler"; const char *outTopicRSSI = "/RSSI_Boiler"; const char *outTopicHeating = "/Heating"; const char *outTopicTempDS18b20 = "/Kotel_ds18b20"; const char *outTopicUpTime = "/UpTime"; const char *outTopicReconnectTime = "/ReconnectTime"; const char *outTopicHeap = "/Heap"; const uint8_t sensorNumRoom_1 = 99; // 1 номер датчика температуры комнаты const uint8_t sensorNumRoom_2 = 11; // 2 номер датчика температуры комнаты const uint8_t sensorNumRoom_3 = 21; // 3 номер датчика температуры комнаты const uint8_t pinReley = 0; const uint8_t pinDS18b20 = 2; int16_t quality_RSSI = 0; float temperRoom = 0.0; float dataTempBase = 23.0; // температура в комнате по умолчанию float dataTempKotel = 60.0; // температура теплоносителя по умолчанию float temperRoom_ds18b20 = 0.0; String temperRoom_dht11_1 = "___"; String temperRoom_dht11_2 = "___"; float temperBoiler_ds18b20 = 0.0; uint32_t millisOld = 0; uint32_t millisOldReconnect = 0; uint32_t millisReconnect = 0; uint32_t pauseTimeTemp = 30000; float gisteresis = 0.1; bool conditionHeater = true; float k = 0.1; // коэффициент фильтрации, 0.0-1.0 WiFiClient espClient; PubSubClient client(espClient); // WebServer server(80); // HTTPUpdateServer httpUpdater; //----------------------------------- String timeCalc(uint32_t t) { uint32_t timer = t / 1000; uint32_t timeSec = (timer % 3600) % 60; uint32_t timeMin = (timer % 3600) / 60; uint32_t timeHour = timer / 3600 % 24; uint32_t timeDay = timer / 60 / 60 / 24; String s = ""; s += timeDay; s += ":"; if (timeHour < 10) s += "0"; s += timeHour; s += ":"; if (timeMin < 10) s += "0"; s += timeMin; s += ":"; if (timeSec < 10) s += "0"; s += timeSec; return s; } //----------------------------------- inline bool mqtt_subscribe(PubSubClient &client, const String &topic) { Serial.print("Subscribing to: "); Serial.println(topic); return client.subscribe(topic.c_str()); } //----------------------------------- inline bool mqtt_publish(PubSubClient &client, const String &topic, const String &value) { Serial.print("Publishing topic "); Serial.print(topic); Serial.print(" = "); Serial.println(value); return client.publish(topic.c_str(), value.c_str()); } //----------------------------------- void mqttReconnectOut() { String topic = "/"; topic += mqtt_client2; topic += outTopicIP; mqtt_publish(client, topic, WiFi.localIP().toString()); topic = "/"; topic += mqtt_client2; topic += outTopicRSSI; mqtt_publish(client, topic, (String)quality_RSSI + '%'); topic = "/"; topic += mqtt_client2; topic += inTopicReboot; mqtt_publish(client, topic, "0"); } //----------------------------------- void mqttDataOut() { String topic = "/"; topic += mqtt_client2; topic += outTopicHeating; mqtt_publish(client, topic, (!conditionHeater) ? "OFF" : "ON"); topic = "/"; topic += mqtt_client2; topic += outTopicTempDS18b20; mqtt_publish(client, topic, (String)temperBoiler_ds18b20); topic = "/"; topic += mqtt_client2; topic += inTopicTempRoom; mqtt_publish(client, topic, (String)temperRoom); topic = "/"; topic += mqtt_client2; topic += inTopicTempDS18b20; mqtt_publish(client, topic, (String)temperRoom_ds18b20); topic = "/"; topic += mqtt_client2; topic += outTopicUpTime; mqtt_publish(client, topic, timeCalc(millis())); // topic = "/"; // topic += mqtt_client2; // topic += outTopicReconnectTime; // mqtt_publish(client, topic, timeCalc(millisReconnect)); topic = "/"; topic += mqtt_client2; topic += inTopicTempDHT11_1; mqtt_publish(client, topic, temperRoom_dht11_1); topic = "/"; topic += mqtt_client2; topic += inTopicTempDHT11_2; mqtt_publish(client, topic, temperRoom_dht11_2); // String heap_data = ""; // heap_data += (conditionHeater) ? 30 : 27; // heap_data += ","; // heap_data += temperBoiler_ds18b20; // heap_data += ","; // heap_data += temperRoom; // heap_data += ","; // heap_data += temperRoom_ds18b20; // heap_data += ","; // heap_data += temperRoom_dht11_1; // heap_data += ","; // heap_data += temperRoom_dht11_2; // topic = "/"; // topic += mqtt_client2; // topic += outTopicHeap; // mqtt_publish(client, topic, heap_data); } //----------------------------------- bool reconnect() { Serial.print("MQTT connect : "); Serial.println(mqtt_server); uint8_t countMQTT = 20; while (!(client.connect(mqtt_client, mqtt_user, mqtt_pass)) && countMQTT--) { Serial.print(countMQTT); Serial.print('>'); delay(500); } if (client.connected()) { Serial.println("MQTT connected - OK !"); String topic = "/"; topic += mqtt_client2; topic += inTopicTempRoom; mqtt_subscribe(client, topic); // topic = "/"; // topic += mqtt_client2; // topic += inTopicTempDS18b20; // mqtt_subscribe(client, topic); topic = "/"; topic += mqtt_client2; topic += inTopicReboot; mqtt_subscribe(client, topic); return true; } else { return false; } } //----------------------------------- bool setupWiFi(const char *wifi_ssid, const char *wifi_pass) { digitalWrite(LED_BUILTIN, LOW); // включаем светодиод Serial.print("\n\nSetup WiFi: "); Serial.println(ssid); WiFi.mode(WIFI_STA); uint8_t countWiFi = 20; // кол-во попыток соединения uint8_t countPause = 500; // пауза между попытками WiFi.begin(wifi_ssid, wifi_pass); while ((WiFi.status() != WL_CONNECTED) && countWiFi--) { Serial.print(countWiFi); Serial.print('>'); delay(countPause); } digitalWrite(LED_BUILTIN, HIGH); // выключаем светодиод if (WiFi.status() == WL_CONNECTED) { // индикация IP Serial.print("\nWiFi connected - OK !\n"); Serial.println(WiFi.localIP()); // индикация силы сигнала int16_t dBm = WiFi.RSSI(); Serial.print("RSSI dBm = "); Serial.println(dBm); quality_RSSI = 2 * (dBm + 100); if (quality_RSSI >= 100) quality_RSSI = 100; Serial.print("RSSI % = "); Serial.println(quality_RSSI); Serial.println(); return true; } else { return false; } } //----------------------------------- void releWork() { if ((temperRoom - gisteresis) > temperRoom_ds18b20) { conditionHeater = true; digitalWrite(pinReley, conditionHeater); } else if ((temperRoom + gisteresis) < temperRoom_ds18b20) { conditionHeater = false; digitalWrite(pinReley, conditionHeater); } // if ((WiFi.status() == WL_CONNECTED) && client.connected()) // { // String topic = "/"; // topic += mqtt_client2; // topic += outTopicHeating; // mqtt_publish(client, topic, (!conditionHeater) ? "OFF" : "ON"); // } } //----------------------------------- void mqtt_callback(char *topic, byte *payload, unsigned int length) { // for (uint8_t i = 0; i < length; i++) // { // Serial.print((char)payload[i]); // } // Serial.println(); String temp = ""; char *topicBody = topic + strlen(mqtt_client2) + 1; if (!strncmp(topicBody, inTopicReboot, strlen(inTopicReboot))) { for (uint8_t i = 0; i < length; i++) temp += (char)payload[i]; if (temp.toInt()) { ESP.restart(); Serial.println("REBOOT !"); } } if (!strncmp(topicBody, inTopicTempRoom, strlen(inTopicTempRoom))) { for (uint8_t i = 0; i < length; i++) temp += (char)payload[i]; temperRoom = temp.toFloat(); byte raw[4]; (float &)raw = temperRoom; for (byte i = 0; i < 4; i++) EEPROM.write(0 + i, raw[i]); EEPROM.commit(); Serial.print("TempRoom: "); Serial.print(temperRoom); Serial.print("\t"); Serial.println(millis() / 1000); releWork(); } // if (!strncmp(topicBody, inTopicTempDS18b20, strlen(inTopicTempDS18b20))) // { // for (uint8_t i = 0; i < length; i++) // temp += (char)payload[i]; // temperRoom_ds18b20 = temp.toFloat(); // Serial.print("TempDs18b20: "); // Serial.println(temperRoom_ds18b20); // } } //----------------------------------- // бегущее среднее float expRunningAverage(float newVal) { static float filVal = 0; filVal += (newVal - filVal) * k; return filVal; } // медиана на 3 значения со своим буфером float medianRoom(float newValRoom) { static float bufRoom[3] = {0, 0, 0}; if (!(bufRoom[0] + bufRoom[1] + bufRoom[2])) bufRoom[0] = bufRoom[1] = bufRoom[2] = newValRoom; static byte countRoom = 0; bufRoom[countRoom] = newValRoom; if (++countRoom >= 3) countRoom = 0; float dataRoom = (max(bufRoom[0], bufRoom[1]) == max(bufRoom[1], bufRoom[2])) ? max(bufRoom[0], bufRoom[2]) : max(bufRoom[1], min(bufRoom[0], bufRoom[2])); // return expRunningAverage(data); return dataRoom; } float medianBoiler(float newValBoiler) { static float bufBoiler[3] = {0, 0, 0}; if (!(bufBoiler[0] + bufBoiler[1] + bufBoiler[2])) bufBoiler[0] = bufBoiler[1] = bufBoiler[2] = newValBoiler; static byte countBoiler = 0; bufBoiler[countBoiler] = newValBoiler; if (++countBoiler >= 3) countBoiler = 0; float dataBoiler = (max(bufBoiler[0], bufBoiler[1]) == max(bufBoiler[1], bufBoiler[2])) ? max(bufBoiler[0], bufBoiler[2]) : max(bufBoiler[1], min(bufBoiler[0], bufBoiler[2])); // return expRunningAverage(data); return dataBoiler; } //----------------------------------- void setup() { Serial.begin(9600); Serial.setTimeout(100); pinMode(pinReley, OUTPUT); digitalWrite(pinReley, LOW); // pinMode(pinDS18b20, OUTPUT); // digitalWrite(pinDS18b20, HIGH); client.setServer(mqtt_server, mqtt_port); client.setCallback(mqtt_callback); EEPROM.begin(4); byte raw[4]; for (byte i = 0; i < 4; i++) raw[i] = EEPROM.read(0 + i); float &num = (float &)raw; (num >= 10.0 && num <= 30.0) ? temperRoom = num : temperRoom = dataTempBase; // server.begin(); // httpUpdater.setup(&server); } //----------------------------------- void loop() { if ((WiFi.status() != WL_CONNECTED) || !client.connected()) { if (setupWiFi(ssid, pass)) if (reconnect()) { mqttReconnectOut(); // millisReconnect = millis() - millisOldReconnect; // millisOldReconnect = millis(); millisOld = millis() - pauseTimeTemp; } } //----------------------------------- if (Serial.available()) { String bufString = Serial.readString(); // читаем как строку uint8_t num_room_sensor = bufString.substring(0, 2).toInt(); if (num_room_sensor == sensorNumRoom_1) { temperRoom_ds18b20 = bufString.substring(3, 8).toFloat(); // medianRoom(bufString.substring(3, 8).toFloat()); } else if (num_room_sensor == sensorNumRoom_2) { temperRoom_dht11_1 = bufString.substring(2, 15); } else if (num_room_sensor == sensorNumRoom_3) { temperRoom_dht11_2 = bufString.substring(2, 15); } } //--------------------------------------------- if (millis() >= millisOld + pauseTimeTemp) { sensors.requestTemperatures(); temperBoiler_ds18b20 = sensors.getTempCByIndex(0); // medianBoiler(sensors.getTempCByIndex(0)); if (dataTempKotel <= temperBoiler_ds18b20) { conditionHeater = true; digitalWrite(pinReley, conditionHeater); } else { releWork(); } if ((WiFi.status() == WL_CONNECTED) && client.connected()) mqttDataOut(); millisOld = millis(); } //--------------------------------------------- // server.handleClient(); client.loop(); delay(1); }