
简介这是一套基于树莓派的信息中心项目面向计算机相关专业学生与开发者适用于课程设计、毕业设计、项目初期立项演示也可作为树莓派开发入门进阶的完整样例。项目核心功能是在一体化界面中展示实时时间、天气预报与空气质量数据覆盖数据获取、后端逻辑、前端渲染和界面图标设计等环节。整体打包为zip压缩包共87个文件包含65个PNG图片、7个SVG图标、6个JS脚本、3个CSS样式表另有HTML入口、MD文档和许可证文件PNG与SVG用于界面展示与效果预览JS、CSS和HTML共同实现页面逻辑、布局与交互MD文档提供详细使用说明和开发笔记目录结构清晰便于按模块阅读与二次开发。压缩包仅3.07MB轻量完整。目前已有89人学习资料经导师指导、答辩评审认可代码测试运行成功可直接用于项目演示也适合在此基础上扩展天气预警、历史数据统计等功能提升综合工程实践能力。1. 树莓派信息中心显示时间、天气和空气质量卡在数据源而不是屏幕如果你手里有一块树莓派想把它变成桌面上那个既能看时间、又能瞥一眼今天要不要带伞的信息中心这个项目的落地难度其实不在硬件而在「天气和空气质量数据从哪里来、多久刷一次、断了网怎么办」。树莓派 4B 这块板子跑一个本地网页服务绰绰有余真正要花心思的是数据采集层的容错和屏幕的显示策略。这套方案的实际形态是树莓派上跑一个轻量 Web 服务负责轮询天气和 AQI 接口前端用全屏浏览器把信息渲染到一块屏幕上——无论是 HDMI 显示器还是 RGB 全彩点阵屏都能用同一套数据接口。整个项目解压后通常就是一个 Python 后端、一个前端页面、一份 systemd 配置和部署文档zip 包里的源码只是起点关键是你自己能把它跑起来并调成想要的样子。本文面向两类人拿它做课设/毕设的学生以及想把手头闲置树莓派变成家庭基础设施的从业者。2. 数据采集层选型天气预报和空气质量用什么源、怎么刷、怎么降级2.1 先定数据源天气 API 和 AQI 接口怎么组合信息中心最核心的数据是「天气预报」和「空气质量」。常见做法是使用和风天气的开发者 API它提供免费额度、中文城市名和逐小时预报一次请求同时能拿到天气和空气质量指数对树莓派这种低功耗设备来说少一次网络请求就少一分故障概率。需要注册两个凭据一个 API Key一个城市 IDLocationID。城市 ID 是一串数字编码例如北京是101010100在控制台里按城市名搜索可得。请求天气实况时最关键的几个参数是location城市 ID 或经纬度坐标推荐用 ID避免解析经纬度的误差keyAPI Key每个免费账号有每分钟请求次数限制一般是 40 次/分钟量级lang返回语言设成zh前端就不用再做翻译映射unit温度单位m表示摄氏度空气质量部分和风提供了单独的「空气质量实况」接口返回aqi、category和六项污染物浓度。如果不想接第三方源也可以只用和风一个平台把天气和 AQI 一起拿下来——这是信息中心类项目最常见的组合方式省去维护两个 API 的麻烦。2.2 刷新模型常驻进程比 Cron 更稳初学者常犯的错是把数据拉取做成 Cron 任务每 5 分钟跑一次脚本写文件。这个方案的问题是——Cron 之间没有状态拉取失败时旧数据会被空文件覆盖前端刷新后出现空白。我一般会写一个常驻 Python 进程内部用一个循环控制刷新间隔把每次成功拉取的数据写入本地 JSON 缓存文件并记录数据时间戳。前端永远只读这个缓存文件不直接面对公网 API。这样做的两个好处一是 API 凭据不会暴露在浏览器网络请求里二是断网时缓存文件依然存在前端能显示「数据更新于 x 分钟前」而不是崩溃。刷新间隔的设定温度建议 10 分钟拉一次逐小时预报可以 30 分钟拉一次。AQI 变化更慢城市站点的国控站数据本来就接近小时级更新10 分钟一次的频率绰绰有余。频繁请求既触发限流又让树莓派的 SD 卡多写垃圾日志。2.3 采集模块的最小实现天气与 AQI 拉取并存下面这个collector.py是信息中心数据采集的最小可运行版本包含天气、空气质量和缓存三件事。需要注意其中的 CityID 和 API Key 按实际值替换。#!/usr/bin/env python3 import json import time import urllib.request API_KEY your_qweather_key LOCATION 101010100 CACHE_FILE /home/pi/info-center/cache/now.json INTERVAL 600 # 拉取间隔10 分钟 def fetch(url): req urllib.request.Request(url, headers{User-Agent: info-center/1.0}) with urllib.request.urlopen(req, timeout8) as resp: return json.loads(resp.read().decode(utf-8)) def collect(): weather fetch( fhttps://devapi.qweather.com/v7/weather/now?location{LOCATION}key{API_KEY}langzhunitm ) air fetch( fhttps://devapi.qweather.com/v7/air/now?location{LOCATION}key{API_KEY}langzh ) payload { fetched_at: int(time.time()), weather: weather[now], # 实况温度、天气现象代码、体感温度等 air: air[now], # aqi、category、pm2p5 等 } with open(CACHE_FILE, w) as f: json.dump(payload, f) while True: try: collect() except Exception as e: # 网络异常时不覆盖旧缓存只输出日志 print(fcollect failed: {e}) time.sleep(INTERVAL)代码逻辑很直白fetch函数统一处理 HTTP GET 和超时collect分别请求天气实况和空气质量接口成功后写缓存文件。关键在于except分支——拉取失败时旧缓存文件原样保留前端仍可工作这是整个信息中心容错的地基。参数上timeout8是给树莓派弱网环境留的底线超过 8 秒直接放弃本次拉取避免进程阻塞。2.3.1 AQI 分级换算后端算好前端只负责显示空气质量接口返回的category字段已经给出「优/良/轻度污染」等文字但不同屏幕上显示风格不统一最好在后端把数值和等级一起处理。国标 AQI 分级如下AQI 范围等级建议显示色0-50优绿51-100良黄101-150轻度污染橙151-200中度污染红201-300重度污染紫300严重污染褐红这个映射表在采集时算好存进缓存是为了让前端代码保持简单——树莓派的浏览器渲染性能有限颜色计算放后端页面只管照着值上色。如果你选用的是全彩 LED 点阵屏颜色值还可以进一步映射成 RGB 分量显示效果比黑白屏鲜明得多。3. 展示层设计Web 面板驱动全彩屏而不是直接画点阵3.1 为什么用「Web 面板 全屏浏览器」驱动显示屏信息中心的屏幕有两种主流方案一是直接驱动 RGB 全彩点阵屏HUB75 接口用 Python 库画点阵渲染字符二是运行一个 Web 页面用浏览器全屏模式显示。做课程设计选后者的人明显更多原因很实际——HTML/CSS 排版的灵活性远高于点阵绘图且同一套页面既能在 HDMI 显示器上看也能通过修改分辨率适配点阵屏。这套方案树莓派 4B 跑起来毫无压力Chromium 在全屏 kiosk 模式下只渲染一个静态页面CPU 占用在个位数百分比。真正需要注意的反而是浏览器缓存——页面里引用的 JS 和 CSS 要禁用缓存否则改了代码屏幕不变排查半天以为是程序问题。3.2 后端接口一个/api/now返回全部数据后端我习惯用 Flask 写比 FastAPI 少一层依赖树莓派上装起来省事。核心逻辑是读取缓存文件并作为 JSON 返回同时带一个fetched_at字段给前端计算「数据已更新多久」。from flask import Flask, jsonify, render_template import json import os app Flask(__name__) CACHE_FILE /home/pi/info-center/cache/now.json app.route(/api/now) def api_now(): with open(CACHE_FILE) as f: data json.load(f) return jsonify(data) app.route(/) def index(): return render_template(index.html) if __name__ __main__: app.run(host0.0.0.0, port8000)host0.0.0.0让局域网内其他设备也能访问——在调试阶段你可以用手机打开树莓派 IP 的 8000 端口不用盯着屏幕看。port8000避开 80 和 443 可能需要 root 权限的问题systemd 服务用普通用户就能拉起。3.3 前端渲染时间本地走、天气轮询走前端页面是信息中心的脸面但它的逻辑要足够简单。时间的秒级跳动用 JavaScript 本地计算天气和 AQI 每 60 秒通过fetch(/api/now)拉一次——这个频率与后端 10 分钟的采集频率匹配避免无效请求。async function refreshData() { const res await fetch(/api/now); const data await res.json(); document.getElementById(temp).innerText data.weather.temp °C; document.getElementById(text).innerText data.weather.text; document.getElementById(aqi).innerText data.air.category data.air.aqi; const updated new Date(data.fetched_at * 1000); document.getElementById(updated).innerText 更新于 updated.toLocaleTimeString(zh-CN); } setInterval(refreshData, 60000); refreshData();代码里setInterval(refreshData, 60000)是本页唯一的自动刷新机制。要说明一点页面自身的轮询只负责数据更新秒针跳动需要另一个setInterval单独更新系统时间两者节奏不同不要混在同一个函数里——否则每分钟一次的数据刷新会阻塞秒针更新视觉效果上秒数会卡顿。fetched_at的展示非常关键它让用户明确知道当前信息是什么时候的断网时这个时间戳会逐渐变大但页面依然可用。3.3.1 天气现象代码到图标的映射和风的天气现象代码返回的是英文大写字符串如CLEAR_DAY、CLOUDY、RAIN。前端要做一张映射表将代码对应到iconfont或 SVG 图标而不是直接显示英文。这是把信息中心做好看的关键细节。映射表通常是几十行 JavaScript Object把CLEAR_DAY、CLEAR_NIGHT、PARTLY_CLOUDY_DAY等常见代码映射为图标类名。4. 树莓派 4B 部署无屏幕安装、开机自启与断网兜底4.1 无屏幕安装 Raspberry Pi OS 的预设参数大多数人手头没有多余的 HDMI 显示器给树莓派用无屏幕安装是刚需。用 Raspberry Pi Imager 烧录系统时会弹出「齿轮」图标里面有四个关键项要预设开启 SSH、设置用户名密码、配置 WiFi、设置主机名为info-pi。这几个参数直接决定了你能否在插电后立刻用 SSH 连上去。烧录完成后boot分区下会自动生成userconf.txt和wpa_supplicant.confRaspberry Pi OS Bookworm 及以后版本推荐用 Imager 预设而非手动创建避免写错格式。WiFi 频段注意选 2.4GHz树莓派 4B 虽然支持 5GHz但某些 AP 下 5GHz 信号在设备启动阶段不稳定无屏幕部署时 2.4GHz 成功率明显更高。之后全流程操作都走 SSH部署过程不再需要额外的键盘和屏幕。4.2 安装依赖Python 环境和 Chromium 全屏参数SSH 登录后先做两件事创建虚拟环境装 Flask确认 Chromium 已安装。Raspberry Pi OS 桌面版自带 Chromium但如果你烧的是 Lite 版需要手动安装并安装轻量窗口管理器。树莓派跑 kiosk 模式的常见搭配是无桌面启动 Chromium 直接占满 framebuffer但这对项目课设来说过于折腾桌面版保持开机进入桌面、再让 Chromium 自启全屏是最省事的方案。Chromium 的全屏参数有讲究建议用一个专门的启动脚本把下面几个参数写死chromium-browser --kiosk \ --noerrdialogs \ --disable-infobars \ --disable-session-crashed-bubble \ --check-for-update-interval31536000 \ http://127.0.0.1:8000各参数的作用--kiosk隐藏地址栏和标签栏页面占满全屏并禁用 F11 退出--noerrdialogs去掉崩溃恢复弹窗否则断电重启后屏幕会停在「未正确关闭」的确认框上信息中心就变成了死屏--disable-infobars消除「Chrome 正被自动化控制」的提示条。--check-for-update-interval设为一年的作用是避免更新弹窗打断显示树莓派上 Chromium 的自动更新检查既无必要又影响稳定性。4.3 systemd 注册两个服务并设置开机顺序信息中心需要两个后台服务数据采集collector和 Web 服务web。做一个directory单位把两个服务组起来After、Requires控制依赖关系Restartalways保证进程崩溃后自动拉起。[Unit] DescriptionInfo Center: collector web [Service] Userpi WorkingDirectory/home/pi/info-center ExecStart/home/pi/info-center/venv/bin/python collector.py Restartalways RestartSec5 [Install] WantedBymulti-user.targetRestartSec5的含义是崩溃后等 5 秒再拉起重试给 DNS 和网络栈留恢复时间WorkingDirectory必须显式指定否则相对路径的缓存文件找不到。Web 服务用同样结构写一个独立 unit只是ExecStart换成 Flask 启动命令。4.3.1 树莓派 4B 的电源与散热对稳定性的影响这是一个常被忽略的坑树莓派 4B 对供电质量敏感劣质电源在 WiFi 和 HDMI 同时开启时会出现瞬时欠压轻则屏幕花屏重则 systemd 服务被内核 OOM 杀掉。信息中心是 7x24 小时运行的设备务必使用 5V 3A 以上的正规电源并加装散热片——实测无散热片时 4B 的 CPU 在持续渲染下会到 80°C 以上触发降频后页面滚动明显卡顿。4.3.2 断网降级让信息中心变成离线钟表断网兜底分两层数据层已经在collector.py里通过异常不覆盖缓存实现了降级显示层需要在页面上给「数据更新时间」一个显眼的样式。如果超过 30 分钟没有更新把时间戳变红页面主体依然显示时间——此时它退化成一个纯时钟这是信息中心可以接受的底线状态。要做单点恢复探测只需在采集进程里加一个小逻辑连续三次拉取失败后把network_down: true写入缓存前端据此调暗天气和 AQI 区域引导视线到时间上。5. 验证信息中心可用的几个手段接口探活、页面恢复、硬件状态5.1 用curl快速定位故障层信息中心出问题第一件事不是看屏幕而是用 SSH 连上去分层排查。三个命令按顺序打curl -s http://127.0.0.1:8000/api/now | head -c 300 systemctl status info-center curl -s http://127.0.0.1:8000/ | grep -o title.*/title第一条命令验证 Web 服务和采集数据链路是否正常输出一段 JSON 就说明核心链路没问题第二条看 systemd 认为服务是否活着第三条验证页面本身可访问。如果第一条返回空但第三条正常问题出在采集进程写缓存失败去看collector日志。如果三条都不通大概率是 Web 服务没起来直接journalctl -u info-center -b -n 20看最后二十行错误。5.2 屏幕黑屏的恢复技巧给 Chromium 加看门狗某些情况下 Chromium 进程还在但渲染卡死表现为屏幕定格不刷新。常见做法是在采集进程里顺带扮演看门狗角色每轮拉取数据时同时请求一次http://127.0.0.1:8000/api/now如果连续两次超时就通过subprocess杀掉 Chromium 进程并重新拉起。这比 systemd 监控更可靠因为 systemd 只看进程是否存在而看门狗能感知渲染是否真正响应。5.3 硬件层面的健康检查树莓派 4B 长时间运行的硬件指标建议记录在案vcgencmd measure_temp看 CPU 温度vcgencmd get_throttled看是否发生欠压降频。返回值不是0x0时就该换电源了。给信息中心加个简单的健康检查接口把这些指标一并输出到/api/health前端隐藏显示但你在手机上随时能拉出来看——排查「半夜屏幕黑掉」这类问题时这个接口能直接告诉你那晚到底是欠压、过热还是 WiFi 断开。如果解决了这些问题再回头看看采集进程的日志里有没有反复出现的超时异常信息中心的稳定性就是这样一处处抠出来的。本文还有配套的精品资源点击获取