Господа форумчане! Всех с Наступающим!
Может образуется у кого минутка глянуть код. Не пойму в чём причина. Собран код из двух отдельных. По отдельности работает каждый. Если месте, только та часть которая отсылает статус нажатой кнопки в MQTT, а включение реле из клиента не происходит. Статус устройства тоже передаётся без проблем. В порт постоянно летит: Failed to recognize incoming topic! - т.е. нет подписки на исходящие топики Publish. Подозреваю, что где-то заковырка с циклами.
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
const int button1 = 16; // указываем пин D0 GPIO16 для первой кнопки
const int button2 = 5; // указываем пин D1 GPIO5 для второй кнопки
const int button3 = 4; // указываем пин D2 GPIO4 для третьей кнопки
const int gpioRelay3 = 14; // указываем пин D5 GPIO14 для реле 1
const int gpioRelay1 = 12; // указываем пин D6 GPIO12 для реле 2
const int gpioRelay2 = 13; // указываем пин D7 GPIO13 для реле 3
const int relayOn = 0x1; // Уровни управления реле
const int relayOff = 0x0; // Уровни управления реле
//const char* ssid = "***"; // Имя точки доступа Wi-Fi
//const char* password = "***"; // Пароль от точки доступа
const char* ssid = "***"; // Имя точки доступа Wi-Fi
const char* password = "***"; // Пароль от точки доступа
const char* mqtt_server = "***"; // Имя сервера MQTT
const int mqtt_port = ***; // Порт для подключения к серверу MQTT
const char* mqtt_clientId = "***"; // определяем ID
const char* mqtt_user = "***"; // Логин от сервера
const char* mqtt_pass = "***"; // Пароль от сервера
const char* mqttTopicControlRelay1 = "relay1/control"; // Топик для внешнего управления реле 1
const char* mqttTopicControlRelay2 = "relay2/control"; // Топик для внешнего управления реле 2
const char* mqttTopicControlRelay3 = "relay3/control"; // Топик для внешнего управления реле 3
const int mqttRelayControlQos = 1;
const char* mqttTopicStatusRelay1 = "relay1/status"; // Топики для публикации статуса реле 1
const char* mqttTopicStatusRelay2 = "relay2/status"; // Топики для публикации статуса реле 2
const char* mqttTopicStatusRelay3 = "relay3/status"; // Топики для публикации статуса реле 3
const char* mqttRelayStatusOn = "on"; // Текстовое отображение для состояния реле
const char* mqttRelayStatusOff = "off"; // Текстовое отображение для состояния реле
const bool mqttRelayStatusRetained = false; // Текстовое отображение для состояния реле
const char* mqttTopicDeviceStatus = "device/status";
const char* mqttDeviceStatusOn = "online";
const char* mqttDeviceStatusOff = "offline";
const int mqttDeviceStatusQos = 1;
const bool mqttDeviceStatusRetained = true;
byte gpioStatus1 = relayOff; // Текущее состояние реле 1
byte gpioStatus2 = relayOff; // Текущее состояние реле 2
byte gpioStatus3 = relayOff; // Текущее состояние реле 3
byte relaySetStatus1 = relayOff; // Полученное ("новое") состояние реле 1
byte relaySetStatus2 = relayOff; // Полученное ("новое") состояние реле 2
byte relaySetStatus3 = relayOff; // Полученное ("новое") состояние реле 3
#define BUFFER_SIZE 100
void callback(char* topic, byte* payload, unsigned int length); // Функция обработки входящих сообщений
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0; // Время публикации предыдущего сообщения (мс)
#define MSG_BUFFER_SIZE (50)
char msg[MSG_BUFFER_SIZE];
int value = 0; // Переменная для формирования публикуемого сообщения
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void reconnect() {
if (!client.connected()) {
Serial.print("MQTT connection...");
client.setServer(mqtt_server, mqtt_port); // Подключение к MQTT клиенту
client.setCallback(mqttOnIncomingMsg); // подписка на входящие топики
// Пробуем подключиться с LWT сообщением "offline"
if (client.connect(mqtt_clientId, mqtt_user, mqtt_pass, mqttTopicDeviceStatus, mqttDeviceStatusQos, mqttDeviceStatusRetained, mqttDeviceStatusOff)) { //
Serial.println("ok");
client.publish(mqttTopicDeviceStatus, mqttDeviceStatusOn, mqttDeviceStatusRetained); // Публикуем статус устройства
client.subscribe(mqttTopicControlRelay1, mqttRelayControlQos); // Подписываемся на топик управления реле 1
client.subscribe(mqttTopicControlRelay2, mqttRelayControlQos); // Подписываемся на топик управления реле 2
client.subscribe(mqttTopicControlRelay3, mqttRelayControlQos); // Подписываемся на топик управления реле 3
client.publish(mqttTopicStatusRelay1, (gpioStatus1 == relayOn ? mqttRelayStatusOn : mqttRelayStatusOff), mqttRelayStatusRetained); // Публикуем текущее состояние реле 1
client.publish(mqttTopicStatusRelay2, (gpioStatus2 == relayOn ? mqttRelayStatusOn : mqttRelayStatusOff), mqttRelayStatusRetained); // Публикуем текущее состояние реле 2
client.publish(mqttTopicStatusRelay3, (gpioStatus3 == relayOn ? mqttRelayStatusOn : mqttRelayStatusOff), mqttRelayStatusRetained); // Публикуем текущее состояние реле 3
client.subscribe("BTN1"); // подписывааемся на топик с данными для 1-ой кнопки button1
client.subscribe("BTN2"); // подписывааемся на топик с данными для 2-ой кнопки button2
client.subscribe("BTN3"); // подписывааемся на топик с данными для 3-ой кнопки button3
Serial.println("connected");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
if (client.connected()){
client.loop();
}
}
}
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // Инициализация светодиода
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
pinMode(gpioRelay1, OUTPUT); // Настройка выводов реле 1
pinMode(gpioRelay2, OUTPUT); // Настройка выводов реле 2
pinMode(gpioRelay3, OUTPUT); // Настройка выводов реле 3
digitalWrite(gpioRelay1, relayOff); // Сброс реле 1 в исходное состояние "отключено"
digitalWrite(gpioRelay2, relayOff); // Сброс реле 2 в исходное состояние "отключено"
digitalWrite(gpioRelay3, relayOff); // Сброс реле 3 в исходное состояние "отключено"
}
void mqttOnIncomingMsg(char* topic, byte* payload, unsigned int length) {
// Для более корректного сравнения строк приводим их к нижнему регистру и обрезаем пробелы с краев
String _topic = topic;
_topic.toLowerCase();
_topic.trim();
String _payload;
for (unsigned int i=0; i<length; i++) {
_payload += String((char)payload[i]);
}
_payload.toLowerCase();
_payload.trim();
if (_topic.equals(mqttTopicControlRelay1)) { // Сравниваем с топиками
if (_payload.equals(mqttRelayStatusOn)) relaySetStatus1 = relayOn; // это топик управления реле 1
if (_payload.equals(mqttRelayStatusOff)) relaySetStatus1 = relayOff; // это топик управления реле 1
} else if (_topic.equals(mqttTopicControlRelay2)) {
if (_payload.equals(mqttRelayStatusOn)) relaySetStatus2 = relayOn; // это топик управления реле 2
if (_payload.equals(mqttRelayStatusOff)) relaySetStatus2 = relayOff; // это топик управления реле 2
} else if (_topic.equals(mqttTopicControlRelay3)) {
if (_payload.equals(mqttRelayStatusOn)) relaySetStatus3 = relayOn; // это топик управления реле 3
if (_payload.equals(mqttRelayStatusOff)) relaySetStatus3 = relayOff; // это топик управления реле 3
} else {
Serial.println("Failed to recognize incoming topic!");
}
}
void mqttChangeRelaysState() { // Переключение состояния реле
if (relaySetStatus1 != gpioStatus1) { // Новое состояние реле 1 отличается от текущего, требуется переключение
gpioStatus1 = relaySetStatus1;
digitalWrite(gpioRelay1, gpioStatus1);
client.publish(mqttTopicStatusRelay1, (gpioStatus1 == relayOn ? mqttRelayStatusOn : mqttRelayStatusOff), mqttRelayStatusRetained);
Serial.print("Relay 1 has changed its state: ");
Serial.println(gpioStatus1 == relayOn ? mqttRelayStatusOn : mqttRelayStatusOff);
}
if (relaySetStatus2 != gpioStatus2) { // Новое состояние реле 2 отличается от текущего, требуется переключение
gpioStatus2 = relaySetStatus2;
digitalWrite(gpioRelay2, gpioStatus2);
client.publish(mqttTopicStatusRelay2, (gpioStatus2 == relayOn ? mqttRelayStatusOn : mqttRelayStatusOff), mqttRelayStatusRetained);
Serial.print("Relay 2 has changed its state: ");
Serial.println(gpioStatus2 == relayOn ? mqttRelayStatusOn : mqttRelayStatusOff);
}
if (relaySetStatus3 != gpioStatus3) { // Новое состояние реле 3 отличается от текущего, требуется переключение
gpioStatus3 = relaySetStatus3;
digitalWrite(gpioRelay3, gpioStatus3);
client.publish(mqttTopicStatusRelay3, (gpioStatus3 == relayOn ? mqttRelayStatusOn : mqttRelayStatusOff), mqttRelayStatusRetained);
Serial.print("Relay 3 has changed its state: ");
Serial.println(gpioStatus3 == relayOn ? mqttRelayStatusOn : mqttRelayStatusOff);
}
}
void loop() {
if (digitalRead(button1) == LOW) {
client.publish("BTN1", "0");
} else
if (digitalRead(button1) == HIGH) {
client.publish("BTN1", "1");
}
if (digitalRead(button2) == LOW) {
client.publish("BTN2", "0");
} else
if (digitalRead(button2) == HIGH) {
client.publish("BTN2", "1");
}
if (digitalRead(button3) == LOW) {
client.publish("BTN3", "0");
} else
if (digitalRead(button3) == HIGH) {
client.publish("BTN3", "1");
}
delay(100);
if (!client.connected()) {
reconnect();
}
client.loop();
mqttChangeRelaysState(); // Управление реле
}
Посоветуйте чего-нибудь дельного, пожалуйста.