Saving a const char* from a JSON to an array

I want to get forecasts from OpenWeatherMap.org. I'm able to make a request ang get the JSON file, and parsing it with ArduinoJson.h library. The JSON have four forecast iterations and I wish to save those four iterations values in arrays.

I've no prpblems to get int, float and long values from the JSON and saving them to arrays. But when it gets to some text data (const char*), I can't save them to a string array. I got conflict between the strings array declaration and the assingning the const char* data to this array while compiling, or if not the ESP8266 mcu reset in loop...

Here are the part of the code causing conflict. If I withdraw all things related to "dt_text", everything for just fine. I have omitted in the following code the setup() and loop() loops, functions are called in those loops...

My goal is to print the forecasts data and foreacasts time (dt_text) later in the sketch, on an lcd or on a serial...

Any help on how to declare/convert/assign those JSON dt_text values to the dt_text[] array without causing conflict ?

Strings are something I haven't work with a lot yet...

I'm using Wemos D1 R2 mini, Arduino IDE 2.0.4.

Thanks a lot !

/////////////////////////////////////////////
//OpenWeatherMap.org setup

#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <ArduinoJson.h>

const char* openWeatherMapApiKey = "your key";
const char* city = "your town";
const char* countryCode = "your country";
const char* units = "metric";  // "metric" or "imperial"
const char* language = "fr";   // description language "en" for English, "fr" for French


unsigned long weatherReadingLastTime = 0;
unsigned long weatherReadingDelay = 600000;  // Timer set to 1 minutes (600000)

//END of OpenWeatherMap.org setup
/////////////////////////////////////////////


long dt[5];
char dt_text[5][20] ;
float temperatures[5];
float feels_like[5];
int humidities[5];
int pressures[5];
float wind_speeds[5];
int weather_ids[5];

void weatherReading() {
  // Check WiFi connection status
  if (WiFi.status() == WL_CONNECTED) {
    getNowWeather();
    getForecastWeather();

    for (int i = 0; i < 5; i++) {
      Serial.print("Time of forecast: ");
      Serial.println(dt_text[i]);
      Serial.print("Weather: ");
      Serial.println(weather_ids[i]);
      Serial.print("Temperature: ");
      Serial.println(temperatures[i]);
      Serial.print("Feel like: ");
      Serial.println(feels_like[i]);
      Serial.print("Pressure: ");
      Serial.println(pressures[i]);
      Serial.print("Humidity: ");
      Serial.println(humidities[i]);
      Serial.print("Wind Speed: ");
      Serial.println(wind_speeds[i]);
      Serial.println();
    }
  } else {
    Serial.println("WiFi Disconnected");
  }
}

void getNowWeather() {
  String serverPath = "http://api.openweathermap.org/data/2.5/weather?q=" + String(city) + "," + String(countryCode) + "&APPID=" + String(openWeatherMapApiKey) + "&units=" + String(units) + "&lang=" + String(language);

  // Parse the JSON response
  String jsonBuffer = httpGETRequest(serverPath.c_str());
  Serial.println(jsonBuffer);

  DynamicJsonDocument doc(4096);
  DeserializationError error = deserializeJson(doc, jsonBuffer);

  if (error) {
    Serial.print(F("Weather NOW deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }

  JsonObject weather_0 = doc["weather"][0];
  weather_ids[0] = weather_0["id"];  // "nuageux"

  JsonObject main = doc["main"];
  dt[0] = doc["dt"];
  strcpy("NOW                ", dt_text[0]);
  temperatures[0] = main["temp"];
  feels_like[0] = main["feels_like"];  // 0.24
  humidities[0] = main["humidity"];    // 87
  pressures[0] = main["pressure"];     // 1009

  JsonObject wind = doc["wind"];
  wind_speeds[0] = wind["speed"];  // 0.41
}

void getForecastWeather() {
  // Getting forcast for cnt events
  const char* cnt = "4";  // number of forecasts

  String serverPath = "http://api.openweathermap.org/data/2.5/forecast?q=" + String(city) + "," + String(countryCode) + "&cnt=" + String(cnt) + "&APPID=" + String(openWeatherMapApiKey) + "&units=" + String(units) + "&lang=" + String(language);

  // Send an HTTP GET request
  String jsonBuffer = httpGETRequest(serverPath.c_str());
  Serial.println(jsonBuffer);

  //Parse the JSON response
  DynamicJsonDocument doc(4096);
  DeserializationError error = deserializeJson(doc, jsonBuffer);

  if (error) {
    Serial.print(F("Weather FORECAST deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }

  JsonArray list = doc["list"];

  for (int i = 0; i < 4; i++) {
    JsonObject item = list[i];
    JsonObject main = item["main"];
    JsonObject weather = item["weather"];
    JsonObject wind = item["wind"];


    dt[i + 1] = item["dt"];
    const char* dt_txt = item["dt_text"];
    strcpy(dt_text[i + 1], dt_txt);
    temperatures[i + 1] = main["temp"];
    feels_like[i + 1] = main["feels_like"];
    humidities[i + 1] = main["humidity"];
    pressures[i + 1] = main["pressure"];
    weather_ids[i + 1] = weather["id"];
    wind_speeds[i + 1] = wind["speed"];
  }
}

String httpGETRequest(const char* serverName) {
  WiFiClient client;
  HTTPClient http;

  // Your IP address with path or Domain name with URL path
  http.begin(client, serverName);

  // Send HTTP POST request
  int httpResponseCode = http.GET();

  String payload = "{}";

  if (httpResponseCode > 0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = http.getString();
  } else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  // Free resources
  http.end();

  return payload;
}

You have a global variable char dt_text[5][20]; and you have a local variable const char* dt_txt = item["dt_text"];.

Which one is which in

strcpy(dt_text[i + 1], dt_txt);

I don't think that the compiler is clever enough to differentiate between the two and I'm reasonably sure that it uses only the local variable in the strcpy(). Change the name of the local variable in getForecastWeather() to something else (e.g. txt or tmpTxt or ...

1 Like

Good point!

I've rewrited the array name diffently. But I still got the problems...

I'm rereading slowly the code to get what's wrong, maybe it's just a synthax problems...

Thanks

I've found the problem : arguments inverted in strcpy AND casting required...

global arrays declarations :

char dt_texts[5][20];
char descriptions[5][41];

Arrays values assignations with strcpy and casting to const char* :

 for (int i = 0; i < 4; i++) {
    JsonObject item = list[i];
    JsonObject main = item["main"];

    strcpy(dt_texts[i+1],(const char*)item["dt_txt"]);
    strcpy(descriptions[i+1],(const char*)item["description"]);
  }saisissez ou collez du code ici

The index [i+1] is because index 0 is for the weather NOW, form another JSON...

The smallaest error can cuase havoc !!!

Here is the completed code :

#include <ESP8266WiFi.h>


// Replace with your network credentials
const char* ssid = "your_ssid";
const char* password = "your_password";

/////////////////////////////////////////////
//OpenWeatherMap.org setup

#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <ArduinoJson.h>

const char* openWeatherMapApiKey = "your_api_key";
const char* city = "your_city";
const char* countryCode = "your_country_index";
const char* units = "metric";  // "metric" or "imperial"
const char* language = "fr";   // description language "en" for English, "fr" for French
const char* cnt = "4";         // number of forecasts

unsigned long weatherReadingLastTime = 0;
unsigned long weatherReadingDelay = 600000;  // Timer set to 1 minutes (600000)

String jsonBuffer;  // Buffer to store receive JSON
//END of OpenWeatherMap.org setup
/////////////////////////////////////////////

// Define variables for storing the forecast data
long dts[5];
char dt_texts[5][20];
float temperatures[5];
float feels_likes[5];
int humidities[5];
int pressures[5];
float wind_speeds[5];
int weather_ids[5];
char descriptions[5][41];

void setup() {
  Serial.begin(112500);

  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected to WiFi");

weatherReading();  
}

void loop() {
  // Get weather from the web periodicly
  if ((millis() - weatherReadingLastTime) > weatherReadingDelay) {
    weatherReadingLastTime = millis();
    weatherReading();
  }
}

void weatherReading() {
  // Check WiFi connection status
  if (WiFi.status() == WL_CONNECTED) {
    getNowWeather();
    getForecastWeather();

    for (int i = 0; i < 5; i++) {
      Serial.print("Time of forecast: ");
      Serial.println(dt_texts[i]);
      Serial.print("Weather: ");
      Serial.println(weather_ids[i]);
         Serial.print("Description: ");
      Serial.println(descriptions[i]);
      Serial.print("Temperature: ");
      Serial.println(temperatures[i]);
      Serial.print("Feel like: ");
      Serial.println(feels_likes[i]);
      Serial.print("Pressure: ");
      Serial.println(pressures[i]);
      Serial.print("Humidity: ");
      Serial.println(humidities[i]);
      Serial.print("Wind Speed: ");
      Serial.println(wind_speeds[i]);
      Serial.println();
    }
  } else {
    Serial.println("WiFi Disconnected");
  }
}

void getNowWeather() {
  String serverPath = "http://api.openweathermap.org/data/2.5/weather?q=" + String(city) + "," + String(countryCode) + "&APPID=" + String(openWeatherMapApiKey) + "&units=" + String(units) + "&lang=" + String(language);

  // Parse the JSON response
  String jsonBuffer = httpGETRequest(serverPath.c_str());
  //Serial.println(jsonBuffer);

  DynamicJsonDocument doc(4096);
  DeserializationError error = deserializeJson(doc, jsonBuffer);

  if (error) {
    Serial.print(F("Weather NOW deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }

  JsonObject weather_0 = doc["weather"][0];
  weather_ids[0] = weather_0["id"];  // "nuageux"
  strcpy(descriptions[0],(const char*)weather_0["description"]);

  JsonObject main = doc["main"];
  dts[0] = doc["dt"];
  strcpy(dt_texts[0], "NOW");
  temperatures[0] = main["temp"];
  feels_likes[0] = main["feels_like"];  // 0.24
  humidities[0] = main["humidity"];    // 87
  pressures[0] = main["pressure"];     // 1009

  JsonObject wind = doc["wind"];
  wind_speeds[0] = wind["speed"];  // 0.41
}

void getForecastWeather() {
  // Getting forcast for cnt events

  String serverPath = "http://api.openweathermap.org/data/2.5/forecast?q=" + String(city) + "," + String(countryCode) + "&cnt=" + String(cnt) + "&APPID=" + String(openWeatherMapApiKey) + "&units=" + String(units) + "&lang=" + String(language);

  // Send an HTTP GET request
  String jsonBuffer = httpGETRequest(serverPath.c_str());
  //Serial.println(jsonBuffer);

  //Parse the JSON response
  DynamicJsonDocument doc(4096);
  DeserializationError error = deserializeJson(doc, jsonBuffer);

  if (error) {
    Serial.print(F("Weather FORECAST deserializeJson() failed: "));
    Serial.println(error.f_str());
    return;
  }

  JsonArray list = doc["list"];

  for (int i = 0; i < 4; i++) {
    JsonObject item = list[i];
    JsonObject main = item["main"];
    JsonObject weather = item["weather"][0];
    JsonObject wind = item["wind"];


    dts[i + 1] = item["dt"];
    strcpy(dt_texts[i+1],(const char*)item["dt_txt"]);
    temperatures[i + 1] = main["temp"];
    feels_likes[i + 1] = main["feels_like"];
    humidities[i + 1] = main["humidity"];
    pressures[i + 1] = main["pressure"];
    weather_ids[i + 1] = weather["id"];
    strcpy(descriptions[i+1],(const char*)weather["description"]);
    wind_speeds[i + 1] = wind["speed"];
  }
}

const int weather_type_ID[] = { 200, 201, 202, 210, 211, 212, 221, 230, 231, 232,       //Group 2xx: Thunderstorm
                                300, 301, 302, 310, 311, 312, 313, 314, 321,            //Group 3xx: Drizzle
                                500, 501, 502, 503, 504, 511, 520, 521, 522, 531,       //Group 5xx: Rain
                                600, 601, 602, 611, 612, 613, 615, 616, 620, 621, 622,  //Group 6xx: Snow
                                701, 711, 721, 731, 741, 751, 761, 762, 771, 781,       //Group 7xx: Atmosphere
                                800,                                                    //Group 800: Clear
                                801, 802, 803, 804 };                                   //Group 80x: Clouds

const char* weather_type_main[] = { "Orage", "Orage", "Orage", "Orage", "Orage", "Orage", "Orage", "Orage", "Orage", "Orage",                         //Group 2xx: Thunderstorm
                                    "Bruine", "Bruine", "Bruine", "Bruine", "Bruine", "Bruine", "Bruine", "Bruine", "Bruine",                         //Group 3xx: Drizzle
                                    "Pluie", "Pluie", "Pluie", "Pluie", "Pluie", "Pluie", "Pluie", "Pluie", "Pluie", "Pluie",                         //Group 5xx: Rain
                                    "Neige", "Neige", "Neige", "Neige", "Neige", "Neige", "Neige", "Neige", "Neige", "Neige", "Neige",                //Group 6xx: Snow
                                    "Buée", "Fumée", "Brume", "Poussière", "Brouillard", "Sable", "Poussière", "Cendres", "Bourrasques", "Tornades",  //Group 7xx: Atmosphere
                                    "Dégagé",                                                                                                         //Group 800: Clear
                                    "Nuageux", "Nuageux", "Nuageux", "Nuageux" };                                                                     //Group 80x: Clouds

const char* weather_type_description[] = { "Orage avec pluie légère", "Orage avec pluie", "orage avec forte pluie", "Orage léger", "Orage", "Gros orage",
                                           "Orage violent", "Orage avec bruine légère", "Orage avec bruine", "Orage avec forte bruine",                      //Group 2xx: Thunderstorm
                                           "Bruine", "Bruine", "Bruine", "Bruine", "Bruine", "Bruine", "Bruine", "Bruine", "Bruine",                         //Group 3xx: Drizzle
                                           "Pluie", "Pluie", "Pluie", "Pluie", "Pluie", "Pluie", "Pluie", "Pluie", "Pluie", "Pluie",                         //Group 5xx: Rain
                                           "Neige", "Neige", "Neige", "Neige", "Neige", "Neige", "Neige", "Neige", "Neige", "Neige", "Neige",                //Group 6xx: Snow
                                           "Buée", "Fumée", "Brume", "Poussière", "Brouillard", "Sable", "Poussière", "Cendres", "Bourrasques", "Tornades",  //Group 7xx: Atmosphere
                                           "Dégagé",                                                                                                         //Group 800: Clear
                                           "Nuageux", "Nuageux", "Nuageux", "Nuageux" };                                                                     //Group 80x: Clouds

String httpGETRequest(const char* serverName) {
  WiFiClient client;
  HTTPClient http;

  // Your IP address with path or Domain name with URL path
  http.begin(client, serverName);

  // Send HTTP POST request
  int httpResponseCode = http.GET();

  String payload = "{}";

  if (httpResponseCode > 0) {
    Serial.print("HTTP Response code: ");
    Serial.println(httpResponseCode);
    payload = http.getString();
  } else {
    Serial.print("Error code: ");
    Serial.println(httpResponseCode);
  }
  // Free resources
  http.end();

  return payload;
}

Great :+1:

Thanks for the feedback.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.