在物联网和网络日益融合的世界中,创建实时监控界面的能力变得至关重要。通过这个实践教程,我们将探索创建一个完整的交通信号灯监控系统,结合 Zephyr OS 物联网的强大功能与现代网络技术。这个项目将作为一个具体示例来理解实时物联网监控的挑战和解决方案。
注意:作为 Zephyr OS 专家,我可以为您的物联网开发项目提供支持。如果您有任何关于 Zephyr OS 的问题或想讨论您的嵌入式开发需求,请随时通过电子邮件或 LinkedIn 或 GitHub 与我联系。
本项目的完整源代码可在 GitHub 上获取。
文章大纲
-
项目概述
-
物联网部分:交通信号灯控制器
- Zephyr OS 简介
- 控制器的 C++ 实现
- 服务器通信
-
后端:服务器和通信
- 使用 Bun 的 HTTP API
- 实时 WebSocket 服务器
- 使用 Redis 进行状态管理
-
前端:监控界面
- 使用 Next.js 15 构建
- 实时 React 组件
- 状态和更新管理
-
基础设施和部署
-
进一步探索
简介
物联网设备的实时监控带来了独特的挑战,从状态管理到双向通信。我们的互联交通信号灯项目完美地说明了这些问题:如何确保物理设备和网络界面之间的可靠同步,同时保持最佳性能?
项目目标
这个教育项目旨在:
- 展示物联网和现代网络技术的集成
- 探索实时通信模式
- 实践全栈开发最佳实践
- 理解物联网监督的挑战
全局架构
我们的系统围绕四个主要组件构建:
- 物联网控制器: 使用 Zephyr OS 和 C++ 开发,模拟交通信号灯控制器
- API 网关: 用于控制器通信的 HTTP 服务器
- WebSocket 服务器: 确保状态变化的实时分发
- Web 界面: 用于可视化和控制的 Next.js 应用程序
关于模拟的重要说明: 在本项目中,我们出于教育目的在 Docker 容器中模拟物联网设备。控制器仅记录状态变化。在实际部署中,该控制器将安装在实际的物联网设备上(如 Raspberry Pi Pico)并通过其 GPIO 物理控制交通信号灯。
使用 Raspberry Pi Pico 的示例
Raspberry Pi Pico 是实际条件下实施此项目的绝佳选择,因为:
- 它官方支持 Zephyr OS
- 它有用于控制交通信号灯 LED 的 GPIO
- 它可以通过各种适合户外部署的长距离通信模块(LoRaWAN、NB-IoT、LTE-M)连接到网络
- 它的成本非常实惠(约 5 欧元)
要从我们的模拟转移到实际部署,您需要:
- 用 GPIO 命令替换日志
- 根据部署环境调整网络配置以适应 WiFi 或长距离通信模块(LoRaWAN、NB-IoT、LTE-M)
- 管理电源供应和弹性
- 添加保护外壳
1. 项目概述
全局架构
我们的交通信号灯监控系统依赖于现代分布式架构,旨在确保物联网设备和用户界面之间的可靠实时通信。
数据流
-
物联网层级
- 基于 Zephyr OS 的交通信号灯控制器管理灯光状态
- 在我们的实现中,状态变化通过 HTTP 传输到 API 网关,但也可以使用其他协议:
- MQTT 用于更轻量和优化的物联网通信
- CoAP 用于受限网络
- LoRaWAN 用于长距离通信
- gRPC 用于提高性能
- 控制器与服务器保持稳定连接
-
后端层级
- API 网关接收更新并将其存储在 Redis 中
- Redis 作为集中式状态存储
- WebSocket 服务器订阅 Redis 事件
- 变更实时广播给已连接的客户端
-
前端层级
- Next.js 应用程序建立 WebSocket 连接
- React 组件自动更新
- 界面显示实时灯光状态
使用的技术
物联网端
后端和通信
前端
学习目标
本项目旨在涵盖现代物联网和网络开发的几个重要方面:
1. 嵌入式编程
- 使用 Zephyr OS 进行物联网开发
- C++ 中的状态和转换管理
- 嵌入式设备的网络通信
2. 分布式架构
- 异构系统之间的通信
- 使用 Redis 的分布式状态管理
- 实时消息传递模式
3. 现代网络开发
- 使用 Next.js 的六边形架构
- 高性能 React 组件
- TypeScript 和强类型
4. DevOps 和基础设施
- 使用 Docker 容器化
- 自动化脚本
- 监控和日志记录
在接下来的章节中,我们将详细探讨系统的每个组件,从基于 Zephyr OS 的物联网控制器开始。
2. 物联网部分:交通信号灯控制器
Zephyr OS 简介
Zephyr OS 是一个开源实时操作系统(RTOS),特别适合嵌入式和物联网系统。在我们的项目中,它提供了几个关键优势:
- 实时管理: 完美适合精确的交通信号灯控制
- 强大的网络栈: 原生 TCP/IP 协议支持
- 减少内存占用: 适合受限设备
- 现代 C++ 支持: 支持面向对象编程
控制器实现
我们的交通信号灯控制器使用现代 C++ 实现,利用 Zephyr OS 功能进行高效的状态管理和通信。
代码结构
状态管理
服务器通信
与后端服务器的通信由专用类使用 Zephyr 的 HTTP API 处理。
HTTP 客户端
日志记录和监控
交通信号灯管理算法
在 main.cpp
中实现的算法以安全和协调的方式管理交通信号灯周期。我们选择了一个简单且具有示范性的实现,可以针对更复杂的用例进行增强。
-
系统初始化
-
主循环
- 系统在南北和东西轴之间交替
- 每个周期包括三个阶段:
- 绿灯(30秒)
- 黄灯(5秒)
- 红灯带安全延迟(2秒)
-
状态变更管理
-
异步通信
- 专用线程处理 HTTP 状态变更发送
- 事件通过
k_msgq
排队
- HTTP 线程异步处理它们
-
安全性和稳健性
- 轴变更之间的安全延迟
- 通信错误处理
- 事件日志记录用于监控
改进路径
这个基本实现可以通过以下方式增强:
-
可定制场景
- 基于时间的持续时间配置
- 特殊模式(夜间、紧急、事件)
- 实时交通适应
-
高级交通管理
-
动态配置
要实现这些改进,我们需要:
- 添加场景抽象层
- 实现动态配置系统
- 集成传感器和复杂业务规则
- 开发更完整的控制 API
这个简单版本仍然非常适合演示基本的物联网和实时通信概念。
项目配置
prj.conf 文件为我们的项目配置 Zephyr OS 功能。此配置启用:
- C++ 和 C++17 标准支持以使用现代语言特性
- 网络功能与 IPv4 和 TCP 用于服务器通信
- 套接字和 HTTP 客户端以发送状态更新
- 日志系统用于调试和监控
这些选项对于我们的物联网控制器通过网络通信并向中央服务器发送交通信号灯状态变化至关重要。
使用 Zephyr OS 的优化编译
与 Linux 等包含许多默认模块和驱动程序的传统操作系统不同,Zephyr OS 使用极简且高度可配置的方法。在编译期间,只有严格必要的组件被包含在最终镜像中:
-
与传统操作系统的区别
- 传统嵌入式 Linux 有几百 MB
- 包含许多未使用的驱动程序和服务
- 启动加载许多多余的组件
- 攻击面更大
-
Zephyr 方法的优势
- 最终镜像仅几百 KB
- 仅包含配置的驱动程序和协议
- 启动几乎瞬时完成
- 攻击面最小
-
精细配置
- 每个功能都是一个 Kconfig 模块
- 依赖关系自动解析
- 优化最大化
- 资源静态分配
这种"从零开始"的方法允许获得高度优化和安全的系统,完全适应物联网约束:
- 有限资源(RAM/Flash)
- 最小能耗
- 快速启动
- 减少攻击面
编译和部署
项目使用 CMake 进行编译:
这个物联网实现说明了几个高级概念:
-
事件驱动编程
- 使用消息队列进行线程间通信
- 定时器用于状态转换管理
-
资源管理
-
稳健性
在下一节中,我们将看到后端如何处理与这些物联网控制器的通信并将更新分发给网络客户端。
3. 后端:服务器和通信
我们的后端由多个服务协同工作,以确保物联网控制器和网络界面之间的顺畅通信。
使用 Bun 的 API 网关
API 网关是物联网控制器的入口点。使用 Bun 实现以获得卓越的性能,它处理 HTTP 请求并维护状态一致性。
请求管理
WebSocket 服务器
WebSocket 服务器确保实时将更新分发给已连接的网络客户端。
服务器实现
使用 Redis 进行状态管理
Redis 在我们的架构中扮演核心角色,既作为消息代理又作为状态存储。
Redis 配置
Redis 订阅者
通信架构
我们的后端实现了几个基本的通信模式:
-
发布/订阅模式
- Redis 作为消息代理
- 生产者和消费者的解耦
- 高效的更新分发
-
网关模式
- 物联网设备的单一入口点
- 数据验证和转换
- 集中式错误处理
-
观察者模式
- 实时变更通知
- WebSocket 连接维护
- 更新分发给客户端
安全性和性能
已实施多项措施以确保安全性和性能:
-
安全性
- 输入数据验证
- 配置的 CORS 头
- 使用 Docker 的网络隔离
-
性能
- 使用 Bun 获得最佳性能
- 持久的 Redis 连接
- 高效的 WebSocket 管理
-
可靠性
在下一节中,我们将探索使用 Next.js 开发的用户界面,它允许可视化和交互我们的交通信号灯系统。
4. 前端:监控界面
我们的系统用户界面使用 Next.js 15 构建,遵循现代开发最佳实践和六边形架构。
前端架构
我们的应用程序遵循六边形架构(端口和适配器)以保持关注点的清晰分离:
适配器实现
适配器通过 WebSocket 处理与后端的通信:
React 组件
主页面
交通信号灯组件
样式和配置
Tailwind 配置
优化和最佳实践
-
性能
- 使用 React 服务器组件
- 渲染优化
- 非关键组件的延迟加载
-
可访问性
- 键盘支持
- 适当的 ARIA 属性
- 优化的颜色对比度
-
可维护性
- 六边形架构
- 使用 TypeScript 的严格类型
- 自动化测试
在下一节中,我们将介绍我们应用程序的基础设施和部署。
5. 基础设施和部署
我们的系统使用 Docker 来确保在所有环境中的一致和可重复部署。
Docker 配置
服务组合
开发脚本
服务管理脚本
开发环境配置
Zephyr 的 Docker 镜像
支持服务
Docker 服务脚本
依赖管理
Next.js 配置
部署最佳实践
-
密钥管理
-
监控
-
安全性
在最后一节中,我们将讨论我们应用程序的测试策略和监控。
6. 进一步探索
为了使这个项目更加健壮和适合生产环境,可以探索几个改进领域:
1. 测试和质量
为确保系统可靠性,我们应该实现:
物联网控制器测试
- 交通信号灯状态机的单元测试
- 网络集成测试
- 错误条件模拟
- 灯光序列验证
前端测试
- 使用 Jest 和 Testing Library 的 React 组件测试
- 使用 Cypress 或 Playwright 的端到端测试
- 使用 Lighthouse 的性能测试
- 可访问性验证
2. 监控和可观察性
为了有效的生产监控,我们应该添加:
-
性能
- 与 Prometheus/Grafana 集成
- 详细的 WebSocket 指标
- 物联网资源监控
-
可靠性
-
安全性
3. 功能改进
系统可以通过以下方式增强:
-
高级界面
-
场景管理
- 基于时间的调度
- 特殊模式(紧急、事件)
- 外部集成 API
-
可扩展性
4. 电池部署的能源优化
对于需要能源自主的项目(偏远地点、无市电区域),需要进行几项优化:
-
电源模式
- 标准模式用于正常运行
- 节能模式用于安静的日子
- 夜间模式带有降低亮度
- 紧急模式用于低电量
-
节能策略
- 状态变更之间的 CPU 休眠
- 网络传输分组
- 动态 LED 亮度调整
-
太阳能供电
- 适当的面板尺寸
- LiFePO4 电池以获得长寿命
- 备用系统
-
电池监控
为了成功部署,建议:
- 持续监控电池健康状况
- 计划预防性更换
- 定期清洁太阳能板
- 实施低电量降级模式
- 提供备用信号
结论
这个项目展示了物联网和现代网络技术的成功集成,创建了一个实时监控系统。主要收获包括:
-
分布式架构
-
现代技术
- 用于物联网的 Zephyr OS
- 用于前端的 Next.js
- 用于实时的 WebSocket
-
最佳实践
这个项目可以作为开发更复杂的物联网应用程序的基础,通过根据您的具体需求调整架构和使用的模式。
实践应用
为了从本教程中获得最大收益并开发您自己的物联网项目,以下是一些实践练习建议:
1. 从小做起
-
简化版本
- 首先创建单个交通信号灯
- 使用不带 WebSocket 的简单 HTTP 服务器
- 在基本网页中显示状态
-
物联网模拟
- 开始时不使用物理硬件
- 用 Node.js 脚本模拟控制器
- 测试通信逻辑
2. 渐进式演进
-
添加 WebSocket
-
集成 Redis
- 首先存储简单状态
- 添加数据持久化
- 实现发布/订阅模式
3. 项目变体
以下是创建您自己版本的一些想法:
-
其他用例
-
替代技术
- 用 ESP32/Arduino 替换 Zephyr OS
- 使用 MQTT 替代 WebSocket
- ...
4. 额外资源
深入了解每个方面:
-
官方文档
-
示例仓库
-
社区
traffic-lights-monitor/tailwind.config.ts
1export default {
2 content: [
3 "./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
4 "./src/components/**/*.{js,ts,jsx,tsx,mdx}",
5 "./src/app/**/*.{js,ts,jsx,tsx,mdx}",
6 "./src/interfaces/**/*.{js,ts,jsx,tsx,mdx}",
7 ],
8 theme: {
9 extend: {
10 colors: {
11 background: "var(--background)",
12 foreground: "var(--foreground)",
13 },
14 borderSpacing: {
15 'road': '16px'
16 },
17 backgroundImage: {
18 'dashed-white': 'repeating-linear-gradient(90deg, white 0 12px, transparent 12px 32px)',
19 'dashed-white-vertical': 'repeating-linear-gradient(0deg, white 0 12px, transparent 12px 32px)',
20 }
21 },
22 },
23 plugins: [],
24}