ESP8266获取天气预报信息,并使用CJSON解析天气预报数据

news2024/12/27 13:00:52

一、实现功能

当前文章介绍如何使用ESP8266和STM32微控制器,搭配OLED显示屏,制作一个能够实时显示天气预报的智能设备。将使用心知天气API来获取天气数据,并使用MQTT协议将数据传递给STM32控制器,最终在OLED显示屏上显示。

心知天气是一家专业的气象数据服务提供商,致力于为全球用户提供高质量、定制化的气象数据服务。其主要产品包括天气API、空气质量API、灾害预警API等。用户可以通过心知天气的API接口,获取准确、实时的天气数据,从而为各种应用场景提供支持,例如智能家居、出行、电商等。心知天气的数据覆盖全球200多个国家和地区,每日处理超过10亿次API请求,是业内领先的气象数据服务提供商之一。
https://www.seniverse.com/

在这里插入图片描述

二、硬件准备

1. ESP8266模块

ESP8266是一款WiFi模块,它具有强大的网络连接功能,可以轻松地连接到互联网。将使用ESP8266模块来获取天气数据,并将其发送给STM32控制器。具体来说,我们将使用正点原子ATK-ESP8266模块,这是一款集成ESP8266芯片的小板子。

2. STM32微控制器

STM32是一款强大的32位微控制器,具有多种接口和功能。将使用STM32F103C8T6控制器,这是一款非常流行的型号,易于获得且价格较为合理。

3. OLED显示屏

OLED是一种非常流行的显示技术,具有高对比度、低功耗、快速响应等优点。将使用0.96英寸128x64像素的OLED显示屏。

三、CJSON解析天气预报数据

3.1 接口返回的数据

{
  "results": [
    {
      "location": {
        "id": "WTEMH46Z5N09",
        "name": "合肥",
        "country": "CN",
        "path": "合肥,合肥,安徽,中国",
        "timezone": "Asia/Shanghai",
        "timezone_offset": "+08:00"
      },
      "now": {
        "text": "阴",
        "code": "9",
        "temperature": "12",
        "feels_like": "18",
        "pressure": "1000",
        "humidity": "89",
        "visibility": "12.0",
        "wind_direction": "西南",
        "wind_direction_degree": "245",
        "wind_speed": "19.0",
        "wind_scale": "3",
        "clouds": "85",
        "dew_point": ""
      },
      "last_update": "2023-04-04T14:20:13+08:00"
    }
  ]
}

3.2 CJSON是什么

CJSON是一款轻量级的C语言JSON解析器,其全称是“cJSON”,由Dave Gamble编写。它简单易用,可嵌入到C应用程序中,既支持JSON字符串的解析,也支持JSON对象的创建及操作。CJSON不依赖于任何其他的库或组件,使用它只需要引入其头文件即可。

CJSON的使用方式相对来说比较简单,需要进行以下几个步骤:

1. 在应用程序中包含cJSON的头文件:#include "cJSON.h"2. 调用cJSON_Parse函数,将JSON字符串转换为CJSON对象。
3. 使用cJSON提供的API函数对CJSON对象进行操作,包括读取、修改、删除、添加等。
4. 在程序结束时,记得释放cJSON对象的内存空间,避免内存泄漏。

CJSON的解析速度相对较快,占用的内存开销也比较小,因此非常适用于资源有限的嵌入式系统中使用。

3.3 解析数据

使用CJSON解析上述JSON数据非常简单,只需要按照以下步骤操作:

  1. 引入CJSON库文件
#include <cJSON.h>
  1. 解析JSON数据并创建cJSON对象
char* json_data = "{\"results\":[{\"location\":{\"id\":\"WTEMH46Z5N09\",\"name\":\"合肥\",\"country\":\"CN\",\"path\":\"合肥,合肥,安徽,中国\",\"timezone\":\"Asia/Shanghai\",\"timezone_offset\":\"+08:00\"},\"now\":{\"text\":\"阴\",\"code\":\"9\",\"temperature\":\"12\",\"feels_like\":\"18\",\"pressure\":\"1000\",\"humidity\":\"89\",\"visibility\":\"12.0\",\"wind_direction\":\"西南\",\"wind_direction_degree\":\"245\",\"wind_speed\":\"19.0\",\"wind_scale\":\"3\",\"clouds\":\"85\",\"dew_point\":\"\"},\"last_update\":\"2023-04-04T14:20:13+08:00\"}]}";
cJSON* root = cJSON_Parse(json_data);

在这个代码片段中,我们首先定义了一个字符串类型的变量json_data,用于存储上述JSON数据。然后,我们调用cJSON_Parse()函数来解析JSON数据,并将解析结果保存在root指针所指向的cJSON对象中。

  1. 从cJSON对象中提取数据
cJSON* location = cJSON_GetObjectItem(root, "location");
char* city = cJSON_GetObjectItem(location, "name")->valuestring;
cJSON* now = cJSON_GetObjectItem(root, "now");
int temperature = cJSON_GetObjectItem(now, "temperature")->valueint;
char* text = cJSON_GetObjectItem(now, "text")->valuestring;

在这个代码片段中,我们使用cJSON_GetObjectItem()函数从root指针所指向的cJSON对象中提取一个名为location的JSON对象,并从该JSON对象中获取名为name的字符串类型变量。类似地,我们也可以从root指针所指向的cJSON对象中提取名为now的JSON对象,并从该JSON对象中获取名为temperaturetext的整型和字符串类型变量。

  1. 释放cJSON对象
cJSON_Delete(root);

最后,我们需要释放之前创建的cJSON对象,以释放内存空间。

完整的代码示例如下:

#include <cJSON.h>
#include <stdio.h>

int main() {
    char* json_data = "{\"results\":[{\"location\":{\"id\":\"WTEMH46Z5N09\",\"name\":\"合肥\",\"country\":\"CN\",\"path\":\"合肥,合肥,安徽,中国\",\"timezone\":\"Asia/Shanghai\",\"timezone_offset\":\"+08:00\"},\"now\":{\"text\":\"阴\",\"code\":\"9\",\"temperature\":\"12\",\"feels_like\":\"18\",\"pressure\":\"1000\",\"humidity\":\"89\",\"visibility\":\"12.0\",\"wind_direction\":\"西南\",\"wind_direction_degree\":\"245\",\"wind_speed\":\"19.0\",\"wind_scale\":\"3\",\"clouds\":\"85\",\"dew_point\":\"\"},\"last_update\":\"2023-04-04T14:20:13+08:00\"}]}";
    cJSON* root = cJSON_Parse(json_data);

    cJSON* location = cJSON_GetObjectItem(root, "location");
    char* city = cJSON_GetObjectItem(location, "name")->valuestring;
    cJSON* now = cJSON_GetObjectItem(root, "now");
    int temperature = cJSON_GetObjectItem(now, "temperature")->valueint;
    char* text = cJSON_GetObjectItem(now, "text")->valuestring;

    printf("City: %s\n", city);
    printf("Temperature: %d\n", temperature);
    printf("Weather: %s\n", text);

    cJSON_Delete(root);

    return 0;
}

在这个代码示例中,使用了cJSON_Parse()cJSON_GetObjectItem()cJSON_Delete()等函数来解析和处理JSON数据。

3.4 获取数据

下面是ESP8266访问HTTP接口请求的代码:

#include <SoftwareSerial.h>

// 定义ESP8266串口对象
SoftwareSerial esp8266(PA10, PA9); // RX, TX

void setup() {
  Serial.begin(9600);

  // 初始化ESP8266串口通信波特率为9600
  esp8266.begin(9600);

  // 发送AT指令测试ESP8266是否正常工作
  esp8266.println("AT");
  delay(500);
  if (esp8266.find("OK")) {
    Serial.println("ESP8266 is working properly.");
  } else {
    Serial.println("ESP8266 is not working properly.");
  }
}

void loop() {
  // 向ESP8266发送HTTP请求
  esp8266.println("AT+CIPSTART=\"TCP\",\"api.seniverse.com\",80");
  if (esp8266.find("OK")) {
    Serial.println("TCP connection established.");
  } else {
    Serial.println("TCP connection failed.");
  }

  String url = "/v3/weather/now.json?key=your_API_KEY&location=your_LOCATION";
  String request = "GET " + url + " HTTP/1.1\r\n" +
                   "Host: api.seniverse.com\r\n" +
                   "User-Agent: STM32/1.0\r\n" +
                   "Connection: close\r\n\r\n";
  int length = request.length();
  String cmd = "AT+CIPSEND=" + String(length);
  esp8266.println(cmd);
  if (esp8266.find(">")) {
    Serial.println("Sending HTTP request...");
    esp8266.print(request);
  } else {
    Serial.println("Failed to send HTTP request.");
  }

  // 接收HTTP响应
  while (esp8266.available()) {
    String response = esp8266.readStringUntil('\n');
    Serial.println(response);
  }

  // 关闭TCP连接
  esp8266.println("AT+CIPCLOSE");
  delay(1000);
}

在这个示例代码中,初始化了ESP8266串口对象,并通过发送AT指令测试ESP8266是否正常工作。然后,在loop()函数中,向ESP8266发送一个HTTP请求,包括请求头和请求体。发送完毕后,等待ESP8266返回HTTP响应并将其打印出来。最后,关闭TCP连接并等待一秒钟,然后重复上述步骤。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/563579.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python篇——数据结构与算法(第二部分)

目录 二、排序算法&#xff08;承接第一部分&#xff09; 1、堆排序算法——树的基础知识补充 2、树的基本概念 3、二叉树基础知识 &#xff08;1&#xff09;满二叉树 &#xff08;2&#xff09;完全二叉树 &#xff08;3&#xff09;二叉树的存储方式&#xff08;表示方式…

Python基础教程:第九章_Python异常模块与包

从现在开始&#xff0c;让我们来进入到新的章节&#xff0c; Python 异常模块与包的内容学习。本章节我们主要分为 6 部分进行讲解&#xff0c;包含了 Python 异常的相关操作以及 Python 的模块操作&#xff0c; Python 的包操作和安装第三方 Python 包的相关操作。 了解异常 …

【Netty】Netty ChannelHandler(四)

文章目录 前言一、ChannelHandler二、ChannelInboundHandler三、ChannelOutboundHandler四、ChannelDuplexHandler总结 前言 前两篇文章我们已经对Netty进行了简单的了解和架构设计原理的剖析。 相关文章链接如下&#xff1a; Netty 概述&#xff08;一&#xff09;Netty 架构…

在互联网寒冬,我们应届生应如何提高竞争力?

前言 在当前就业形势下&#xff0c;如何提高应届生在职场中的竞争力&#xff1f;具有哪些有效的方法和策略可供选择&#xff1f;这是一个备受关注的热点话题。哪些方面会对应届生的职场发展起到关键的推动和支撑作用呢&#xff1f;我也来讲一下我是打算如何提升自己的职场竞争力…

移动应用架构解析:用户界面层、业务逻辑层、数据访问层

移动应用的成功离不开一个良好的架构设计&#xff0c;在移动应用开发过程中&#xff0c;合理的层次结构对于应用的可维护性、可扩展性和可测试性至关重要。 移动应用的常见层次结构包括用户界面层、业务逻辑层、数据访问层&#xff0c;但是随着跨平台开发框架的不断发展&#…

【低压配电漏电继电器660V/LLJ-100H/AC220V 中性点漏电保护 JOSEF】

LLJ-F(S)系列漏电继电器 系列型号&#xff1a; LLJ-10F(S)漏电继电器LLJ-15F(S)漏电继电器LLJ-16F(S)漏电继电器 LLJ-25F(S)漏电继电器LLJ-30F(S)漏电继电器LLJ-32F(S)漏电继电器 LLJ-60F(S)漏电继电器LLJ-63F(S)漏电继电器LLJ-80F(S)漏电继电器 LLJ-100F(S)漏电继电器LLJ-120…

医学影像检测方法(B超、DR、CT、MRI)

医学影像检测方法 当涉及到医学影像学时&#xff0c;B超&#xff08;超声波检查&#xff09;、DR&#xff08;数字X射线摄影&#xff09;、CT&#xff08;计算机断层扫描&#xff09;和MRI&#xff08;磁共振成像&#xff09;是常见的诊断工具。以下是对这四种影像技术的基本概…

智能门锁揭开新方案:NV340D芯片打造更智能安全的语音解锁体验

智能门锁可以实现一键开锁、实时监控等功能&#xff0c;带来了更便捷、智能的门禁管理体验&#xff0c;逐渐成为人们生活中必不可少的一部分。近年来&#xff0c;随着人工智能技术的不断进步&#xff0c;越来越多的智能门锁开始集成语音控制系统&#xff0c;以提供更加方便的门…

人民大学与加拿大女王大学金融硕士项目——职场不会拒绝一个优秀的金融人才

在金融行业摸爬滚打多年的金融人&#xff0c;通过多年的拼搏与积累&#xff0c;已身处于一个相对舒适、从容的阶段&#xff0c;能沉淀下来再学习的金融人更是令人钦佩。在繁忙的工作之余他们依然保持对学业的热情&#xff0c;以应对瞬息万变的环境发展。人民大学与加拿大女王大…

Unity AssetBundle资源热更插件

Unity AssetBundle资源热更插件 CatAssetManager运行模式 - Package Only新建一个AssetBundle更改AssetBundle的Group分类更改AssetBundle的打包方式 构建规则 加密方式输出AssetBundle 运行模式 - Updateable查看我们热更的Bundle输出目录WebServer目录上传到服务器上选择热更…

u盘数据不见了能恢复吗?可以试试这3种方法

U盘通常体积小巧&#xff0c;存储容量较大&#xff0c;在现代社会中广泛使用。用户可以将各种类型的数据存储到U盘中&#xff0c;如照片、音乐、视频、文档等。但是使用过程中U盘数据无故消失了怎么办呢&#xff1f;在未备份u盘数据的情况下&#xff0c;u盘数据不见了能恢复吗&…

Jenkins发送邮件、定时执行、持续部署

集成Allure报告只需要配置构建后操作即可。但如果是web自动化&#xff0c;或是用HTMLTestRunner生成报告&#xff0c;构建后操作要选择Publish HTML reports&#xff0c;而构建中还要添加Execute system Groovy script插件&#xff0c;内容&#xff1a; System.setProperty(&q…

FT2000+ openEuler 20.03 LTS SP3 NUMA关闭 numa=off 对应用程序申请内存大小的影响,NUMA开关作用

测试程序 编写内存消耗程序 eatMemory.c #define _GNU_SOURCE#include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <string.h> #include <unistd.h> #include <sys/time.h> #include <sched.h> #include <…

k8s入门实战(Pod-Label-Deployment)

k8s入门实战(Pod-Label-Deployment) Pod Pod 是可以在 Kubernetes 中创建和管理的、最小的可部署的计算单元。 k8s架构图&#xff1a; k8s集群启动后&#xff0c;集群中各个组件也是以pod方式运行 [rootmaster ~]# kubectl get pod -n kube-system NAME …

RAR压缩文件如何转换成ZIP格式?

压缩文件有多种不同的格式&#xff0c;有时候因为需求不同&#xff0c;我们需要把RAR压缩文件转换成ZIP格式&#xff0c;那要如何操作呢&#xff1f;下面小编分享2种简单的方法。 方法一&#xff1a; 如果需要转换的RAR压缩包不是很多&#xff0c;我们可以直接把文件名字后缀“…

Spring Boot日志系统大揭秘:从零开始学习Spring Boot日志:常见问题解答和最佳实践

一. 关于 Spring Boot 日志的使用 Spring Boot 日志机制和工具用于记录应用程序的日志信息和追踪应用程序的执行过程。它集成了常用的日志框架&#xff0c;如 Log4j、logback、Java Util Logging等&#xff0c;并提供简单易用的配置方式&#xff0c;让开发人员可以方便地监控应…

【web基础与HTTP协议】

目录 一、Web基础1、域名1.1、域名的概述1.2、域名空间结构1.3、域名注册 2、网页的概念2.1、网页的概述2.2、网址的概述1、URI和URL的区别 二、HTML概述1、HTML 基本标签2、HTML 文件结构如下3、头标签中常用标签4、内容标签中常用标签 三、静态网页与动态网页3.1、目前常用的…

day4--链表内指定区间反转

迭代方法 1. 第m个节点的前一个节点pre和第n个节点&#xff1b; 2. 将第m个节点到第n个节点的链表部分反转&#xff1b; 3. 将pre节点的next指向反转后链表的头节点&#xff0c;将反转后链表的尾节点的next指向n1节点。 /*** struct ListNode {* int val;* struct ListNode…

hive如何实现oracle中复杂的update sql

hive3.1有update语法&#xff0c;但是目前没用还是采用的非事务表&#xff0c;所以我们用其他的办法来解决hive的update问题 简单的update oracle update student set namecclovezbf where id1 hive insert overwrite table student select id, if(id1,cclovezbf,name) n…

【正点原子STM32连载】 第十九章 窗口门狗(WWDG)实验摘自【正点原子】STM32F103 战舰开发指南V1.2

1&#xff09;实验平台&#xff1a;正点原子stm32f103战舰开发板V4 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id609294757420 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十九…