# MPPT 太阳能充电控制器监控系统 基于 C 语言的 MPPT(最大功率点跟踪)太阳能充电控制器实时监控与数据采集系统。通过 **Modbus TCP** 采集设备运行数据,使用 **Mongoose** 提供 Web 仪表盘与 REST API,并将历史数据持久化到 **SQLite3**,支持多设备监控与远程参数下发。 - 协议标准:DM 系列 ModBus 485 协议 V2.1(Modbus RTU over TCP) - 支持平台:Ubuntu 24.04(x86_64)/ 树莓派 5 8G(aarch64) - 当前版本:v2.4.0 --- ## 目录 - [功能特性](#功能特性) - [系统架构](#系统架构) - [目录结构](#目录结构) - [运行环境](#运行环境) - [快速开始](#快速开始) - [配置说明](#配置说明) - [Web 界面](#web-界面) - [REST API](#rest-api) - [Modbus 协议](#modbus-协议) - [数据库](#数据库) - [systemd 后台部署](#systemd-后台部署) - [文档索引](#文档索引) - [常见问题](#常见问题) - [许可证](#许可证) --- ## 功能特性 - **实时数据采集**:每 2 秒轮询一次设备(可配置),读取电池电压、光伏电压、充电电流、功率、电量、温度、故障码、充电状态、设备类型等全部运行参数。 - **多设备支持**:单网关下最多支持 16 台 MPPT 设备(地址 1~247),可在配置文件中指定设备地址列表。 - **远程参数设置**:通过 Web 界面下发设备参数,自动适配 **FC 0x06(写单寄存器)** 与 **FC 0x10(写多寄存器)**,内置参数范围校验。 - **历史数据存储**:按可配置间隔(默认 10 秒)将数据写入 SQLite3,支持数据保留周期自动清理。 - **历史数据查询**:按时间范围查询,趋势图可视化 + 分页数据表格;默认查询区间为中国时区(UTC+8)前一天至今。 - **Web 仪表盘**:实时监控、历史查询、设备设置三个标签页,响应式布局,浏览器直接访问。 - **可靠连接**:10 秒连接/读写超时(可配置),断线自动重连;TCP 缓冲区残留清理,避免地址不匹配。 - **Web 服务自愈**:HTTP 服务异常退出后自动重新监听,配合 systemd 实现进程级与线程级双重保障。 - **并发安全**:互斥锁保护共享数据与 Socket 收发,串行化轮询线程与写入线程。 --- ## 系统架构 ``` ┌──────────────────────────────────────────────────────────┐ │ mppt_monitor 进程 │ │ │ │ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ │ │ Modbus 轮询 │ │ 数据存储 │ │ 信号处理 │ │ │ │ 线程 │ │ 线程 │ │ SIGINT/TERM │ │ │ │ (2 秒/次) │ │ (10 秒/次) │ │ 优雅退出 │ │ │ └──────┬───────┘ └──────┬───────┘ └──────────────┘ │ │ │ │ │ │ ▼ ▼ │ │ ┌────────────────────────────────┐ ┌──────────────┐ │ │ │ 共享数据 + sock_mutex │ │ SQLite3 DB │ │ │ └────────────────────────────────┘ │ (WAL 模式) │ │ │ ▲ └──────────────┘ │ │ │ sock_mutex │ │ ┌──────┴───────────────────────────────────────────┐ │ │ │ Mongoose HTTP 服务器(自愈线程) │ │ │ │ REST API / 静态文件 www/index.html │ │ │ └──────────────────────────────────────────────────┘ │ └───────────────────────────┬──────────────────────────────┘ │ Modbus TCP (RTU over TCP) ▼ discover.zhonjin.com:40635 (MPPT 设备网关) │ ┌───────────────┼───────────────┐ ▼ ▼ ▼ MPPT #1 MPPT #2 ... MPPT #16 ``` 三个工作线程与一个 HTTP 事件循环: | 线程 | 职责 | 周期 | |------|------|------| | Modbus 轮询线程 | 连接/重连设备、读取 Input/Output 寄存器、更新共享数据 | 2 秒(可配置) | | 数据存储线程 | 将最新数据批量写入 SQLite,清理过期数据 | 10 秒(可配置) | | HTTP 事件循环 | 处理 REST 请求与静态页面,异常自动重启 | 事件驱动 | | 主线程 | 周期打印摘要、等待退出信号 | 10 秒 | --- ## 目录结构 ``` mppt_monitor/ ├── src/ # 应用源代码 │ ├── main.c # 主程序:线程、信号处理、启动编排 │ ├── modbus_client.h/.c # Modbus TCP 客户端(CRC、读写、参数校验) │ ├── web_server.h/.c # Mongoose HTTP 服务与 REST API │ ├── config.h/.c # INI 配置文件解析 │ └── db.h/.c # SQLite3 历史数据存储与查询 ├── www/ │ └── index.html # Web 仪表盘(Chart.js,单文件) ├── lib/ # 第三方库(随仓库提供,无需联网下载) │ ├── cJSON-1.7.19/ # cJSON 1.7.19 │ └── mongoose-7.23/ # Mongoose 7.23 ├── config.ini # 运行时配置文件 ├── Makefile # 构建脚本 ├── INSTALL.md # 快速安装指南 ├── CHANGELOG.md # 变更日志(持续更新) ├── TECHNICAL.md # 技术方案文档(持续更新) └── FAQ.md # 问答归档(持续更新) ``` > 说明:本仓库根目录的 `README.md`、`LICENSE`、`.gitignore` 为仓库级文件;实际工程位于 `mppt_monitor/` 子目录。 --- ## 运行环境 ### 硬件 - 主机:PC / 工控机 / 树莓派 5(建议 4GB 以上内存) - 被控设备:DM 系列 MPPT 太阳能充电控制器(经 Modbus TCP 网关接入) - 网络:主机需能访问设备网关地址与端口 ### 软件 - 操作系统:Ubuntu 24.04 LTS 或 Raspberry Pi OS(64 位) - 编译器:GCC(支持 C11) - 构建工具:GNU Make - 依赖库:SQLite3(运行库 + 开发头文件) - 可选:OpenSSL 3.x(TLS 支持,构建时自动探测) - 浏览器:Chrome / Edge / Firefox(用于访问仪表盘) --- ## 快速开始 ### 1. 安装依赖 **Ubuntu 24.04:** ```bash sudo apt-get update sudo apt-get install -y build-essential make libsqlite3-dev pkg-config # 可选 OpenSSL sudo apt-get install -y libssl-dev ``` **树莓派 5(Raspberry Pi OS 64 位):** ```bash sudo apt-get update sudo apt-get install -y build-essential make libsqlite3-dev pkg-config libssl-dev ``` ### 2. 获取代码并编译 ```bash git clone https://git.zhonjin.com:40717/steven_roc/mppt_monitor.git cd mppt_monitor/mppt_monitor # 工程目录 make ``` 构建产物为 `build/mppt_monitor`。第三方库(cJSON、Mongoose)已随仓库提供,无需联网下载。 常用构建命令: ```bash make # 编译 make clean # 清理构建产物 make run # 编译并运行 make debug # 带调试符号与 AddressSanitizer ``` ### 3. 修改配置 按需编辑 `config.ini`(主要确认设备地址、网关地址、Web 端口)。默认配置: - 网关:`discover.zhonjin.com:40635` - 设备地址:`1` - 轮询间隔:2 秒 - Web 端口:`8085` ### 4. 运行 ```bash ./build/mppt_monitor ``` 启动后浏览器访问: ``` http://<主机IP>:8085 ``` > 若设置了环境变量 `DEPLOY_RUN_PORT`,Web 端口会以该变量为准(用于沙箱/容器部署)。 --- ## 配置说明 配置文件 `config.ini` 采用 INI 格式,分节如下: ```ini [modbus] host = discover.zhonjin.com # 设备网关域名或 IP port = 40635 # 网关端口 timeout_sec = 10 # 连接 / 读写超时(秒) poll_interval_sec = 2 # 轮询间隔(秒) [storage] db_path = mppt_data.db # SQLite 数据库文件路径 interval_sec = 10 # 历史数据存储间隔(秒) retention_days = 365 # 数据保留天数(超过自动清理,0 表示永久) [server] port = 8085 # Web 服务端口(DEPLOY_RUN_PORT 优先) page_size = 20 # 历史查询默认每页条数 [devices] device_addrs = 1 # 设备地址列表,逗号分隔,如 1,2,3 ``` 修改配置后需重启程序生效。 --- ## Web 界面 浏览器访问 `http://<主机IP>:8085`,包含三个标签页: 1. **实时监控(Real-time Monitor)** - 展示各设备电池电压、光伏电压、充电电流、功率、电量、温度、充电状态、故障码等 - 数据按轮询周期自动刷新 2. **历史查询(History Query)** - 日期时间范围选择器,默认中国时区前一天至今 - Chart.js 趋势曲线 + 分页数据表格 3. **设备设置(Device Settings)** - 选择设备与参数,输入值后下发 - 提交前做参数范围校验,写入结果即时提示 --- ## REST API 所有接口返回 `application/json`,并支持 CORS(跨域访问)。 | 方法 | 路径 | 说明 | |------|------|------| | GET | `/api/health` | 健康检查(服务存活、连接状态) | | GET | `/api/status` | 系统运行状态汇总 | | GET | `/api/data` | 所有设备最新实时数据 | | GET | `/api/devices` | 已配置设备列表 | | GET | `/api/settings?device_addr=¶m=` | 查询指定设备指定参数当前值 | | POST | `/api/settings` | 下发设备参数 | | GET | `/api/history` | 历史数据分页查询 | | GET | `/api/history/stats` | 历史数据统计信息 | ### 查询历史数据 ``` GET /api/history?device_addr=1&start=&end=&page=1&page_size=20 ``` ### 下发参数 ```bash curl -X POST http://<主机IP>:8085/api/settings \ -H 'Content-Type: application/json' \ -d '{"device_addr": 1, "param": "battery_type", "value": 4}' ``` 请求字段: | 字段 | 类型 | 必填 | 说明 | |------|------|------|------| | `device_addr` | number | 是 | 设备地址(1~247) | | `param` | string | 是 | 参数标识(见协议寄存器映射) | | `value` | number | 是 | 目标值 | 成功响应: ```json {"success": true, "device_addr": 1, "param": "battery_type", "value": 4} ``` 失败响应: ```json {"success": false, "error": "错误原因"} ``` --- ## Modbus 协议 - 传输方式:Modbus RTU over TCP(RTU 帧封装在 TCP 连接上,帧尾带 CRC-16) - 校验:CRC-16/Modbus(多项式 0xA001,初值 0xFFFF,低字节在前) - 功能码: | 功能码 | 用途 | |--------|------| | 0x04 | 读 Input Register(运行数据,只读) | | 0x03 | 读 Holding/Output Register(可设置参数) | | 0x06 | 写单个 Holding Register(单参数下发,优先使用) | | 0x10 | 写多个 Holding Register(设备不支持 0x06 时回退) | 示例(读 10 个 Input 寄存器,设备地址 1): ``` 请求:01 04 00 00 00 0A 70 0D 响应:01 04 14 01 0C 01 81 00 10 00 07 00 2E 00 14 00 60 00 02 00 01 00 3C E9 F1 ``` 完整寄存器地址表、读写格式、异常码与参数取值范围详见 **TECHNICAL.md** 与协议文档。 **写寄存器双通道自适应策略:** 1. 优先发送 FC 0x06(写单寄存器,响应为请求回显,共 8 字节); 2. 若设备回异常码"功能不支持 / 地址非法",再回退 FC 0x10(写多寄存器,正常响应 8 字节); 3. 每条指令前保留总线空闲间隔,配合 `sock_mutex` 串行化,避免帧交错。 --- ## 数据库 - 引擎:SQLite3,单文件(默认 `mppt_data.db`) - 模式:开启 **WAL**(Write-Ahead Logging),提升并发读写性能 - 优化:在时间与设备地址字段建立索引 - 维护:按 `retention_days` 自动清理过期数据 历史记录表按"设备地址 + 时间戳"存储每次采集的全部参数,供趋势图与分页查询使用。详细表结构见 **TECHNICAL.md**。 --- ## systemd 后台部署 生产环境建议用 systemd 管理进程,实现开机自启与异常自动重启。 1. 创建服务文件 `/etc/systemd/system/mppt-monitor.service`: ```ini [Unit] Description=MPPT Solar Charge Controller Monitor After=network-online.target Wants=network-online.target [Service] Type=simple WorkingDirectory=/opt/mppt_monitor ExecStart=/opt/mppt_monitor/build/mppt_monitor Restart=always RestartSec=5 Environment=DEPLOY_RUN_PORT=8085 [Install] WantedBy=multi-user.target ``` 2. 部署并启用: ```bash sudo cp -r . /opt/mppt_monitor sudo systemctl daemon-reload sudo systemctl enable --now mppt-monitor sudo systemctl status mppt-monitor journalctl -u mppt-monitor -f # 查看日志 ``` > 树莓派部署的完整步骤(含系统烧录、网络、防火墙、时区配置)见 **TECHNICAL.md** 树莓派章节。 --- ## 文档索引 工程目录 `mppt_monitor/` 下提供以下持续更新文档: | 文档 | 内容 | |------|------| | [INSTALL.md](mppt_monitor/INSTALL.md) | 快速安装与运行指南 | | [CHANGELOG.md](mppt_monitor/CHANGELOG.md) | 版本变更与每次 bug 修复详细说明 | | [TECHNICAL.md](mppt_monitor/TECHNICAL.md) | 完整技术方案:架构、协议、API、数据库、编译配置、Ubuntu/树莓派/Docker 部署、故障排查 | | [FAQ.md](mppt_monitor/FAQ.md) | 历史问题与排查结论归档,按分类累计追加 | --- ## 常见问题 - **写入提示 "Empty request body"**:已在新版本修复。POST 需携带合法 JSON 与 `Content-Type: application/json`;新版本含 body 解析回退机制。 - **写入一直失败**:新版本默认使用 FC 0x06 并在需要时回退 FC 0x10,兼容更多固件;请同时确认参数值在允许范围内。 - **读不到数据 / 连接被立即断开**:优先排查网络可达性与服务端 **IP 白名单/授权**。可在主机上执行 `nc -vz discover.zhonjin.com 40635` 检测端口;若 TCP 能连但秒断,多为访问授权限制。 - **历史数据查不到**:确认存储间隔配置、数据库路径可写,并确认查询时间范围内程序在持续运行。 - **编译报 `sqlite3.h: No such file`**:安装开发包 `sudo apt-get install libsqlite3-dev`。 更多排查步骤见 [FAQ.md](mppt_monitor/FAQ.md)。 --- ## 许可证 详见 [LICENSE](LICENSE)。 第三方组件版权归各自所有者: - cJSON 1.7.19 - Mongoose 7.23(注意其商用授权条款) - SQLite3(公有领域) - Chart.js(用于 Web 仪表盘)