Здравствуйте! Ваш проект лучший для изучения. Но есть несколько вопросов. mqtt работает только на отправку. Как лучше реализовать и прием? И не хватило знаний как в index.htm добавить еще одно меню без пароля.
Пока сделал так.
/* Инициализация GPIO для управления внешней нагрузкой */
gpio_12(); // Простое превышение температуры (выставляется в WEB интерфейсе)
// gpio_13(); // Простое превышение влажности (выставляется в WEB интерфейсе)
// gpio_14(); // Расхождение расчетной абсолютной влажности между показаниями с двух датчиков, например, BME280
/* Добавление в планировщик заданий по отправке данных на внешнии ресурсы */
cron.add(cron::time_1m, sendDataToMQTT); // Отправка данных MQTT брокеру
cron.add(cron::time_5m, sendDataToThingSpeak); // Отправка данных на сервер "ThingSpeak"
cron.add(cron::time_5m + cron::minute, sendDataToNarodmon); // Отправка данных на севрер "Народный мониторинг"
/* Добавление в планировщик заданий по контролю датчиков (холодный старт) */
sensors.checkLine(); // один раз
// cron.add(cron::time_12h, [&](){ sensors.checkLine(); }, true); // Проверка шины и инициализация датчиков при необходимости
cron.add(cron::time_5s, [&](){ sensors.dataUpdate(); }, true); // Сбор данных с датчиков
/* Добавление в планировщик задания (горячий старт) */
cron.add(cron::time_10m, [&](){ sensors.logUpdate(); }, "httpSensorsLog"); // Обновление журнала (httpSensorsLog - не обязательный уникальный ID для быстрого поиска задания другими программными модулями)
// получение данных по mqtt
mqttAPI.setCallback(callback);
}
void loop() {
/* Обработчики */
wifi.handleEvents();
http.handleClient();
cron.handleEvents();
if (wifi.transferDataPossible() and conf.param("mqtt_server").length()) {
mqttAPI.loop();
}
}
И в services
#ifndef SERVICES_H
#define SERVICES_H
#include <PubSubClient.h>
#include <ESP8266HTTPClient.h>
#include "webserver.h"
WiFiClient wifiClient;
PubSubClient mqttAPI(wifiClient);
String httpCodeStr(int code) {
switch(code) {
case -1: return "CONNECTION REFUSED";
case -2: return "SEND HEADER FAILED";
case -3: return "SEND PAYLOAD FAILED";
case -4: return "NOT CONNECTED";
case -5: return "CONNECTION LOST";
case -6: return "NO STREAM";
case -7: return "NO HTTP SERVER";
case -8: return "TOO LESS RAM";
case -9: return "ENCODING";
case -10: return "STREAM WRITE";
case -11: return "READ TIMEOUT";
default: return http.codeTranslate(code);
}
}
String mqttCodeStr(int code) {
switch (code) {
case -4: return "CONNECTION TIMEOUT";
case -3: return "CONNECTION LOST";
case -2: return "CONNECT FAILED";
case -1: return "MQTT DISCONNECTED";
case 0: return "CONNECTED";
case 1: return "CONNECT BAD PROTOCOL";
case 2: return "CONNECT BAD CLIENT ID";
case 3: return "CONNECT UNAVAILABLE";
case 4: return "CONNECT BAD CREDENTIALS";
case 5: return "CONNECT UNAUTHORIZED";
default: return String(code);
}
}
bool mqttPublish(String topic, String data) {
yield();
if (conf.param("mqtt_path").length()) topic = conf.param("mqtt_path") + "/" + topic;
return mqttAPI.publish(topic.c_str(), data.c_str(), true);
}
bool mqttPublish(String topic, float data) { return mqttPublish(topic, String(data)); }
bool mqttPublish(String topic, int32_t data) { return mqttPublish(topic, String(data)); }
bool mqttPublish(String topic, uint32_t data) { return mqttPublish(topic, String(data)); }
bool mqttSubscribe(String topic) {
yield();
if (conf.param("mqtt_path").length()) topic = conf.param("mqtt_path") + "/" + topic;
return mqttAPI.subscribe(topic.c_str());
}
void restAPIsend(String host, uint16_t port, String query) {
HTTPClient restAPI;
restAPI.setUserAgent("weather station " + WiFi.hostname());
restAPI.setTimeout(3000);
restAPI.begin(host, port, query);
int code = restAPI.GET();
#ifdef console
console.printf("answer: %s\n", httpCodeStr(code).c_str());
#endif
restAPI.end();
yield();
}
/* mqtt.it4it.club */
void callback(char* topic, byte* payload, unsigned int length) {
String Tmsg = "";
for (int i = 0; i < length; i++) {
Tmsg = Tmsg+(char)payload[i];
}
#ifdef console
console.print("Message arrived [");
console.print(topic);
console.print("/");
console.print(Tmsg);
console.println("]");
#endif
if (topic = "Meteo/tgaz") {
conf.param("gpio12", Tmsg);
#ifdef console
console.println(conf.param("gpio12"));
#endif
}
}
/* mqtt.it4it.club */
void reconnect() {
if (wifi.transferDataPossible() and conf.param("mqtt_server").length()) {
// баг при прямой передаче значения (c_str) из конфига в setServer (не забыть поправить!)
String server = conf.param("mqtt_server");
int port = conf.param("mqtt_port").toInt();
mqttAPI.setServer(server.c_str(), port);
mqttAPI.connect(WiFi.hostname().c_str(),
(conf.param("mqtt_login").length() ? conf.param("mqtt_login").c_str() : 0),
(conf.param("mqtt_pass").length() ? conf.param("mqtt_pass").c_str() : 0)
);
if (mqttAPI.connected()) {
#ifdef console
console.println(F("services: send data to MQTT server"));
#endif
mqttSubscribe("tgaz");
mqttPublish("t_need", conf.param("gpio12"));
mqttPublish("temperature", sensors.get("out_temperature"));
mqttPublish("humidity", sensors.get("out_humidity"));
mqttPublish("pressure", sensors.get("out_pressure"));
mqttPublish("co2", sensors.get("out_co2"));
} else {
#ifdef console
console.printf("answer: %s\n", mqttCodeStr(mqttAPI.state()).c_str());
#endif
}
}
}
void sendDataToMQTT() {
if (wifi.transferDataPossible() and conf.param("mqtt_server").length()) {
if (mqttAPI.connected()) {
#ifdef console
console.println(F("services: send data to MQTT server"));
#endif
mqttPublish("t_need", conf.param("gpio12"));
mqttPublish("temperature", sensors.get("out_temperature"));
mqttPublish("humidity", sensors.get("out_humidity"));
mqttPublish("pressure", sensors.get("out_pressure"));
mqttPublish("co2", sensors.get("out_co2"));
} else {
reconnect();
#ifdef console
#endif
}
}
}
/* https://thingspeak.com/ */
void sendDataToThingSpeak() {
if (wifi.transferDataPossible() and conf.param("thingspeak_key").length()) {
#ifdef console
console.println(F("services: send data to ThingSpeak"));
#endif
String query;
query += "&field1=" + String(sensors.get("out_light"));
query += "&field2=" + String(sensors.get("out_temperature"));
query += "&field3=" + String(sensors.get("out_humidity"));
query += "&field4=" + String(sensors.get("out_pressure"));
query += "&field5=" + String(sensors.get("out_co2"));
restAPIsend("api.thingspeak.com", 80, "/update?api_key=" + conf.param("thingspeak_key") + query);
}
}
/* https://narodmon.ru/ */
void sendDataToNarodmon() {
if (wifi.transferDataPossible() and conf.param("narodmon_id").length()) {
#ifdef console
console.println(F("services: send data to Narodmon"));
#endif
String query;
query += "&L1=" + String(sensors.get("out_light"));
query += "&T1=" + String(sensors.get("out_temperature"));
query += "&H1=" + String(sensors.get("out_humidity"));
query += "&P1=" + String(sensors.get("out_pressure"));
query += "&CO2=" + String(sensors.get("out_co2"));
// query += "&H2=" + String(sensors.get("out_absoluteHumidity"));
restAPIsend("narodmon.ru", 80, "/get?id=" + conf.param("narodmon_id") + query);
}
}
#endif