Обработка ответа от веб сервера GET

lie

✩✩✩✩✩✩✩
28 Дек 2020
14
0
Доброго времени.
Столкнулся с проблемой обработки ответа от веб сервера на GET запрос с ардуины.
С 1 параметром работает нормально, но я бы хотел обрабатывать несколько значений, это к сожалению никак не получается. Не исключаю возможности того что знаний попросту не хватает и тем не менее прошу помощи в решении.
Как мне известно сервер возвращает ответ с заголовками после заголовков приходит сам ответ. Я читал и построчно и посимвольно - все бестолку.
В идеале конечно хотел бы использовать JSON но это второй этап. На данное время нужно понять как разбирать ответ из нескольких параметров, допустим такой
запрос: index.php?i=1&s=2
ответ: r1=0|r2=1 или JSON {"r1":"0","r2":"1"}
спасибо заранее за помощь.
 

bort707

★★★★★★✩
21 Сен 2020
3,058
910
так вы показывайте, как вы пробовали это делать
 

lie

✩✩✩✩✩✩✩
28 Дек 2020
14
0
Так и думал что первый ответ будет именно таким, Да конечно покажу но вечером так как в данный момент я на работе.
Без примера я так понимаю вариантов нет? На первый взгляд вопрос пустяковый для тех кто знает, а тех кто не очень повод пофлудить.
Хорошо я понял, вечером покажу кусок. На вскидку напишу так:
Примерно так:
String currentLine = "";
  client.connect(server, 80);
  client.print( "GET /index.php?dat=");
  client.print(dat);
  client.println();
  delay (50);
          if (client.connected())
          {
            while (client.available())
            {
              char inChar = client.read();
              currentLine += inChar;
              if (currentLine == "R1=0")
              {
                  digitalWrite(R1, HIGH);
                  println("r1=1");
               }
              if(currentLine == "R1=1")
              {
                  digitalWrite(R1, LOW);
                  println("r1=0");
               }
            }
            client.stop();
          }[/COD
но здесь для 1 параметра а мне необходимо для нескольких
 

kDn

★★★★★✩✩
18 Ноя 2019
1,103
437
@lie, так а вопрос-то в чем? Как распарсить строку i=1&s=2 ? Ну дык просто - "&" разделитель, по нему находите параметры, а дальше уже из каждого параметра берете название/значение. Вот только логика по которой из i и s вы получаете r1 и r2 для меня загадочная, если же устраивает i=1|s=2 в качестве ответа - то тут вообще достаточно реплейса.
 

lie

✩✩✩✩✩✩✩
28 Дек 2020
14
0
@lie, так а вопрос-то в чем? Как распарсить строку i=1&s=2 ? Ну дык просто - "&" разделитель, по нему находите параметры, а дальше уже из каждого параметра берете название/значение. Вот только логика по которой из i и s вы получаете r1 и r2 для меня загадочная, если же устраивает i=1|s=2 в качестве ответа - то тут вообще достаточно реплейса.
Вот в том и проблема что не выходит. Пробовал и разделять по символу в массив, и просто резать, и целиком брать значение... не работает. В стартовом топике значения параметров разные согласен, это написано для примера.
логика простая ардуинка с определённой переодичновтью (по таймеру) отсылает значения на веб сервер, который эти значения сохраняет и отображает в веб морде. В ответе на гет запрос формируется ответ о том или ином действии (допустим включение реле)
в данном случае не имеет значения что посылает ардуинка, важно что получает.
Допустим получает строку r1=0|r2=1|r3=1
Мы понимаем что реле 1 нужно отключить, реле 2 нужно включить и соответственно реле 3 нужно включить.
Вот тут и происходит затык. Я прошу на основе данной информации показать как правильно найти и разобрать строку с ответом.
или хотя бы просто как найти строку с ответом.
Скорее всего в цикле нужно найти строку целиком (но она может быть разная), или заключить её в начальный и конечный тег чтобы по нему выбирать, а потом распарсить.
Как правильнее?
 

kDn

★★★★★✩✩
18 Ноя 2019
1,103
437
@lie, я не использую этот вебсервер, а ставить его мне на опыты лень. Задачи парсинга в общем-то типичные, для начала надо просто получить строку содержащую ответ и от этого решать задачу. А для AsyncWebServer парсинг уже готовый есть, в принципе можете глянуть исходники и выдрать его оттуда :)
Вот как у меня разбор параметров организован:
C++:
    server.on(PSTR("/cmd"), HTTP_ANY, [this](AsyncWebServerRequest *request) {
        String result;
        int params = request->params();
        for(int i=0;i<params;i++){
            AsyncWebParameter* p = request->getParam(i);
            if(p->isFile()){ //p->isPost() is also true
                //Serial.printf("FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size());
            } else if(p->isPost()){
                //Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
            } else {
                //Serial.printf("GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
                result = httpCallback(p->name(), p->value(), !p->value().isEmpty());
            }
        }
        request->send(200, FPSTR(PGmimetxt), result);
    });
* Тут предполагается, что каждый параметр это отдельная команда, которые я выполняю последовательно, если же мне нужно несколько значений передать, то использую просто массивы.
** Врядли вам это конечно поможет, тем более что пример под esp8266/esp32, но по крайней мере исходники сервера поглядеть можете, как минимум реализацию getParam() :)
 

bort707

★★★★★★✩
21 Сен 2020
3,058
910
Допустим получает строку ?r1=0|r2=1|r3=1
Вы работаете неправильно, потому что ищете строки типа "r2=1" целиком. Допустим, сейчас у вас после равно может быть только ноль и один, вы можете в коде жестко задать две строки. А представьте, что вы захотите так передать цвет RGB в строке типа "r=192|g=34|b=45" Неужели будете в скетче задавать все возможные значения? :)
Делайте так:
1. Сначала ищете в ответе символ "?" - это начало строки параметров.
2. Далее ищете в строке разделитель - у вас это "|"
3. То что между - это строка типа "параметр=значение". Извлекаете до знака равно - имя, после - значение.
4. Повторяеете пп 2-4, пока строка не кончится
 

lie

✩✩✩✩✩✩✩
28 Дек 2020
14
0
Вы работаете неправильно, потому что ищете строки типа "r2=1" целиком. Допустим, сейчас у вас после равно может быть только ноль и один, вы можете в коде жестко задать две строки. А представьте, что вы захотите так передать цвет RGB в строке типа "r=192|g=34|b=45" Неужели будете в скетче задавать все возможные значения? :)
Делайте так:
1. Сначала ищете в ответе символ "?" - это начало строки параметров.
2. Далее ищете в строке разделитель - у вас это "|"
3. То что между - это строка типа "параметр=значение". Извлекаете до знака равно - имя, после - значение.
4. Повторяеете пп 2-4, пока строка не кончится
логика понятна , я и так пробовал вроде. не скажу.. Вечером попробую и рабочий код если получится выложу. Спасибо

@lie, я не использую этот вебсервер, а ставить его мне на опыты лень. Задачи парсинга в общем-то типичные, для начала надо просто получить строку содержащую ответ и от этого решать задачу. А для AsyncWebServer парсинг уже готовый есть, в принципе можете глянуть исходники и выдрать его оттуда :)
Вот как у меня разбор параметров организован:
C++:
    server.on(PSTR("/cmd"), HTTP_ANY, [this](AsyncWebServerRequest *request) {
        String result;
        int params = request->params();
        for(int i=0;i<params;i++){
            AsyncWebParameter* p = request->getParam(i);
            if(p->isFile()){ //p->isPost() is also true
                //Serial.printf("FILE[%s]: %s, size: %u\n", p->name().c_str(), p->value().c_str(), p->size());
            } else if(p->isPost()){
                //Serial.printf("POST[%s]: %s\n", p->name().c_str(), p->value().c_str());
            } else {
                //Serial.printf("GET[%s]: %s\n", p->name().c_str(), p->value().c_str());
                result = httpCallback(p->name(), p->value(), !p->value().isEmpty());
            }
        }
        request->send(200, FPSTR(PGmimetxt), result);
    });
* Тут предполагается, что каждый параметр это отдельная команда, которые я выполняю последовательно, если же мне нужно несколько значений передать, то использую просто массивы.
** Врядли вам это конечно поможет, тем более что пример под esp8266/esp32, но по крайней мере исходники сервера поглядеть можете, как минимум реализацию getParam() :)
Это для сервера на ардуине? или я не прав? просто у меня выделенный сервер к нему я и с телефона подключаюсь. Паралельно пишу под андроид приложение
 

kDn

★★★★★✩✩
18 Ноя 2019
1,103
437
Это для сервера на ардуине? или я не прав? просто у меня выделенный сервер к нему я и с телефона подключаюсь. Паралельно пишу под андроид приложение
Код с AsyncWebServer который крутится на esp8266/esp32, фреймворк - Arduino. Т.е. контроллер другой, но фреймворк тот же. Так что затрудняюсь однозначно ответить на вопрос. :)
 

lie

✩✩✩✩✩✩✩
28 Дек 2020
14
0
Код с AsyncWebServer который крутится на esp8266/esp32, фреймворк - Arduino. Т.е. контроллер другой, но фреймворк тот же. Так что затрудняюсь однозначно ответить на вопрос. :)
я и говорю на ардуине веб , а у меня на удалённом
 

kDn

★★★★★✩✩
18 Ноя 2019
1,103
437
@lie, да тут в общем-то не суть важно - то ли сервер разбирающий запрос, то ли клиент разбирающий ответ... Идея та же. Ну хорошо, у вас есть сторонний веб-сервер, а сам контроллер клиент. Значит вы попросту в браузере можете составить запрос который ожидает сервер, получить от него ответ и уже исходя из ответа писать парсер.
 

Борисыч

★✩✩✩✩✩✩
17 Дек 2020
19
11
lookatmusic.com
Немного по ответу сервера. Ответ удобнее будет разбирать если он "закрыт" т.е. в виде r1=0|r2=1|r3=1| (палка в конце). По коду понятно будет.
Можно избежать этого если знаешь границы значений - допустим 1 символ, (0, 1) или 1байт. Если байт, его имеет смысл передавать в hex формате всегда двумя символами. Передача hex позволяет отправлять много данных одним пакетом, не озадачиваясь r1=,r2=,r3=...
Вот один из пакетов которые я ловлю

KosBorCFG43...600ff00#
Вместо троеточия ещё много шестнадцатиричной каши.

Пакет начинается с KosBorCFG ( в вашем случае r1= ) и завершается '#' - у вас'|'.

Дальше как я его разбираю
C++:
bool checkForKeyword(String &value, const String keyword ){
    int first = serialString.indexOf( keyword ); // индекс первого символа названия параметра
    if( first<0 ) return false; // нету его
    value=serialString.substring( first+keyword.length() ); // отрезаем от начала значения до конца строки
    int second = value.indexOf( "#" ); // есть маркер завершения?
    if( second<0 ) return false; // нету его, возможно не пришёл пока
    value=value.substring( 0, second ); // вырезаем только значение
    serialString.remove( first, keyword.length()+value.length()+1 ); // считаем эту часть глобальной строки обработанной и удаляем
    return true;
}
String serialString - глобальная переменная накопитель, в нее насыпает управлятор или по COM или по websocket, смотря кто управляет сейчас.
Параметры -
String &value - искомое значение
String keyword - значение какого ключевого слова мы хотим получить.
Функция возвращет true/false в смысле нашла/не нашла.

Для обработки ваших данных нужно поменять в коде '#' на '|' и позвать функцию три раза

C++:
String value;
if( checkForKeyword(value, "r1=") ){
    // обрабатываем r1
}
if( checkForKeyword(value, "r2=") ){
    // обрабатываем r2
}
if( checkForKeyword(value, "r3=") ){
    // обрабатываем r3
}
Это всё подразумевает что нет ограничений по памяти. Если есть - нужно иначе делать. Если нужно напишу.
 

lie

✩✩✩✩✩✩✩
28 Дек 2020
14
0
Немного по ответу сервера. Ответ удобнее будет разбирать если он "закрыт" т.е. в виде r1=0|r2=1|r3=1| (палка в конце). По коду понятно будет.
Можно избежать этого если знаешь границы значений - допустим 1 символ, (0, 1) или 1байт. Если байт, его имеет смысл передавать в hex формате всегда двумя символами. Передача hex позволяет отправлять много данных одним пакетом, не озадачиваясь r1=,r2=,r3=...
Вот один из пакетов которые я ловлю

KosBorCFG43...600ff00#
Вместо троеточия ещё много шестнадцатиричной каши.

Пакет начинается с KosBorCFG ( в вашем случае r1= ) и завершается '#' - у вас'|'.

Дальше как я его разбираю
C++:
bool checkForKeyword(String &value, const String keyword ){
    int first = serialString.indexOf( keyword ); // индекс первого символа названия параметра
    if( first<0 ) return false; // нету его
    value=serialString.substring( first+keyword.length() ); // отрезаем от начала значения до конца строки
    int second = value.indexOf( "#" ); // есть маркер завершения?
    if( second<0 ) return false; // нету его, возможно не пришёл пока
    value=value.substring( 0, second ); // вырезаем только значение
    serialString.remove( first, keyword.length()+value.length()+1 ); // считаем эту часть глобальной строки обработанной и удаляем
    return true;
}
String serialString - глобальная переменная накопитель, в нее насыпает управлятор или по COM или по websocket, смотря кто управляет сейчас.
Параметры -
String &value - искомое значение
String keyword - значение какого ключевого слова мы хотим получить.
Функция возвращет true/false в смысле нашла/не нашла.

Для обработки ваших данных нужно поменять в коде '#' на '|' и позвать функцию три раза

C++:
String value;
if( checkForKeyword(value, "r1=") ){
    // обрабатываем r1
}
if( checkForKeyword(value, "r2=") ){
    // обрабатываем r2
}
if( checkForKeyword(value, "r3=") ){
    // обрабатываем r3
}
Это всё подразумевает что нет ограничений по памяти. Если есть - нужно иначе делать. Если нужно напишу.
Конечно нужно. В плане развития даже.
А вообще интересно в JSON там мне кажется проще будет. Но у меня вчера не вышло. Примеров много а у меня не работает ни один 8( печаль.
А в JSON вообще просто всё, я в вебке его использую, а вот на ардуине не могу применить.
 

kDn

★★★★★✩✩
18 Ноя 2019
1,103
437
А в JSON вообще просто всё, я в вебке его использую, а вот на ардуине не могу применить.
А в чем собственно проблема? Создаете объект и работаете с ним.
C++:
    DynamicJsonDocument doc(1024);
    JsonObject obj = doc.to<JsonObject>();

    obj["key"] = "value";

    ...
        
    if(obj.containsKey("key")){
        String val = obj["key"].as<String>();
    }
Маленький пример, а так-то читайте документацию. Ну и если нужно целиком JSON сериализировать/десериализировать - то тоже документация в помощь. Особенно на предмет того почему используются шаманства вида:
C++:
      String tmp; // Тут шаманство, чтобы не ломало JSON
      serializeJson(docArrMessages, tmp);
      deserializeJson(docArrMessages, tmp);
или ручные вызовы сборщика мусора :)
 

Борисыч

★✩✩✩✩✩✩
17 Дек 2020
19
11
lookatmusic.com
Готового кода у меня нет, один из вариантов примерно такой

C++:
while( Serial.available() ) {
    char ch = Serial.read();
    if( !Serial.available() ) break; // дальше ничего нет, выходим
    if( ( ch!='r'  ) continue; // не наш символ, ждём дальше
    char rIndex = Serial.read(); // сейчас должен быть индекс в названии ( 1, 2, 3)
                                    // он понадобится
    if( !( ('1'<=rIndex) && (rIndex<='3') ) continue;// не наше
    if( !Serial.available() ) break;
    ch = Serial.read();
    if( ch != '=' ) continue; // нет готового заголовка вида 'r1='
    String value=""; // подразумеваем, что будет не более 3 цифр и разделитель
                        // про отрицательные числа - не слышали
    while( Serial.available() && value.length() <= 4   ) {
        ch = Serial.read();
        if( ch=='|' ){ // разделитель - запоминаем, выходим
            value += ch;
            break;
        }
        if( ('0'<=ch) && (ch<='9') ){
            value += ch; // цифирь, запоминаем
        }else{
            // есть не цифровой символ до разделителя - ошибка
            // обработать на свой вкус.
        }
    }

    // здесь в value должно быть похоже на "123|" или "1|"

    if( value.indexOf('|') == value.length()-1 ){
        // строка завершается '|', всё в порядке
        value.remove( value.length()-1 ); // удалили разделитель, в строке значение
        uint8_t val = value.toInt();
        switch( rIndex ){ // кого мы сегодня встречаем?
            case '1': r1=val; break;
            case '2': r2=val; break;
            case '3': r3=val; break;
            // defolt: не нужен, т.к. мы пропустили сюда только 123
        }
    }else{
            // ошибка обработать на свой вкус.
    }
}
Другим вариантом может быть накопление строки ограниченной длинны и её обработка по получению разделителя.
Скажем выделяем строку 6 символов и заполняем её.
b // 1
bu // 2
bub // 3
bubu // 4
bubur // 5
bubur1 // шесть есть, а разделителя нет. удаляем нулевой символ и продолжаем читать
ubur1= // шесть есть, а разделителя нет. удаляем нулевой символ и продолжаем читать
bur1=1 // шесть есть, а разделителя нет. удаляем нулевой символ и продолжаем читать
ur1=1| // есть разделитель, от него работаем назад

Насчёт JSON. Разбрать полный формат JSON с вложенными массивами строками и пр. - весьма не простая задача. Придёт он всё равно обычной строкой. Некая библиотека этот разбор за вас сделает, но увеличится код и энергопотребление, упадет быстродействие. Готовы на это?
 
  • Лойс +1
Реакции: Старик Похабыч

kDn

★★★★★✩✩
18 Ноя 2019
1,103
437
Некая библиотека этот разбор за вас сделает, но увеличится код и энергопотребление, упадет быстродействие. Готовы на это
Ну дали бы сразу ссылку на эту некую библиотеку, а также расчёт затрат :). При прочих равных я бы воспользовался таки проверенным кодом, чтобы не изобретать своих велосипедов. А то ведь по такой логике и ваше использование класса String вместо работы с массивом - это как бы не хорошо, чего уж не работать с ASCIIZ, как в старые добрые времена, когда про UTF8 даже не думали. :)

 

Борисыч

★✩✩✩✩✩✩
17 Дек 2020
19
11
lookatmusic.com
Ну дали бы сразу ссылку ...
Вы библиотекой JSON это r1=0|r2=1 разберёте?
Я добавив 4 строки кода, разберу и это r1=0|r2=1 и вот это JSON {"r1":"0","r2":"1","r3":"G.L.A.S.H.A"} . Вы же знаете какие :).

Изобретение велосипедов - необходимая часть обучения. Не писавшие велосипедов не напишут "проверенным кодом".
Насчёт ASCIIZ и UTF, честно говоря, вообще не понял к чему. Ну да, мой код не варит кофе. Дык его(кофе) и не просили ;).
ЗЫ
А чего вы по ненашему пишете? Добавляйте перевод сразу....
 

kDn

★★★★★✩✩
18 Ноя 2019
1,103
437
Писание на нескольких языках - ещё +1. Но вы уверены, что все читающие эту ветку поймут по-ненашему? Или вы уверены, что мысль которую вы публикуете настолько важна что ради неё стоит лезть в переводчик?
Вы знаете, я и с переводчиком не могу понять какую мысль пытаетесь донести вы. Для начала автор изначально был не прочь работать с JSON-объектами, ну и ко всему прочему для программиста английский попросту должен быть понятен без переводчика, иначе в этой теме ему делать нечего. Я уже предложил воспользоваться переводчиком самостоятельно, если что-то непонятно. Здесь же пишу вроде русскими буквами, хотя могу и другими as well.

Не делайте пожалуйста предположений о моих ( и не только ) знаниях и квалификациях.
Это не красиво, да и при сравнении конфуз может случиться ;)
И предложений не нужно. Я давно и счастлив.;)
Я не делаю предположений. А утверждаю исходя из контекста диалога. Я вообще не с вами общался изначально. Увидел ошибочное утверждение и поправил вас.
Скачал предлагаемую вами библиотеку - 237к исходников.
Вы серьёзно?
Чтоб разобрать "r1=0|r2=1 или JSON {"r1":"0","r2":"1"} "? Карл! 237 килобайт!
237к чужого, пусть даже "trusted by thousands of developpers all over the world.(доверяют тысячи разработчиков по всему миру)" кода?
Вы действительно так делаете? Бррррр....
Я более чем серьезен. Код открыт, код написан для множества платформ. Статистика для esp8266 по потреблению памяти, только что поглядел: Total: 56.1 KB Flash, 0 bytes RAM, что в общем-то ерунда при 4Мб флеша. А вообще заявлено следующее: https://arduinojson.org/v6/how-to/reduce-memory-usage/ , если чего непонятно - переводчик в помощь.

Ну и на всякий случай - сначала разберитесь в вопросе, а затем давайте рекомендации, не наоборот. А раз разговор переходит в плоскость "да ты, да я" - то я пожалуй на этом с вами разговор и закончу. Длиной меряйтесь с кем-то другим, мне это не интересно. Я по другую сторону стола стою.
 

lie

✩✩✩✩✩✩✩
28 Дек 2020
14
0
Вы знаете, я и с переводчиком не могу понять какую мысль пытаетесь донести вы. Для начала автор изначально был не прочь работать с JSON-объектами, ну и ко всему прочему для программиста английский попросту должен быть понятен без переводчика, иначе в этой теме ему делать нечего. Я уже предложил воспользоваться переводчиком самостоятельно, если что-то непонятно. Здесь же пишу вроде русскими буквами, хотя могу и другими as well.


Я не делаю предположений. А утверждаю исходя из контекста диалога. Я вообще не с вами общался изначально. Увидел ошибочное утверждение и поправил вас.

Я более чем серьезен. Код открыт, код написан для множества платформ. Статистика для esp8266 по потреблению памяти, только что поглядел: Total: 56.1 KB Flash, 0 bytes RAM, что в общем-то ерунда при 4Мб флеша. А вообще заявлено следующее: https://arduinojson.org/v6/how-to/reduce-memory-usage/ , если чего непонятно - переводчик в помощь.

Ну и на всякий случай - сначала разберитесь в вопросе, а затем давайте рекомендации, не наоборот. А раз разговор переходит в плоскость "да ты, да я" - то я пожалуй на этом с вами разговор и закончу. Длиной меряйтесь с кем-то другим, мне это не интересно. Я по другую сторону стола стою.
Попробую JSON. И не ругайтесь, какая разница какой подход если работает, это вопрос оптимизации, мне JSON ближе, как говорится на вкус и цвет. Спасибо за ответы всем.
 

lie

✩✩✩✩✩✩✩
28 Дек 2020
14
0
Вот так не работает когда выставляю пины на релюшки 2 и 3
ставлю 3 и 4 работает но реле 2 не включается парабокс какой то
C++:
void json() {
  char buffer[10];
  h = dht.readHumidity();
  t = dht.readTemperature();
  String tem = dtostrf(t, 5, 2, buffer);
  String vla = dtostrf(h, 5, 2, buffer);

  if (client.connect(server, 80))
    {
    // Make a HTTP request:
    client.print ("GET /API/add_data.php");
    client.print ("?");

    // String getter = "tem=" + tem + "&vla=" + vla + "&pow1=1&pow2=0 HTTP/1.1";
    String getter = "tem=" + tem + "&vla=" + vla + " HTTP/1.1";
    Serial.println("Запрос GET /API/add_data.php?" + getter);

    client.println( getter );
    client.print( "Host: " );
    client.println(server);
    client.println( "Connection: close" );
    client.println();
    client.println();
    delay(200);
     while (client.available()) {
    line = client.readStringUntil('\r');
  }
  Serial.println(line);
  int dlina = line.length();
  Serial.println(dlina);
  StaticJsonDocument<500> docJson; // Создаем буфер
  if (deserializeJson(docJson, line)) Serial.println("deserialize OK!");

  parametrRele.Rele1 = (const char*)docJson["rele1"];
  parametrRele.Rele2 = (const char*)docJson["rele2"];
  // parametrRele.temperatura   = docJson["rele1"]["temp"];
  //Serial.println(parametrRele.Rele1);
  //Serial.println(parametrRele.Rele2);
  if (parametrRele.Rele1 == "1"){ digitalWrite (RELE1, LOW); Serial.println("Р1 ВКЛ."); } else {digitalWrite (RELE1, HIGH); Serial.println("Р1 ОТКЛ.");}
  if (parametrRele.Rele2 == "1"){ digitalWrite (RELE2, LOW); Serial.println("Р2 ВКЛ.");} else {digitalWrite (RELE2, HIGH); Serial.println("Р1 ОТКЛ.");}
      client.stop();
    client.flush();
    delay(100);

  }  else
    {
      client.stop();
      Serial.println("Ошибка подключения ");
      delay(5000);
      //client.connect(server, 80);
    }
    delay(500);
}
 
Изменено:

lie

✩✩✩✩✩✩✩
28 Дек 2020
14
0
В 40 строке спецом digitalWrite (RELE1, LOW); а в иначе digitalWrite (RELE2, HIGH ?
Я после уже увидел но это не влияет код зависает только получив ИП

Блин как только включаю реле 2 плата зависает, в чем проблема то ребят?

Как только реле 2 на 4 пине включаю висяк