From ad8afd58e32dec3463af15e78b68a4a92059bb87 Mon Sep 17 00:00:00 2001 From: vlapa Date: Sat, 13 Jun 2026 21:13:35 +0300 Subject: First --- src/main.cpp | 484 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 484 insertions(+) create mode 100644 src/main.cpp (limited to 'src/main.cpp') diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..390a297 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,484 @@ +/* + Система контроля температуры для управления котлом + * СЕРВЕР * = 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); +} \ No newline at end of file -- cgit v1.2.3