开发背景

在公网部署多个服务时,使用 Uptime Kuma 监控是较为通用的方案。但在日常使用中,频繁打开网页或手机端查看服务运行状态并不高效。

为实现服务状态的直观展示,本项目基于 ESP8266 开发板与 0.96 寸 OLED 显示屏,设计了一款桌面监控终端。

该终端通过定期拉取 Uptime Kuma 公开页 API,实现服务状态与在线率的实时监控,同时集成 NTP 校时与农历历法显示功能,兼具桌面时钟的作用。

功能介绍

设备上电并完成初始化后,将在以下两个页面之间进行 15 秒定时轮播,以避免 OLED 屏幕烧屏:

  1. 服务状态页面:展示预设监控项的名称、当前在线状态(用图形化标志 √ / × / ?来表示)以及 24 小时在线率。

  2. 时钟与万年历页面:显示24小时制时间、公历、星期以及农历月日。

异常处理与稳定性设计

  • 校时容错:优先通过 NTP 同步北京时间;若 NTP 响应超时,系统自动切换至基于系统运行时间的后备机制,保证页面不空白,待网络恢复后自动重新校准。

  • 数据缓存:设置数据有效周期,避免不必要的网络请求。Uptime Kuma 状态每 2 分钟轮询一次;农历 API 仅在跨夜变更时触发 1 次请求,最大限度节省 API 额度与开销。

硬件架构与接线方案

硬件清单

  • 主控:ESP8266 开发板(NodeMCU / WeMos D1 mini)

  • 显示屏:0.96 寸 SSD1306 OLED 显示屏(I2C 总线接口)

  • 供电方式:USB 5V 稳压输入

硬件接线映射

显示屏与开发板通过 I2C 接口通信,接线关系如下:

ESP8266-UptimeKuma-Monitor_wiring-diagram.jpg

ESP8266 引脚

SSD1306 OLED 引脚

信号说明

3.3V

VCC

电源正极

GND

GND

电源地

D2 (GPIO4)

SDA

I2C 数据线

D1 (GPIO5)

SCL

I2C 时钟线

编译环境要求

在 Arduino IDE 中编译本代码时,请确保相关依赖库版本一致,避免因接口变更导致编译报错:

  • ESP8266 Core:2.7.4

  • U8g2:2.36.19

  • ArduinoJson:7.2.0(必须为 V7.x 版本,代码语法不兼容 V6.x)

代码设计与实现思路

  • GUI 绘制:使用 U8g2 库完成文本与图形的点阵渲染。

  • JSON 解析:使用 ArduinoJson 7.x 库进行 HTTP 响应数据的解析。

技术解析

(1)静态监控项配置

ESP8266 的可用 SRAM 资源较为有限。若采用动态解析 API 结构来自动生成监控项列表,将引入较为庞大的 JSON AST 解析树,极易引发堆内存溢出及异常重启。

因此,本项目在设计上将监控项数量固定为 3 个,通过在编译期配置监控项 ID(monitorIds)与显示名称(monitorNames),以保障系统长效稳定地运行。

(2)多 NTP 服务端冗余配置

针对单 NTP 服务器在特定网络环境下容易超时的问题,代码中配置了多个国内 NTP 服务器节点,并增加了重试等待机制,提高了系统初始化的校时成功率。

(3)内存优化的 JSON 解析策略

Uptime Kuma 的 /api/status-page/heartbeat/{slug} 接口返回数据约 3KB。直接完整反序列化会对 ESP8266 产生内存压力。所以我使用 deserializeJson(doc, https.getStream()) 直接从网络流反序列化,避免先将完整响应存入内存,配合 DynamicJsonDocument 将文档内存上限控制在 4096 字节以内。

(4)中文字符的点阵取模处理

由于加载完整中文字库会挤占大部分 Flash 与 RAM 资源,项目采用按需取模策略:仅对必要显示的“农”、“历”、“月”三个汉字进行 16x16 点阵取模,其余监控名称及系统提示统一使用标准 ASCII 字符集呈现。

5. 项目地址

本项目代码及相关硬件接线图已按照 GPLv3 开源协议公开发布。

GitHub 仓库:https://github.com/aisixiongnu/ESP8266-UptimeKuma-Monitor

如果这个项目对你有帮助,欢迎在 GitHub 上点一个 Star,这对我的开源项目会有很大帮助。