ioBroker: переменный топик
- Войдите на сайт для отправки комментариев
Втр, 14/01/2020 - 18:09
Братья по разуму!
Можете помочь, не могу сделать переменный топик для ioBroker, (их у меня 28 шт. только для света)
//Функция обработки входящих соединений - прием данных по подписке
void callback(char* topic, byte* payload, unsigned int length)
{ //преобразуем тему(topic) и значение (payload) в строку
payload[length] = '\0';
String strTopic = String(topic);
String strPayload = String((char*)payload);
//Чтение статусов
for (i = 0; i < 28; i++){ //цикл 1
String Index= String(i, DEC);
String Stsv = String("svet/stsv" + Index);
if (strTopic == Stsv) { // управление светом
stsv[i] = strPayload.toInt();
digitalWrite(led[i], stsv[i]);
tmr[i] = millis(); }
} // конец цикла
}//end void callback
выдает ошибку: invalid types 'byte {aka unsigned char}[byte {aka unsigned char}]' for array subscript
переменная i в начале скетча обозначена как байт
Мда...
Мда...
эт точно. хотел что-то поумнее написать - но тут иначе и не скажешь :)
Рядом с ошибкой обычно номер строки написан.
у меня 1.8 : показывает на строку
закомментил её,
показывает на предыдущую строку
у меня 1.8 : показывает на строку
закомментил её,
показывает на предыдущую строку
где и как описан массив stsv[] ?
Да, действительно - непростительная ошибка в определении массивов!
Идем дальше
if (client.connect("svet1")) { // Once connected, publish an announcement... if (flags == 1) { for (i = 0; i < 4; i++){ //цикл 1 String Index= String(i, DEC); String Stsv = String("svet1/stsv" + Index); dtostrf(stsv[i], 1, 0, buff); client.publish(Stsv, buff); }}выдает: no matching function for call to 'PubSubClient::publish(String&, char [20])'
курю библиотеку PubSubClient
курю библиотеку PubSubClient
вам не библиотеку надо курить, а книжку по С/С++ штудировать. Разберитесь в отличиях String и char* и в работе с массивами.
А потом подумайте - неужели преобразование числа в String, формирование из него имени топика. а потом поиск этого имени среди 28 одинаковых имен - это правильный метод поиска нужного топика в массиве? Я вам сразу скажу - это бредятина, а не алгоритм...
Предлагаете
Предлагаете
нет, предлагаю просто найти в строчке topic номер и использовать как индекс.
интересно, если бы у вас было 50000 вариантов -тоже в цикле сравнивали 50 тысяч строк??
да, согласен, спасибо! Свежий взгляд помог, а то мой замылился с этим иоброкером
Если имя топика в конце содержит цифры, и по ним надо ориентироваться, то просто ищем с конца первый символ - не цифру, а остальные справа - будут цифрами. Что-то типа этого:
void callback(char* topic, byte* payload, unsigned int length) { const char* ptr = topic + strlen(topic); while(ptr >= topic && (*ptr >= '0' && *ptr <= '9')) { ptr--; } int idx = atoi(ptr); }Навскидку, не проверял, но там всё понятно по алгоритму, надеюсь: просто смотрим на конец имени топика, и перемещаемся влево, пока встретим символы, отличные от ['0'-'9'].
Оно, конечно, по уже установившейся традиции, ТС скрыл свой суперскетч от нас, чтобы мы не стырили, потому, точно не скажешь, но, вот сдаётся мне в строке №4 выход за границу массива.
у меня 1.8 : показывает на строку
закомментил её,
Подход верный, продолжайте так, комментируйте все строки с ошибками.
спасибо, парни, за тычки в нужную сторону, скетч полностью могу выложить, когда он станет рабочим. думаю над ошибкой в посте 6
думаю над ошибкой в посте 6
Думать не надо, надо посмотреть объявления методов PubSubClient и понять, что String он не принимает в качестве параметра, а принимает - char*. Поэтому, вместо
достаточно написать:
и учить основы языка - будет вовне необязательно, лишнее это, никому не нужное.
Ура! Заработало!
Спасибо DIYMan и b707!
На плане два светильника из 28. Использую Mega+W5100.
Кнопки будут реализованы на PCF8574.
В скетче, для примера, использованы 4 кнопки, подключенные к Меге.
#include <SPI.h> #include <Ethernet.h> #include <PubSubClient.h> byte mac[] = { 0xDE, 0xAA, 0xBB, 0xFF, 0xEE, 0xDD }; IPAddress ip(192, 168, 0, 210); //вводим IP IPAddress Server(192, 168, 0, 1); char buff[20]; byte flag[4]; // флаг кнопок byte flags= 0; // флаг отправки byte stsv[4]; // статус светодиодов unsigned long tmr[4]; const long zad = 600000; // задержка 60 мин const byte insvet[] = {43,45,47,49}; // номер ноги кнопки на ноль const byte led[] = {22,24,26,28}; // номер ноги светодиода byte i, val; EthernetClient ethClient; PubSubClient client(ethClient); //Функция обработки входящих соединений - прием данных по подписке void callback(char* topic, byte* payload, unsigned int length) { //преобразуем тему(topic) и значение (payload) в строку payload[length] = '\0'; String strTopic = String(topic); String strPayload = String((char*)payload); //Чтение статусов for (i = 0; i < 4; i++){ //цикл1 String Index= String(i, DEC); String Stsv = String("svet1/stsv" + Index); if (strTopic ==Stsv.c_str()) { // управление светом stsv[i] = strPayload.toInt(); digitalWrite(led[i], stsv[i]); tmr[i] = millis(); } } // конец цикл1 }//end void callback void setup() { client.setServer(Server, 1883); client.setCallback(callback); Ethernet.begin (mac, ip);//запускаем сервер с указанными ранее MAC и IP // Serial.begin(9600); delay(790); //ждем Ethernet.begin for (i = 0; i < 4; i++){ //цикл 2 pinMode(insvet[i], INPUT); //вывод-вход digitalWrite(insvet[i],HIGH); //включаем внутр. резистор pinMode(led[i], OUTPUT); //вывод-выход digitalWrite(led[i],0); //выключаем все tmr[i] = millis(); } //конец цикл2 if (client.connect("svet1")) { for (i = 0; i < 4; i++){ //цикл3 String Index= String(i, DEC); String Stsv = String("svet1/stsv" + Index); client.subscribe(Stsv.c_str()); //подписка на топики } //цикл3 }//end client.connect } // конец setup void loop() { for (i = 0; i < 4; i++){ //Ручное управление светом: цикл4 val = !digitalRead(insvet[i]); if(val==1 && flag[i]==0) //если кнопка нажата { stsv[i] = !stsv[i]; flags = 1; digitalWrite(led[i], stsv[i]); flag[i]=1; if (stsv[i] ==1) {tmr[i] = millis();} //установка времени вкл света } if(val==0 && flag[i]==1) //если кнопка НЕ нажата { flag[i] = 0; } //обнуляем переменную flag if (stsv[i] ==1 && millis()-tmr[i] > zad) //время вышло? {stsv[i] = 0; digitalWrite(led[i], 0); flags = 1;} }//конец цикл4 if (flags == 1) { //если есть изменение статуса света if (client.connect("svet1")) { for (i = 0; i < 4; i++){ //цикл 1 String Index= String(i, DEC); String Stsv = String("svet1/stsv" + Index); dtostrf(stsv[i], 1, 0, buff); client.publish(Stsv.c_str(), buff); flags = 0; } }// end Client connected }// end if (flags == 1) client.loop(); delay(1); } // end void loopСкетч оччень простой получился!
Есть конечно огрехи, будем вылизывать!