说明
- 有不少网络API是通过http get或者post方式进行请求的,
- 实际上这些api的请求往往都是相对固定的格式,而http是建立在tcp上的,我们往往只需要在TCP client的基础上,进行简单的模拟 即可实现这些API的访问
- 本文以高德的天气API,基于ch32v208的tcp client例程,来实现实时天气的获取
实现
先获取api请求所用到的key
这里按照其网页文档来就行
模拟请求
用浏览器,或者curl之类的工具模拟请求我们的API:
下面我们用curl模拟请求合肥的实时天气
$ curl http://restapi.amap.com/v3/weather/weatherInfo\?city\=340100\&key\=<你申请的apikey>
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 255 100 255 0 0 1782 0 --:--:-- --:--:-- --:--:-- 1795{"status":"1","count":"1","info":"OK","infocode":"10000","lives":[{"province":"安徽","city":"合肥市","adcode":"340100",
"weather":"晴","temperature":"8","winddirection":"东南","windpower":"≤3","humidity":"41","reporttime":"2022-12-30 13:04:50"}]}
对请求进行抓包分析
由于请求比较简单,我们简单的抓下http请求的数据,然后用芯片去模拟就行
构造tcp请求数据包
#define API_DOMAIN "restapi.amap.com" /*DNS请求的API的域名*/
#define API_CITY "340100" /*安徽合肥*/
#define API_KEY "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" /*申请到的APIkey*/
const char header[] = \
"GET /v3/weather/weatherInfo?city=%s&key=%s HTTP/1.1\r\n" \
"Host: %s\r\n"\
"User-Agent: curl/7.85.0\r\n"\
"Accept: */*\r\n"\
"\r\n";
char message[1024];
sprintf(message,header,API_CITY,API_KEY ,API_DOMAIN);
uint32_t send_len
send_len = strlen(message);
tcp建立后,进行请求
i = WCHNET_SocketSend(SocketId,message,&send_len);
tcp收到数据进行解析
这里我们拿到的是json数据,我们通过strstr比较简单的获取json的起始地址(判断收到的数据第一次出现{" 的位置)
char *json_start = strstr((char *)SocketInf[id].RecvReadPoint,"{\"");
if(json_start == NULL) {
WCHNET_SocketRecv(id, NULL, &len);
return ;
}
然后使用cJSON 进行解析即可,注意cJSON的free和delete
cJSON *arrayItem = cJSON_GetObjectItem(root,"status");
out = cJSON_Print(arrayItem);
//PRINT("%s\n",out);
cJSON_free(out);
arrayItem = cJSON_GetObjectItem(root,"info");
out = cJSON_Print(arrayItem);
//PRINT("%s\n",out);
cJSON_free(out);
arrayItem = cJSON_GetObjectItem(root,"infocode");
out = cJSON_Print(arrayItem);
PRINT("%s\n",out);
cJSON_free(out);
arrayItem = cJSON_GetObjectItem(root,"lives");
out = cJSON_Print(arrayItem);
PRINT("%s\n",out);
cJSON_free(out);
arrayItem = cJSON_GetArrayItem(arrayItem,0);
out = cJSON_Print(arrayItem);
PRINT("%s\n",out);
cJSON_free(out);
cJSON *item;
item = cJSON_GetObjectItem(arrayItem,"province");
out = cJSON_Print(item);
PRINT("province:%s\n",out);
cJSON_free(out);
item = cJSON_GetObjectItem(arrayItem,"city");
out = cJSON_Print(item);
PRINT("city:%s\n",out);
cJSON_free(out);
item = cJSON_GetObjectItem(arrayItem,"adcode");
out = cJSON_Print(item);
PRINT("adcode:%s\n",out);
cJSON_free(out);
item = cJSON_GetObjectItem(arrayItem,"weather");
out = cJSON_Print(item);
PRINT("weather:%s\n",out);
cJSON_free(out);
item = cJSON_GetObjectItem(arrayItem,"temperature");
out = cJSON_Print(item);
PRINT("temperature:%s\n",out);
cJSON_free(out);
item = cJSON_GetObjectItem(arrayItem,"winddirection");
out = cJSON_Print(item);
PRINT("winddirection:%s\n",out);
cJSON_free(out);
item = cJSON_GetObjectItem(arrayItem,"windpower");
out = cJSON_Print(item);
PRINT("windpower:%s\n",out);
cJSON_free(out);
item = cJSON_GetObjectItem(arrayItem,"humidity");
out = cJSON_Print(item);
PRINT("humidity:%s\n",out);
cJSON_free(out);
item = cJSON_GetObjectItem(arrayItem,"reporttime");
out = cJSON_Print(item);
PRINT("reporttime:%s\n",out);
cJSON_free(out);
cJSON_Delete(root);
最终的结果
"10000"
[{
"province": "安徽",
"city": "���肥市",
"adcode": "340100",
"weather": "晴",
"temperature": "8",
"winddirection": "东南",
"windpower": "≤3",
"humidity": "40",
"reporttime": "2022-12-30 13:31:36"
}]
{
"province": "安徽",
"city": "合肥市",
"adcode": "340100",
"weather": "晴",
"temperature": "8",
"winddirection": "东南",
"windpower": "≤3",
"humidity": "40",
"reporttime": "2022-12-30 13:31:36"
}
province:"安徽"
city:"合肥市"
adcode:"340100"
weather:"晴"
temperature:"8"
winddirection:"东南"
windpower:"≤3"
humidity:"40"
reporttime:"2022-12-30 13:31:36"
TCP Disconnect
附件
工程放到,ch32v20x evt>EXAM\ETH 下
把自己申请的apikey 替换掉
#define API_KEY "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" /*申请到的APIkey*/
串口打印在PA9,115200
https://gitee.com/iot-fan/iot-fan_at_cnblogs/tree/master/CH32V208/AN/ch32v208_http_get_amap_weather_api_test