ESP32 IDF 获取天气信息

一、注册天气获取账号我使用的知心天气,没有获取天气账号的小伙伴可以去注册一下,知心天气官网:https://www.seniverse.com/取得天气获取的API后,可以直接在浏览器中访问测试一下,如下图所示:

ESP32 IDF 获取天气信息

文章插图
这里我就不赘述了 , 稍微花点信息就可以明白天气是怎么获取的了 。
二、天气信息获取到的天气格式是JSON的数据,直接在浏览器中不好观察,所以我将它整理了一下 , 如下所示:
【ESP32 IDF 获取天气信息】{ "results":[{"location":{"id":"WKEZD7MXE04F","name":"贵阳","country":"CN","path":"贵阳,贵阳,贵州,中国","timezone":"Asia/Shanghai","timezone_offset":"+08:00"},"daily":[{"date":"2022-10-24","text_day":"多云","code_day":"4","text_night":"多云","code_night":"4","high":"24","low":"12","rainfall":"0.00","precip":"0.00","wind_direction":"东南","wind_direction_degree":"135","wind_speed":"8.4","wind_scale":"2","humidity":"57"},{"date":"2022-10-25","text_day":"多云","code_day":"4","text_night":"多云","code_night":"4","high":"24","low":"14","rainfall":"0.00","precip":"0.00","wind_direction":"南","wind_direction_degree":"180","wind_speed":"8.4","wind_scale":"2","humidity":"62"},{"date":"2022-10-26","text_day":"阴","code_day":"9","text_night":"阵雨","code_night":"10","high":"24","low":"13","rainfall":"4.63","precip":"0.94","wind_direction":"南","wind_direction_degree":"180","wind_speed":"3.0","wind_scale":"1","humidity":"87"}],"last_update":"2022-10-24T08:00:00+08:00"} ]} 其中有些格式可能看不知道什么意思,不要怕,看官方的注释,如下所示:
{"results": [{"location": {"id": "C23NB62W20TF","name": "西雅图","country": "US","path": "西雅图,华盛顿州,美国","timezone": "America/Los_Angeles","timezone_offset": "-07:00"},"now": {"text": "多云", //天气现象文字"code": "4", //天气现象代码"temperature": "14", //温度,单位为c摄氏度或f华氏度"feels_like": "14", //体感温度,单位为c摄氏度或f华氏度"pressure": "1018", //气压,单位为mb百帕或in英寸"humidity": "76", //相对湿度,0~100,单位为百分比"visibility": "16.09", //能见度,单位为km公里或mi英里"wind_direction": "西北", //风向文字"wind_direction_degree": "340", //风向角度,范围0~360,0为正北,90为正东,180为正南,270为正西"wind_speed": "8.05", //风速 , 单位为km/h公里每小时或mph英里每小时"wind_scale": "2", //风力等级,请参考:http://baike.baidu.com/view/465076.htm"clouds": "90", //云量 , 单位%,范围0~100,天空被云覆盖的百分比 #目前不支持中国城市#"dew_point": "-12" //露点温度,请参考:http://baike.baidu.com/view/118348.htm #目前不支持中国城市#},"last_update": "2015-09-25T22:45:00-07:00" //数据更新时间(该城市的本地时间)}]} 三、ESP32获取天气信息这里我使用的是ESP-IDF环境,并且是通过 socket 的方式进行获取
  1. socket 通信思路如下图所示:
    ESP32 IDF 获取天气信息

    文章插图
  2. 创建socket连接
    函数int socket(int domain, int type, int protocol)含义函数socket()为通信创建一个端点,并为该套接字返回一个文件描述符 。返回值int,若发生错误则返回-1domain表示需要创建的协议 。如:AF_INET表示IPv4,AF_INET6表示IPv6 , AF_UNIX表示本地套接字type创建时,选择需要的通行方式,如:SOCK_STREAM表示TCP,SOCK_DGRAM表示UDP,SOCK_SEQPACKET表示可靠的顺序包服务,SOCK_RAW表示网络层上的原始协议protocol表示指定要使用的实际传输协议最常见的有IPPROTO_TCP, IPPROTO_SCTP, IPPROTO_UDP, IPPROTO_DCCP等 。如果填0(IPPRORO_IP)则根据前两个参数自动选择协议/* 创建套接字 */socket_handle = socket(dns_info->ai_family, dns_info->ai_socktype, 0); // 0(IPPROTO_IP)可以用来表示选择一个默认的协议 。if(socket_handle < 0) {ESP_LOGE(TAG, "... Failed to allocate socket");close(socket_handle);freeaddrinfo(dns_info);false;}
  3. 连接 connect连接时需要用到服务器的信息 , 而获取天气信息是通过域名的方式获取的,在连接之前,我们需要使用getaddrinfo()函数进行DNS解析
    /* 域名解析 */int err = getaddrinfo(WEB_SERVER, WEB_PORT, &hints, &dns_info);if(err != 0 || dns_info == NULL) {ESP_LOGE(TAG, "DNS lookup failed err=%d dns_info=%p", err, dns_info);return false;}/* 连接服务器 */if(connect(socket_handle, dns_info->ai_addr, dns_info->ai_addrlen) != 0) {ESP_LOGE(TAG, "... socket connect failed errno=%d", errno);close(socket_handle);freeaddrinfo(dns_info);false;}
  4. 通过写数据,发送get请求
    /* 想缓冲区中写入服务请求信息 */if (write(socket_handle, REQUEST, strlen(REQUEST)) < 0) {ESP_LOGE(TAG, "... socket send failed");close(socket_handle);false;}

    推荐阅读