Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
971 views
in Technique[技术] by (71.8m points)

arduino - How to concatenate const char* to get another JSON via https

I'm trying to get JSON (YouTube Data API) multiple times after a response of JSON using ESP32 board with ArduinoJSON library (to reach activeLiveChatId and comments). But I couldn't concatenate const char value to make new URL. Maybe my code should be wrong hundling const char*. Could you suggest me the some solution? Below is my draft sketch.

#include <string>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <stdlib.h>

// Fingerprint for demo URL, expires on June 2, 2021, needs to be updated well before this date

char ssid[] = "myssid";       // your network SSID (name)
char password[] = "mypass";  // your network key

#define API_KEY "myapikey"  // your google apps API Token
#define CHANNEL_ID "mychannelid" // makes up the url of channel
#define servername "www.googleapis.com"

WiFiClientSecure client;

void setup() {
  Serial.begin(115200);
  // Set WiFi to station mode and disconnect from an AP if it was previously connected
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  // Attempt to connect to Wifi network:
  Serial.print("Connecting Wifi: ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  IPAddress ip = WiFi.localIP();
  Serial.println(ip);
  delay(3000);

  if ((WiFi.status() == WL_CONNECTED)) {
    String url1 = ("https://"servername"/youtube/v3/search?eventType=live&part=id&channelId="CHANNEL_ID"&type=video&key="API_KEY);
    String url2prefix = "https://"servername"/youtube/v3/videos?part=liveStreamingDetails&field=activeLiveChatId&id=";
    String url2postfix = "&key="API_KEY;
    const char* items_0_id_videoId;
    HTTPClient https;
    
    Serial.print("[HTTPS] begin...
");
    if (https.begin(client, url1)) {  // HTTPS
      Serial.print("[HTTPS] GET...
");
      // start connection and send HTTP header
      int httpCode = https.GET();
      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d
", httpCode);
        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = https.getString();
          DynamicJsonDocument doc(96);
          StaticJsonDocument<64> filter;
          filter["items"][0]["id"]["videoId"] = true;
          DeserializationError error = deserializeJson(doc, payload, DeserializationOption::Filter(filter));
          if (error) {
            Serial.print(F("deserializeJson() failed: "));
            Serial.println(error.c_str());
            return;
          }
 
          const char* kind = doc["kind"]; // "youtube#searchListResponse"
          const char* etag = doc["etag"]; // 
          const char* regionCode = doc["regionCode"]; // "JP"
          int pageInfo_totalResults = doc["pageInfo"]["totalResults"]; // 1
          int pageInfo_resultsPerPage = doc["pageInfo"]["resultsPerPage"]; // 1
          JsonObject items_0 = doc["items"][0];
          const char* items_0_kind = items_0["kind"]; // "youtube#searchResult"
          const char* items_0_etag = items_0["etag"]; // 
          const char* items_0_id_kind = items_0["id"]["kind"]; // "youtube#video"
          items_0_id_videoId = items_0["id"]["videoId"]; // 

          Serial.printf(
          "ID: %s
",
          items_0_id_videoId);
        }
      }
    }
    String url2 = url2prefix + items_0_id_videoId + url2postfix;
    //retrieve activeLiveChatId
    if (https.begin(client, url2)) {  // HTTPS
      Serial.print("[HTTPS] GET...
");
      // start connection and send HTTP header
      int httpCode = https.GET();
      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTPS] GET... code: %d
", httpCode);
        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = https.getString();
          Serial.println(payload);
          // Stream& input;
          DynamicJsonDocument doc(96);
          StaticJsonDocument<64> filter;
          filter["items"][0]["liveStreamingDetails"]["activeLiveChatId"] = true;
          DeserializationError error = deserializeJson(doc, payload, DeserializationOption::Filter(filter));

          if (error) {
            Serial.print(F("deserializeJson() failed: "));
            Serial.println(error.c_str());
            return;
          }
  
          const char* items_0_liveStreamingDetails_activeLiveChatId = doc["items"][0]["liveStreamingDetails"]["activeLiveChatId"];
        
          Serial.printf(
          "livechatID: %s
",
          items_0_liveStreamingDetails_activeLiveChatId
          );
        }
      } else {
        Serial.printf("[HTTP] GET... failed, error: %s
", https.errorToString(httpCode).c_str());
      }
      https.end();
    } else {
      Serial.printf("[HTTP] Unable to connect
");
    }
  }
}  

void loop() {
  // wait for WiFi connection
  Serial.println("Wait 10s before next round...");
  delay(10000);
}
question from:https://stackoverflow.com/questions/65895562/how-to-concatenate-const-char-to-get-another-json-via-https

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You're getting read-only strings of type const char* from your JSON parser - that's OK. You can concatenate them without restriction, but you have to provide memory to hold the result of the concatenation.

There are a few ways to solve this

  1. strncat() (good old-fashioned C). Have a look at this thread explaining strcat(). In essence, allocate enough memory to hold the new string and then store the concatenation result there (error handling omitted for clarity). Assuming the strings you want to concatenate are str1 and str2:
    const size_t cat_buf_len = strlen(str1) + strlen(str2) + 1;
    char* cat_buf = (char*) malloc(cat_buf_len);
    strncpy(cat_buf, str1, cat_buf_len);
    strncat(cat_buf, str2, cat_buf_len - strlen(cat_buf));
    // ... use the concatenated string in cat_buf
    free(cat_buf); 
  1. snprintf() (C). Similar to strcat() - a bit easier on the eyes, but not as efficient.
    const size_t cat_buf_len = strlen(str1) + strlen(str2) + 1;
    char* cat_buf = (char*) malloc(cat_buf_len);
    snprintf(cat_buf, cat_buf_len, "%s%s", str1, str2);
    // ... use the concatenated string in cat_buf
    free(cat_buf); 
  1. Arduino String (C++). The String type operates on heap, manages its own memory and is a bit easier to use. It does risk fragmenting the heap, though, if not used carefully.
    String cat_str = String(str1) + str2;

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...