From fe80320b1d9bdfc343a90aabbdf9cb1edc06cd80 Mon Sep 17 00:00:00 2001 From: SmartUA Date: Wed, 5 May 2021 19:33:23 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D1=81=D0=BB=D0=B5=D0=B4=D0=BD?= =?UTF-8?q?=D0=B8=D0=B9=20=D0=BA=D0=BE=D0=B4=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B4=20=D0=BE=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=BE=D0=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AAOffice_kitchen.ino | 72 ++++++++++++++++++++++++++++++------------- README.md | 43 ++++++++++++++++---------- Описание.docx | Bin 0 -> 15352 bytes 3 files changed, 77 insertions(+), 38 deletions(-) create mode 100644 Описание.docx diff --git a/AAOffice_kitchen.ino b/AAOffice_kitchen.ino index 0a9c7da..cbfb4e0 100644 --- a/AAOffice_kitchen.ino +++ b/AAOffice_kitchen.ino @@ -41,7 +41,7 @@ StaticJsonDocument<200> doc; WiFiClient espClient; PubSubClient MqttClient(espClient); -IPAddress IpMqtt(192, 168, 89, 210); +IPAddress IpMqtt(192, 168, 89, 210); WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP, "192.168.89.210", 0, 60000); //Собственно сервер времени смещение и частоат запроса, но он вручную @@ -49,14 +49,18 @@ NTPClient timeClient(ntpUDP, "192.168.89.210", 0, 60000); //Собственно const char *wmhostname = "KitchenWater"; const PROGMEM char *willmess = "{\"conn\":\"err\"}"; -const PROGMEM char *mqttHostName = "192.168.89.210"; //Хостнейм брокера 192.168.89.210 cctv.automation.art:8889 -unsigned int mqttPort = 1883; // 1883 //Порт брокера 1883 +//const PROGMEM char *mqttHostName = "192.168.0.111"; //Хостнейм брокера 192.168.89.210 cctv.automation.art:8889 + +unsigned int mqttPort = 1883; // 1883 //Порт брокера 1883 + const PROGMEM char *mqttLogin = "AA_Lab", *mqttPass = "automation.art$"; const char *mqttIPHost; - + //тут хранится IP хоста по хостнейму -unsigned long timingUpdate, timingReqSensor, timingSendMqtt; //Таймеры для millis() -int PROGMEM nextM5Update = 450000; //каждые 7.5 минут запрос обновления с сервера //опрос датчиков раз в 10 секунд +unsigned long timingUpdate, timingSendStatus; //Таймеры для millis() +int PROGMEM nextM5Update = 18050000; //каждые 7.5 минут запрос обновления с сервера //опрос датчиков раз в 10 секунд +int PROGMEM nextSendStatus = 10000; + String getMacAddress(); String macc = getMacAddress(); @@ -68,7 +72,7 @@ int reqCounter = 0; short int rssi = 0; bool flagHIGH = false; char bufTopic[140], bufWillTopic[150]; - + volatile short int debounce = 0; TaskHandle_t Task1; @@ -146,7 +150,7 @@ void setup() String willTopicTemp = "aastudio/sens/" + macc + "/status"; Serial.println(topicTemp); - Serial.println(willTopicTemp); + Serial.println(willTopicTemp); topicTemp.toCharArray(bufTopic, topicTemp.length() + 1); willTopicTemp.toCharArray(bufWillTopic, willTopicTemp.length() + 1); @@ -164,15 +168,15 @@ void setup() // wm.setShowStaticFields(true); // force show static ip fields // wm.setShowDnsFields(true); // force show dns field always // wm.setConnectTimeout(20); // how long to try to connect for before continuing - wm.setConfigPortalTimeout(1); // auto close configportal after n seconds + wm.setConfigPortalTimeout(35); // auto close configportal after n seconds // wm.setCaptivePortalEnable(false); // disable captive portal redirection // wm.setAPClientCheck(true); // avoid timeout if client connected to softap // wifi scan settings // wm.setRemoveDuplicateAPs(false); // do not remove duplicate ap names (true) - wm.setMinimumSignalQuality(10); // set min RSSI (percentage) to show in scans, null = 8% + wm.setMinimumSignalQuality(15); // set min RSSI (percentage) to show in scans, null = 8% // wm.setShowInfoErase(false); // do not show erase button on info page wm.setScanDispPerc(true); // show RSSI as percentage not graph icons - wm.setConfigPortalBlocking(false); + //wm.setConfigPortalBlocking(false); // wm.setBreakAfterConfig(true); // always exit configportal even if wifi save fails wm.setWiFiAutoReconnect(true); // if true, enable autoreconnecting //wm.setHostname(wmhostname); @@ -466,7 +470,8 @@ int SendMqttReq(bool sendVal = true, bool sendStatus = true, byte statusConn = 1 doc["bsid"] = WiFi.BSSIDstr(); //doc["lasterror"] = errorID; doc["ts"] = timeNow; - doc["sv"] = VersionSW; + doc["exp"] = timeNow+15; + doc["sv"] = VersionSW; JsonData = ""; serializeJson(doc, JsonData); @@ -575,15 +580,14 @@ void Task1code(void *pvParameters) attachInterrupt(digitalPinToInterrupt(safetyPin), detectWaterOn, CHANGE); } - if (M5.Btn.pressedFor(60000)) + if (M5.Btn.pressedFor(90000)) { checkButton(); } - if (M5.Btn.pressedFor(2000)) + if (M5.Btn.wasReleasefor(2000)) { - Serial.println("KNOPKA SUKA"); - BuzTicker.detach(); + BuzTicker.detach(); } MqttClient.loop(); @@ -595,15 +599,27 @@ void Task1code(void *pvParameters) void Task2code(void *pvParameters) { for (;;) - { + { M5.update(); - wm.process(); + // wm.process(); if (WiFi.status() != WL_CONNECTED) { disPreSet((uint8_t *)image_wifi, 0, 0); } + +// if (WiFi.status() != WL_CONNECTED) +// { +// Serial.println(WiFi.status()); +// disPreSet((uint8_t *)image_wifi, 0, 0); +// errorID = 6; +// delay(3000); +// ESP.restart(); +// } + + + if (safetyStateNow != safetyStateOld) { Serial.println("safetyStateNow != safetyStateOld"); @@ -621,17 +637,31 @@ void Task2code(void *pvParameters) disPreSet((uint8_t *)image_arrow, 0, 0); } + + if (millis() - timingSendStatus > nextSendStatus) + { + SendMqttReq(false, true, 1); + timingSendStatus = millis(); + } + + + //По таймеру запруск обновления прошивки if (millis() - timingUpdate > nextM5Update) { SendMqttReq(false, true, 4); - // reqNtpTime(); + reqNtpTime(); OTAUpdate(); - // //Serial.print("OTAUpdate() - "); - // //Serial.println(millis()); + SendMqttReq(false, true, 1); timingUpdate = millis(); } + + + + + + //Таймер отправки данных в брокер if (!MqttClient.connected()) diff --git a/README.md b/README.md index 1db0db9..c2e2ff7 100644 --- a/README.md +++ b/README.md @@ -4,27 +4,38 @@ Подать питание после подключения датчика. -aastudio/94B97E92C24C/data/0 - -{"val":1,"ts":1615825905} - - -aastudio/94B97E92C24C/status -{"conn":"on","rssi":-74,"bsid":"70:4F:57:AA:2F:8A","ts":1615825905,"sv":2} -{"conn": "err"} - - - -Обозначения на схеме: - -"+" - подача питания 5 В (для удобства подключения всех проводов с одной стороны). Можно взять,но не более 0.5А (предохранитель) если питание от USB. +Обозначения на клемнике: +"+" - подача питания 5 В (для удобства подключения всех проводов с одной стороны). Можно взять для питания еще чего то от атома, но не более 0.5А (предохранитель) если питание от USB. "-" - ground "->" - уходящий сигнал на датчик 3.3В "<-" - приходящий сигнал через поплавок -{"swver":5,"waterlevel":1,"rssi":-69,"bsid":"70:4F:57:AA:2F:8A","lasterror":7,"time":1615576359} +Топики: +aastudio/sens/94B97E92C24C/data/0 +{"val":1,"ts":1616771531} + +aastudio/sens/94B97E92C24C/status +{"conn":"on","rssi":-65,"bsid":"08:55:31:57:99:A7","ts":720,"exp":735,"sv":3} +{"conn": "err"} + + +Отправка статуса каждые 10 секунд. + +Для отключения Бузера необходимо нажать на экран в течении 2х секунд. +При длительном нажатии кнопки более 90 секунд - сброс +Запрос обновления прошивки раз в 7 часов + +Датчик следует подключать к проводам или клемнику напрямую, скруткой или спайкой для избежания наводок и ненадежных соединиений. + + +Желтый круг - проблема подключения к MQTT +Красный знак - проблема подключения к WIFI +Зеленые точки - все хорошо. +Красная стрелочка указывающая вниз на синюю воду - сработка. + +Бузер срабатывает в любом режиме, независимо от подключения к Wifi или Mqtt. Экран @@ -33,8 +44,6 @@ https://github.com/m5stack/M5Atom/blob/master/README.md http://wikihandbk.com/wiki/ESP32:%D0%9F%D1%80%D0%B8%D0%BC%D0%B5%D1%80%D1%8B/%D0%98%D1%81%D0%BF%D0%BE%D0%BB%D1%8C%D0%B7%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_ESP32_%D0%B2%D0%BC%D0%B5%D1%81%D1%82%D0%B5_%D1%81_PIR-%D0%B4%D0%B0%D1%82%D1%87%D0%B8%D0%BA%D0%BE%D0%BC_%D0%B4%D0%B2%D0%B8%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F - - Старт diff --git a/Описание.docx b/Описание.docx new file mode 100644 index 0000000000000000000000000000000000000000..0e5ef1cd1fdc21643cd2efe0cb38cc2b6b66f643 GIT binary patch literal 15352 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 z