如何解决如何连接 const char* 以通过 https 获取另一个 JSON
在使用带有 ArduinoJSON 库的 ESP32 板响应 JSON 后,我尝试多次获取 JSON(YouTube 数据 API)(以获取 activeLiveChatId 和评论)。但我无法连接 const char 值来创建新 URL。也许我的代码处理 const char* 应该是错误的。 你能给我建议一些解决方案吗?下面是我的草图。
#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...\n");
if (https.begin(client,url1)) { // HTTPS
Serial.print("[HTTPS] GET...\n");
// 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\n",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\n",items_0_id_videoId);
}
}
}
String url2 = url2prefix + items_0_id_videoId + url2postfix;
//retrieve activeLiveChatId
if (https.begin(client,url2)) { // HTTPS
Serial.print("[HTTPS] GET...\n");
// 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\n",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,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\n",items_0_liveStreamingDetails_activeLiveChatId
);
}
} else {
Serial.printf("[HTTP] GET... failed,error: %s\n",https.errorToString(httpCode).c_str());
}
https.end();
} else {
Serial.printf("[HTTP] Unable to connect\n");
}
}
}
void loop() {
// wait for WiFi connection
Serial.println("Wait 10s before next round...");
delay(10000);
}
解决方法
您从 JSON 解析器获得了 const char*
类型的只读字符串 - 没关系。您可以无限制地连接它们,但您必须提供内存来保存连接的结果。
有几种方法可以解决这个问题
-
strncat()
(很好的老式 C)。看看这个thread explaining strcat()。本质上,分配足够的内存来保存新字符串,然后将连接结果存储在那里(为清楚起见省略了错误处理)。假设您要连接的字符串是str1
和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);
-
snprintf()
(C)。与strcat()
类似 - 看起来更容易一些,但效率不高。
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",str2);
// ... use the concatenated string in cat_buf
free(cat_buf);
- Arduino
String
(C++)。 String 类型在堆上操作,管理自己的内存,使用起来更容易一些。但是,如果不小心使用,它确实存在堆碎片化的风险。
String cat_str = String(str1) + str2;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。