mppt_monitor

steven_roc 010a36f0ac feat(android): 新增MPPT Android客户端v1.0.0并推送Gogs il y a 3 jours
assets 2943850534 feat: 升级 mongoose 7.22 → 7.23 il y a 1 mois
mppt_monitor 7963aad1d9 chore: 清理自动同步验证产生的临时配置行 il y a 5 jours
mppt_monitor_android 010a36f0ac feat(android): 新增MPPT Android客户端v1.0.0并推送Gogs il y a 3 jours
.coze f09f650a43 fix: 添加 .coze 配置文件并支持 DEPLOY_RUN_PORT 环境变量动态端口 il y a 2 mois
.gitignore 175cfebd04 Merge remote-tracking branch 'origin/master' il y a 5 jours
LICENSE 995a924ade Initial commit il y a 5 jours
MPPTMonitor-v1.0.0.apk 010a36f0ac feat(android): 新增MPPT Android客户端v1.0.0并推送Gogs il y a 3 jours
README.md 2c9eee7784 docs: 完善README项目说明文档 il y a 4 jours

README.md

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

目录


功能特性

  • 实时数据采集:每 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:

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 位):

sudo apt-get update
sudo apt-get install -y build-essential make libsqlite3-dev pkg-config libssl-dev

2. 获取代码并编译

git clone https://git.zhonjin.com:40717/steven_roc/mppt_monitor.git
cd mppt_monitor/mppt_monitor          # 工程目录
make

构建产物为 build/mppt_monitor。第三方库(cJSON、Mongoose)已随仓库提供,无需联网下载。

常用构建命令:

make            # 编译
make clean      # 清理构建产物
make run        # 编译并运行
make debug      # 带调试符号与 AddressSanitizer

3. 修改配置

按需编辑 config.ini(主要确认设备地址、网关地址、Web 端口)。默认配置:

  • 网关:discover.zhonjin.com:40635
  • 设备地址:1
  • 轮询间隔:2 秒
  • Web 端口:8085

4. 运行

./build/mppt_monitor

启动后浏览器访问:

http://<主机IP>:8085

若设置了环境变量 DEPLOY_RUN_PORT,Web 端口会以该变量为准(用于沙箱/容器部署)。


配置说明

配置文件 config.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=&param= 查询指定设备指定参数当前值
POST /api/settings 下发设备参数
GET /api/history 历史数据分页查询
GET /api/history/stats 历史数据统计信息

查询历史数据

GET /api/history?device_addr=1&start=<unix秒>&end=<unix秒>&page=1&page_size=20

下发参数

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 是 目标值

成功响应:

{"success": true, "device_addr": 1, "param": "battery_type", "value": 4}

失败响应:

{"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:

    [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. 部署并启用:

    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 快速安装与运行指南
CHANGELOG.md 版本变更与每次 bug 修复详细说明
TECHNICAL.md 完整技术方案:架构、协议、API、数据库、编译配置、Ubuntu/树莓派/Docker 部署、故障排查
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。


许可证

详见 LICENSE。

第三方组件版权归各自所有者:

  • cJSON 1.7.19
  • Mongoose 7.23(注意其商用授权条款)
  • SQLite3(公有领域)
  • Chart.js(用于 Web 仪表盘)