Вопрос по MQTT
- Войдите на сайт для отправки комментариев
Втр, 20/06/2017 - 14:32
Вопрос можети нубский, но чёт не могу сообразить ( нуб нубом) как в функции void loop() получить значение топика чтобы логику писать в нём а не в нутри void callback а в void loop(), а то во всех примерах разбор подпискии идёт в нутри void callback
void loop() {
client.loop();
vikl_1.update();
// Get the updated value :
int stat_vikl_1 = vikl_1.read();
int value2 = 0; // тут должно быть значение топика на который подписались
if ( stat_vikl_1 == LOW || value2 == LOW ) {
digitalWrite(RELAY_1, HIGH );
}
else {
digitalWrite(RELAY_1, LOW );
}
}
// пример функции
void callback(char* topic, byte* payload, unsigned int length) {
if ((char)subscribe[0] == '1') {
rState1 = true;
digitalWrite(RELAY_1, rState1); // Turn the LED on (Note that LOW is the voltage level
} else {
rState1 = false;
digitalWrite(RELAY_1, rState1); // Turn the LED off by making the voltage HIGH
}
}
Остальной скетч секретный? Кто этот колбэк вызывает, когда и зачем нам догадываться нужно?
скетча рабочего ещё нет, только наброски
#include <ESP8266WiFi.h> #include <PubSubClient.h> #include <Bounce2.h> //----------------------------- const char* ssid = "11111"; const char* pass = "22222"; IPAddress server (192,168,1,120); int mqtt_port = 1883; const char* mqtt_user = "33333"; const char* mqtt_pass = "444444"; #define RELAY_1 5 #define BUTTON_1 4 #define BUTTON_2 14 // проходной переключатель //#define humidity_topic "sensors/humidity_1" #define relays_topic "dom/koridor/relay1/status" #define relays_regim "dom/koridor/relay1/regim" WiFiClient wclient; PubSubClient client(wclient, server); boolean rState1 = false; boolean btnPress = false; boolean regim = false; boolean lastbtnStat = false; boolean lastbtnStat2 = false; Bounce vikl_1 = Bounce(); void setup() { pinMode(RELAY_1, OUTPUT); // инициализация пинов реле и выключателей pinMode(BUTTON_1, INPUT); //pinMode(BUTTON_2, INPUT); vikl_1.attach(BUTTON_1); vikl_1.interval(5); // interval in ms digitalWrite(RELAY_1, rState1); Serial.begin(115200); //client.setCallback(callback); //delay(100); //WiFi.begin(ssid, password); //delay(6000); //client.connect("ESP8266Client"); connect_wifi(); // подключение к сети и брокеру client.subscribe(relays_topic); client.subscribe(relays_regim); // lastbtnStat2 = digitalRead(BUTTON_2); } void loop() { client.loop(); vikl_1.update(); // Get the updated value : int stat_vikl_1 = vikl_1.read(); int value2 = 0; if ( stat_vikl_1 == LOW || value2 == LOW ) { digitalWrite(RELAY_1, HIGH ); } else { digitalWrite(RELAY_1, LOW ); } } void callback(char* topic, byte* payload, unsigned int length) { if ((char)subscribe[0] == '1') { rState1 = true; digitalWrite(RELAY_1, rState1); // Turn the LED on (Note that LOW is the voltage level // but actually the LED is on; this is because // it is acive low on the ESP-01) } else { rState1 = false; digitalWrite(RELAY_1, rState1); // Turn the LED off by making the voltage HIGH } } void connect_MQTT() { // Loop until we're reconnected if (WiFi.status() == WL_CONNECTED) { if (!client.connected()) { Serial.println("Connecting to MQTT server"); if (client.connect(MQTT::Connect("arduinoClient") .set_auth(mqtt_user, mqtt_pass))) { Serial.println("Подключились к MQTT серверу"); } else { Serial.println("Не удаётся подключится к MQTT серверу"); } } } } void connect_wifi() { if (WiFi.status() != WL_CONNECTED) { Serial.print("Подключение к WiFi-"); Serial.print(ssid); Serial.println("..."); WiFi.begin(ssid, pass); if (WiFi.waitForConnectResult() != WL_CONNECTED) Serial.println("WiFi подключён"); connect_MQTT(); } else { Serial.println("Не удалось подключится к WiFi"); } }Ну, в таком виде (с закомментированной строкой 41) callback не вызывается вовсе.
вот в этм и пытаюсь разобраться, где и как правльно это сделать. В примерах этот класс обьявляется в функции подключения к брокеру (мне это не нравится) и там же стразу идёт логика обработки полученных сообщений, вот и хочу разобраться как правильно и как работает. ну и наверняка просто туп не понимаю элементарных вещей)
А в чём Ваша проблема? Для чего Вам нужно получать всё в функции loop? Чем Вам callback не угодила.
Сделать-то это можно, но я не понимаю зачем и потому не вижу "граблей".
вот в этм и пытаюсь разобраться, где и как правльно это сделать. В примерах этот класс обьявляется в функции подключения к брокеру (мне это не нравится) и там же стразу идёт логика обработки полученных сообщений,
простите, а чем вам это не нравится? Смысл callback - чтобы вы в своей программе могли выполнять какие-то операции во время таймаутов сетевых соединений. Если вам это не надо - можете вообще этим не пользоваться
UPD - посмотрел либу - был неправ. Смысл callback - вернуть вам топик и прочую инфу. Без вызова callback вы ее, похоже, просто не получите. Если вам не нравится обрабатывать ее тут же - тогда просто запоминайте ее, а обрабатывайте потом. Но непонятно, зачем так делать
ну не хотелось бы писать логику в теле функции) (как я понял основной код в ардуино вызывается и работает в loop, вот это и хотелось получить и сомения в доступности переменных одной функции в теле другой) как-то на мой взглдя не правильно совать логику по функциям). пойду дальше осмысливать значение этой функции (callback) и разибраться со свойствами класса. п.с. я не программист)
ну не хотелось бы писать логику в теле функции) (как я понял основной код в ардуино вызывается и работает в loop, вот это и хотелось получить и сомения в доступности переменных одной функции в теле другой) как-то на мой взглдя не правильно совать логику по функциям). пойду дальше осмысливать значение этой функции (callback) и разибраться со свойствами класса. п.с. я не программист)
Желание поместить все в loop() - это типичная ошибка новичка. "Совать логику по функциям" - это не только не ошибка, это как раз более правильный и разумный стиль программирования. В программе, в которой в loop вы видите только вызовы десятка функций и больше ничего - разбираться значительно проще, чем в типичном коде новичка, где все запихано в бесконечный loop().
А сомнения в доступности переменных одной функции в теле другой - это верное сомнение, но для этого существуют глобальные переменные.
как-то на мой взглдя не правильно совать логику по функциям
Это как раз правильно.
Вообще-то все банально просто
void Handler() {} // это у нас обработчик. bool event = 0; // это у нас событие void callback(bool _event, void (*_Handler)() ) { if (_event) _Handler(); } void setup() { } void loop() { // вариант 1 if (event) Handler(); // вариант 2 с callback callback(event, Handler); }Остальное это просто варианты и ничего больше.
код какой-то нелогичный. Или это только теоретический пример? Callback получает и ивент и хендлер "снаружи", а внутри всего лишь соединяет их друг с другом? А смысл?
Вот так было бы полезнее:
void callback(int _event) { if (_event == 0) _Handler0(); else if (_event == 1) _Handler1(); else if (_event == 2) _Handler2(); .... else if (_event == 100) _Handler100(); } void setup() { } void loop() { callback(event); }или через case
Я же сказал: остальное - варианты. А как ивенты , данные для определение иветнов и хендлеров попадают в калбек функцию не важно. Ведь могут попасть как глобальные переменные, а может засунуты в условие функции. Я чаще использую классы. В классах возможна инкапсуляция данных и куча различных методов в одной куче. Чего одиночная фунция лишена.
В классах возможна инкапсуляция данных и куча различных методов в одной куче. Чего одиночная фунция лишена.
хм... зато метод класса в виде хендлера так просто по ссылке не передать. Очень извращаться придется... Проще всего, если это вызов метода для конкретного экземпляра - тогда обернуть его в обычную "одинокую функцию" и передавать по ссылке без всякого ООП :)
пойду дальше осмысливать значение этой функции (callback) и разибраться со свойствами класса. п.с. я не программист)
шо там разбираться? - она делает
23if((char)subscribe[0] =='1') {24rState1 =true;25digitalWrite(RELAY_1, rState1);// Turn the LED on (Note that LOW is the voltage level26}else{27rState1 =false;28digitalWrite(RELAY_1, rState1);// Turn the LED off by making the voltage HIGH29}п.с. я не программист - какого класса? О_О
Вот я не пойму , зачем передавать метод класса в качестве хендлера. Это же глупо. То что передавать можно, так это ответ Клопауцию , зачем в библиотеке 2 файла .h и .сpp. Так вот для этого. Если классы и их методы, то это прерогатива разработчика класса. А вот хенлеры это дело пользователя. Опять же есть классы, а есть объекты по классам. Это функции сами по себе . Сама себе и "класс", сама себе и "метод класса", сама себе и "объект класса". Так что проще через обычные функции. Я и это пробовал. В Qt есть специальные функции для коннектов методов и слотов предствителей классов. Я ими не пользуюсь, так как много текста будет.
В Qt есть специальные функции для коннектов методов и слотов предствителей классов. Я ими не пользуюсь, так как много текста будет.
оффтоп конечно, но можно в 2-3х предложениях - что не так с сигналами и слотами в Qt? Я когда-то пробовал писать в Qt - и для меня как раз сигналы и слоты показались наиболее удобным и простым механизмом... в отличии в целом от написания графического интерфейса. который я не понимаю и не люблю :)
С Qt скорее всего организовано так, как я пишу это ручками. Создается или внешний, или внутрений обработчик в одном представителе, который дергает переменную в другом. Вот только это все очень замаскировано дополнительной функцией или графическим интерфейсом среды разработки. Вот только я пришел к этому самостоятельно, просто следуя по ходу развития программирования вообще и в частности в Си. А вот на счет графического интерфейса, так все там просто и сложно. Просто, если вы поймете концепцию делегирования вместо множественного наследования и придумаете кучу английских слов для обозначения переменных и методов.
Подскажите что значит подписаться (SUBSCRIBE) и отписаться (UNSUBSCRIBE) на топик
1) Брокер начнет слать клиенту обновления топика
2) Брокер перестанет слать обновления.
#include <SPI.h> // Библиотека SPI шины #include <Ethernet.h> // Ethernet библиотека #include <PubSubClient.h> // Библиотека MQTT int LAMP0, LAMP1, LAMP2, LAMP3, LAMP4, LAMP5, LAMP6, LAMP7, LAMP8, LAMP9, LAMP10, LAMP11, LAMP12; int relay1 = 40; int relay2 = 41; int relay3 = 42; int relay4 = 43; byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; byte serverArduino[] = { 192, 168, 7, 150 }; byte ip[] = { 192, 168, 7, 250 }; void callback(char* topic, byte* payload, unsigned int length) { int r,hl; Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); char receivedChar = (char)payload[0]; Serial.print(receivedChar); if(receivedChar=='0') hl = LOW; else hl = HIGH; if(String(topic)=="PowerPanel/relay1") r = relay1; else if(String(topic)=="PowerPanel/relay2") r = relay2; else if(String(topic)=="PowerPanel/relay3") r = relay3; else if(String(topic)=="PowerPanel/relay4") digitalWrite(relay4, HIGH); // зажигаем светодиод delay(500); // ждем секунду digitalWrite(relay4, LOW); // выключаем светодиод delay(500); // ждем секунду digitalWrite(r, hl); Serial.println(); } EthernetClient ethClient; PubSubClient client(serverArduino, 1883, callback, ethClient); void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.println("Attempting MQTT connection..."); // Attempt to connect if (client.connect("arduinoPowerPanel")) { Serial.println("connected"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); delay(5000); } } } void setup() { Ethernet.begin(mac, ip); // Инициализируем mac, ip Serial.begin(9600); Serial.println(F("Relay Test!")); /* Тестовое сообщ. при откр. Монитора порта. Так же обёртываем сообщения в макрос F() для экономии ОЗУ */ pinMode (22, INPUT_PULLUP); pinMode (24, INPUT_PULLUP); pinMode (26, INPUT_PULLUP); pinMode (28, INPUT_PULLUP); pinMode (30, INPUT_PULLUP); pinMode (31, INPUT_PULLUP); pinMode (32, INPUT_PULLUP); pinMode (33, INPUT_PULLUP); pinMode (34, INPUT_PULLUP); pinMode (35, INPUT_PULLUP); pinMode (36, INPUT_PULLUP); pinMode (37, INPUT_PULLUP); pinMode (38, INPUT_PULLUP); pinMode(relay1, OUTPUT); pinMode(relay2, OUTPUT); pinMode(relay3, OUTPUT); pinMode(relay4, OUTPUT); if (client.connect("arduinoPowerPanel")) { Serial.print("online"); client.publish("PowerPanel/relay1", "1"); client.subscribe("PowerPanel/relay1"); client.publish("PowerPanel/relay2", "1"); client.subscribe("PowerPanel/relay2"); client.publish("PowerPanel/relay3", "1"); client.subscribe("PowerPanel/relay3"); client.publish("PowerPanel/relay4", "1"); client.subscribe("PowerPanel/relay4"); } } void loop() { if (!client.connected()) { reconnect(); } client.loop(); LAMP0 = !digitalRead (22); if (LAMP0 == 0) { Serial.print(" LAMP0 - "); Serial.println(0); client.publish("home/data/status/Relay/0", "0"); }else if (LAMP0 == 1) { Serial.print(" LAMP0 - "); Serial.println(1); client.publish("home/data/status/Relay/0", "1"); } delay(100); LAMP1 = !digitalRead (24); if (LAMP1 == 0) { Serial.print(" LAMP1 - "); Serial.println(0); client.publish("home/data/status/Relay/1", "0"); }else if (LAMP1 == 1) { Serial.print(" LAMP1 - "); Serial.println(1); client.publish("home/data/status/Relay/1", "1"); } delay(100); LAMP2 = !digitalRead (26); if (LAMP2 == 0) { (" LAMP2 - "); Serial.println(0); client.publish("home/data/status/Relay/2", "0"); }else if (LAMP2 == 1) { Serial.print(" LAMP2 - "); Serial.println(1); client.publish("home/data/status/Relay/2", "1"); } delay(100); LAMP3 = !digitalRead (28); if (LAMP3 == 0) { ///Serial.print(" LAMP3 - "); Serial.println(0); client.publish("home/data/status/Relay/3", "0"); }else if (LAMP3 == 1) { ///Serial.print(" LAMP3 - "); Serial.println(1); client.publish("home/data/status/Relay/3", "1"); } delay(100); LAMP4 = !digitalRead (30); if (LAMP4 == 0) { ///Serial.print(" LAMP4 - "); Serial.println(0); client.publish("home/data/status/Relay/4", "0"); }else if (LAMP4 == 1) { ///Serial.print(" LAMP4 - "); Serial.println(1); client.publish("home/data/status/Relay/4", "1"); } delay(100); LAMP5 = !digitalRead (31); if (LAMP5 == 0) { ///Serial.print(" LAMP5 - "); Serial.println(0); client.publish("home/data/status/Relay/5", "0"); }else if (LAMP5 == 1) { ///Serial.print(" LAMP5 - "); Serial.println(1); client.publish("home/data/status/Relay/5", "1"); } delay(100); LAMP6 = !digitalRead (32); if (LAMP6 == 0) { ///Serial.print(" LAMP6 - "); Serial.println(0); client.publish("home/data/status/Relay/6", "0"); }else if (LAMP6 == 1) { ///Serial.print(" LAMP6 - "); Serial.println(1); client.publish("home/data/status/Relay/6", "1"); } delay(100); LAMP7 = !digitalRead (33); if (LAMP7 == 0) { ///Serial.print(" LAMP7 - "); Serial.println(0); client.publish("home/data/status/Relay/7", "0"); }else if (LAMP7 == 1) { ///Serial.print(" LAMP7 - "); Serial.println(1); client.publish("home/data/status/Relay/7", "1"); } delay(100); LAMP8 = !digitalRead (34); if (LAMP8 == 0) { ///Serial.print(" LAMP8 - "); Serial.println(0); client.publish("home/data/status/Relay/8", "0"); }else if (LAMP8 == 1) { ///Serial.print(" LAMP8 - "); Serial.println(1); client.publish("home/data/status/Relay/8", "1"); } delay(100); LAMP9 = !digitalRead (35); if (LAMP9 == 0) { ///Serial.print(" LAMP9 - "); Serial.println(0); client.publish("home/data/status/Relay/9", "0"); }else if (LAMP9 == 1) { ///Serial.print(" LAMP9 - "); Serial.println(1); client.publish("home/data/status/Relay/9", "1"); } delay(100); LAMP10 = !digitalRead (36); if (LAMP10 == 0) { ///Serial.print(" LAMP10 - "); Serial.println(0); client.publish("home/data/status/Relay/10", "0"); }else if (LAMP10 == 1) { ///Serial.print(" LAMP10 - "); Serial.println(1); client.publish("home/data/status/Relay/10", "1"); } delay(100); LAMP11 = !digitalRead (37); if (LAMP11 == 0) { ///Serial.print(" LAMP11 - "); Serial.println(0); client.publish("home/data/status/Relay/11", "0"); }else if (LAMP11 == 1) { ///Serial.print(" LAMP11 - "); Serial.println(1); client.publish("home/data/status/Relay/11", "1"); } delay(100); LAMP12 = !digitalRead (38); if (LAMP12 == 0) { ///Serial.print(" LAMP12 - "); Serial.println(0); client.publish("home/data/status/Relay/12", "0"); }else if (LAMP12 == 1) { ///Serial.print(" LAMP12 - "); Serial.println(1); client.publish("home/data/status/Relay/12", "1"); } delay(100); }Доброго времени суток !
Я далеко не программист, прошу не судить строго!
Стояла задача считать значения логической единицы с пина и передать по MQTT в MJDOM.
Задачу выполнил вроде все работает.
Также необходимо по MQTT включать РЕЛЕ тут вроде все получилось, но возникла вот такая проблема при обкатке, спустя час два работы arduino перестает включать реле, но при этом логические единица и ноль (от первой задачи) в мониторе порта отображаются корректно и MJDOM. Перезагружаем arduino и все вновь на какое то время работает.
Что то мне подсказывает, что из Callback убрать нужно delay.
Да и этот момент
charreceivedChar = (char)payload[0]; я бы заменил как в мануале на:byte* p = (byte*)malloc(length); memcpy(p,payload,length); client.publish("outTopic", p, length); free(p);Ну и на закуску проверить не обрывается соединение где нибудь.
"Что то мне подсказывает, что из Callback убрать нужно delay"
Вынести в отдельную операцию (функцию), так получается что? От него нужно что бы реле кратко временно выключилось и выключилось.
"Ну и на закуску проверить не обрывается соединение где нибудь."
Ну я так понимаю если первая часть которая работает по MQTT значит cоединение есть. Тут я так понял именно проблема с callback
то что написали пошел пробовать
Да и вообще в callback я бы сделал проверку из какого топика прилетело, а затем, что прилетело, ну и дернуть реле.
Не удобно просить ну так как я уже на это убил 7 дней, все же попрошу можете помочь допилить. а то про проверку написали я уже в ступаре ...
Просто я так понял где используют конструкцию типа:
'pub' was not declared in this scope
все что я пересмотрел везде используется Wifi а в моем случаи его нет вот и в ступаре я ... (((
Спасибо!
void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect("arduinoClient")) { Serial.println("connected"); client.publish("PowerPanel/relay1", "1"); client.subscribe("PowerPanel/relay1"); client.publish("PowerPanel/relay2", "1"); client.subscribe("PowerPanel/relay2"); client.publish("PowerPanel/relay3", "1"); client.subscribe("PowerPanel/relay3"); client.publish("PowerPanel/relay4", "1"); client.subscribe("PowerPanel/relay4"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void callback(char *topic, byte *payload, unsigned int length) { Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); if (strcmp(topic, "PowerPanel/relay1")) { if ((char)payload[0] == '1') digitalWrite(relay1, HIGH); else digitalWrite(relay1, LOW); } else if (strcmp(topic, "PowerPanel/relay2")) { if ((char)payload[0] == '1') digitalWrite(relay2, HIGH); else digitalWrite(relay2, LOW); } Serial.println(); }Возможно из за того что вы не в reconect подписываетесь на топики.
Так что то же стоит перенести из setup().
Ну и остальное перепроверяйте и пробуйте.
Спасибо пошел пробовать что получится интересно ))) Спасибо ! а как насчет того что бы вне callback сделать влючение и выключение реле
Сделал как Вы писали теперь у меня получается следующее:
relay1 на 40 пине
PowerPanel/relay1 1
отправляешь в топик и включается 41 пин, хотя relay1 на 40
PowerPanel/relay2 1
включается 40 пин ....
как такое может быть все пересмотрел на два раза ...
Вижу тока то что в порт не прилетает 0 или 1 сообщение ... только надпись топика
Наводящий вопрос - что произойдёт в этом условии, если topic эквивалентен "PowerPanel/relay1":
if(strcmp(topic,"PowerPanel/relay1"))?я так понимаю если наводящий вопрос задан тот тут ошибка в структуре выполняемой операции... должно быть
else if (strcmp(topic, "PowerPanel/relay1"))
а выше общий if
Реле у тебя управляюца нулем, видимо.
Хорошо. По- другому спрошу. Каким уровнем включается реле?
В текущий момент времени реле едут только у меня сейчас я тыстовый вариант на макете собираю включаю вместо реле светодиоды. Вот то что сейчас по коду у меня ткните где мог накосячить в нем...
Сейчас проблема в том что включая relay1 включается relay2
ну и следующая моя проблема будет как в не callback сделать кратковременное включение и потом выключение реле
#include <SPI.h> // Библиотека SPI шины #include <Ethernet.h> // Ethernet библиотека #include <PubSubClient.h> // Библиотека MQTT int LAMP0, LAMP1, LAMP2, LAMP3, LAMP4, LAMP5, LAMP6, LAMP7, LAMP8, LAMP9, LAMP10, LAMP11, LAMP12; int relay1 = 40; int relay2 = 41; int relay3 = 42; int relay4 = 43; byte mac[] = { 0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xED }; byte serverArduino[] = { 192, 168, 7, 150 }; byte ip[] = { 192, 168, 7, 250 }; void callback(char* topic, byte* payload, unsigned int length); EthernetClient ethClient; PubSubClient client(serverArduino, 1883, callback, ethClient); void callback(char *topic, byte *payload, unsigned int length) { Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); if (strcmp(topic, "PowerPanel/relay1")) { if ((char)payload[0] == '1') digitalWrite(relay1, HIGH); else digitalWrite(relay1, LOW); } else if (strcmp(topic, "PowerPanel/relay2")) { if ((char)payload[0] == '1') digitalWrite(relay2, HIGH); else digitalWrite(relay2, LOW); } Serial.println(); } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect("arduinoClient")) { Serial.println("connected"); client.publish("PowerPanel/relay1", "1"); client.subscribe("PowerPanel/relay1"); client.publish("PowerPanel/relay2", "1"); client.subscribe("PowerPanel/relay2"); client.publish("PowerPanel/relay3", "1"); client.subscribe("PowerPanel/relay3"); client.publish("PowerPanel/relay4", "1"); client.subscribe("PowerPanel/relay4"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void setup() { Ethernet.begin(mac, ip); // Инициализируем mac, ip Serial.begin(9600); Serial.println(F("Relay Test!")); /* Тестовое сообщ. при откр. Монитора порта. Так же обёртываем сообщения в макрос F() для экономии ОЗУ */ pinMode (22, INPUT_PULLUP); pinMode (24, INPUT_PULLUP); pinMode (26, INPUT_PULLUP); pinMode (28, INPUT_PULLUP); pinMode (30, INPUT_PULLUP); pinMode (31, INPUT_PULLUP); pinMode (32, INPUT_PULLUP); pinMode (33, INPUT_PULLUP); pinMode (34, INPUT_PULLUP); pinMode (35, INPUT_PULLUP); pinMode (36, INPUT_PULLUP); pinMode (37, INPUT_PULLUP); pinMode (38, INPUT_PULLUP); pinMode(relay1, OUTPUT); pinMode(relay2, OUTPUT); pinMode(relay3, OUTPUT); pinMode(relay4, OUTPUT); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); LAMP0 = !digitalRead (22); if (LAMP0 == 0) { Serial.print(" LAMP0 - "); Serial.println(0); client.publish("home/data/status/Relay/0", "0"); }else if (LAMP0 == 1) { Serial.print(" LAMP0 - "); Serial.println(1); client.publish("home/data/status/Relay/0", "1"); } delay(100); LAMP1 = !digitalRead (24); if (LAMP1 == 0) { Serial.print(" LAMP1 - "); Serial.println(0); client.publish("home/data/status/Relay/1", "0"); }else if (LAMP1 == 1) { Serial.print(" LAMP1 - "); Serial.println(1); client.publish("home/data/status/Relay/1", "1"); } delay(100); LAMP2 = !digitalRead (26); if (LAMP2 == 0) { (" LAMP2 - "); Serial.println(0); client.publish("home/data/status/Relay/2", "0"); }else if (LAMP2 == 1) { Serial.print(" LAMP2 - "); Serial.println(1); client.publish("home/data/status/Relay/2", "1"); } delay(100); LAMP3 = !digitalRead (28); if (LAMP3 == 0) { ///Serial.print(" LAMP3 - "); Serial.println(0); client.publish("home/data/status/Relay/3", "0"); }else if (LAMP3 == 1) { ///Serial.print(" LAMP3 - "); Serial.println(1); client.publish("home/data/status/Relay/3", "1"); } delay(100); LAMP4 = !digitalRead (30); if (LAMP4 == 0) { ///Serial.print(" LAMP4 - "); Serial.println(0); client.publish("home/data/status/Relay/4", "0"); }else if (LAMP4 == 1) { ///Serial.print(" LAMP4 - "); Serial.println(1); client.publish("home/data/status/Relay/4", "1"); } delay(100); LAMP5 = !digitalRead (31); if (LAMP5 == 0) { ///Serial.print(" LAMP5 - "); Serial.println(0); client.publish("home/data/status/Relay/5", "0"); }else if (LAMP5 == 1) { ///Serial.print(" LAMP5 - "); Serial.println(1); client.publish("home/data/status/Relay/5", "1"); } delay(100); LAMP6 = !digitalRead (32); if (LAMP6 == 0) { ///Serial.print(" LAMP6 - "); Serial.println(0); client.publish("home/data/status/Relay/6", "0"); }else if (LAMP6 == 1) { ///Serial.print(" LAMP6 - "); Serial.println(1); client.publish("home/data/status/Relay/6", "1"); } delay(100); LAMP7 = !digitalRead (33); if (LAMP7 == 0) { ///Serial.print(" LAMP7 - "); Serial.println(0); client.publish("home/data/status/Relay/7", "0"); }else if (LAMP7 == 1) { ///Serial.print(" LAMP7 - "); Serial.println(1); client.publish("home/data/status/Relay/7", "1"); } delay(100); LAMP8 = !digitalRead (34); if (LAMP8 == 0) { ///Serial.print(" LAMP8 - "); Serial.println(0); client.publish("home/data/status/Relay/8", "0"); }else if (LAMP8 == 1) { ///Serial.print(" LAMP8 - "); Serial.println(1); client.publish("home/data/status/Relay/8", "1"); } delay(100); LAMP9 = !digitalRead (35); if (LAMP9 == 0) { ///Serial.print(" LAMP9 - "); Serial.println(0); client.publish("home/data/status/Relay/9", "0"); }else if (LAMP9 == 1) { ///Serial.print(" LAMP9 - "); Serial.println(1); client.publish("home/data/status/Relay/9", "1"); } delay(100); LAMP10 = !digitalRead (36); if (LAMP10 == 0) { ///Serial.print(" LAMP10 - "); Serial.println(0); client.publish("home/data/status/Relay/10", "0"); }else if (LAMP10 == 1) { ///Serial.print(" LAMP10 - "); Serial.println(1); client.publish("home/data/status/Relay/10", "1"); } delay(100); LAMP11 = !digitalRead (37); if (LAMP11 == 0) { ///Serial.print(" LAMP11 - "); Serial.println(0); client.publish("home/data/status/Relay/11", "0"); }else if (LAMP11 == 1) { ///Serial.print(" LAMP11 - "); Serial.println(1); client.publish("home/data/status/Relay/11", "1"); } delay(100); LAMP12 = !digitalRead (38); if (LAMP12 == 0) { ///Serial.print(" LAMP12 - "); Serial.println(0); client.publish("home/data/status/Relay/12", "0"); }else if (LAMP12 == 1) { ///Serial.print(" LAMP12 - "); Serial.println(1); client.publish("home/data/status/Relay/12", "1"); } delay(100); }Наводящий вопрос - что произойдёт в этом условии, если topic эквивалентен "PowerPanel/relay1":
if(strcmp(topic,"PowerPanel/relay1"))?Точняк! Мой косяк ))
А почему тут инвертировать strcmp нужно ?
и как в не сделать вкл/выкл что бы в callback не использовать delay
Ну про strcmp можно в гугле спросить.
Да и про то как без delay можно там же найти. "Мигаем светодиодом без delay"
Пошел на просторы GOOGLE большое спасибо !!!! Не ожидал что на форуме быстро решение найдется... будем тестить скетч дальше на стабильность !!!
СПАСИБО !
А почему тут инвертировать strcmp нужно ?
Инвертировать не нужно. Нужно знать, что она возвращает.
Ясно уже более менее на просторах гугла нашел ответ....
Подскажите люди добрые,нашел вот такой скетч на просторах интернета, как внего добавить проверку логина и пароля для подключения к mqtt брокеру?
Скетч:
#include <ESP8266WiFi.h> #include <PubSubClient.h> #include <ELECHOUSE_CC1101_RCS_DRV.h> #include <RCSwitch.h> const char* ssid = "Login"; const char* password = "pass"; const char* mqtt_server = "192.168.0.1"; char clientRSSI[50]; const int PIN_WIFI_LED = D4; const int PIN_433_LED = D0; RCSwitch c1101 = RCSwitch(); void callback(char* topic, byte* payload, unsigned int length); WiFiClient espClient; PubSubClient client(mqtt_server, 1883, callback, espClient); void callback(char* topic, byte* payload, unsigned int length) { } void reconnectWifi() { WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); } String str = String(WiFi.RSSI()); str.toCharArray(clientRSSI, str.length()+1); } void reconnectMQTT() { while (!client.connected()) { if (client.connect("Generic433","sensors/433/health", 0, true, "offline")) { client.setCallback(callback); client.publish("sensors/433/rssi", clientRSSI, true); client.publish("sensors/433", "started", true); client.publish("sensors/433/health", "online", true); digitalWrite(PIN_WIFI_LED, HIGH); } else { delay(1000); } } } void setup() { Serial.begin(9600); pinMode(PIN_WIFI_LED, OUTPUT); digitalWrite(PIN_WIFI_LED, LOW); pinMode(PIN_433_LED, OUTPUT); digitalWrite(PIN_433_LED, LOW); ELECHOUSE_cc1101.setMHZ(433.92); ELECHOUSE_cc1101.Init(PA10); c1101.enableReceive(D2); ELECHOUSE_cc1101.SetRx(); } unsigned long ledBackoffTimer = 0; void loop() { if(ledBackoffTimer != 0) { if(millis() > (ledBackoffTimer + 50)) { ledBackoffTimer = 0; digitalWrite(PIN_433_LED, LOW); } } if (c1101.available()) { forward(c1101.getReceivedValue(), c1101.getReceivedBitlength()); c1101.resetAvailable(); ledBackoffTimer = millis(); digitalWrite(PIN_433_LED, HIGH); } if(WiFi.status() != WL_CONNECTED) { digitalWrite(PIN_WIFI_LED, LOW); reconnectWifi(); } if (!client.connected()) { digitalWrite(PIN_WIFI_LED, LOW); reconnectMQTT(); } client.loop(); } unsigned long lastReceived = 0; unsigned long lastDecimal = 0; void forward(unsigned long decimal, unsigned int length) { if(lastDecimal == decimal && millis() < lastReceived + 2000) { return; } else { lastDecimal = decimal; lastReceived = millis(); const char* bits = bitstring(decimal, length); char total[250]; sprintf(total, "{\"decimal\":\"%d\", \"binary\":\"%s\"}", decimal, bits); client.publish("sensors/433/receive", total); } } static char * bitstring(unsigned long decimal, unsigned int bitLength) { static char bin[64]; unsigned int i=0; while (decimal > 0) { bin[32+i++] = ((decimal & 1) > 0) ? '1' : '0'; decimal = decimal >> 1; } for (unsigned int j = 0; j< bitLength; j++) { if (j >= bitLength - i) bin[j] = bin[ 31 + i - (j - (bitLength - i)) ]; else bin[j] = '0'; } bin[bitLength] = '\0'; return bin; }#include <ESP8266WiFi.h> #include <PubSubClient.h> #include <OneWire.h> #include <DallasTemperature.h> #define ONE_WIRE_BUS 0 // пин датчика температуры #define LEDPIN 2 // пин ШИМ ленты const char *ssid = "****"; //название сети const char *password = "****"; //пароль сети const char *mqtt_server = "****"; //адрес mqtt брокера OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); DeviceAddress insideThermometer; WiFiClient espClient; //инициализация вифи PubSubClient client(espClient); //инициализация mqtt клиента float tempC; char tempCMQTT[5]; //пороговые значения. Выставляются по желанию. Сейчас уставнолены тестовые зхначения float t1 = 30.0; //порог выключения FAN float t2 = 31.5; // порог включения FAN int PinPomp = 3; // Порт включения реле FAN int need_val; // то что прилетело в топике int old_val; // то что установлено сейчас // функция получения топиков от брокера void callback(char* topic, byte* payload, unsigned int length) { Serial.println(); Serial.print(topic); // выводим в сериал порт название топика Serial.print(" => "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } // выводим в сериал порт значение полученных данных String strTopic = String(topic); //получаем название топика if (strTopic == "ESP02/led") //проверяем из нужного ли топика пришли данные { payload[length] = 0; //чистим от мусора, длинна строки String strPayload = String((char*)payload); //считываем значение топика need_val = map(strPayload.toInt(), 0, 100, 1023, 0); //приводим значение 0-100 в значение 1000-0 if (need_val > old_val) { for (int i = old_val; i <= need_val; i++) //то плавно включаем свет { analogWrite(LEDPIN, i); delay(3); //каждые 10мс увелияение на 1 } } else { for (int i = old_val; i >= need_val; i--) //то плавно включаем свет { analogWrite(LEDPIN, i); delay(3); //каждые 10мс увелияение на 1 } } old_val = need_val; //analogWrite(LEDPIN, stled); //устанавливаем уровень шим сигнала Serial.print(" => "); Serial.print(need_val); // для отладки } } void setup(void) { Serial.begin(9600); Serial.println("Dallas Temperature IC Control Library Demo"); Serial.print("Locating devices..."); sensors.begin(); Serial.print("Found "); Serial.print(sensors.getDeviceCount(), DEC); Serial.println(" devices."); Serial.print("Parasite power is: "); if (sensors.isParasitePowerMode()) Serial.println("ON"); else Serial.println("OFF"); if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0"); Serial.print("Device 0 Address: "); printAddress(insideThermometer); Serial.println(); sensors.setResolution(insideThermometer, 9); Serial.print("Device 0 Resolution: "); Serial.print(sensors.getResolution(insideThermometer), DEC); Serial.println(); dtostrf(tempC, 5, 2, tempCMQTT); ////!!!!!!!!!!!!!!!!!!!!!!!! pinMode(PinPomp, OUTPUT); pinMode(LEDPIN, OUTPUT); //устанвливаем ка выход //pinMode(PinAlarm, OUTPUT); NoPomp(); //инициация выхода fan // digitalWrite(PinAlarm, HIGH); //инициация выхода тревоги } //***************************************************************************************************** void loop(void) { if (WiFi.status() != WL_CONNECTED) //если нет подключения к вифи { WiFi.begin(ssid, password); //конектимся if (WiFi.waitForConnectResult() != WL_CONNECTED) return; //если не получилось то повторяем } if (WiFi.status() == WL_CONNECTED) //если подключились { if (!client.connected()) //если нет mqtt { // то подключаемся к mqtt client.setServer(mqtt_server, 1883); client.setCallback(callback); client.connect("ESP02led"); //id клиента(должно быть уникальным в сети) client.subscribe("ESP02/led"); //подписываемся на топик } if (client.connected()) { // если подключились client.loop(); // то запускаем цикл получения топиков))) } } sensors.requestTemperatures(); // запрашиваем датчик printTemperature(insideThermometer); // Считаем темп. и выведем в порт монитора (для отладки) if (tempC > t2) //больше температуры начала работы FAN. { DoPomp(); // подтвердим включение FAN } else if (tempC < t1) // меньше первого порога. { NoPomp(); } delay(2000); } //***************************************************************************************** // функция определения адреса термодатчика на шине void printAddress(DeviceAddress deviceAddress) { for (uint8_t i = 0; i < 8; i++) { if (deviceAddress[i] < 16) Serial.print("0"); Serial.print(deviceAddress[i], HEX); } } // функция получения температуры и вывода его на порт монитора void printTemperature(DeviceAddress deviceAddress) { tempC = sensors.getTempC(deviceAddress); Serial.println(tempC, 1); client.publish ("ESP02/led/temp", 'tempCMQTT'); ////!!!!!!!!!!!!!!!!!!!!!!!! } // функция включения FAN void DoPomp() { digitalWrite(PinPomp, HIGH); Serial.println("FAN enable"); } // функция выключения FAN void NoPomp() { digitalWrite(PinPomp, LOW); Serial.println("FAN disable"); }1) dtostrf ();
2) Использовать таймер.
Да тока понял что в топике надо писать конверт значения ...
И все же добавив на ESP 01, возможность определения температуры и исходя из температуры включение вентилятора столкнулся с такой проблемой что
#include <ESP8266WiFi.h> #include <PubSubClient.h> #include <OneWire.h> #include <DallasTemperature.h> #define ONE_WIRE_BUS 0 // пин датчика температуры #define LEDPIN 2 // пин ШИМ ленты #define PERIOD_1 60000 unsigned long timer_1; const char *ssid = "****"; //название сети const char *password = "*****"; //пароль сети const char *mqtt_server = "********"; //адрес mqtt брокера OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); DeviceAddress insideThermometer; WiFiClient espClient; //инициализация вифи PubSubClient client(espClient); //инициализация mqtt клиента float tempC; char tempCMQTT[5]; //пороговые значения. Выставляются по желанию. Сейчас уставнолены тестовые зхначения float t1 = 45.0; //порог выключения FAN float t2 = 35.0; //порог включения FAN int PinPomp = 3; // Порт включения реле FAN int need_val; // то что прилетело в топике int old_val; // то что установлено сейчас nh // функция получения топиков от брокера void callback(char* topic, byte* payload, unsigned int length) { Serial.println(); Serial.print(topic); // выводим в сериал порт название топика Serial.print(" => "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); } // выводим в сериал порт значение полученных данных String strTopic = String(topic); //получаем название топика if (strTopic == "ESP02/led") //проверяем из нужного ли топика пришли данные { payload[length] = 0; //чистим от мусора, длинна строки String strPayload = String((char*)payload); //считываем значение топика need_val = map(strPayload.toInt(), 0, 100, 1023, 0); //приводим значение 0-100 в значение 1000-0 if (need_val > old_val) { for (int i = old_val; i <= need_val; i++) //то плавно включаем свет { analogWrite(LEDPIN, i); delay(3); //каждые 10мс увелияение на 1 } } else { for (int i = old_val; i >= need_val; i--) //то плавно включаем свет { analogWrite(LEDPIN, i); delay(3); //каждые 10мс увелияение на 1 } } old_val = need_val; //analogWrite(LEDPIN, stled); //устанавливаем уровень шим сигнала Serial.print(" => "); Serial.print(need_val); // для отладки } } void setup(void) { Serial.begin(9600); Serial.println("Dallas Temperature IC Control Library Demo"); Serial.print("Locating devices..."); sensors.begin(); Serial.print("Found "); Serial.print(sensors.getDeviceCount(), DEC); Serial.println(" devices."); Serial.print("Parasite power is: "); if (sensors.isParasitePowerMode()) Serial.println("ON"); else Serial.println("OFF"); if (!sensors.getAddress(insideThermometer, 0)) Serial.println("Unable to find address for Device 0"); Serial.print("Device 0 Address: "); printAddress(insideThermometer); Serial.println(); sensors.setResolution(insideThermometer, 9); Serial.print("Device 0 Resolution: "); Serial.print(sensors.getResolution(insideThermometer), DEC); Serial.println(); pinMode(PinPomp, OUTPUT); pinMode(LEDPIN, OUTPUT); //устанвливаем ка выход //pinMode(PinAlarm, OUTPUT); NoPomp(); //инициация выхода fan // digitalWrite(PinAlarm, HIGH); //инициация выхода тревоги } //***************************************************************************************************** void loop(void) { if (millis() - timer_1 >= PERIOD_1) { // условие таймера timer_1 = millis(); // сброс таймера client.publish ("ESP02/led/temp", dtostrf(tempC, 5, 2, tempCMQTT)); ////!!!!!!!!!!!!!!!!!!!!!!!! } if (WiFi.status() != WL_CONNECTED) //если нет подключения к вифи { WiFi.begin(ssid, password); //конектимся if (WiFi.waitForConnectResult() != WL_CONNECTED) return; //если не получилось то повторяем } if (WiFi.status() == WL_CONNECTED) //если подключились { if (!client.connected()) //если нет mqtt { // то подключаемся к mqtt client.setServer(mqtt_server, 1883); client.setCallback(callback); client.connect("ESP02led"); //id клиента(должно быть уникальным в сети) client.subscribe("ESP02/led"); //подписываемся на топик } if (client.connected()) { // если подключились client.loop(); // то запускаем цикл получения топиков))) } } sensors.requestTemperatures(); // запрашиваем датчик printTemperature(insideThermometer); // Считаем темп. и выведем в порт монитора (для отладки) if (tempC > t2) //больше температуры начала работы FAN. { DoPomp(); // подтвердим включение FAN } else if (tempC < t1) // меньше первого порога. { NoPomp(); } delay(2000); } //***************************************************************************************** // функция определения адреса термодатчика на шине void printAddress(DeviceAddress deviceAddress) { for (uint8_t i = 0; i < 8; i++) { if (deviceAddress[i] < 16) Serial.print("0"); Serial.print(deviceAddress[i], HEX); } } // функция получения температуры и вывода его на порт монитора void printTemperature(DeviceAddress deviceAddress) { tempC = sensors.getTempC(deviceAddress); Serial.println(tempC, 1); } // функция включения FAN void DoPomp() { digitalWrite(PinPomp, HIGH); Serial.println("FAN enable"); } // функция выключения FAN void NoPomp() { digitalWrite(PinPomp, LOW); Serial.println("FAN disable"); }tempCMQTT побольше сделайте. Туда ещё и терминатор строки должен влезать, как минимум.