
1. 嵌入式设备获取天气数据的必要性在智能家居、农业监测、户外设备等嵌入式应用场景中实时获取天气数据往往是刚需。比如我去年做的智能花盆项目就需要根据当地降雨情况自动调节浇水量。传统方案是直接爬取天气网站但嵌入式设备通常内存有限像树莓派Zero这类设备只有512MB内存根本跑不动浏览器引擎来解析网页。这时候RESTful API的优势就显现出来了。中央气象台的API返回结构化JSON数据体积通常不超过10KBESP8266这种Wi-Fi模块都能轻松处理。实测下来用API获取北京朝阳区的天气数据整个请求响应过程仅需300ms左右比网页解析方案快5倍以上。2. API接口详解与使用准备2.1 接口地址与功能说明中央气象台提供了三个核心接口省份列表接口http://www.nmc.cn/rest/province城市列表接口http://www.nmc.cn/rest/province/{省份代码}天气数据接口http://www.nmc.cn/rest/weather?stationid{城市代码}这里有个坑要注意省份代码并非行政区划代码而是特殊编码规则。比如北京是ABJA拼音首字母但河南却是AHA而不是AHN。建议先把省份列表缓存到设备本地我在项目里是这样存储的typedef struct { char code[4]; // 如ABJ char name[20]; // 如北京市 } Province; Province provinces[] { {ABJ, 北京市}, {AHA, 河南省}, // 其他省份... };2.2 网络连接配置以ESP32为例配置Wi-Fi连接的代码要特别注意重试机制#include WiFi.h void connectWiFi() { WiFi.begin(SSID, password); int retry 0; while (WiFi.status() ! WL_CONNECTED retry 10) { delay(500); Serial.print(.); retry; } if (retry 10) { Serial.println(连接超时); // 这里可以触发设备重启 } }3. 分步实现天气数据获取3.1 获取省份代码首次调用时建议全量获取省份数据。这里给出Arduino平台的HTTP请求示例#include HTTPClient.h String getProvinces() { HTTPClient http; http.begin(http://www.nmc.cn/rest/province); int httpCode http.GET(); if (httpCode HTTP_CODE_OK) { String payload http.getString(); http.end(); return payload; } http.end(); return ; }返回的JSON数据建议用ArduinoJson库解析6.0以上版本支持流式解析特别适合内存受限设备#include ArduinoJson.h void parseProvinces(String json) { DynamicJsonDocument doc(2048); deserializeJson(doc, json); for (JsonObject item : doc.asJsonArray()) { const char* code item[code]; const char* name item[name]; // 存储到本地... } }3.2 获取城市代码获取到省份代码后比如北京是ABJ就可以查询该省下所有城市String getCities(String provinceCode) { String url http://www.nmc.cn/rest/province/ provinceCode; // 后续请求逻辑与省份获取类似... }城市代码的规律性不强建议建立本地映射表。我在项目中使用的是紧凑型存储方案typedef struct { uint16_t code; // 城市代码转成数值 char name[10]; // 城市名称 } City; City beijingCities[] { {54511, 北京}, {54499, 昌平}, // 其他城市... };3.3 获取实时天气数据这是最核心的接口返回数据包含温度、湿度、风力等多项指标。以朝阳区代码54433为例String getWeather(uint16_t cityCode) { String url http://www.nmc.cn/rest/weather?stationid String(cityCode); // 发送HTTP请求... }解析天气数据时需要特别注意温度单位是摄氏度天气图标代码对应关系0晴1多云2阴3雨4雪4. 嵌入式环境优化策略4.1 数据本地缓存方案频繁请求API既耗电又占带宽我的经验是省份/城市数据烧录到设备的ROM中天气数据根据更新频率缓存实时数据每30分钟更新预报数据每天更新2次使用SPIFFS文件系统的缓存示例#include SPIFFS.h void saveWeather(String data) { File file SPIFFS.open(/weather.json, w); file.print(data); file.close(); }4.2 低功耗处理技巧对于电池供电设备我有几个实测有效的方案使用ESP32的深度睡眠模式esp_sleep_enable_timer_wakeup(30 * 60 * 1000000); // 30分钟 esp_deep_sleep_start();压缩传输数据用gzip压缩后数据量减少70%错峰请求在整点后的随机时间发起请求避免服务器拥塞4.3 错误处理与容灾嵌入式设备必须考虑网络不稳定的情况设置超时建议3秒http.setTimeout(3000);实现重试机制最多3次保留最后一次有效数据网络异常时切换备用数据源如DS18B20本地温度传感器5. 完整实现案例5.1 硬件准备清单主控板ESP32-WROOM带Wi-Fi存储4MB SPI Flash显示屏0.96寸OLED可选电源18650电池充放电模块5.2 软件架构设计main.c ├── 网络管理 │ ├── WiFi连接 │ └── HTTP请求 ├── 数据解析 │ ├── JSON处理 │ └── 数据缓存 └── 业务逻辑 ├── 定时任务 └── 异常处理5.3 核心代码片段初始化流程void setup() { Serial.begin(115200); SPIFFS.begin(true); loadConfig(); // 加载本地配置 connectWiFi(); if (!checkProvinceData()) { fetchProvinceData(); } }主循环逻辑void loop() { static uint32_t lastUpdate 0; if (millis() - lastUpdate 30*60*1000) { updateWeather(); lastUpdate millis(); } displayWeather(); delay(1000); }6. 常见问题排查6.1 数据获取失败检查Wi-Fi信号强度RSSI应大于-70dBmSerial.println(WiFi.RSSI());验证API地址是否变更查看HTTP返回码200成功404接口不存在500服务器错误6.2 内存不足问题使用ArduinoJson的流式解析减少字符串拷贝适当增大堆空间ESP32默认约160KB6.3 数据解析异常检查JSON格式是否正确验证字段类型if (!doc[data][real][weather].isNull()) { float temp doc[data][real][weather][temperature]; }注意数值型数据的单位7. 进阶优化方向7.1 多数据源融合可以结合中国天气网、和风天气等备用数据源当主接口不可用时自动切换。我在实际项目中实现了优先级策略首选中央气象台官方数据次选和风天气免费版最后使用本地传感器7.2 预测算法优化在嵌入式设备上实现简单的天气趋势预测// 基于最近3小时温度变化率 float trend (currentTemp - temp3hAgo) / 3; if (trend 0.5) { Serial.println(温度快速上升); }7.3 能耗监控添加电流检测电路实时监控设备功耗float getCurrent() { int adc analogRead(CURRENT_PIN); return adc * 0.001; // 根据分压电阻换算 }