• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Решено Парсинг ответа с сайта

ave

New member
Подскажите, как правильно написать эту функцию, чтобы она принимала ответ в строку и раздиляла эту строку на три строки по "/".
Формат ответа с сайта:
PHP:
<? echo "1/20.2/25.4\r"; ?>
Ошибка на команде pch = strtok(line,"/");
Не знаю как формат переменных String и char согласовать.
Код:
while (client.available()) {
    //char line = client.read();
    String line = client.readStringUntil('\r');
    char *pch;
    Serial.print("Reply: ");
    Serial.println(line);
    pch = strtok(line,"/");
    while (pch != NULL) {
      Serial.println(pch);
      pch = strtok(NULL,"/");
    }
    //if (line == '1') digitalWrite(led,1); else digitalWrite(led,0);
}
 

Юрий Ботов

Moderator
Команда форума
как то так:
String S = "123";
char buf[30];
S.toCharArray(buf, 30);
а этот buf уже отдаешь в strtok(buf,"/\"")
 

lsm

Разработчик Smart.js
Команда форума
Если точно известно что компоненты всего три, то:

Код:
char a[20], b[20], c[20];


if (sscanf(line.c_str(), "%19[^/]/%19[^/]/%19s", a, b, c) == 3) {
   // success
} else {
   // error
}
 

ave

New member
lsm, да, у меня всегда три компоненты.
Но у мены возникает ошибка, такая же как здесь:
Вопрос - sscanf
И ее решение мне не понятно.
 

ave

New member
https://zxlogin.com/zxloginteplo.php?com=n&newt1=19.94&newt2=19.87&s=1&id=10650774
По этой посылке от модуля данные в базу записываются и хостинг выдает ответ "1/30/20", но у меня почему-то в середину while вызов не попадает. "Ok" не выводится. В чем может быть причина? Как работает client.available()?
Код:
client.print(String("GET ")+url+" HTTP/1.1\r\nHost: "+host_zxlogin+"\r\nConnection: close\r\n\r\n");
client.flush();     // ждем отправки всех данных

while (client.available()) {
  Serial.println("Ok");
}
 
Последнее редактирование:

pvvx

Активный участник сообщества
Как работает client.available()?
Вроде говорит, есть ли у клиета принятые данные.
Что-то по вашему адресу мусор с "1/30/20"
Код:
#include <WiFi.h>
#include <myAP.h>

#ifndef _MYAPCFG_H_
char ssid[] = "yourNetwork"; //  your network SSID (name)
char pass[] = "password";    // your network password (use for WPA, or use as key for WEP)
#endif //_MYAPCFG_H_

char server[] = "zxlogin.com";    // name address for Google (using DNS)

WiFiSSLClient client;
/* if ssl_handshake returned -0x7200 ->
SSL_MAX_CONTENT_LEN to sufficient size (maximum value is 16384).
default value 4096. */
extern "C" unsigned int mfl_code_to_length[]; // mfl_code_to_length[0] = SSL_MAX_CONTENT_LEN

void setup() {
  mfl_code_to_length[0] = 16384; // = max SSL_MAX_CONTENT_LEN
  // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
  WiFi.begin(ssid,pass);
}

void loop() {
  printf("\r\n");
  if (client.connect(server, 443)) {
    // Make a HTTP request:
    char * buf = new char [512];
    sprintf(buf, "GET /zxloginteplo.php?com=n&newt1=19.94&newt2=19.87&s=1&id=10650774 HTTP/1.1\r\n\Host: %s\r\n\Connection: close\r\n", server);
    client.println(buf);
    delete [] buf;
    while (client.connected()) {
      // if there are incoming bytes available
      // from the server, read them and print them:
      while (client.available()
             // пропуск HTTP заголовка
             && client.read() == 13 && client.read() == 10
             && client.read() == 13 && client.read() == 10) {
        while (client.available()) Serial.write((unsigned char)client.read());
        delay(50);
        printf("disconnecting...");
        client.stop();
        sys_info();
        delay(60000);
        return;
      }
    }
  }
  delay(10000);
}
Код:
Initializing WIFI ...
WIFI initialized
Interface 0 IP address : 192.168.1.122
b
п»ї1/30/20
0

disconnecting...
CLK CPU         166666666 Hz
RAM heap        74216 bytes
TCM heap        27928 bytes

b
п»ї1/30/20
0

disconnecting...
CLK CPU         166666666 Hz
RAM heap        74224 bytes
TCM heap        27928 bytes

b
п»ї1/30/20
0

disconnecting...
CLK CPU         166666666 Hz
RAM heap        74224 bytes
TCM heap        27928 bytes
 
Последнее редактирование:

pvvx

Активный участник сообщества
Ещё ваш сервер выдает данные в Transfer-Encoding: chunked... Ему бир-бар, даже если указать HTTP/1.0.
А эксплореру - сжатым в gzip. Но эксплорер в заголовке запроса разрешает gzip...
HTTP/0.9 и HTTP/2 он ответил:
Код:
HTTP/1.1 400 Bad Request
Server: nginx
Date: Tue, 22 Nov 2016 06:09:32 GMT
Content-Type: text/html
Content-Length: 166
Connection: close

<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>nginx</center>
</body>
</html>
Дурной сервер: Transfer-Encoding: chunked: Он стал доступен только начиная с HTTP версии 1.1 (HTTP/1.1).
Ответ его без "HTTP/x" GET URI — для версии протокола 0.9;
Код:
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>nginx</center>
</body>
</html>
:)
 
Последнее редактирование:

ave

New member
Как работает сжатие GZIP
По вашим наводкам нахожу полезные статьи и узнаю все больше интересного и нового для себя.
Но, пока не понимаю куда копать чтобы решить проблему.

1. В ответе в конце строки убрал \r.
PHP:
<? echo "1/20/30"; ?>
2. Перекодировал страницу с UTF-8 в ANSI (в ответе нет русских букв и трафик будет меньше, я так думаю).
3. Заменил протокол GET посылки на HTTP/0.9.

И еще есть непонятные моменты.

client.flush() - Здесь ждем отправки всех данных, здесь понятно.
while (client.available()) - А здесь не понятно.

До прихода ответа, я так понимаю client.available() = 0.
Но програма подождала отправки и не дожидаясь ответа идет дальше минуя while (0).
Я думаю тут что-то не то.
 
Последнее редактирование:

ave

New member
ClientAvailable Программирование Ардуино

Я так понял функция while (client.available()) должна быть в основном цикле loop(), а то она у меня была в функции sendServer_zxlogin() из которой программа успешно выходила и не могла там принять ответ. client.stop() убрал из sendServer_zxlogin(), но все равно ответ не приходит. ((
Код:
void loop (void) {
  server.handleClient();
  delay(1);
  while (client.available()) {
    Serial.println("Ok");
    client.stop();
  }
}
 
Последнее редактирование:

ave

New member
Заработало! Наконец то ответ получил.
Закомментировал client.flush(). Почему ответ приходит только после отключения client.flush()...

ClientFlush Программирование Ардуино
StreamFlush Программирование Ардуино


Код:
void sendServer_zxlogin(int state) {
  if (!client.connect(host_zxlogin,httpsPort)) {
    Serial.print(host_zxlogin);
    Serial.println(" - Connection failed.");
    client.stop();
    return;
  }

  String url = "/zxloginteplo.php?com=n&newt1="+(String)ft1+"&newt2="+(String)ft2+"&s="+(String)ledStatus+"&id="+(String)chipId;

  Serial.print("Sending URL: ");
  Serial.print(host_zxlogin);
  Serial.println(url);

  client.print(String("GET ")+url+" HTTP/1.1\r\nHost: "+host_zxlogin+"\r\nConnection: close\r\n\r\n");
  //client.flush();     // ждем отправки всех данных
}

void loop (void) {
  server.handleClient();
  delay(1);

  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }
}
В терминале:
Код:
Sending URL: zxlogin.com/zxloginteplo.php?com=n&newt1=19.62&newt2=19.62&s=0&id=10650774
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 22 Nov 2016 19:54:20 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: close

7
1/30/20
0
 
Последнее редактирование:

ave

New member
Парсинг ответа сервера с фиксированным количеством параметров "{1/30/20}".
Добавил "{}" для упрощения выделения строки.
Код:
while (client.available() && client.read() == '{') {
    int a,b,c;
    char *pch;
    char buf[30];
    String var;
    String line = client.readStringUntil('}');
    line.toCharArray(buf,30);
    pch = strtok(buf,"/");
    var = (String)pch;
    a = var.toInt();
    pch = strtok(NULL,"/");
    var = (String)pch;
    b = var.toInt();
    pch = strtok(NULL,"/");
    var = (String)pch;
    c = var.toInt();
    Serial.println(a);
    Serial.println(b);
    Serial.println(c);
    client.flush();
    client.stop();
    return;
}
В терминале:
Код:
Sending URL: zxlogin.com/zxloginteplo.php?com=n&newt1=19.37&newt2=19.31&s=0&id=10650774
1
30
20
 
Последнее редактирование:

achuser

New member
Если точно известно что компоненты всего три, то:

Код:
char a[20], b[20], c[20];


if (sscanf(line.c_str(), "%19[^/]/%19[^/]/%19s", a, b, c) == 3) {
   // success
} else {
   // error
}
вся беда в том, что sscanf на esp не работает, по крайней мере под IDE...

Считать данные, как в примере выше возможно, но тут проблема в том, что только в заданном формате, например sscanf мог работать со строкой любого размера и кол-ва переменных. А здесь если задано 3, то одну или 4 не передашь, будет кидать мусор в сериал...

Никто аналог sscanf не придумал еще под есп? :)
 
Последнее редактирование:

achuser

New member
Гляну на досуге, пока решил немного иным путем пойти,чтобы меньше со строкой работать, но ежели аналогичная функция будет, можно и вернуться к ней :)

Пока проблема нарисовалась другая, nodeMCU зависает минут через 25 работы, ардуина у меня работала неделями )
 
Сверху Снизу