hehung 发表于 2022-6-2 14:30

【平头哥RVB2601创意应用开发】6. 获取天气信息

本帖最后由 hehung 于 2022-6-2 23:40 编辑

<p><strong>一. 前言&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</strong></p>

<p>&nbsp;&nbsp;&nbsp;&nbsp;RVB2601开发板自带有w800 wifi芯片,可以用来获取天气信息,本帖将详细讲解如何使用RVB2601来获取天气信息。</p>

<p>&nbsp;</p>

<p><strong>二. 准备工作</strong></p>

<p>&nbsp; &nbsp; 1. 获取天气网址查找</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; 我们需要找到一个可以获取天气的API,而且是http方式的,亲测https方式的API是用不了。</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; 经过长时间的查找,终于找到了一个比较好用的平台:<a href="https://www.nowapi.com/api/weather.realtime" target="_blank">https://www.nowapi.com/api/weather.realtime</a></p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; 该平台有多种获取天气的方式,支持http/https请求的GET/POST方式,我们需要用到的就是http GET方式,本文使用了实时天气这个API。</p>

<p></p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; API的使用方式可以参考网站上的教程,不在赘述,有几点需要注意:</p>

<p><strong>&nbsp; &nbsp; &nbsp; &nbsp; (1)必须注册账号才可以使用;</strong></p>

<p><strong>&nbsp; &nbsp; &nbsp; &nbsp; (2)一个小时最多能获取200次,所以不能太频繁;</strong></p>

<p><strong>&nbsp; &nbsp; &nbsp; &nbsp; (3)免费使用得只是试用,有三个月的期限;</strong></p>

<p><strong>&nbsp; &nbsp; &nbsp; &nbsp; (4)使用API的时候需要自己的UID以及appKey在账户中查找即可。</strong></p>

<p>&nbsp; &nbsp; 2. 加载cJSON库</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; CDK自带cJSON,直接下载添加即可,添加方式如下:</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; (1)打开一个工程,随便打开一个即可。</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; (2)打开&nbsp;展开sdk_chip_ch2601,随便选择一个库,右键单击选择 View details in Web ...,会弹出组件资源的网页;<br />
</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; (3)在 组件搜索中搜索cJson,选择版本,点击下载并使用</p>

<p></p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;(4)应该在Packages中会自动加载cjson这个库(组件),如果没有自动添加,手动添加即可,简单操作不在赘述</p>

<p><strong>三. 代码实现</strong></p>

<p>&nbsp; &nbsp;<strong> 注:代码中使用到了w800_api.c中函数,但是这些函数是不能直接被外部接口调用的,直接调用会报找不到函数的ERROR。所以我将w800_api.h中的外部申明函数全部放到了w800.h中。</strong></p>

<p></p>

<p>&nbsp; &nbsp; 1. GET获取http数据</p>

<p>&nbsp; &nbsp; w800连接tcp服务器的时候使用的是IP地址,不能直接使用网址,所以我们需要查找到API网址所对应的IP地址,打开cmd,输入<strong>ping 网</strong>址,就可以知道IP地址了:</p>

<p></p>

<p>&nbsp; &nbsp; 2.连接服务器</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; 通过NowAPi的文档可以知道,获取天气可以使用多种方式,我使用的是cityId的方式,城市代码可以通过这个网址查找:<a href="https://blog.csdn.net/mxh3600/article/details/121580770" target="_blank">https://blog.csdn.net/mxh3600/article/details/121580770</a></p>

<p></p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; 北京是:101010100,我所在地区为成都,所以我填写的是101270101</p>

<pre>
<code>static int Weather_GetWeather(void)
{
        uint16_t url_len;
        int timeout = 200;
    char url;

    sprintf(url, "GET http://api.k780.com/?app=weather.today&amp;cityId=101270101&amp;appkey=自己的UID&amp;sign=自己的AppKey&amp;format=json\r\n", city_key);/* NowApi,免费200次/h,三个月 */
    url_len = strlen(url);

        /* 连接到服务器 - 天气:wthrcdn.etouch.cn */
        Network_W800ConnectTcpServer("103.205.5.249", 80);
        w800_send_data((const uint8_t*)url, url_len, timeout);

    return 0;
}

/* 连接到指定服务器 */
static void Network_W800ConnectTcpServer(char *server_ip, uint16_t port)
{
        char ssid;
        int bssid;
        int channel;
        int rssi;
       
        w800_ap_info(ssid, bssid , &amp;channel,&amp;rssi);
#if (DEBUG_PRINT == STD_ON)
        printf("ssid: %s\r\n", ssid);
        printf("channel: %d\r\n", channel);
        printf("rssi: %d\r\n", rssi);
#endif
       
        w800_connect_remote(0, 2, server_ip, port);
}</code></pre>

<p>&nbsp; &nbsp; 3. 注册数据接收回调函数</p>

<p>&nbsp; &nbsp; 连接了服务器之后,就开始等待服务器返回JSON数据了,<strong>w800_api中的默认接收回调函数不能用,我们需要自己修改</strong></p>

<p>&nbsp; &nbsp; 修改如下,重新注册回调函数,其实回调函数注册一次就行了。可以在程序开始就注册,其中Network_W800RcvCb就是我们的回调函数,后面会讲解如何实现。</p>

<pre>
<code>w800_packet_input_cb_register(&amp;Network_W800RcvCb);</code></pre>

<p>&nbsp; &nbsp; <strong><span style="color:#e74c3c;">注:在这里修改了回调函数之后会导致其他需要用到联网服务的程序可能不能正常接收数据,比如NTP不能正常接收时间戳,所以我们在使用NTP的时候需要将回调函数重新注册为默认的回调函数,同样的官方未提供接口,需要我们自己实现,我在w800_devops.c中增加了一个函数用于注册默认的回调函数,如下图,如果需要使用NTP,可以调用这个函数即可。</span></strong></p>

<p></p>

<p>&nbsp; &nbsp; 4. 回调函数内容实现(处理接收到的JSON数据)</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; (1)数据定义</p>

<p>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 我在软件中需要用到的数据就是本日的最低温度,最高温度,当前温度,当前湿度,以及当前天气,所以将这些数据做成了一个结构体,方便后期处理,如下:</p>

<pre>
<code>typedef struct
{
    int temp_low;
    int temp_high;
    int temp_curr;
    int humi_curr;
    char *weather_today;
    char *weather_curr;
} s_WeatherType;

static s_WeatherType weather_info;</code></pre>

<p>&nbsp; &nbsp; &nbsp; &nbsp; (2)回调函数实现</p>

<pre>
<code>/* W800数据接收回调函数 */
void Network_W800RcvCb(int linkid,
                     void *data,
                     size_t len,
                     char remote_ip,
                     uint16_t remote_ports)
{
        uint8_t *buf;
        buf = (uint8_t *)data;
        cJSON *body = NULL;
        cJSON *cjson_succ_flg = NULL;

        if((0 == len) || (NULL == buf))
        {
                return;
        }

#if (DEBUG_PRINT == STD_ON)
        printf(&quot;receive data len: %d\r\n&quot;,len);
        printf(&quot;receive data:&quot;);
        for(uint16_t i = 0; i &lt; len; i++)
        {
                printf(&quot;%c&quot;, buf<i>);       
        }       
        printf(&quot;\r\n&quot;);
#endif

        body = cJSON_Parse((const char*)buf);
        cjson_succ_flg = cJSON_GetObjectItem(body, &quot;success&quot;);    /* 获取天气是否成功标志 */
        /* 判断是否真的获取到了天气信息,防止获取到了乱码 */
        if(NULL != strstr((const char *)cJSON_Print(cjson_succ_flg), (const char *)&quot;1&quot;))
        {
                Weather_CjsonParse(cJSON_Print(cJSON_GetObjectItem(body, &quot;result&quot;)));
                weather_get_succ_flg = 1;
        }
    else
    {
      weather_get_succ_flg = 0;
                weather_update_cnt = 0;
    }
        cJSON_Delete(body);//释放内存
}

/* 处理获取的JSON代码 */
static void Weather_CjsonParse(char *json_data)
{
        cJSON *body = NULL;   
        cJSON *cjson_weather = NULL;
        cJSON *cjson_temp_L = NULL;
        cJSON *cjson_temp_H = NULL;
        cJSON *cjson_temp_curr = NULL;
        cJSON *cjson_weather_t = NULL;
        cJSON *cjson_humi_curr = NULL;

    body = cJSON_Parse((const char*)json_data);

        cjson_temp_L = cJSON_GetObjectItem(body, &quot;temp_low&quot;);
        cjson_temp_H = cJSON_GetObjectItem(body, &quot;temp_high&quot;);
        cjson_weather = cJSON_GetObjectItem(body, &quot;weather_curr&quot;);
        cjson_weather_t = cJSON_GetObjectItem(body, &quot;weather&quot;);
        cjson_temp_curr = cJSON_GetObjectItem(body, &quot;temp_curr&quot;);
        cjson_humi_curr = cJSON_GetObjectItem(body, &quot;humidity&quot;);

        sscanf(cJSON_Print(cjson_temp_L), &quot;\&quot;%d\&quot;&quot;, &amp;weather_info.temp_low);
        sscanf(cJSON_Print(cjson_temp_H), &quot;\&quot;%d\&quot;&quot;, &amp;weather_info.temp_high);
        // sscanf(cJSON_Print(cjson_weather), &quot;\&quot;%s\&quot;&quot;, weather_info.weather_curr);    //这种方式不能删除后面的引号,用strtok可以
        // sscanf(cJSON_Print(cjson_weather_t), &quot;\&quot;%s\&quot;&quot;, weather_info.weather_today);
        sscanf(cJSON_Print(cjson_temp_curr), &quot;\&quot;%d\&quot;&quot;, &amp;weather_info.temp_curr);
        sscanf(cJSON_Print(cjson_humi_curr), &quot;\&quot;%d%%\&quot;&quot;, &amp;weather_info.humi_curr);
    weather_info.weather_curr = strtok(cJSON_Print(cjson_weather), &quot;\&quot;&quot;);
        weather_info.weather_today = strtok(cJSON_Print(cjson_weather_t), &quot;\&quot;&quot;);

#if (DEBUG_PRINT == STD_ON)
        printf(&quot;%s\r\n&quot;, json_data);
        printf(&quot;\n---temp_low:%d\n--temp_high:%d\n--current:%s\n--today:%s\n--current temp:%d\n--current humi:%d\n&quot;, weather_info.temp_low, weather_info.temp_high, weather_info.weather_curr,
                              weather_info.weather_today, weather_info.temp_curr, weather_info.humi_curr);
#endif
        cJSON_Delete(body);//释放内存
}</i></code></pre>

<p><i>&nbsp;</i></p>

<p><i><strong>四.查看效果</strong></i></p>

<p><i>&nbsp; &nbsp; 编辑好了代码之后,下载运行,结果如下,可以成功获取指定信息:</i></p>

<p><i></i></p>

<p><i>&nbsp;</i></p>

<p><i>&nbsp;</i></p>

lugl4313820 发表于 2022-6-3 21:24

感谢过节也在分享,祝端午快乐,精彩继续!

hehung 发表于 2022-6-3 21:53

lugl4313820 发表于 2022-6-3 21:24
感谢过节也在分享,祝端午快乐,精彩继续!

<p>谢谢,同乐<img height="48" src="https://bbs.eeworld.com.cn/static/editor/plugins/hkemoji/sticker/facebook/congra.gif" width="48" /></p>

lele_liu 发表于 2022-6-5 09:39

<p>感谢楼主的分享,谢谢................</p>
页: [1]
查看完整版本: 【平头哥RVB2601创意应用开发】6. 获取天气信息