Go Down

Topic: Appending char arrays to dynamic char array (Read 84 times) previous topic - next topic

Nosen

Nov 12, 2019, 02:32 pm Last Edit: Nov 12, 2019, 02:43 pm by Nosen
I'm having difficulties with my code.

I have a for loop that generates char arrays.
i want to save these char arrays in a dynamic array, by appending each to the end of the array.
I'm not particularly good at c++ pointers, so any help would be appreciated. How do you do this?

Details of the project:

I'm building a small iot device that displays the bus departures of my small bus stop.
The API I'm calling gives me all departures within the hour.

I'm using ArduinoJson to deserialize a big json document. I want to extract the useful data.
This method uses a for do-while loop. Using simple variable names works well, but only the last bus departure is preserved after the deserialization is done.

I would like to save all buses' data in a dynamic array. The data is currently in char array format (basic strings).

How do you accomplish this?
Thanks!


Nosen

Sorry for my poor english, it's not my first language.

TheMemberFormerlyKnownAsAWOL

It's not your natural language skills that are an issue, it's the fact that we can't see the fruits of your programming language skills.

groundFungus

I think that it is very hard to help with code that we cannot see.    Read the how to use this forum stickies to see how to post code.

Nosen

Sorry!

Here is the code currently (omitted the API keys and wifi details naturally)

Code: [Select]
/*
  This sketch makes use of the SL Realtidsinformation 4 API
  to fetch and present the json data in the serial monitor.
  It's written to be easily remixable to fit your project.

  Read about the APIs here:
  https://www.trafiklab.se/api/sl-realtidsinformation-4
  https://www.trafiklab.se/api/sl-platsuppslag
*/


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

// Enter your WiFi credentials here:
const char* wifiName   = "your-wifi";
const char* wifiPass   = "your-pass";

// Enter your API key for SL Platsuppslag here (if you don't need SL Platsuppslag just set fetchStopInfo to false):
const char* PUAPIKey       = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

// Enter your API key for SL Realtidsinformation 4 here:
const char* RTD4APIKey     = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
// Enter site ID (e.g. 9001 for T-centralen, 9192 for Slussen):
const char* RTD4siteID     = "9001";
// Enter time window (60 minutes is max):
const char* RTD4timeWindow = "60";

const bool fetchStopInfo = true;// Set to false if not using the SL Platsuppslag API.

const bool lookForMetros = true;
const bool lookForBuses  = true;
const bool lookForTrains = true;
const bool lookForTrams  = true;
const bool lookForShips  = true;

const bool lookForStopPointDeviations  = true;

WiFiClient client;

DynamicJsonDocument doc(16 * 1024);

void setup() {

  Serial.begin(115200);
  delay(10);
  Serial.println();

  Serial.print("Connecting to ");
  Serial.println(wifiName);

  WiFi.begin(wifiName, wifiPass);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }


  Serial.println();
  Serial.println("WiFi connected.");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());   //You can get IP address assigned to ESP


  if (fetchStopInfo) {
    stopInfoFetcher(PUAPIKey, RTD4siteID);
  }


}
void loop() {

  client.connect("api.sl.se", 80);

  client.print("GET /api2/realtimedeparturesV4.json?key=");
  client.print(RTD4APIKey);
  client.print("&siteid=");
  client.print(RTD4siteID);
  client.print("&timewindow=");
  client.print(RTD4timeWindow);
  client.println(" HTTP/1.0");
  client.println("Host: api.sl.se");
  client.println("Connection: close");
  client.println();

  if (lookForMetros) {
    findTransport("Metros");
  }

  if (lookForBuses) {
    findTransport("Buses");
  }

  if (lookForTrains) {
    findTransport("Trains");
  }

  if (lookForTrams) {
    findTransport("Trams");
  }

  if (lookForShips) {
    findTransport("Ships");
  }

  if (lookForStopPointDeviations) {
    findStopPointDeviations();
  }


  client.stop();

  delay(300000);  //GET Data at every 5 minutes
}

void stopInfoFetcher(const char* APIkey, const char* siteID) {
  client.connect("api.sl.se", 80);

  client.print("GET /api2/typeahead.json?key=");
  client.print(APIkey);
  client.print("&searchstring=");
  client.print(siteID);
  client.print("&stationsonly=True&maxresults=1");
  client.println(" HTTP/1.0");
  client.println("Host: api.sl.se");
  client.println("Connection: close");
  client.println();

  client.find("\"ResponseData\":[");
  Serial.println();
  Serial.println(F("Stop Point Info: "));
  do {
    // Parse the JSON object
    deserializeJson(doc, client);
    if (doc.isNull()) {
      Serial.println("No stop info found.");
      break;
    }
    Serial.print(F("Name: "));
    Serial.println(doc["Name"].as<char*>());
    Serial.print(F("SiteId: "));
    Serial.println(doc["SiteId"].as<char*>());
    Serial.print(F("Type: "));
    Serial.println(doc["Type"].as<char*>());
    Serial.print(F("X: "));
    Serial.println(doc["X"].as<char*>());
    Serial.print(F("Y: "));
    Serial.println(doc["Y"].as<char*>());
    Serial.print(F("Products: "));
    Serial.println(doc["Products"].as<char*>());
  }
  while (client.findUntil(",", "]"));

  client.stop();

}




void findTransport(char* type) {
  Serial.println();
  Serial.print(F("#### "));
  Serial.print(type);
  Serial.println(F(" ####"));
  char* beginning = "\"";
  char* ending = "\":[";
  char searchTerm[20];
  sprintf(searchTerm, "%s%s%s", beginning, type, ending);

  client.find(searchTerm);

  do {
    // Parse the JSON object
    deserializeJson(doc, client);
    if (doc.isNull()) {
      Serial.print("No ");
      Serial.print(type);
      Serial.println(" found.");
      break;
    }
    Serial.println();
    Serial.print(F("GroupOfLine: "));
    Serial.println(doc["GroupOfLine"].as<char*>());
    Serial.print(F("DisplayTime: "));
    Serial.println(doc["DisplayTime"].as<char*>());
    Serial.print(F("TransportMode: "));
    Serial.println(doc["TransportMode"].as<char*>());
    Serial.print(F("LineNumber: "));
    Serial.println(doc["LineNumber"].as<char*>());
    Serial.print(F("Destination: "));
    Serial.println(doc["Destination"].as<char*>());
    Serial.print(F("JourneyDirection: "));
    Serial.println(doc["JourneyDirection"].as<int>());
    Serial.print(F("StopAreaName: "));
    Serial.println(doc["StopAreaName"].as<char*>());
    Serial.print(F("StopAreaNumber: "));
    Serial.println(doc["StopAreaNumber"].as<int>());
    Serial.print(F("StopPointNumber: "));
    Serial.println(doc["StopPointNumber"].as<int>());
    Serial.print(F("StopPointDesignation: "));
    Serial.println(doc["StopPointDesignation"].as<char*>());
    Serial.print(F("TimeTabledDateTime: "));
    Serial.println(doc["TimeTabledDateTime"].as<char*>());
    Serial.print(F("ExpectedDateTime: "));
    Serial.println(doc["ExpectedDateTime"].as<char*>());
    Serial.print(F("JourneyNumber: "));
    Serial.println(doc["JourneyNumber"].as<int>());
    if (doc["Deviations"].isNull() == false) {
      Serial.println(F("# Deviations #"));
    }
    for (int i = 0; i < doc["Deviations"].size(); i++) {
      Serial.print(F("Text: "));
      Serial.println(doc["Deviations"][i]["Text"].as<char*>());
      Serial.print(F("Consequence: "));
      Serial.println(doc["Deviations"][i]["Consequence"].as<char*>());
      Serial.print(F("ImportanceLevel: "));
      Serial.println(doc["Deviations"][i]["ImportanceLevel"].as<int>());
    }



  } while (client.findUntil(",", "]"));
}

void findStopPointDeviations() {
  client.find("\"StopPointDeviations\":[");
  Serial.println();
  Serial.println(F("#### Stop Point Deviations ####"));
  do {
    // Parse the JSON object
    deserializeJson(doc, client);
    if (doc.isNull()) {
      Serial.println("No stop point deviations found.");
      break;
    }
    Serial.println(F("# StopInfo #"));
    Serial.print(F("StopAreaNumber: "));
    Serial.println(doc["StopInfo"]["StopAreaNumber"].as<int>());
    Serial.print(F("StopAreaName: "));
    Serial.println(doc["StopInfo"]["StopAreaName"].as<char*>());
    Serial.print(F("TransportMode: "));
    Serial.println(doc["StopInfo"]["TransportMode"].as<char*>());
    Serial.print(F("GroupOfLine: "));
    Serial.println(doc["StopInfo"]["GroupOfLine"].as<char*>());
    Serial.println(F("# Deviation #"));
    Serial.print(F("Text: "));
    Serial.println(doc["Deviation"]["Text"].as<char*>());
    Serial.print(F("Consequence: "));
    Serial.println(doc["Deviation"]["Consequence"].as<char*>());
    Serial.print(F("ImportanceLevel: "));
    Serial.println(doc["Deviation"]["ImportanceLevel"].as<int>());

  } while (client.findUntil(",", "]"));
}

UKHeliBob

Quote
i want to save these char arrays in a dynamic array, by appending each to the end of the array.
I'm not particularly good at c++ pointers, so any help would be appreciated. How do you do this?
If the char arrays are zero terminated, aka C style strings (lowercase s), then you can concatenate them with an existing string using the strcat() function but the target string must be declared large enough to hold the maximum number of characters necessary plus 1 for the terminating zero
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Idahowalker

#7
Nov 12, 2019, 04:17 pm Last Edit: Nov 12, 2019, 04:18 pm by Idahowalker
Here is this, found with some words in a internet search engine, https://arduino.stackexchange.com/questions/3774/how-can-i-declare-an-array-of-variable-size-globally

Which reads:
Quote
2/ How can I have an array which size is dynamic (i.e. not known until runtime)?

For that you will need dynamic allocation, which works on Arduino, but is generally not advised as this can cause the "heap" to become fragmented.
and then shows you the code how its done.

But then your array will be just like a improperly used String.

If, you are using an ESP32-WROOM or, even better, a ESP32-WROVER, and the ESP32 OS, freeRTOS, this would not be a problem as their are dynamic storage allocation thingies. And if using a ESP32-WROVER, in the Arduino IDE, you get access to 4MB of 'spare' RAM to put your large storage items into.


Go Up