0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

【HarmonyOS HiSpark Wi-Fi IoT 套件试用连载】七、获取网络天气数据

开发板试用精选 来源:开发板试用 作者:电子发烧友论坛 2022-11-02 14:49 次阅读

本文来源电子发烧友社区,作者:李元江, 帖子地址:https://bbs.elecfans.com/jishu_2025428_1_1.html

元旦好冷,哪也不想去,那就趁着有空,写写帖子吧。今天的帖子我写的是关于如何从网络获取天气数据,以及如何解析出我们需要的天气数据。

一、天气数据获取
首先说说怎么获取天气数据。现在可以从很多平台获取到天气数据,我使用的平台是心知天气,如何只是获取实时天气情况和最近几天天气情况是免费的,只要注册账号就可以使用。地址为:https://www.seniverse.com/。心知天气里面不仅支持天气数据获取,还支持其他数据获取。这里我们需要获取天气实况和逐日天气情况。每个API有一个请求示例地址,逐日天气请求示例地址如下,每个参数都会有相关说明。
213542d4cqq9z0511mcq92.jpg
在浏览器地址栏输入请求示例地址后,可以查看返回数据内容情况。
213610apvffl1vt26u6vka.jpg
有了这个数据获取接口,接下来以下步骤来获取数据。
  • 连接心知天气服务器心知天气服务器地址为116.62.81.138。端口号为80,连接方式为TCP
  • 发送Get请求成功连接到心知天气服务器后,需要发送Get请求才能获取到数据。我要获取最近三天的天气预报情况,请求地址为https://api.seniverse.com/v3/weather/daily.json?key=SgJs9V9ghopE5WSBe&location=shenzhen&language=zh-Hans&unit=c&start=0&days=3则我们需要发送的数据为“Get https://api.seniverse.com/v3/weather/daily.json?key=SgJs9V9ghopE5WSBe&location=shenzhen&language=zh-Hans&unit=c&start=0&days=3rnrn”注意:最后为两个回车换行。之后会返回天气数据包,但是该数据包是Json格式的数据,需要解析才能得到我们真正需要的数据。下面是我使用调试助手获取到的数据情况。

213934ognro1mzzmugg628.jpg

二、软件设计
1、添加cJson功能

从网络上直接获取到的天气数据是Json格式的,需要进行解析才能得到所需天气数据。解析Json格式数据我借助第三方软件包cJson,通过cJson解析出数据。其实在wifiiot的例程源代码中,已经添加有cJson了。

213736xc9hmxw9n5is5iss.jpg

但是要使用cJson功能,还需要下面操作。在OLED下的BUILD.gn文件中include_dirs加入 "//third_party/cJSON",

213757i99pvk9ogwoz4tvp.jpg

2、Json数据解析

在OLED下面新建从cjsonparse.c和cjsonparse.h文件,主要是关于Json数据解析的函数。这里我们获取得天气数据有两个:实时天气情况和未来三天天气数据情况,所以需要解析实时天气Json数据和未来三天天气Json数据。

解析实时天气,主要是为了获取现在的温度和天气情况代码。

  1. int cJSON_NowWeatherParse(char *JSON,weather *Weather)
  2. {
  3. cJSON *json,*arrayItem,*object,*subobject,*item;
  4. json = cJSON_Parse(JSON); //解析JSON数据包
  5. if(json == NULL) //检测JSON数据包是否存在语法上的错误,返回NULL表示数据包无效
  6. {
  7. printf("Error before: [%s]n",cJSON_GetErrorPtr()); //打印数据包语法错误的位置
  8. return 1;
  9. }
  10. else
  11. {
  12. if((arrayItem = cJSON_GetObjectItem(json,"results")) != NULL) //匹配字符串"results",获取数组内容
  13. {
  14. cJSON_GetArraySize(arrayItem); //获取数组中对象个数
  15. //printf("cJSON_GetArraySize: size=%dn",size);
  16. if((object = cJSON_GetArrayItem(arrayItem,0)) != NULL)//获取父对象内容
  17. {
  18. /* 匹配子对象1 */
  19. if((subobject = cJSON_GetObjectItem(object,"location")) != NULL)
  20. {
  21. }
  22. /* 匹配子对象2 */
  23. if((subobject = cJSON_GetObjectItem(object,"now")) != NULL)
  24. {
  25. printf("---------------------------------now-------------------------------n");
  26. //匹配子对象2成员"text"
  27. if((item = cJSON_GetObjectItem(subobject,"text")) != NULL)
  28. {
  29. printf("%s : %sn",item->string,item->valuestring);
  30. }
  31. //匹配子对象2成员"code"
  32. if((item = cJSON_GetObjectItem(subobject,"code")) != NULL)
  33. {
  34. printf("%s : %sn",item->string,item->valuestring);
  35. Weather->nowcode = str2int(item->valuestring);
  36. }
  37. //匹配子对象2成员"temperature"
  38. if((item = cJSON_GetObjectItem(subobject,"temperature")) != NULL)
  39. {
  40. printf("%s : %sn",item->string,item->valuestring);
  41. Weather->nowtemp = str2int(item->valuestring);
  42. }
  43. }
  44. /* 匹配子对象last_update */
  45. if((subobject = cJSON_GetObjectItem(object,"last_update")) != NULL)
  46. {
  47. printf("----------------------------last_update----------------------------n");
  48. printf("%s : %snn",subobject->string,subobject->valuestring);
  49. }
  50. }
  51. }
  52. }
  53. cJSON_Delete(json); //释放cJSON_Parse()分配出来的内存空间
  54. return 0;
  55. }
复制代码

解析未来三天天气情况数据,主要为了获取今天、明天、后天的最高、最低温度、天气情况代码、湿度情况。当然也可以解析获取更改天气情况数据,但是这里我只解析获取那么多。

  1. //解析三天天气
  2. int cJSON_TayWeatherParse(char *JSON,weather *weather)
  3. {
  4. cJSON *root;
  5. cJSON *pSub;
  6. cJSON *arrayItem;
  7. cJSON *pItem;
  8. cJSON *pSubItem;
  9. cJSON *pChildItem;
  10. cJSON *pLastItem;
  11. char *pr;
  12. root = cJSON_Parse((const char*)JSON);
  13. if(root != NULL)
  14. {
  15. pSub = cJSON_GetObjectItem(root,"results");
  16. if(pSub != NULL)
  17. {
  18. arrayItem = cJSON_GetArrayItem(pSub,0);
  19. pr = cJSON_Print(arrayItem);
  20. pItem = cJSON_Parse(pr);
  21. if(pItem != NULL)
  22. {
  23. pSubItem = cJSON_GetObjectItem(pItem,"daily");
  24. if(pSubItem != NULL)
  25. {
  26. int size = cJSON_GetArraySize(pSubItem);
  27. for(int i=0;i;i++)
  28. {
  29. if(i==3)break;
  30. arrayItem = cJSON_GetArrayItem(pSubItem,i);
  31. pr = cJSON_Print(arrayItem);
  32. pLastItem = cJSON_Parse(pr);
  33. if(pLastItem != NULL)
  34. {
  35. if((pChildItem =cJSON_GetObjectItem(pLastItem,"high")) != NULL)
  36. {
  37. printf("%s : %sn",pChildItem->string,pChildItem->valuestring);
  38. weather->high[i] = str2int(pChildItem->valuestring);
  39. }
  40. if((pChildItem =cJSON_GetObjectItem(pLastItem,"low")) != NULL)
  41. {
  42. printf("%s : %sn",pChildItem->string,pChildItem->valuestring);
  43. weather->low[i] = str2int(pChildItem->valuestring);
  44. }
  45. if((pChildItem =cJSON_GetObjectItem(pLastItem,"code_day"))!=NULL)
  46. {
  47. printf("%s : %sn",pChildItem->string,pChildItem->valuestring);
  48. weather->code[i] = str2int(pChildItem->valuestring);
  49. }
  50. if((pChildItem =cJSON_GetObjectItem(pLastItem,"humidity"))!=NULL)
  51. {
  52. printf("%s : %sn",pChildItem->string,pChildItem->valuestring);
  53. weather->humi[i] = str2int(pChildItem->valuestring);
  54. }
  55. }
  56. cJSON_Delete(pLastItem);
  57. }
  58. }
  59. }
  60. cJSON_Delete(pItem);
  61. }
  62. }
  63. cJSON_Delete(root);
  64. return 0;
  65. }
复制代码
3、 获取天气数据

新建getweather.c文件,主要获取天气数据的功能函数。设置的代码中主要经过如下步骤获取和解析天气情况数据。

  • 1、连接网络
  • 2、 连接到服务器
  • 3、发送近三天天气情况请求
  • 4、接收数据
  • 5、解析近三天天气Json数据
  • 6、关闭与服务器连接
  • 7、从新连接到服务器
  • 8、发送实时天气情况请求
  • 9、接收数据
  • 10、解析实时天气Json数据
  • 11、关闭与服务器连接
  • 12、断开与网络的连接
  1. #include
  2. #include
  3. #include
  4. #include
  5. #include "net_demo.h"
  6. #include "net_common.h"
  7. #include "net_params.h"
  8. #include "wifi_connecter.h"
  9. #include "ohos_init.h"
  10. #include "cmsis_os2.h"
  11. #include "cjsonparse.h"
  12. #define WEATHERIPADDR "116.62.81.138"
  13. #define WEATHERPORT 80
  14. static char requestday[] = "GET https://api.seniverse.com/v3/weather/daily.json?key=SgJs9V9ghopE5WSBe&location=shenzhen&language=zh-Hans&unit=c&start=0&days=3rnrn";
  15. static char requestnow[] = "GET https://api.seniverse.com/v3/weather/now.json?key=SgJs9V9ghopE5WSBe&location=shenzhen&language=zh-Hans&unit=crnrn";
  16. static char response[1000] = "";
  17. weather weatherValue;
  18. bool getWeather(void){
  19. bool sucflag = false;
  20. WifiDeviceConfig config = {0};
  21. // 准备AP的配置参数
  22. strcpy(config.ssid, PARAM_HOTSPOT_SSID);
  23. strcpy(config.preSharedKey, PARAM_HOTSPOT_PSK);
  24. config.securityType = PARAM_HOTSPOT_TYPE;
  25. osDelay(10);
  26. int netId = ConnectToHotspot(&config);
  27. /*获取最近三天天气情况*/
  28. int32_t retval = 0;
  29. int sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP socket
  30. struct sockaddr_in serverAddr = {0};
  31. serverAddr.sin_family = AF_INET;// AF_INET表示IPv4协议
  32. serverAddr.sin_port = htons(WEATHERPORT);// 端口号,从主机字节序转为网络字节序
  33. if (inet_pton(AF_INET, WEATHERIPADDR, &serverAddr.sin_addr) <= 0) {  // 将主机IP地址从“点分十进制”字符串 转化为 标准格式(32位整数)
  34. printf("inet_pton failed!rn");
  35. goto do_cleanup;
  36. }
  37. // 尝试和目标主机建立连接,连接成功会返回0 ,失败返回 -1
  38. if (connect(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
  39. printf("connect failed!rn");
  40. goto do_cleanup;
  41. }
  42. printf("connect to server %s success!rn", WEATHERIPADDR);
  43. // 建立连接成功之后,这个TCP socket描述符 —— sockfd 就具有了 “连接状态”,发送、接收 对端都是 connect 参数指定的目标主机和端口
  44. //retval = send(sockfd, requestnow, sizeof(requestnow), 0);
  45. retval = send(sockfd, requestday, sizeof(requestday), 0);
  46. if (retval < 0) {
  47. printf("send request failed!rn");
  48. goto do_cleanup;
  49. }
  50. printf("send request{%s} %ld to server done!rn", requestday, retval);
  51. retval = recv(sockfd, &response, sizeof(response), 0);
  52. if (retval <= 0) {
  53. printf("send response from server failed or done, %ld!rn", retval);
  54. goto do_cleanup;
  55. }
  56. response[retval] = '';
  57. int i = 0;
  58. /*打印接收到数据*/
  59. while(i)
  60. {
  61. printf("%c",response[i]);
  62. i++;
  63. }
  64. cJSON_TayWeatherParse(response,&weatherValue);
  65. close(sockfd);
  66. /*获取现在的天气情况*/
  67. sockfd = socket(AF_INET, SOCK_STREAM, 0); // TCP socket
  68. if (inet_pton(AF_INET, WEATHERIPADDR, &serverAddr.sin_addr) <= 0) {  // 将主机IP地址从“点分十进制”字符串 转化为 标准格式(32位整数)
  69. printf("inet_pton failed!rn");
  70. goto do_cleanup;
  71. }
  72. // 尝试和目标主机建立连接,连接成功会返回0 ,失败返回 -1
  73. if (connect(sockfd, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) {
  74. printf("connect failed!rn");
  75. goto do_cleanup;
  76. }
  77. retval = send(sockfd, requestnow, sizeof(requestnow), 0);
  78. if (retval < 0) {
  79. printf("send request failed!rn");
  80. goto do_cleanup;
  81. }
  82. printf("send request{%s} %ld to server done!rn", requestnow, retval);
  83. retval = recv(sockfd, &response, sizeof(response), 0);
  84. if (retval <= 0) {
  85. printf("send response from server failed or done, %ld!rn", retval);
  86. goto do_cleanup;
  87. }
  88. response[retval] = '';
  89. i = 0;
  90. /*打印接收到数据*/
  91. while(i)
  92. {
  93. printf("%c",response[i]);
  94. i++;
  95. }
  96. cJSON_NowWeatherParse(response,&weatherValue);
  97. sucflag=true;
  98. do_cleanup:
  99. close(sockfd);
  100. DisconnectWithHotspot(netId);
  101. if(sucflag)
  102. return true;
  103. else
  104. return false;
  105. }
复制代码
4、加入任务中

把获取天气数据功能增加到任务中。在oled_demo.c中static void OledTask(void *arg)函数增加以下代码。

  1. AdcRead(ANALOG_KEY_CHAN_NAME, &data, WIFI_IOT_ADC_EQU_MODEL_4, WIFI_IOT_ADC_CUR_BAIS_DEFAULT, 0);
  2. float voltage = ConvertToVoltage(data);
  3. if(voltage>0.45 && voltage<0.65)
  4. {
  5. OledShowString(16,7,"Sync time...",1);
  6. getNtpTime();
  7. OledFillScreen(0);
  8. }
  9. else if(voltage>0.9 && voltage<1)
  10. {
  11. OledShowString(0,7,"Get Weather...",1);
  12. if(getWeather())
  13. OledFillScreen(0);
  14. else
  15. {
  16. OledShowString(0,7,"Get fail...",1);
  17. }
  18. }
复制代码

按下oled显示板的右边按钮,会进入获取天气情况功能。现在我这里只是通过串口打印出来的数据,观察数据获取和解析情况,还没有把解析后的天气数据显示到oled上。

5、修改BUILD.gn

修改OLED文件夹下的BUILD.gn文件,sources中加入getweather.c和cjsonparse.c

  1. sources = [
  2. "oled_demo.c",
  3. "oled_ssd1306.c",
  4. "timeconv.c",
  5. "envrionment_demo.c",
  6. "aht20.c",
  7. "wifi_connecter.c",
  8. "getNTP.c",
  9. "getweather.c",
  10. "cjsonparse.c",
  11. ]
复制代码

三、结果演示

按下OLED显示板右边按键,会进入天气数据功能,之后显示“Get Weather....”提示。天气数据获取失败后,会显示“Get fail...”提示。

214220iyvnrgrc8jq8y303.jpg

可以从串口打印输出的信息,观察到获取的Json数据情况和解析后的数据情况。

213858izk35ikaklkzupe3.jpg


四、总结

网络天气数据的获取主要经过如下步骤

  • 连接网络
  • 连接服务器
  • 请求数据
  • 解析Json数据

2021年第一篇帖子,先写到这里。下一篇是关于通过TCP连接与手机APP进行数据交互的帖子。当然手机APP是我之前做好的。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • wi-fi
    +关注

    关注

    14

    文章

    2132

    浏览量

    124422
  • HarmonyOS
    +关注

    关注

    79

    文章

    1973

    浏览量

    30143
  • HiSpark
    +关注

    关注

    1

    文章

    156

    浏览量

    6924
收藏 人收藏

    评论

    相关推荐

    Wi-Fi 8要来了!未来Wi-Fi技术演进方向揭秘

    电子发烧友网报道(文/梁浩斌)Wi-Fi 7芯片早在2022年就有产品推出,直到去年年底,Wi-Fi 7设备开始大量推出市场。但从普及率来看,根据奥维云网的数据,截至2024年9月,线上家用路由器
    的头像 发表于 11-24 03:14 1542次阅读
    <b class='flag-5'>Wi-Fi</b> 8要来了!未来<b class='flag-5'>Wi-Fi</b>技术演进方向揭秘

    华为海思正式进入Wi-Fi FEM赛道?

    大家都知道了,2018年11 月离开锐迪科(RDA),前往福建晋江创立三伍微,专注于Wi-Fi射频前端芯片,从路由器Wi-Fi FEM,到手机Wi-Fi FEM,再到IoT FEM全覆
    发表于 12-11 17:42

    Wi-Fi 4到Wi-Fi 7:网速飙升40倍的无线革命

    Wi-Fi 4首次引入MIMO和40 MHz频宽,是基础的高效无线网络标准。   Wi-Fi 5 Wi-Fi 5拥有更高的数据速率,专注于
    的头像 发表于 12-09 10:10 227次阅读
    从<b class='flag-5'>Wi-Fi</b> 4到<b class='flag-5'>Wi-Fi</b> 7:网速飙升40倍的无线革命

    Wi-Fi 7与Wi-Fi 6E有什么区别

    也许很多人还在考虑是否要将使用的Wi-Fi设备升级到Wi-Fi 6或Wi-Fi 6E,而这些标准的继任者却已经开始“登堂入室”了。Wi-Fi 7是新一代
    的头像 发表于 11-07 11:38 712次阅读

    IR900 Wi-Fi联网的配置过程

    例如上图,IR900 通过Wi-Fi接口连接公司办公无线网络 inhand-office (SSID为无线网络的名称) 首先将Wi-Fi接口与WLAN接口解绑 登陆IR900后,进
    发表于 07-25 06:09

    AT 0.60.0.0看不到我的Wi-Fi网络,为什么?

    我对 AT 0.60.0.0 有一点问题。当我通过 AT CWLAP 显示所有网络时,我看不到我的路由器 AP 网络,但我可以连接到它。当我在智能手机中打开 Wi-Fi 热点时,我可以看到我的热点
    发表于 07-18 08:31

    DA16200 超低功耗 Wi-Fi 模块开发套件 Pro数据手册

    电子发烧友网站提供《DA16200 超低功耗 Wi-Fi 模块开发套件 Pro数据手册.rar》资料免费下载
    发表于 05-30 17:53 1次下载
    DA16200 超低功耗 <b class='flag-5'>Wi-Fi</b> 模块开发<b class='flag-5'>套件</b> Pro<b class='flag-5'>数据</b>手册

    DA16200 超低功耗 Wi-Fi 模块开发套件数据手册

    电子发烧友网站提供《DA16200 超低功耗 Wi-Fi 模块开发套件数据手册.rar》资料免费下载
    发表于 05-30 17:13 0次下载
    DA16200 超低功耗 <b class='flag-5'>Wi-Fi</b> 模块开发<b class='flag-5'>套件数据</b>手册

    验证物联网Wi-Fi HaLow用例的MM6108-EKH08开发套件来啦

    验证物联网Wi-Fi HaLow用例的MM6108-EKH08开发套件来啦 MM6108-EKH08开发套件专为验证物联网Wi-Fi HaLow用例而设计。该
    的头像 发表于 04-11 12:01 1721次阅读
    验证物联网<b class='flag-5'>Wi-Fi</b> HaLow用例的MM6108-EKH08开发<b class='flag-5'>套件</b>来啦

    Wi-Fi 7与Wi-Fi 6的相关知识科普

    科普:Wi-Fi 7 vs. Wi-Fi 6,青出于蓝
    的头像 发表于 03-12 10:59 739次阅读
    <b class='flag-5'>Wi-Fi</b> 7与<b class='flag-5'>Wi-Fi</b> 6的相关知识科普

    Wi-Fi的诞生与发展

    和5GHz两个频段,承载着不断增长的网络需求。ABIResearch显示,2022年Wi-Fi上传流量激增80%,Wi-Fi数据流量已超过蜂窝流量,且成为流量增量贡
    的头像 发表于 03-07 08:26 1212次阅读
    <b class='flag-5'>Wi-Fi</b>的诞生与发展

    Wi-Fi HaLow和传统Wi-Fi的区别

    Wi-Fi HaLow和传统Wi-Fi的区别  Wi-Fi是一种无线网络技术,可以连接到互联网或局域网,为用户提供无线上网的便利。随着科技的发展和互联网的普及,
    的头像 发表于 02-02 15:28 1254次阅读

    康普携手Wi-Fi联盟,RUCKUS Wi-Fi 7系列接入点成Wi-Fi

     康普高级副总裁兼网络、智能蜂窝和安全解决方案总裁Bart Giordano对此表示: “我们非常荣幸能与Wi-Fi Alliance形成长期合作伙伴关系,将我们的RUCKUS Wi-Fi 7 接入点平台作为
    的头像 发表于 01-23 14:10 751次阅读

    BT Wi-Fi模式是否可以通过ModustoolBox对套件进行编程来实现?

    想配置用于分析 CYW43439 的 CY8CPROTO-062S2-43439 原型开发套件。 浏览文档我无法弄清楚如何在不同的 Wi-Fi 和蓝牙模式(电源模式、连接模式等)下配置套件。 在
    发表于 01-22 06:19

    Wi-Fi联盟已正式确认Wi-Fi 7标准,无线网络新时代来临!Wi-Fi 联盟已开始对 Wi-Fi 7 设备

    无线网络wi-fi
    北京中科同志科技股份有限公司
    发布于 :2024年01月10日 10:43:56