跳转到内容

HTTPS API数据获取(Node-RED)

HTTPS API数据获取(Node-RED)

本节介绍使用 Node-RED 从 REST API 获取天气数据。电子纸显示屏显示天气数据,该数据先从 API 获取,在 Node-RED 中处理,然后通过 MQTT 发送到 ESP32。完成本节后,你将能够:

  • 在 Node-RED 中配置 HTTP Request 节点
  • 从公共 REST API(OpenWeatherMap)获取数据
  • 处理 API 响应和错误情况
  • 为通过 MQTT 传输到 ESP32 准备数据

开始本节前,请确保:

  • Node-RED 已安装并运行(参见第 9 章)
  • MQTT Broker(Mosquitto)正在运行
  • 基本理解 REST API
  • OpenWeatherMap API 密钥(在 openweathermap.org 免费注册)
[天气 API] ──HTTPS──→ [Node-RED] ──MQTT──→ [ESP32] ──SPI──→ [电子墨水屏]
[调试/日志]

Node-RED 作为中间件:

  1. 定期从 API 获取天气数据
  2. 解析 JSON 响应
  3. 提取相关值(温度、湿度、预报)
  4. 通过 MQTT 将处理后的数据发布到 ESP32

为什么用 Node-RED 而非 ESP32 直接获取?

Section titled “为什么用 Node-RED 而非 ESP32 直接获取?”
考量ESP32 直接获取Node-RED 中间件
API 密钥安全暴露在固件中存储在服务器上
数据处理内存有限完整的 JavaScript
多个显示屏各自独立获取一次获取,多端订阅
错误处理复杂且含延迟使用 catch 节点轻松处理
API 速率限制难以管理集中控制
固件更新API 更改需要更新固件无需更改固件
  1. 访问 openweathermap.org
  2. 点击 Sign In → Create an Account
  3. 注册后,转到 API Keys 标签页
  4. 复制默认 API 密钥(或创建一个新密钥)

重要提示:新 API 密钥可能需要 1-2 小时才能激活。在 Node-RED 中使用前,先在浏览器中测试密钥。

查找你所在位置的纬度和经度:

Terminal window
# 选项 1:使用 latlong.net
https://www.latlong.net/
# 选项 2:使用 OpenWeatherMap 的地理编码 API
# https://api.openweathermap.org/geo/1.0/direct?q={city}&limit=1&appid={API_KEY}

示例:中国北京 → lat: 39.9042, lon: 116.4074

在 Node-RED 中创建一个包含以下节点的新流程:

流程图

[Inject(时间戳)] ─→ [HTTP Request] ─→ [JSON Parse] ─→ [Function] ─→ [MQTT Out]
[Debug]

创建一个 Inject 节点来触发流程:

  • 名称每 30 分钟触发
  • 载荷timestamp
  • 重复interval,每 30 分钟

添加 HTTP Request 节点来获取天气数据:

  • 方法GET
  • URL
https://api.openweathermap.org/data/2.5/weather?lat=39.9042&lon=116.4074&units=metric&appid=YOUR_API_KEY
  • 名称获取天气数据
  • 返回A parsed JSON object

参数说明

  • lat:纬度
  • lon:经度
  • units=metric:以摄氏度返回温度
  • appid:你的 API 密钥

添加 JSON 节点来解析响应:

  • 名称解析 JSON
  • 动作Always convert to JSON object

添加 Function 节点来提取和格式化数据:

// 从 OpenWeatherMap 响应中提取相关数据
const weatherData = {
temperature: msg.payload.main.temp.toFixed(1),
feels_like: msg.payload.main.feels_like.toFixed(1),
humidity: msg.payload.main.humidity,
pressure: msg.payload.main.pressure,
description: msg.payload.weather[0].description,
icon: msg.payload.weather[0].icon,
city: msg.payload.name,
timestamp: new Date().toISOString()
};
// 设置输出为 JSON 字符串,用于 MQTT
msg.payload = JSON.stringify(weatherData);
return msg;

名称格式化天气数据

添加 MQTT Out 节点来发布格式化后的数据:

  • 服务器:选择你的 Mosquitto Broker
  • 主题factory/weather/data
  • QoS1
  • 名称发布天气数据

步骤 4:完整流程 JSON(可直接导入)

Section titled “步骤 4:完整流程 JSON(可直接导入)”

将此 JSON 复制并导入到 Node-RED:

[
{
"id": "trigger",
"type": "inject",
"name": "每 30 分钟触发",
"repeat": "1800",
"crontab": "",
"once": true,
"payload": "",
"payloadType": "date",
"wires": [["http_req"]]
},
{
"id": "http_req",
"type": "http request",
"name": "获取天气数据",
"method": "GET",
"url": "https://api.openweathermap.org/data/2.5/weather?lat=39.9042&lon=116.4074&units=metric&appid=YOUR_API_KEY",
"ret": "obj",
"tls": "",
"wires": [["json_parse"]]
},
{
"id": "json_parse",
"type": "json",
"name": "解析 JSON",
"action": "",
"property": "payload",
"wires": [["format_data"]]
},
{
"id": "format_data",
"type": "function",
"name": "格式化天气数据",
"func": "const weatherData = {\n temperature: msg.payload.main.temp.toFixed(1),\n feels_like: msg.payload.main.feels_like.toFixed(1),\n humidity: msg.payload.main.humidity,\n pressure: msg.payload.main.pressure,\n description: msg.payload.weather[0].description,\n icon: msg.payload.weather[0].icon,\n city: msg.payload.name,\n timestamp: new Date().toISOString()\n};\n\nmsg.payload = JSON.stringify(weatherData);\nreturn msg;",
"wires": [["mqtt_out"]]
},
{
"id": "mqtt_out",
"type": "mqtt out",
"name": "发布天气数据",
"topic": "factory/weather/data",
"qos": "1",
"retain": "false",
"broker": "your_broker_id",
"wires": []
}
]
  1. 在 Node-RED 中点击 部署
  2. 点击 Inject 节点上的按钮手动触发
  3. 检查 Debug 面板的输出:

预期调试输出

{
"temperature": "25.5",
"feels_like": "24.0",
"humidity": 60,
"pressure": 1013,
"description": "scattered clouds",
"icon": "03d",
"city": "London",
"timestamp": "2026-05-17T10:30:00.000Z"
}

使用 MQTT Explorer 或命令行进行验证:

Terminal window
# 订阅天气主题
mosquitto_sub -h localhost -t "factory/weather/data"
# 预期输出(触发后):
# {"temperature":"25.5","humidity":60,"description":"scattered clouds",...}

添加错误处理以防止损坏的数据到达 ESP32:

带错误处理的 Function 节点

// 检查 API 是否返回有效数据
if (!msg.payload || !msg.payload.main) {
// 出错时返回缓存/默认数据
const fallbackData = {
temperature: "--.-",
humidity: "--",
description: "无数据",
error: true,
timestamp: new Date().toISOString()
};
msg.payload = JSON.stringify(fallbackData);
return msg;
}
// 正常处理
const weatherData = {
temperature: msg.payload.main.temp.toFixed(1),
humidity: msg.payload.main.humidity,
description: msg.payload.weather[0].description,
error: false,
timestamp: new Date().toISOString()
};
msg.payload = JSON.stringify(weatherData);
return msg;

在开发期间,使用静态 JSON 以避免达到 API 速率限制:

带静态 JSON 的 Inject 节点

创建一个带有静态天气数据的第二个 Inject 节点:

{
"temperature": "25.5",
"feels_like": "24.0",
"humidity": 60,
"pressure": 1013,
"description": "scattered clouds",
"icon": "03d",
"city": "London",
"timestamp": "2026-05-17T10:30:00.000Z"
}

将其直接连接到 MQTT Out 节点用于离线测试。

  • Node-RED 流程部署无错误
  • API 返回有效的 JSON 数据
  • 数据正确格式化并发布到 MQTT
  • MQTT Explorer 显示已发布的消息
  • ESP32 接收 MQTT 数据(如果已连接)

症状

Error: ETIMEDOUT
Error: "Not found"

解决方案

  1. 检查 API 密钥是否正确
  2. 确认 API 密钥已激活(超过 1 小时)
  3. 检查互联网连接
  4. 验证 URL 参数(lat、lon、units、appid)

症状

Error: Unexpected token

解决方案

  • 在 HTTP Request 节点后直接添加调试节点,查看原始响应
  • 检查 API 是否返回了错误消息而非数据
  • 使用 Catch 节点添加 JSON 解析错误处理

症状

  • MQTT Out 节点显示无错误
  • ESP32 未收到数据

解决方案

  • 验证 MQTT 代理是否正在运行:docker ps | grep mosquitto
  • 检查发布者和订阅者之间的主题名称是否匹配
  • 验证 QoS 设置是否一致
  • 开发期间使用静态测试数据——避免达到 API 速率限制
  • 在 Function 节点中添加错误处理——防止损坏的数据传播
  • 设置 inject 的 “once: true”——部署后立即获取初始数据
  • 不要超过每 10 分钟一次获取频率——遵守 API 速率限制
  • 不要在共享流程中硬编码 API 密钥——使用环境变量
  1. Node-RED 通过 HTTP Request 节点从公共 API 获取天气数据
  2. JSON 数据在 Function 节点中解析和转换
  3. 处理后的数据通过 MQTT 发布到 ESP32
  4. Node-RED 处理错误情况并提供回退数据
  5. 30 分钟更新间隔在数据新鲜度和 API 速率限制之间取得平衡