diff --git a/M5Atom_airqa.ino b/M5Atom_airqa.ino index ee055e3..f9ff406 100644 --- a/M5Atom_airqa.ino +++ b/M5Atom_airqa.ino @@ -30,11 +30,11 @@ //Наша кнопочка при нажатии на которую произойдет вызов wifi менеджера и перезагрузка в станцию #define TRIGGER_PIN 39 -unsigned int VersionSW = 22; //65536 Версия прошивки +unsigned int VersionSW = 225; //65536 Версия прошивки //15 - добавлено то, се, забыл вообще дописать что добавленоSerial //19 - вывод в консоль всех действий, ошибки с обновлнеием - починил, прияногое мигание светодиодом, тест для поиска metrics. -//21 - убран мак из вывода в топике +//21 - убран мак из вывода в топике //22 - поправлено поиск сервера по metrics local. WiFiManager wm; // обьект менеджера @@ -54,11 +54,17 @@ IPAddress IpMqtt; WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "0.ua.pool.ntp.org", 7200, 60000); //Собственно сервер времени смещение и частоат запроса, но он вручную -const PROGMEM char *mqttHostName = "metrics"; //Хостнейм брокера metrics.local //192.168.89.210 -unsigned int mqttPort = 1883; //Порт брокера 1883 -const PROGMEM char *topicName = "/aastudio/"; // +mac адресс девайса Префикс топика -const PROGMEM char *mqttLogin = "login", //Логин пароль - необходимо сменить код при connect() +const PROGMEM char *mqttHostName = "cctv.automation.art"; //Хостнейм брокера metrics.local cctv.automation.art //192.168.89.210 +unsigned int mqttPort = 8889; //Порт брокера 1883 8889 + +String getMacAddress(); +String macc = getMacAddress(); + +char *topicName, *willTopicName; +// +mac адресс девайса Префикс топика +const PROGMEM char *mqttLogin = "login", //Логин пароль - необходимо сменить код при connect() *mqttPass = "password"; + const char *mqttIPHost; //тут хранится IP хоста по хостнейму unsigned long timingUpdate, timingReqSensor, timingSendMqtt; //Таймеры для millis() @@ -74,12 +80,10 @@ int PROGMEM nextMqttSend = 60000; //Отправка float PROGMEM tcoeff[3] = {-11.18, -9.62, -10.6}; //Температура float PROGMEM hcoeff[3] = {13.77, 14.07, 15.56}; //Влажность float callibrationT = 0, callibrationH = 0; -String macc = ""; //Глобальное хранение мас адреса float TempAv, HumAv, Eco2Av, TvocAv; byte errorID = 0; long rssi = 0; -//int hall=0; //Кусок кода поправить - так делать нельзя #define NUM_AVER 5 @@ -117,15 +121,30 @@ void setup() digitalWrite(23, LOW); WiFi.mode(WIFI_STA); - Serial.begin(115200); - Serial.setDebugOutput(true); - delay(3000); + //////Serial.begin(115200); + //////Serial.setDebugOutput(true); + delay(1000); - Serial.println("\n Starting station"); + char prefix[] = "/aastudio/"; + char statusPrefix[] = "/status"; + char bufprefix[200]; + + char maccbuff[15]; + macc.toCharArray(maccbuff, 15); + + strcpy(prefix, bufprefix); + strcpy(maccbuff, bufprefix); + topicName = bufprefix; + + strcpy(statusPrefix, bufprefix); + + willTopicName = bufprefix; + + //////Serial.println("\n Starting station"); pinMode(TRIGGER_PIN, INPUT); // wm.resetSettings(); // wipe settings // add a custom input field - int customFieldLength = 40; + // int customFieldLength = 40; // new (&custom_field) WiFiManagerParameter("customfieldid", "Custom Field Label", "Custom Field Value", customFieldLength,"placeholder=\"Custom Field Placeholder\""); // test custom html input type(checkbox) // new (&custom_field) WiFiManagerParameter("customfieldid", "Custom Field Label", "Custom Field Value", customFieldLength,"placeholder=\"Custom Field Placeholder\" type=\"checkbox\""); // custom html type @@ -162,17 +181,17 @@ void setup() res = wm.autoConnect("AirQaPortal", "12345678"); // Подключение к анонимной точке доступа if (!res) { - Serial.println("Failed to connect or hit timeout"); + //////Serial.println("Failed to connect or hit timeout"); // ESP.restart(); } else { - Serial.println("Server AirQaPortal start"); + //////Serial.println("Server AirQaPortal start"); } if (!ccs.begin()) //The device's I2C address is 0x5A { - Serial.println("Failed to start sensor CCS811! "); + //////Serial.println("Failed to start sensor CCS811! "); } ccs.setTempOffset(8.6); @@ -190,53 +209,56 @@ void setup() //Установка сервера и порта void setMqttServer() { - // Serial.println("======WHERE IS METRICS.LOCAL====="); mdns_init(); - // Serial.print("MDNS SAY: "); - IPAddress ipaddr = MDNS.queryHost("metrics"); // .local omitted - // Serial.println(ipaddr.toString()); - - if(ipaddr.toString() == "0.0.0.0") { - Serial.println("Trying again to resolve mDNS"); + + IPAddress IpMqtt, ipaddr; + + ipaddr = MDNS.queryHost(mqttHostName); // .local omitted + // //////Serial.println(ipaddr.toString()); + if (ipaddr.toString() == "0.0.0.0") + { + Serial.println("MDNS.queryHost==0.0.0.0"); + + int err = WiFi.hostByName(mqttHostName, IpMqtt); + if (err == 1) + { + delay(50); + setServCall(IpMqtt); + } + else + { + Serial.print("Error code hostByName(): "); + Serial.println(err); + } } - else { - MqttClient.setServer(ipaddr, mqttPort); - MqttClient.setCallback(callback); - Serial.println("Set MQTT Server - OK"); + else + { + setServCall(ipaddr); } - // Serial.print("HOSTBYNAME SAY: "); - // int errtest = WiFi.hostByName("metrics", ipaddr); - // Serial.println(ipaddr.toString()); - // Serial.println("=======END TEST======"); + Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str()); + Serial.println(ESPhttpUpdate.getLastError()); + Serial.println(ESPhttpUpdate.getLastErrorString().c_str()); +} - // int err = WiFi.hostByName(mqttHostName, IpMqtt); - // if (err == 1) - // { - // delay(50); - - // MqttClient.setServer(IpMqtt, mqttPort); - // MqttClient.setCallback(callback); - // Serial.println("Set MQTT Server - OK"); - // } - // else - // { - // Serial.print("Error code hostByName(): "); - // Serial.println(err); - // } +void setServCall(IPAddress SetIpaddr) +{ + MqttClient.setServer(SetIpaddr, mqttPort); + MqttClient.setCallback(callback); + //////Serial.println("Set MQTT Server - OK"); } //Функция получения данных из MQTT если мы подпишемся на топики void callback(char *topic, byte *payload, unsigned int length) { - Serial.print("Message arrived ["); - Serial.print(topic); - Serial.print("] "); + //////Serial.print("Message arrived ["); + //////Serial.print(topic); + ////Serial.print("] "); for (int i = 0; i < length; i++) { - Serial.print((char)payload[i]); + ////Serial.print((char)payload[i]); } - Serial.println(); + ////Serial.println(); } //Запрос времени NTP и установка локлаьного времени @@ -245,9 +267,9 @@ void reqNtpTime() timeClient.update(); uint32_t timeEpoch = timeClient.getEpochTime(); setTime(timeEpoch); - Serial.print(timeEpoch); - Serial.print(" <=ntp== ==device=> "); - Serial.println(now()); + ////Serial.print(timeEpoch); + ////Serial.print(" <=ntp== ==device=> "); + ////Serial.println(now()); if (timeEpoch < 100000) { errorID = 1; @@ -257,23 +279,26 @@ void reqNtpTime() //Нажатие кнопки для сброса void checkButton() { - Serial.println("Button Pressed to RESET"); + ////Serial.println("Button Pressed to RESET"); wm.resetSettings(); + + disconnectMQTT(); + ESP.restart(); - Serial.println("Starting config portal"); + ////Serial.println("Starting config portal"); wm.setConfigPortalTimeout(120); if (!wm.startConfigPortal("AirQaPortal", "12345678")) //Логин и пароль точки доступа { - Serial.println("failed to connect or hit timeout"); + ////Serial.println("failed to connect or hit timeout"); delay(1000); // ESP.restart(); } else { - Serial.println("Clien connected to AP"); + ////Serial.println("Clien connected to AP"); } } @@ -289,30 +314,24 @@ String getParam(String name) void saveParamCallback() { - Serial.println("[CALLBACK] saveParamCallback fired"); - Serial.println("PARAM customfieldid = " + getParam("customfieldid")); + ////Serial.println("[CALLBACK] saveParamCallback fired"); + ////Serial.println("PARAM customfieldid = " + getParam("customfieldid")); } //Обновление прошивки, происходит проверка и загрузка void OTAUpdate() { - Serial.println("OTAUpdate() START"); + ////Serial.println("OTAUpdate() START"); bool flagOTA = false; String keyOTA; String payload; - OTApreferences.begin("ota-config"); - if (WiFi.status() == WL_CONNECTED) { HTTPClient http; - String getMacNow = getMacAddress(); - //const char *clientId = macc.c_str(); + String serverPath = "http://meteosence.s-host.net/airqa/airquality.php?meteopas=e93gme9hAt9nSWaV&mac=" + macc + "&meteodata=gethash"; - String serverPath = "http://meteosence.s-host.net/airqa/airquality.php?meteopas=e93gme9hAt9nSWaV&mac=" + getMacNow + "&meteodata=gethash"; - - Serial.print("URL and GET request: "); Serial.println(serverPath); http.begin(serverPath.c_str()); @@ -320,15 +339,16 @@ void OTAUpdate() if (httpResponseCode > 0) { - Serial.print("HTTP Response code: "); - Serial.println(httpResponseCode); + ////Serial.print("HTTP Response code: "); + ////Serial.println(httpResponseCode); payload = http.getString(); - Serial.print("Data from HTTP request (OTA Hash): "); - Serial.println(payload); + ////Serial.print("Data from HTTP request (OTA Hash): "); + ////Serial.println(payload); if (payload != "errno" || payload != "errfi") { + OTApreferences.begin("ota-config"); keyOTA = OTApreferences.getString("md5HashOTA"); if (keyOTA.length() <= 0) @@ -336,29 +356,29 @@ void OTAUpdate() OTApreferences.putString("md5HashOTA", "undifined"); } - - Serial.print("md5HashOTA in device: "); + ////Serial.print("md5HashOTA in device: "); keyOTA = OTApreferences.getString("md5HashOTA"); - Serial.println(keyOTA); + ////Serial.println(keyOTA); if (payload != keyOTA) { flagOTA = true; OTApreferences.putString("md5HashOTA", payload); - Serial.println("flagOTA = true;"); + ////Serial.println("flagOTA = true;"); } + OTApreferences.end(); } else { - Serial.print("Hosting return error: "); - Serial.println(payload); + ////Serial.print("Hosting return error: "); + ////Serial.println(payload); errorID = 3; } } else { - Serial.print("Error HTTP Response code: "); - Serial.println(httpResponseCode); + ////Serial.print("Error HTTP Response code: "); + ////Serial.println(httpResponseCode); errorID = 2; } // Free resources @@ -366,21 +386,28 @@ void OTAUpdate() } else { - Serial.println("WHY WiFi is Disconnected??"); + ////Serial.println("WHY WiFi is Disconnected??"); } if (flagOTA == true) { - flagOTA = false; - Serial.println("flagOTA = false;"); + // flagOTA = false; + // ////Serial.println("flagOTA = false;"); + + disconnectMQTT(); + + ESPhttpUpdate.rebootOnUpdate(true); t_httpUpdate_return ret = ESPhttpUpdate.update("http://meteosence.s-host.net/airqa/airatoms.bin"); //После update ничего не происходит, такая вот особенность. //Если все прошло хорошо, перезагрузка на новую прошивку - Serial.print("ret "); - Serial.println(ret); + // Если указано значение true, модуль ESP перезагрузится после успешного завершения обновления. В случае ложного , модуль не перезагружается автоматически. Загруженная новая прошивка остается в стадии обновления флэш-памяти на модуле ESP. + // Процесс загрузки во время следующего запуска модуля путем сброса скопирует обновленное микропрограммное обеспечение в фактическую область программы, и запустится новая программа эскиза. Значение по умолчанию верно. + + ////Serial.print("ret "); + ////Serial.println(ret); switch (ret) { @@ -388,7 +415,7 @@ void OTAUpdate() Serial.printf("HTTP_UPDATE_FAILD Error (%d): %s", ESPhttpUpdate.getLastError(), ESPhttpUpdate.getLastErrorString().c_str()); Serial.println(ESPhttpUpdate.getLastError()); Serial.println(ESPhttpUpdate.getLastErrorString().c_str()); - Serial.println("HTTP_UPDATE_FAILD Error"); + //Serial.println("HTTP_UPDATE_FAILD Error"); delay(3000); ESP.restart(); break; @@ -406,7 +433,6 @@ void OTAUpdate() break; } } - OTApreferences.end(); } //Функция для индикации Led @@ -486,15 +512,13 @@ String getMacAddress() //Установка коефициентов калибровки void SetCallibrationCoeff() { - // Serial.print("Mac: "); - // Serial.println(getMacAddress()); + // ////Serial.print("Mac: "); + // ////Serial.println(getMacAddress()); //[24A160474D14, 5002919F5450, 5002918A38CC] //tcoeff[0,1,2] //hcoeff[0,1,2] - macc = getMacAddress(); - if (macc == "24A160474D14") { callibrationT = tcoeff[0]; @@ -516,16 +540,7 @@ void SetCallibrationCoeff() //Ниже отдельные функции средних арифметических для каждого параместра с историей float middleArifmT(float newVal) { - // Serial.print(newVal); - // Serial.print(" "); - // принимает новое значение valArrayT[idxT] = newVal; // пишем каждый раз в новую ячейку - // for (int t = 0; t <= 6; t++) - // { - // Serial.print(valArrayT[t]); - // Serial.print(" "); - // } - if (++idxT >= NUM_AVER) idxT = 0; // перезаписывая самое старое значение averageT = 0; // обнуляем среднее @@ -535,7 +550,7 @@ float middleArifmT(float newVal) } averageT /= NUM_AVER; // делим - // Serial.println(averageT); + // ////Serial.println(averageT); return averageT; // возвращаем } @@ -608,18 +623,23 @@ void reqSensorData() hdc1080Temp = hdc1080.readTemperature() + callibrationT; hdc1080Hum = hdc1080.readHumidity() + callibrationH; - if(hdc1080Temp < -40 || hdc1080Temp > 60 ) { errorID = 6; } + if (hdc1080Temp < -40 || hdc1080Temp > 60) + { + errorID = 6; + } - if(hdc1080Hum < 0 || hdc1080Temp > 100 ) { errorID = 7; } - // Serial.println("Original data: "); - // Serial.println(hdc1080.readTemperature()); - // Serial.println(hdc1080.readHumidity()); - - // Serial.println("Calibration data: "); - // Serial.print(hdc1080Temp); - // Serial.println(" "); - // Serial.println(hdc1080Hum); + if (hdc1080Hum < 0 || hdc1080Temp > 100) + { + errorID = 7; + } + // ////Serial.println("Original data: "); + // ////Serial.println(hdc1080.readTemperature()); + // ////Serial.println(hdc1080.readHumidity()); + // ////Serial.println("Calibration data: "); + // ////Serial.print(hdc1080Temp); + // ////Serial.println(" "); + // ////Serial.println(hdc1080Hum); TempAv = middleArifmT(hdc1080Temp); HumAv = middleArifmH(hdc1080Hum); @@ -627,7 +647,7 @@ void reqSensorData() TvocAv = middleArifmTVOC(tvoc); rssi = WiFi.RSSI(); - // hall=hallRead(); + // hall=hallRead(); if (hdc1080Hum > 50 || hdc1080Hum < 39) { @@ -653,27 +673,18 @@ void reqSensorData() //Отправка данных по MQTT void SendMqttReq() { - //Serial.println("Data in SendMqttReq()"); - // Serial.print(TempAv); - // Serial.print(" "); - // Serial.print(HumAv); - // Serial.print(" "); - // Serial.print(Eco2Av); - // Serial.print(" "); - // Serial.println(TvocAv); char HumidityInt[8], TemperatureInt[8]; dtostrf(TempAv * 100, 4, 0, TemperatureInt); dtostrf(HumAv * 100, 4, 0, HumidityInt); - // doc["mac"] = String(getMacAddress()); doc["swver"] = VersionSW; doc["t"] = atoi(TemperatureInt); doc["h"] = atoi(HumidityInt); doc["eco"] = (int)Eco2Av; doc["tvoc"] = (int)TvocAv; doc["rssi"] = rssi; - // doc["hall"]= hall; + // doc["hall"]= hall; doc["error"] = errorID; //По умолчанию 0 doc["time"] = now(); @@ -684,14 +695,11 @@ void SendMqttReq() Serial.println(JsonData); //Вывод JSON строки в консоль JsonData.toCharArray(resultString, JsonData.length() + 1); - String finishTopic = ""; - finishTopic = String(topicName) + "/" + macc; - //Serial.println(finishTopic); if (mqttSendFlag == true) { - MqttClient.publish(finishTopic.c_str(), resultString); - //Serial.println("SentToTopic - ok"); - errorID=0; + MqttClient.publish(topicName, resultString, true); + //////Serial.println("SentToTopic - ok"); + errorID = 0; } } @@ -706,34 +714,58 @@ void reconnectMqtt() byte circle = 0; while (!MqttClient.connected()) { - Serial.print("MQTT reconnect..."); + ////Serial.print("MQTT reconnect..."); circle++; - if (circle == 10) + if (circle == 5) { break; - } + } const char *clientId = macc.c_str(); //macc += String(random(0xffff), HEX); - if (MqttClient.connect(clientId)) + //const char *id, + // const char *user, + // const char *pass, + // const char* willTopic, + // uint8_t willQos, + // boolean willRetain, + // const char* willMessage, + // boolean cleanSession + + //String WillfinishTopic = String(topicName) + macc + String(willTopicName); + ////Serial.println(WillfinishTopic); + + if (MqttClient.connect(clientId, NULL, NULL, willTopicName, 2, true, "Offline")) { //String finishTopic = ""; // finishTopic = String(topicName) + "/" + macc; - //MqttClient.publish(finishTopic.c_str(), "Reconnect NOW"); + MqttClient.publish(topicName, "CONNECT", true); - Serial.println("Reconnect NOW"); - errorID=8; + ////Serial.println("Reconnect NOW"); + errorID = 8; // client.subscribe("inTopic"); mqttSendFlag = true; } else { - Serial.print("failed сonnect to MQTT, rc="); + ////Serial.print("failed сonnect to MQTT, rc="); Serial.println(MqttClient.state()); + /* + -4 : MQTT_CONNECTION_TIMEOUT - the server didn't respond within the keepalive time + -3 : MQTT_CONNECTION_LOST - the network connection was broken + -2 : MQTT_CONNECT_FAILED - the network connection failed + -1 : MQTT_DISCONNECTED - the client is disconnected cleanly + 0 : MQTT_CONNECTED - the client is connected + 1 : MQTT_CONNECT_BAD_PROTOCOL - the server doesn't support the requested version of MQTT + 2 : MQTT_CONNECT_BAD_CLIENT_ID - the server rejected the client identifier + 3 : MQTT_CONNECT_UNAVAILABLE - the server was unable to accept the connection + 4 : MQTT_CONNECT_BAD_CREDENTIALS - the username/password were rejected + 5 : MQTT_CONNECT_UNAUTHORIZED - the client was not authorized to connect + */ mqttSendFlag = false; - delay(1000); + delay(100); } } } @@ -756,8 +788,8 @@ void loop() { reqNtpTime(); OTAUpdate(); - // Serial.print("OTAUpdate() - "); - // Serial.println(millis()); + // ////Serial.print("OTAUpdate() - "); + // ////Serial.println(millis()); timingUpdate = millis(); } @@ -766,8 +798,8 @@ void loop() { reqSensorData(); ledset('b', true); - // Serial.print("reqSensorData() - "); - // Serial.println(millis()); + // ////Serial.print("reqSensorData() - "); + // ////Serial.println(millis()); timingReqSensor = millis(); } @@ -786,10 +818,17 @@ void loop() ledset('w', true); } - // Serial.println("============="); + // ////Serial.println("============="); // rssi = WiFi.RSSI(); - // Serial.println(rssi); - // Serial.println("============="); + // ////Serial.println(rssi); + // ////Serial.println("============="); MqttClient.loop(); } + +int disconnectMQTT() +{ + MqttClient.publish(topicName, "DISCONNECT", false); + MqttClient.disconnect(); + return 0; +} \ No newline at end of file diff --git a/README.md b/README.md index 8477ed7..30315fe 100644 --- a/README.md +++ b/README.md @@ -53,3 +53,10 @@ Информация для датчика 1080 https://www.terraelectronica.ru/news/5287 + + +https://pubsubclient.knolleary.net/api.html + +https://ipc2u.ru/articles/prostye-resheniya/chto-takoe-mqtt/#kachestvo + +https://www.hivemq.com/blog/mqtt-essentials-part-9-last-will-and-testament/ \ No newline at end of file