esp8266, почему теряются последние значения из буфера?

lean_74
Offline
Зарегистрирован: 22.12.2015

полгода работало и перестало...

#include <ESP8266WiFi.h>                  // Библиотека для создания Wi-Fi подключения (клиент или точка доступа)
#include <WiFiClient.h>                   // Библиотека для связи с сетевыми хостами (локальными и интернет)
#include <TimeLib.h>                      // Библиотека для работы с временем
#include <ArduinoJson.h>                  // Библиотека для разбора JSON


const char* ssid = "Lenovo";            // Указываем имя WiFi-сети, к которой будет подключаться ESP8266 для доступа в Интернет
const char* password = "88888";    // Указываем пароль для подключения к WiFi-сети

String regionID = "11207";                  // Код региона по Yandex для выбора часового пояса https://tech.yandex.ru/xml/doc/dg/reference/regions-docpage/

String SunriseTime, SunsetTime, Temperature;
char icon[20];

WiFiClient client;                        // Создаём объект для работы с удалёнными хостами

void setup() {
  Serial.begin(115200);                                         // Инициализируем вывод данных на серийный порт со скоростью 9600 бод
  Serial.println("\n\n");
  WiFi.begin(ssid, password);                                 // Соединяемся с WiFi-сетью
  
  while (WiFi.status() != WL_CONNECTED)                       // Пока соединение не установено
    delay(500);                                               //  делаем задержку в пол секунды, пока соединение не установится
    
  while (!TimeAndWeather())                                   // Синхронизируем время микроконтроллера с реальным временем и получаем информацию о погоде
    delay(500);
  
  Serial.print("Tekuschie data i vremya: ");
  digitalClockDisplay();                                      // Выводим дату и время
  Serial.println();
  Serial.println("Voshod v " + SunriseTime);                  // Выводим время восхода
  Serial.println("Zakat v " + SunsetTime);                    // Выводим время восхода
  Serial.println();
  Serial.println("Temperatura: " + Temperature + " C");       // Выводим время восхода
  WeatherDisplay();                                           // Выводим информацию о погоде
}

void loop() {}

bool TimeAndWeather () {                                                    // Функция синхронизации времени работы программы с реальным временем и получения информации о погоде
  if (client.connect("yandex.com",443)) {                                   // Если удаётся установить соединение с указанным хостом (Порт 443 для https)
    client.println("GET /time/sync.json?geo=" + regionID + " HTTP/1.1\r\nHost: yandex.com\r\nConnection: close\r\n\r\n"); // Отправляем параметры запроса
    delay(300);                                                             // Даём серверу время, чтобы обработать запрос
    char endOfHeaders[] = "\r\n\r\n";                                       // Системные заголовки ответа сервера отделяются от остального содержимого двойным переводом строки
    if (!client.find(endOfHeaders)) {                                       // Отбрасываем системные заголовки ответа сервера
      Serial.println("Invalid response");                                   // Если ответ сервера не содержит системных заголовков, значит что-то пошло не так
      return false;                                                         // и пора прекращать всё это дело
    }


 
    Serial.println("chitaem dannie");  
  String line2;
  while ( client.available() )
  {
    char c = client.read();
    line2 += c;
  }
    Serial.print("line2= "); 
    Serial.println(line2); 
//line2=line2+"}]}}}"; 
  
 //   const size_t capacity = 750;                                            // Эта константа определяет размер буфера под содержимое JSON (https://arduinojson.org/v5/assistant/)
 //   DynamicJsonBuffer jsonBuffer(capacity); // Инициализируем буфер под JSON
    DynamicJsonDocument root(2048);
    
//    JsonObject& root = jsonBuffer.parseObject(client);  // Парсим JSON-модержимое ответа сервера

  // Parse JSON object
  DeserializationError error = deserializeJson(root, line2);
  if (error) {
    Serial.print(F("deserializeJson() failed: "));
    Serial.println(error.c_str());
    return 0;
  }
    
    
    client.stop();                                                          // Разрываем соединение с сервером
String StringCurrentTime = line2.substring(8,18);
//    String StringCurrentTime = root["time"].as<String>().substring(0,10);   // Достаём значение реального текущего времени из JSON и отбрасываем от него миллисекунды
    String StringOffset =  root["clocks"][regionID]["offset"].as<String>(); // Достаём значение смещения времени по часовому поясу (в миллисекундах)
    SunriseTime =  root["clocks"][regionID]["sunrise"].as<String>();        // Достаём время восхода - Третий уровень вложенности пары ключ/значение clocks -> значение RegionID -> sunrise 
    SunsetTime =  root["clocks"][regionID]["sunset"].as<String>();          // Достаём время заката - Третий уровень вложенности пары ключ/значение clocks -> значение RegionID -> sunset
    Temperature =  root["clocks"][regionID]["weather"]["temp"].as<String>();// Достаём время заката - Четвёртый уровень вложенности пары ключ/значение clocks -> значение RegionID -> weather -> temp
    strcpy(icon, root["clocks"][regionID]["weather"]["icon"].as<String>().c_str());       // Достаём иконку - Четвёртый уровень вложенности пары ключ/значение clocks -> значение RegionID -> weather -> icon

  //  jsonBuffer.clear();                                                     // Очищаем буфер парсера JSON
    
    unsigned long CurrentTime = StringToULong(StringCurrentTime);           // Переводим значение реального времени в секундах, считанное с Яндекса, из String в unsigned long
    unsigned long Offset = StringToULong(StringOffset) / 1000;              // Переводим значение смещения времени по часовому поясу, считанное с Яндекса, из String в unsigned long и переводим его в секунды
    setTime(CurrentTime + Offset);                                          // Синхронизируем время
    
    return true;
  }
}

unsigned long StringToULong(String Str) {                     // Эта функция преобразует String в unsigned long
  unsigned long ULong = 0;
  for (int i = 0; i < Str.length(); i++) {                    // В цикле посимвольно переводим строку в unsigned long
     char c = Str.charAt(i);
     if (c < '0' || c > '9') break;
     ULong *= 10;
     ULong += (c - '0');
  }
  return ULong;
}

void digitalClockDisplay(){                                   // Эта функция выводит дату и время на монитор серийного порта
  Serial.print(leadNull(day()));
  Serial.print(".");
  Serial.print(leadNull(month()));
  Serial.print(".");
  Serial.print(year());
  Serial.print(" ");
  Serial.print(leadNull(hour()));
  Serial.print(":");
  Serial.print(leadNull(minute()));
  Serial.print(":");
  Serial.print(leadNull(second()));
  Serial.println();
}

String leadNull(int digits){                                    // Функция добавляет ведущий ноль
  String out = "";
  if(digits < 10)
    out += "0";                                               
  return out + String(digits);
}

void WeatherDisplay(){  
  char * out = strtok(icon,"-");        // Выделяем первую часть из строки до символа '-'
  while (out != NULL) {                 // Выделяем последующие части строки в цикле, пока значение out не станет нулевым (пустым)
      if (String(out) == "skc")         // Перебираем в условиях все возможные варианты, зашифрованные в названии иконки
        Serial.println("Yasno");
      else if (String(out) == "ovc")
        Serial.println("Pasmurno");
      else if (String(out) == "bkn")
        Serial.println("Oblachno");
      else if (String(out) == "ra")
        Serial.println("Dozhd'");
      else if (String(out) == "ts")
        Serial.println("Groza");
      else if (String(out) == "sn")
        Serial.println("Sneg");
      else if (String(out) == "bl")
        Serial.println("Metel'");
      else if (String(out) == "fg")
        Serial.println("Tuman");
      else if (String(out) == "n")
        Serial.println("\nTemnoe vremya sutok");
      else if (String(out) == "d")
        Serial.println("\nSvetloe vremya sutok");
      
      out = strtok(NULL,"-");              // Выделяем очередную часть
   }
}

 

обрезает последние пять скобок

chitaem dannie
line2= {"time":1565610960269,"clocks":{"11207":{"id":11207,"name":"Kopeysk","offset":18000000,"offsetString":"UTC+5:00","showSunriseSunset":true,"sunrise":"05:20","sunset":"20:35","isNight":false,"skyColor":"#71c0f4","weather":{"temp":25,"icon":"bkn-d","link":"https://yandex.ru/pogoda/kopeysk"},"parents":[{"id":11225,"name":"Chelyabinsk Oblast"},{"id":225,"name":"Russia"
deserializeJson() failed: IncompleteInput

если раскоментировать 62 сточку то

chitaem dannie
line2= {"time":1565609452719,"clocks":{"11207":{"id":11207,"name":"Kopeysk","offset":18000000,"offsetString":"UTC+5:00","showSunriseSunset":true,"sunrise":"05:20","sunset":"20:35","isNight":false,"skyColor":"#6ec0f5","weather":{"temp":24,"icon":"bkn-d","link":"https://yandex.ru/pogoda/kopeysk"},"parents":[{"id":11225,"name":"Chelyabinsk Oblast"},{"id":225,"name":"Russia"
Tekuschie data i vremya: 12.08.2019 16:30:52

Voshod v 05:20
Zakat v 20:35

Temperatura: 24 C
Oblachno

Svetloe vremya sutok

 

b707
Offline
Зарегистрирован: 26.05.2017

похоже что слищком рано заканчиваете читать. У вас код написан из предположения, что весь json придет одной посылкой - а это в общем-то, никто не гарантирует. Рано или поздно этот код должен был заглючить - и вот заглючил.

Читайте входной поток, пока не получите все закрывающие скобки.

lean_74
Offline
Зарегистрирован: 22.12.2015

и где об этом можно почитать? или пример глянуть?

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 пишет:

и где об этом можно почитать? или пример глянуть?

честно говоря, не знаю. Могу только на словах

Заведите счетчик скобок.

Когда Вы в строчке 56 читаете символ - нужно проверить, не является ли он скобкой. Сначала читаете ответ до первой открывающей скобки - тут начинается json  Потом, если скобка открывающая - увеличиваете счетчик, закрывающая - уменьшаете. Когда счетчик снова придет к нулю - значит весь json прочитан

lean_74
Offline
Зарегистрирован: 22.12.2015

а как узнать что json не одной посылкой пришел?(ну понятно, скобки считываем) и если вторая посылка, то она снова с заголовками или просто через какое-то время приходит? т.е просто повторяем цикл с 54 по 58?

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 пишет:

а как узнать что json не одной посылкой пришел?(ну понятно, скобки считываем) и если вторая посылка, то она снова с заголовками или просто через какое-то время приходит? т.е просто повторяем цикл с 54 по 58?

ну если начало json пришло, а скобок закрывающих нет - значит ждем следующей посылки

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

через какое то время могут прийти данные, причем размер данных не предсказуем, в вашем примере размер строки уже 429 байт, может тупо не влазит в какую либо переменную или память....

Такие вещи обрабатываются online - принимаете некое ключевое слово, например "sunrise", значит далее идет строка с данными, заносите в переменные, очищаете входной буфер, ждете приема другой ключевой фразы и т.д.

lean_74
Offline
Зарегистрирован: 22.12.2015

добавил после 62 строки

delay(1000); 
   String line3;
  while ( client.available() )
  {
    char c = client.read();
    line3 += c;
  }
  
    Serial.print("line3= "); 
    Serial.println(line3); 

получил

chitaem dannie
line2= {"time":1565615641942,"clocks":{"11207":{"id":11207,"name":"Kopeysk","offset":18000000,"offsetString":"UTC+5:00","showSunriseSunset":true,"sunrise":"05:20","sunset":"20:35","isNight":false,"skyColor":"#7ac2f1","weather":{"temp":24,"icon":"bkn-d","link":"https://yandex.ru/pogoda/kopeysk"},"parents":[{"id":11225,"name":"Chelyabinsk Oblast"},{"id":225,"name":"Russia"
line3= 
deserializeJson() failed: IncompleteInput

т.е там больше ничего нет.

lean_74
Offline
Зарегистрирован: 22.12.2015

andycat пишет:

через какое то время могут прийти данные, причем размер данных не предсказуем, в вашем примере размер строки уже 429 байт, может тупо не влазит в какую либо переменную или память....

Скетч использует 269772 байт (25%) памяти устройства. Всего доступно 1044464 байт.
Глобальные переменные используют 29464 байт (35%) динамической памяти, оставляя 52456 байт для локальных переменных. Максимум: 81920 байт.
Uploading 273920 bytes from C:\Users\9D20~1\AppData\Local\Temp\arduino_build_193731/JSON_Time_Weather1.ino.bin to flash at 0x00000000
................................................................................ [ 29% ]
................................................................................ [ 59% ]
................................................................................ [ 89% ]
............................                                                     [ 100% ]

 

b707
Offline
Зарегистрирован: 26.05.2017

похоже на переполнение буфера.

а если тот же запрос сделать не ардуиной, а из браузера - приходит все?

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 пишет:

Скетч использует 269772 байт (25%) памяти устройства. Всего доступно 1044464 байт.
Глобальные переменные используют 29464 байт (35%) динамической памяти, оставляя 52456 

это самая общая диагностика, она не гарантирует отсутсвие проблем. Памяти может быть дофига, но буфер обьявлен фиксировано - и в данные в него не входят.

lean_74
Offline
Зарегистрирован: 22.12.2015

b707 пишет:

а если тот же запрос сделать не ардуиной, а из браузера - приходит все?

да все приходит

lean_74
Offline
Зарегистрирован: 22.12.2015

b707 пишет:

 Памяти может быть дофига, но буфер обьявлен фиксировано - и в данные в него не входят.

чтото не нашел, где задается размер буфера для wifi клиента...

b707
Offline
Зарегистрирован: 26.05.2017

lean_74 пишет:

b707 пишет:

а если тот же запрос сделать не ардуиной, а из браузера - приходит все?

да все приходит

ну тогда точно проблема в вашем коде. Либо не успеваете принимать, либо буфера не хватает, либо что-то еще. Может код слишком медленный и часть приходящих теряет

wdrakula
wdrakula аватар
Онлайн
Зарегистрирован: 15.03.2016

Коллеги, это ЕСП, туда всё влезет. Нужно аккуратно парсить. Для ЕСП есть прекрасный JSON парсер. Ищи на гитхабе.

lean_74
Offline
Зарегистрирован: 22.12.2015

wdrakula пишет:

Коллеги, это ЕСП, туда всё влезет. Нужно аккуратно парсить. Для ЕСП есть прекрасный JSON парсер. Ищи на гитхабе.

у этой библиотеки есть метод 

DeserializationError error = deserializeJson(root, client);

где client - это wifi клиент, только у меня мозгов не хватило его победить. выдает ошибку.

lean_74
Offline
Зарегистрирован: 22.12.2015

точно что-то с размером буфера связано, т.к поставил другой регион - работает

chitaem dannie
line2= {"time":1565670149987,"clocks":{"213":{"id":213,"name":"Moscow","offset":10800000,"offsetString":"UTC+3:00","showSunriseSunset":true,"sunrise":"04:56","sunset":"20:11","isNight":false,"skyColor":"#add0ff","weather":{"temp":15,"icon":"skc-d","link":"https://yandex.ru/pogoda/moscow"},"parents":[{"id":225,"name":"Russia"}]}}}
line3= 0ff","weather":{"temp":15,"icon":"skc-d","link":"https://yandex.ru/pogoda/moscow"},"parents":[{"id":225,"name":"Russia"}]}}}
Tekuschie data i vremya: 13.08.2019 07:22:29

Voshod v 04:56
Zakat v 20:11

Temperatura: 15 C
Yasno

Svetloe vremya sutok

строка длинной 325 символов работает, а 375 - нет.  как увеличить буфер?

 

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Парсить строку online

lean_74
Offline
Зарегистрирован: 22.12.2015

andycat пишет:
Парсить строку online

это конечно правильней, но победил пока так, а именно поставил библиотеку ArduinoJson-5.13.5 более ранней версии вот рабочий код.

#include <ESP8266WiFi.h>                  // Библиотека для создания Wi-Fi подключения (клиент или точка доступа)
#include <WiFiClient.h>                   // Библиотека для связи с сетевыми хостами (локальными и интернет)
#include <TimeLib.h>                      // Библиотека для работы с временем
#include <ArduinoJson.h>                  // Библиотека для разбора JSON


const char* ssid = "Lenovo";            // Указываем имя WiFi-сети, к которой будет подключаться ESP8266 для доступа в Интернет
const char* password = "88888";    // Указываем пароль для подключения к WiFi-сети

String regionID = "11207";                  // Код региона по Yandex для выбора часового пояса https://tech.yandex.ru/xml/doc/dg/reference/regions-docpage/

String SunriseTime, SunsetTime, Temperature;
char icon[20];

WiFiClient client;                        // Создаём объект для работы с удалёнными хостами

void setup() {
  Serial.begin(115200);                                         // Инициализируем вывод данных на серийный порт со скоростью 9600 бод
  Serial.println("\n\n");
  WiFi.begin(ssid, password);                                 // Соединяемся с WiFi-сетью
  
  while (WiFi.status() != WL_CONNECTED)                       // Пока соединение не установено
    delay(500);                                               //  делаем задержку в пол секунды, пока соединение не установится
    
  while (!TimeAndWeather())                                   // Синхронизируем время микроконтроллера с реальным временем и получаем информацию о погоде
    delay(500);
  
  Serial.print("Tekuschie data i vremya: ");
  digitalClockDisplay();                                      // Выводим дату и время
  Serial.println();
  Serial.println("Voshod v " + SunriseTime);                  // Выводим время восхода
  Serial.println("Zakat v " + SunsetTime);                    // Выводим время восхода
  Serial.println();
  Serial.println("Temperatura: " + Temperature + " C");       // Выводим время восхода
  WeatherDisplay();                                           // Выводим информацию о погоде
}

void loop() {}

bool TimeAndWeather () {                                                    // Функция синхронизации времени работы программы с реальным временем и получения информации о погоде
  if (client.connect("yandex.com",443)) {                                   // Если удаётся установить соединение с указанным хостом (Порт 443 для https)
    client.println("GET /time/sync.json?geo=" + regionID + " HTTP/1.1\r\nHost: yandex.com\r\nConnection: close\r\n\r\n"); // Отправляем параметры запроса
    delay(200);                                                             // Даём серверу время, чтобы обработать запрос
    char endOfHeaders[] = "\r\n\r\n";                                       // Системные заголовки ответа сервера отделяются от остального содержимого двойным переводом строки
    if (!client.find(endOfHeaders)) {                                       // Отбрасываем системные заголовки ответа сервера
      Serial.println("Invalid response");                                   // Если ответ сервера не содержит системных заголовков, значит что-то пошло не так
      return false;                                                         // и пора прекращать всё это дело
    }
    Serial.println("chitaem dannie");      
    const size_t capacity = 750;                                            // Эта константа определяет размер буфера под содержимое JSON (https://arduinojson.org/v5/assistant/)
    DynamicJsonBuffer jsonBuffer(capacity); // Инициализируем буфер под JSON

    JsonObject& root = jsonBuffer.parseObject(client);                      // Парсим JSON-модержимое ответа сервера
     if (!root.success()) {   //Check for errors in parsing
 
    Serial.println("Parsing failed");
    delay(5000);
    return 0;
 
  }

    client.stop();                                                          // Разрываем соединение с сервером

    String StringCurrentTime = root["time"].as<String>().substring(0,10);   // Достаём значение реального текущего времени из JSON и отбрасываем от него миллисекунды
    Serial.print("StringCurrentTime= "); 
    Serial.println(StringCurrentTime); 

    String StringOffset =  root["clocks"][regionID]["offset"].as<String>(); // Достаём значение смещения времени по часовому поясу (в миллисекундах)
    SunriseTime =  root["clocks"][regionID]["sunrise"].as<String>();        // Достаём время восхода - Третий уровень вложенности пары ключ/значение clocks -> значение RegionID -> sunrise 
    SunsetTime =  root["clocks"][regionID]["sunset"].as<String>();          // Достаём время заката - Третий уровень вложенности пары ключ/значение clocks -> значение RegionID -> sunset
    Temperature =  root["clocks"][regionID]["weather"]["temp"].as<String>();// Достаём время заката - Четвёртый уровень вложенности пары ключ/значение clocks -> значение RegionID -> weather -> temp
    strcpy(icon, root["clocks"][regionID]["weather"]["icon"].as<String>().c_str());       // Достаём иконку - Четвёртый уровень вложенности пары ключ/значение clocks -> значение RegionID -> weather -> icon

    jsonBuffer.clear();                                                     // Очищаем буфер парсера JSON
    
    unsigned long CurrentTime = StringToULong(StringCurrentTime);           // Переводим значение реального времени в секундах, считанное с Яндекса, из String в unsigned long
    unsigned long Offset = StringToULong(StringOffset) / 1000;              // Переводим значение смещения времени по часовому поясу, считанное с Яндекса, из String в unsigned long и переводим его в секунды
    setTime(CurrentTime + Offset);                                          // Синхронизируем время
    
    return true;
  }
}

unsigned long StringToULong(String Str) {                     // Эта функция преобразует String в unsigned long
  unsigned long ULong = 0;
  for (int i = 0; i < Str.length(); i++) {                    // В цикле посимвольно переводим строку в unsigned long
     char c = Str.charAt(i);
     if (c < '0' || c > '9') break;
     ULong *= 10;
     ULong += (c - '0');
  }
  return ULong;
}

void digitalClockDisplay(){                                   // Эта функция выводит дату и время на монитор серийного порта
  Serial.print(leadNull(day()));
  Serial.print(".");
  Serial.print(leadNull(month()));
  Serial.print(".");
  Serial.print(year());
  Serial.print(" ");
  Serial.print(leadNull(hour()));
  Serial.print(":");
  Serial.print(leadNull(minute()));
  Serial.print(":");
  Serial.print(leadNull(second()));
  Serial.println();
}

String leadNull(int digits){                                    // Функция добавляет ведущий ноль
  String out = "";
  if(digits < 10)
    out += "0";                                               
  return out + String(digits);
}

void WeatherDisplay(){  
  char * out = strtok(icon,"-");        // Выделяем первую часть из строки до символа '-'
  while (out != NULL) {                 // Выделяем последующие части строки в цикле, пока значение out не станет нулевым (пустым)
      if (String(out) == "skc")         // Перебираем в условиях все возможные варианты, зашифрованные в названии иконки
        Serial.println("Yasno");
      else if (String(out) == "ovc")
        Serial.println("Pasmurno");
      else if (String(out) == "bkn")
        Serial.println("Oblachno");
      else if (String(out) == "ra")
        Serial.println("Dozhd'");
      else if (String(out) == "ts")
        Serial.println("Groza");
      else if (String(out) == "sn")
        Serial.println("Sneg");
      else if (String(out) == "bl")
        Serial.println("Metel'");
      else if (String(out) == "fg")
        Serial.println("Tuman");
      else if (String(out) == "n")
        Serial.println("\nTemnoe vremya sutok");
      else if (String(out) == "d")
        Serial.println("\nSvetloe vremya sutok");
      
      out = strtok(NULL,"-");              // Выделяем очередную часть
   }
}

 

lean_74
Offline
Зарегистрирован: 22.12.2015

b707
Offline
Зарегистрирован: 26.05.2017

классное табло. Три матрицы вертикально, если я правильно вижу?

lean_74
Offline
Зарегистрирован: 22.12.2015

b707 пишет:

классное табло. Три матрицы вертикально, если я правильно вижу?

нет одна 64х32

lean_74
Offline
Зарегистрирован: 22.12.2015

andycat пишет:
Парсить строку online

похоже придется переписывать, погоду и время запрашиваю раз в 10 минут, 10 раз опрашиваю, если неудачно, жду еще 10 мин.

chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
StringCurrentTime= 1565682888
08.2019 12:55:46
Oblachno

Svetlo
08.2019 12:57:02
Oblachno
08.2019 12:58:18
Oblachno
08.2019 12:59:34
Oblachno
08.2019 13:00:49
Oblachno
08.2019 13:02:05
Oblachno
08.2019 13:03:21
Oblachno
08.2019 13:04:37
Oblachno
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
08.2019 13:10:05
Oblachno
08.2019 13:11:21
Oblachno
08.2019 13:12:36
Oblachno
08.2019 13:13:52
Oblachno
08.2019 13:15:08
Oblachno
08.2019 13:16:24
Oblachno
08.2019 15:09:01
Oblachno
08.2019 15:10:16
Oblachno
08.2019 15:11:32
Oblachno
08.2019 15:12:48
Oblachno
08.2019 15:14:04
Oblachno
08.2019 15:15:19
Oblachno
08.2019 15:16:35
Oblachno
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
08.2019 15:22:04
Oblachno
08.2019 15:23:20
Oblachno
08.2019 15:24:36
Oblachno
08.2019 15:25:52
Oblachno
08.2019 15:27:07
Oblachno
08.2019 15:28:23
Oblachno
08.2019 15:29:39
Oblachno
08.2019 15:30:55
Oblachno
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
08.2019 15:34:45
Oblachno
08.2019 15:36:01
Oblachno
08.2019 15:37:17
Oblachno
08.2019 15:38:32
Oblachno
08.2019 15:39:48
Oblachno
08.2019 15:41:04
Oblachno
08.2019 15:42:20
Oblachno
08.2019 15:43:35
Oblachno
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
StringCurrentTime= 1565693095
08.2019 15:45:53
Oblachno
Dozhd'

Svetlo
08.2019 15:47:09
Oblachno
08.2019 15:48:25
Oblachno
08.2019 15:49:41
Oblachno
08.2019 15:50:56
Oblachno
08.2019 15:52:12
Oblachno
08.2019 15:53:28
Oblachno
08.2019 15:54:44
Oblachno
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
StringCurrentTime= 1565693728
08.2019 15:56:26
Oblachno
Dozhd'

Svetlo
08.2019 15:57:42
Oblachno
08.2019 15:58:58
Oblachno
08.2019 16:00:14
Oblachno
08.2019 16:01:30
Oblachno
08.2019 16:02:45
Oblachno
08.2019 16:04:01
Oblachno
08.2019 16:05:17
Oblachno
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
StringCurrentTime= 1565694381
08.2019 16:07:19
Oblachno

Svetlo
08.2019 16:08:35
Oblachno
08.2019 16:09:51
Oblachno
08.2019 16:11:07
Oblachno
08.2019 16:12:23
Oblachno
08.2019 16:13:38
Oblachno
08.2019 16:14:54
Oblachno
08.2019 16:16:10
Oblachno
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
08.2019 16:21:38
Oblachno
08.2019 16:22:54
Oblachno
08.2019 16:24:10
Oblachno
08.2019 16:25:26
Oblachno
08.2019 16:26:41
Oblachno
08.2019 16:27:57
Oblachno
08.2019 16:29:13
Oblachno
08.2019 16:30:29
Oblachno
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
StringCurrentTime= 1565696047
08.2019 16:35:05
Oblachno

Svetlo
08.2019 16:36:21
Oblachno
08.2019 16:37:37
Oblachno
08.2019 16:38:53
Oblachno
08.2019 16:40:08
Oblachno
08.2019 16:41:24
Oblachno
08.2019 16:42:40
Oblachno
08.2019 16:43:56
Oblachno
podkluchaem server
chitaem dannie
StringCurrentTime= 1565696648
08.2019 16:45:12
Oblachno

Svetlo
08.2019 16:46:28
Oblachno
08.2019 16:47:43
Oblachno
08.2019 16:48:59
Oblachno
08.2019 16:50:15
Oblachno
08.2019 16:51:31
Oblachno
08.2019 16:52:46
Oblachno
08.2019 16:54:02
Oblachno
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
Parsing failed
podkluchaem server
chitaem dannie
StringCurrentTime= 1565697300
08.2019 16:55:58
Oblachno

Svetlo
08.2019 16:57:14
Oblachno
08.2019 16:58:30
Oblachno
08.2019 16:59:46
Oblachno
08.2019 17:01:02
Oblachno

andycat а можно пример online обработки, а то мне этот "интернет вещей" туго дается.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

lean_74 пишет:

andycat а можно пример online обработки, а то мне этот "интернет вещей" туго дается.

нету примера :(

т.к. такой конкретной задачи никогда не делал.

Тупо поиск ключевой подстроки в буфере и данных после них, поищите в инете - наверняка масса примеров "парсить входящую строку модема". Вот старый похожий пример - кольцевой буфер размером с длину команды, но комментариев мало, без бутылки разобраться сложно.

http://arduino.ru/forum/apparatnye-voprosy/vse-o-sim800l-i-vse-chto-s-nim-svyazano?page=1#comment-439631

Upd: вот из последнего, читаются входные данные до конца строки (в вашем случае до какого то символа), потом уже обрабатывается буфер, после успешной обработки или ограничения по таймеру очищается буфер и дальше читаются данные.

void loadDataFromModem() { // load data from modem to buf - only one line (string)
  if (Serial.available()) {
    byte br;
    while (Serial.available()) {
      br = Serial.read();
      if (br) {
        if (pos_buf >= (max_size_resp_buf - 1)) pos_buf = 0;
        resp_buf[pos_buf] = br; ++pos_buf;
        if (br == '\n') if ((pos_buf > 1) && (resp_buf[pos_buf - 2] == '\r')) break; // new string*/
      }
    }
    resp_buf[pos_buf] = 0; // stop byte of string
  }
}

 

lean_74
Offline
Зарегистрирован: 22.12.2015

andycat перечитал 4 раза... пойду лучше напьюсь... всегда считал себя неглупым человеком, но перед многими из этого форума снимаю шляпу,  всех перечислять не буду, но Вы в этом списке!

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

lean_74 пишет:

пойду лучше напьюсь... 

правильно, я всегда так делаю

lean_74
Offline
Зарегистрирован: 22.12.2015

DetSimen пишет:

lean_74 пишет:

пойду лучше напьюсь... 

правильно, я всегда так делаю

Деда Чин-Чин. Со всем уважением.

lean_74
Offline
Зарегистрирован: 22.12.2015

может кому пригодиться, парсим напрямую, без библиотеки Json

#include <ESP8266WiFi.h>                  // Библиотека для создания Wi-Fi подключения (клиент или точка доступа)
#include <WiFiClient.h>                   // Библиотека для связи с сетевыми хостами (локальными и интернет)
#include <TimeLib.h>                      // Библиотека для работы с временем
//#include <ArduinoJson.h>                  // Библиотека для разбора JSON


const char* ssid = "Lenovo";            // Указываем имя WiFi-сети, к которой будет подключаться ESP8266 для доступа в Интернет
const char* password = "88888";    // Указываем пароль для подключения к WiFi-сети

String regionID = "11207";                  // Код региона по Yandex для выбора часового пояса <a href="https://tech.yandex.ru/xml/doc/dg/reference/regions-docpage/" title="https://tech.yandex.ru/xml/doc/dg/reference/regions-docpage/" rel="nofollow">https://tech.yandex.ru/xml/doc/dg/reference/regions-docpage/</a>

String SunriseTime, SunsetTime, Temperature;
char icon[20];

WiFiClient client;                        // Создаём объект для работы с удалёнными хостами

void setup() {
  Serial.begin(115200);                                         // Инициализируем вывод данных на серийный порт со скоростью 9600 бод
  Serial.println("\n\n");
  WiFi.begin(ssid, password);                                 // Соединяемся с WiFi-сетью
  
  while (WiFi.status() != WL_CONNECTED)                       // Пока соединение не установено
    delay(500);                                               //  делаем задержку в пол секунды, пока соединение не установится
    
  while (!TimeAndWeather())                                   // Синхронизируем время микроконтроллера с реальным временем и получаем информацию о погоде
    delay(500);
  
  Serial.print("Tekuschie data i vremya: ");
  digitalClockDisplay();                                      // Выводим дату и время
  Serial.println();
  Serial.println("Voshod v " + SunriseTime);                  // Выводим время восхода
  Serial.println("Zakat v " + SunsetTime);                    // Выводим время восхода
  Serial.println();
  Serial.println("Temperatura: " + Temperature + " C");       // Выводим время восхода
  WeatherDisplay();                                           // Выводим информацию о погоде
}

void loop() {}

bool TimeAndWeather () {                                                    // Функция синхронизации времени работы программы с реальным временем и получения информации о погоде
  if (client.connect("yandex.com",443)) {                                   // Если удаётся установить соединение с указанным хостом (Порт 443 для https)
    client.println("GET /time/sync.json?geo=" + regionID + " HTTP/1.1\r\nHost: yandex.com\r\nConnection: close\r\n\r\n"); // Отправляем параметры запроса
    delay(300);                                                             // Даём серверу время, чтобы обработать запрос
    char endOfHeaders[] = "\r\n\r\n";                                       // Системные заголовки ответа сервера отделяются от остального содержимого двойным переводом строки
    if (!client.find(endOfHeaders)) {                                       // Отбрасываем системные заголовки ответа сервера
      Serial.println("Invalid response");                                   // Если ответ сервера не содержит системных заголовков, значит что-то пошло не так
      return false;                                                         // и пора прекращать всё это дело
    }


 
    Serial.println("chitaem dannie");  
  String line2;
  while ( client.available() )
  {
    char c = client.read();
    line2 += c;
  }
//    Serial.print("line2= "); 
//    Serial.println(line2);
 String StringCurrentTime = line2.substring(8,18);
   
    int n_offset=line2.indexOf("offset"); 
    int  k_offset = line2.indexOf(',',n_offset);
    String StringOffset= line2.substring(n_offset+8,k_offset); //18000000
    

    int n_sunrise=line2.indexOf("sunrise"); 
    int  k_sunrise = line2.indexOf(',',n_sunrise);
    SunriseTime= line2.substring(n_sunrise+9,k_sunrise); //18000000
   
    int n_sunset=line2.indexOf("sunset"); 
    int  k_sunset = line2.indexOf(',',n_sunset);
    SunsetTime= line2.substring(n_sunset+8,k_sunset); //18000000

    int n_temp=line2.indexOf("temp"); 
    int  k_temp = line2.indexOf(',',n_temp);
    Temperature= line2.substring(n_temp+6,k_temp); //18000000

    int n_icon=line2.indexOf("icon"); 
    int  k_icon = line2.indexOf(',',n_icon);
    String Stringicon= line2.substring(n_icon+6,k_icon); //18000000
   
    client.stop();                                                          // Разрываем соединение с сервером
    strcpy(icon,Stringicon.c_str());       // Достаём иконку - Четвёртый уровень вложенности пары ключ/значение clocks -> значение RegionID -> weather -> icon

    
    unsigned long CurrentTime = StringToULong(StringCurrentTime);           // Переводим значение реального времени в секундах, считанное с Яндекса, из String в unsigned long
    unsigned long Offset = StringToULong(StringOffset) / 1000;              // Переводим значение смещения времени по часовому поясу, считанное с Яндекса, из String в unsigned long и переводим его в секунды
    setTime(CurrentTime + Offset);                                          // Синхронизируем время
    
    return true;
  }
}

unsigned long StringToULong(String Str) {                     // Эта функция преобразует String в unsigned long
  unsigned long ULong = 0;
  for (int i = 0; i < Str.length(); i++) {                    // В цикле посимвольно переводим строку в unsigned long
     char c = Str.charAt(i);
     if (c < '0' || c > '9') break;
     ULong *= 10;
     ULong += (c - '0');
  }
  return ULong;
}

void digitalClockDisplay(){                                   // Эта функция выводит дату и время на монитор серийного порта
  Serial.print(leadNull(day()));
  Serial.print(".");
  Serial.print(leadNull(month()));
  Serial.print(".");
  Serial.print(year());
  Serial.print(" ");
  Serial.print(leadNull(hour()));
  Serial.print(":");
  Serial.print(leadNull(minute()));
  Serial.print(":");
  Serial.print(leadNull(second()));
  Serial.println();
}

String leadNull(int digits){                                    // Функция добавляет ведущий ноль
  String out = "";
  if(digits < 10)
    out += "0";                                               
  return out + String(digits);
}

void WeatherDisplay(){  
  char * out = strtok(icon,"-");        // Выделяем первую часть из строки до символа '-'
  while (out != NULL) {                 // Выделяем последующие части строки в цикле, пока значение out не станет нулевым (пустым)
      if (String(out) == "skc")         // Перебираем в условиях все возможные варианты, зашифрованные в названии иконки
        Serial.println("Yasno");
      else if (String(out) == "ovc")
        Serial.println("Pasmurno");
      else if (String(out) == "bkn")
        Serial.println("Oblachno");
      else if (String(out) == "ra")
        Serial.println("Dozhd'");
      else if (String(out) == "ts")
        Serial.println("Groza");
      else if (String(out) == "sn")
        Serial.println("Sneg");
      else if (String(out) == "bl")
        Serial.println("Metel'");
      else if (String(out) == "fg")
        Serial.println("Tuman");
      else if (String(out) == "n")
        Serial.println("\nTemnoe vremya sutok");
      else if (String(out) == "d")
        Serial.println("\nSvetloe vremya sutok");
      
      out = strtok(NULL,"-");              // Выделяем очередную часть
   }
}