TECHNICAL.md 29 KB

TECHNICAL.md - 技术方案文档

本文档持续更新,记录 MPPT Monitor 的完整技术架构、协议细节、API 设计。


十二、树莓派 5 8G 安装配置指南(兼容 Ubuntu 24.04)

12.1 硬件要求

组件 规格 说明
主板 Raspberry Pi 5 8GB BCM2712 四核 Cortex-A76 @ 2.4GHz
存储 microSD 卡 ≥32GB 或 NVMe SSD 推荐 SSD 提升数据库写入性能
电源 官方 27W USB-C 电源 确保稳定供电
网络 以太网 或 Wi-Fi 用于连接 Modbus 设备和 Web 访问
散热 主动散热风扇 长时间运行必备

12.2 操作系统安装

方式一:Ubuntu 24.04 Server(推荐)

  1. 下载镜像

    # 从 Ubuntu 官网下载 Raspberry Pi 专用镜像
    wget https://cdimage.ubuntu.com/releases/24.04/release/ubuntu-24.04.1-preinstalled-server-arm64+raspi.img.xz
    
  2. 烧录镜像

    # 使用 Raspberry Pi Imager 或 dd 命令
    sudo dd if=ubuntu-24.04.1-preinstalled-server-arm64+raspi.img.xz of=/dev/sdX bs=4M status=progress
    
  3. 首次启动配置

    # 连接显示器和键盘,或通过网络 SSH 登录
    # 默认用户名/密码:ubuntu/ubuntu
    # 首次登录会要求修改密码
    

方式二:Raspberry Pi OS(Debian Bookworm)

# 使用 Raspberry Pi Imager 选择 Raspberry Pi OS (64-bit)
# 或手动下载:https://www.raspberrypi.com/software/operating-systems/

12.3 系统初始化配置

# 1. 更新系统
sudo apt update && sudo apt upgrade -y

# 2. 设置时区(中国)
sudo timedatectl set-timezone Asia/Shanghai

# 3. 设置主机名
sudo hostnamectl set-hostname mppt-monitor

# 4. 配置静态 IP(可选,编辑 /etc/netplan/01-netcfg.yaml)
# network:
#   version: 2
#   ethernets:
#     eth0:
#       dhcp4: no
#       addresses: [192.168.1.100/24]
#       gateway4: 192.168.1.1
#       nameservers:
#         addresses: [8.8.8.8, 114.114.114.114]

# 5. 重启
sudo reboot

12.4 安装编译依赖

# 基础编译工具
sudo apt install -y build-essential gcc make

# SQLite3 开发库
sudo apt install -y libsqlite3-dev

# OpenSSL 开发库(可选,用于 HTTPS)
sudo apt install -y libssl-dev

# 验证安装
gcc --version
sqlite3 --version
pkg-config --libs openssl  # 如果安装了 OpenSSL

12.5 编译项目

# 1. 传输项目文件到树莓派
# 方式一:SCP
scp -r mppt_monitor/ ubuntu@192.168.1.100:~/

# 方式二:Git
git clone <your-repo-url> ~/mppt_monitor

# 2. 进入项目目录
cd ~/mppt_monitor

# 3. 编译
make clean && make

# 4. 验证编译结果
ls -la build/mppt_monitor
file build/mppt_monitor
# 应显示:ELF 64-bit LSB executable, ARM aarch64

12.6 配置文件

# 编辑配置文件
nano config.ini
[modbus]
host = discover.zhonjin.com
port = 40635
timeout_sec = 10
reconnect_interval_sec = 2

[devices]
# 设备地址列表(逗号分隔,1-247)
addresses = 1

[storage]
# 数据存储间隔(秒)
interval_sec = 10
# 数据库文件路径
db_path = mppt_data.db

[web]
# Web 服务端口
port = 8085
# 历史数据分页大小
page_size = 20

12.7 运行服务

# 方式一:直接运行(调试用)
./build/mppt_monitor

# 方式二:后台运行
nohup ./build/mppt_monitor > /var/log/mppt_monitor.log 2>&1 &

# 方式三:systemd 服务(推荐生产环境)
sudo make systemd
sudo systemctl enable mppt-monitor
sudo systemctl start mppt-monitor

# 查看服务状态
sudo systemctl status mppt-monitor

# 查看日志
sudo journalctl -u mppt-monitor -f

12.8 systemd 服务配置

# 创建服务文件
sudo tee /etc/systemd/system/mppt-monitor.service << 'EOF'
[Unit]
Description=MPPT Solar Monitor - DM Series
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/mppt_monitor
ExecStart=/home/ubuntu/mppt_monitor/build/mppt_monitor
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal

# 安全加固
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/home/ubuntu/mppt_monitor

[Install]
WantedBy=multi-user.target
EOF

# 重载 systemd
sudo systemctl daemon-reload

# 启用并启动服务
sudo systemctl enable mppt-monitor
sudo systemctl start mppt-monitor

12.9 防火墙配置

# 如果使用 UFW 防火墙
sudo ufw allow 8085/tcp    # Web 服务端口
sudo ufw allow 22/tcp      # SSH(如果还没开放)
sudo ufw enable

12.10 性能优化

12.10.1 CPU 调度优化

# 设置 CPU 性能模式为 performance
sudo apt install -y cpufrequtils
echo 'GOVERNOR="performance"' | sudo tee /etc/default/cpufrequtils
sudo systemctl restart cpufrequtils

12.10.2 数据库优化

# SQLite3 性能优化(在 db.c 中已配置)
# - WAL 模式:允许读写并发
# - 同步模式:NORMAL(平衡性能和安全性)
# - 缓存大小:2000 页

12.10.3 网络优化

# 优化 TCP 参数(/etc/sysctl.d/99-mppt.conf)
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5
net.core.somaxconn = 1024

# 应用配置
sudo sysctl -p /etc/sysctl.d/99-mppt.conf

12.11 监控和维护

12.11.1 查看运行状态

# 服务状态
sudo systemctl status mppt-monitor

# 实时日志
sudo journalctl -u mppt-monitor -f --since "1 hour ago"

# 资源使用
top -p $(pgrep mppt_monitor)

12.11.2 数据库维护

# 查看数据库大小
ls -lh ~/mppt_monitor/mppt_data.db

# 查看记录数
sqlite3 ~/mppt_monitor/mppt_data.db "SELECT COUNT(*) FROM history_data;"

# 清理旧数据(保留最近 30 天)
sqlite3 ~/mppt_monitor/mppt_data.db "DELETE FROM history_data WHERE created_at < datetime('now', '-30 days');"

# 数据库优化
sqlite3 ~/mppt_monitor/mppt_data.db "VACUUM;"

12.11.3 自动备份

# 创建备份脚本
cat << 'EOF' > ~/mppt_monitor/backup.sh
#!/bin/bash
BACKUP_DIR="/home/ubuntu/backups"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
cp ~/mppt_monitor/mppt_data.db "$BACKUP_DIR/mppt_data_$DATE.db"
# 保留最近 7 天的备份
find $BACKUP_DIR -name "mppt_data_*.db" -mtime +7 -delete
EOF
chmod +x ~/mppt_monitor/backup.sh

# 添加 cron 定时任务(每天凌晨 2 点备份)
crontab -e
# 添加:0 2 * * * /home/ubuntu/mppt_monitor/backup.sh

12.12 故障排查

12.12.1 服务无法启动

# 检查端口占用
sudo ss -tuln | grep 8085

# 检查日志
sudo journalctl -u mppt-monitor -n 100

# 手动运行查看错误
./build/mppt_monitor

12.12.2 Modbus 连接失败

# 测试网络连通性
ping discover.zhonjin.com

# 测试端口连通性
nc -zv discover.zhonjin.com 40635

# 检查 DNS 解析
nslookup discover.zhonjin.com

12.12.3 数据库锁定

# 检查数据库锁
sqlite3 ~/mppt_monitor/mppt_data.db "PRAGMA busy_timeout = 5000;"

# 如果数据库损坏,尝试恢复
sqlite3 ~/mppt_monitor/mppt_data.db ".recover" > recovered.sql

12.13 升级指南

# 1. 停止服务
sudo systemctl stop mppt-monitor

# 2. 备份数据
cp ~/mppt_monitor/mppt_data.db ~/mppt_monitor/mppt_data.db.backup

# 3. 拉取新代码
cd ~/mppt_monitor
git pull

# 4. 重新编译
make clean && make

# 5. 启动服务
sudo systemctl start mppt-monitor

# 6. 验证
curl http://localhost:8085/api/health

十三、Ubuntu 24.04 x86_64 安装配置(PC/服务器)

13.1 系统要求

组件 最低配置 推荐配置
CPU 双核 2.0GHz 四核 3.0GHz+
内存 2GB 4GB+
存储 10GB SSD 50GB+
网络 100Mbps 1Gbps

13.2 安装步骤

# 1. 安装 Ubuntu 24.04 Server
# 从 https://ubuntu.com/download/server 下载 ISO

# 2. 安装依赖
sudo apt update && sudo apt upgrade -y
sudo apt install -y build-essential gcc make libsqlite3-dev libssl-dev

# 3. 编译项目
cd ~/mppt_monitor
make clean && make

# 4. 运行服务
sudo make systemd
sudo systemctl enable mppt-monitor
sudo systemctl start mppt-monitor

13.3 Docker 部署(可选)

# Dockerfile
FROM ubuntu:24.04

RUN apt update && apt install -y \
    build-essential gcc make libsqlite3-dev \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /app
COPY . .
RUN make clean && make

EXPOSE 8085
CMD ["./build/mppt_monitor"]
# 构建和运行
docker build -t mppt-monitor .
docker run -d --name mppt -p 8085:8085 -v $(pwd)/data:/app mppt-monitor

一、系统概述

1.1 项目目标

开发一个轻量级 C 语言嵌入式监控程序,通过 Modbus RTU over TCP 协议读取 MPPT 太阳能充电控制器的实时数据,并通过 HTTP REST API 对外提供 JSON 格式的实时数据接口。支持历史数据定时存储到 SQLite3 数据库,并提供带趋势图表的历史数据查询页面。

1.2 架构总览

┌─────────────────────────────────────────────────────────┐
│                    MPPT Monitor                          │
│                                                          │
│  ┌──────────────┐     ┌──────────────┐                  │
│  │ Modbus TCP   │     │ Mongoose HTTP│                  │
│  │ Client       │     │ Server :8085 │                  │
│  │ (Thread)     │     │ (Main Thread)│                  │
│  └──────┬───────┘     └──────┬───────┘                  │
│         │                     │                          │
│         ▼                     ▼                          │
│  ┌──────────────────────────────────┐                   │
│  │     Shared Data (mppt_data_t)    │                   │
│  │     Protected by pthread_mutex   │                   │
│  └──────────┬───────────────────────┘                   │
│             │                                           │
│             ▼                                           │
│  ┌──────────────────────┐                              │
│  │  SQLite3 Database    │                              │
│  │  (历史数据存储)       │                              │
│  └──────────────────────┘                              │
│                                                          │
└─────────────────────────────────────────────────────────┘
         │                           │
         ▼                           ▼
  ┌─────────────┐           ┌─────────────────┐
  │ MPPT Device │           │ Web Browser /   │
  │ TCP:40635   │           │ REST Client     │
  └─────────────┘           └─────────────────┘

1.3 线程模型

线程 职责 说明
Main Thread Mongoose HTTP 事件循环 处理 HTTP 请求、Web 服务器看门狗
Modbus Thread Modbus 数据采集 每 2 秒读取一次寄存器,自动重连

二、Modbus 通信协议

2.1 连接信息

参数 值
协议 Modbus RTU over TCP(原始 TCP Socket)
目标地址 discover.zhonjin.com
目标端口 40635
从机地址 0x01
功能码 0x04(读输入寄存器)
起始寄存器 0x0000(对应 30001)
寄存器数量 10(30001~30010)
超时时间 10 秒
轮询间隔 2000ms

2.2 请求帧格式

发→ 01 04 00 00 00 0A 70 0D

字节解析:
  01       - 从机地址 (Slave Address)
  04       - 功能码: 读输入寄存器 (Read Input Registers)
  00 00    - 起始寄存器地址 (0x0000 = 30001)
  00 0A    - 寄存器数量 (10个)
  70 0D    - CRC-16 校验 (低字节在前)

2.3 响应帧格式

收← 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

字节解析:
  01       - 从机地址
  04       - 功能码
  14       - 数据长度 (20字节 = 10个寄存器 × 2字节)
  01 0C    - 寄存器1: 电池电压 (268 → 26.8V)
  01 81    - 寄存器2: 光伏电压 (385 → 38.5V)
  00 10    - 寄存器3: 光伏充电电流 (16 → 1.6A)
  00 07    - 寄存器4: 累计发电量 (7 → 0.7kWh)
  00 2E    - 寄存器5: 机器温度 (46 → 46°C)
  00 14    - 寄存器6: 故障代码 (20 → 正常)
  00 60    - 寄存器7: 电池电量 (96 → 96%)
  00 02    - 寄存器8: 电池串数 (2)
  00 01    - 寄存器9: 充电状态 (1 → 充电中)
  00 3C    - 寄存器10: 设备类型 (60)
  E9 F1    - CRC-16 校验

2.4 寄存器映射表

寄存器 地址 参数名 原始值 实际值 单位 说明
30001 0x0000 电池电压 raw/10 V 24V系统正常范围 20-30V
30002 0x0001 光伏电压 raw/10 V 光伏板输出电压
30003 0x0002 光伏充电电流 raw/10 A 当前充电电流
30004 0x0003 累计发电量 raw/10 kWh 历史总发电量
30005 0x0004 机器温度 raw °C 控制器温度
30006 0x0005 故障代码 raw - 0/20=正常
30007 0x0006 电池电量 raw % SOC 百分比
30008 0x0007 电池串数 raw - 保留字段
30009 0x0008 充电状态 raw - 0=空闲 1=充电 2=吸收 3=浮充
30010 0x0009 设备类型 raw - 设备型号代码

2.5 CRC-16/Modbus 算法

多项式: 0xA001 (0x8005 的反转)
初始值: 0xFFFF
字节序: 低字节在前 (Little-Endian on wire)

算法流程:
  1. 初始化 CRC = 0xFFFF
  2. 对每个字节:
     a. CRC ^= byte
     b. 循环 8 次:
        - 如果 CRC 最低位为 1: CRC = (CRC >> 1) ^ 0xA001
        - 否则: CRC >>= 1
  3. 返回 CRC 值

三、HTTP REST API

3.1 服务配置

参数 值
监听地址 0.0.0.0
监听端口 8085
HTTP 库 Mongoose 7.22
JSON 库 cJSON 1.7.19

3.2 API 端点

GET /api/data - 获取完整 MPPT 数据

响应示例:

{
  "timestamp": "2026-08-04T15:30:00",
  "data_valid": true,
  "battery": {
    "voltage": 26.8,
    "soc": 96,
    "string_count": 2
  },
  "pv": {
    "voltage": 38.5,
    "current": 1.6,
    "power": 61.6
  },
  "cumulative_energy_kwh": 0.7,
  "device": {
    "temperature": 46.0,
    "fault_code": 20,
    "fault_desc": "Normal",
    "charge_state": 1,
    "charge_state_desc": "Charging (Bulk)",
    "device_type": 60
  },
  "raw_registers": [268, 385, 16, 7, 46, 20, 96, 2, 1, 60]
}

GET /api/status - 获取连接与设备状态

响应示例:

{
  "connection": {
    "state": "connected",
    "host": "discover.zhonjin.com",
    "port": 40635,
    "reconnect_count": 0
  },
  "device_online": true,
  "consecutive_failures": 0,
  "last_update": "2026-08-04T15:30:00"
}

GET /api/health - 健康检查

响应:

{"status": "ok"}

GET / - HTML 监控面板

返回内嵌的 HTML 仪表盘页面,每 2 秒自动刷新数据。


四、Mongoose 7.22 API 迁移指南

4.1 新旧 API 对比

旧 API (7.x 早期) 新 API (7.22) 说明
mg_http_match_uri(hm, "/path") mg_match(hm->uri, mg_str("/path"), NULL) URI 匹配
struct mg_str { const char *ptr; size_t len; } struct mg_str { char *buf; size_t len; } 字符串结构体
hm->uri.ptr hm->uri.buf 访问字符串数据

4.2 关键变更

  1. URI 匹配: 使用 mg_match() 替代 mg_http_match_uri()

    // 旧方式(已废弃)
    if (mg_http_match_uri(hm, "/api/data")) { ... }
    
    // 新方式(mongoose-7.22)
    if (mg_match(hm->uri, mg_str("/api/data"), NULL)) { ... }
    
  2. 字符串结构体: ptr 改为 buf

    // 旧方式
    const char *data = hm->uri.ptr;
    
    // 新方式
    char *data = hm->uri.buf;
    
  3. 通配符匹配: 支持 ?(单字符)、*(不含/)、#(含/)

    // 匹配 /api/ 下所有路径
    mg_match(hm->uri, mg_str("/api/#"), NULL)
    

五、错误处理与容错机制

5.1 Modbus 连接容错

连接失败 → 等待 2 秒 → 重试
读取超时 → 记录失败计数
连续 3 次失败 → 断开连接 → 重新建立连接
DNS 解析失败 → 等待后重试

5.2 Web 服务器容错

主循环每 5 秒检查一次 Web 服务器状态
如果监听连接丢失 → 自动重新启动 HTTP 监听
SIGPIPE 信号被忽略 → 防止客户端断开导致进程退出

5.3 数据一致性

Modbus 线程写入数据时使用 pthread_mutex 保护
Web 线程读取数据时加锁读取
确保 HTTP 响应中的数据不会在序列化过程中被修改

5.4 设备参数写入(Web → Modbus)与并发保护(v2.3.3)

Web 设备参数设置(POST /api/settings → modbus_write_register())与 Modbus 轮询线程共用同一个 TCP Socket。为避免帧交错导致的写入失败/数据错乱, 采用如下并发模型:

┌─────────────────────────────────────────────────────────────┐
│  sock_mutex (pthread_mutex_t)  串行化所有 Socket 收发操作      │
├─────────────────────────────────────────────────────────────┤
│  轮询线程: read_input/read_output → modbus_send_recv()        │
│           (内部加锁: drain → send → recv → 解锁)              │
│  写入线程: modbus_write_register()                            │
│           (加锁: drain → send(frame) → recv(resp) → 解锁)     │
└─────────────────────────────────────────────────────────────┘

关键点:

  • 每条 Modbus 命令(发送 + 接收完整响应)都在一次性持锁窗口内完成,杜绝并发帧交错。
  • data_mutex 负责设备数据快照的读写一致性,与 sock_mutex 职责分离,避免死锁。

5.5 写多寄存器(FC 0x10)响应帧规范(v2.3.3 修复)

Modbus 功能码 0x10(写多个寄存器)的正常响应帧为 8 字节:

字节 内容 说明
0 设备地址 回显请求地址
1 功能码 0x10 写多个寄存器
2-3 起始地址 回显写入的起始寄存器地址
4-5 寄存器数量 回显写入的数量(本系统为 1)
6-7 CRC-16 前 6 字节 CRC

异常响应帧为 5 字节(地址 + 0x90 + 异常码 + CRC-2)。

⚠️ Bug 历史:v2.3.2 及以前版本将正常响应错误地按 6 字节解析, 并把"寄存器数量(0x00,0x01)"误当成 CRC 校验,导致每次写入都必然 CRC 失败 (Web 设置恒报"写入失败")。v2.3.3 已修复为按 8 字节规范解析。

5.6 单/多寄存器写入双通道自适应(v2.4.0)

Web 设置写入的单个参数,统一通过 modbus_write_register(),按下列顺序自适应选择功能码:

POST /api/settings
      │
      ▼
  参数范围校验 modbus_validate_setting()
      │
      ▼
  ① FC 0x06 写单个寄存器
     请求 8B: [addr][06][regHi][regLo][valHi][valLo][CRClo][CRChi]
     响应 8B: 原样回显 + CRC
      ├─ 成功(功能码=0x06、地址/值回显正确、CRC 正确)→ 返回成功
      ├─ 异常码 0x01(功能不支持)/0x02(地址非法) → 进入 ②
      └─ 超时 / 其他异常 → 直接报错,不盲目重试
      │
      ▼
  ② FC 0x10 写多个寄存器(数量=1)
     请求 13B / 响应 8B(见 5.5)
功能码 名称 请求长 响应长 适用
0x06 Write Single Register 8B 8B 首选,单参数写入,兼容性最好
0x10 Write Multiple Registers 13B 8B 回退方案,仅当设备不支持 0x06

设计理由:大量 DM 系列 / 低端 MPPT 固件对单参数只接受 FC 0x06, 对 0x10 回异常或静默不回。v2.4.0 之前固定 0x10 是部分设备写入失败的根因。

5.7 Web 服务自愈(v2.4.0)

HTTP 服务运行在独立线程,内部为"监听 → mg_http_listen 事件循环 → 异常退出 → 等待 → 重新监听"的循环; 即使监听失败或事件循环异常返回,也会自动重试,保证 Web 服务长期在线。 应用整体仍由 systemd 托管(见树莓派章节),形成"进程级 + 线程级"双重保障。


六、性能参数

指标 值 说明
数据采集间隔 2 秒 可通过 MODBUS_POLL_MS 调整
HTTP 响应延迟 < 1ms 纯内存数据,无磁盘 IO
内存占用 ~2MB 含 Mongoose 缓冲区
CPU 占用 < 1% 空闲时几乎不消耗 CPU
网络开销 ~30 bytes/2s Modbus 请求/响应

七、配置系统

7.1 config.ini 文件格式

[modbus]
host = discover.zhonjin.com
port = 40635
slave_addr = 0x01
timeout_sec = 10
poll_ms = 2000

[storage]
interval_sec = 10
db_path = mppt_data.db

[web]
port = 8085
page_size = 50

7.2 配置项说明

配置段 键 类型 默认值 说明
modbus host string discover.zhonjin.com Modbus 设备域名/IP
modbus port int 40635 Modbus TCP 端口
modbus slave_addr hex 0x01 Modbus 从机地址
modbus timeout_sec int 10 连接超时(秒)
modbus poll_ms int 2000 轮询间隔(毫秒)
storage interval_sec int 10 数据存储间隔(秒)
storage db_path string mppt_data.db SQLite 数据库文件路径
web port int 8085 HTTP 服务端口
web page_size int 50 历史数据默认分页大小

7.3 配置解析逻辑

  • 配置文件不存在时使用内置默认值,程序正常启动
  • 配置值解析失败时回退到默认值并输出警告日志
  • 十六进制值支持 0x 前缀(如 slave_addr = 0x01)

八、历史数据存储

8.1 数据库设计

使用 SQLite3 作为轻量级嵌入式数据库,无需额外服务进程。

history_data 表结构

CREATE TABLE IF NOT EXISTS history_data (
    id              INTEGER PRIMARY KEY AUTOINCREMENT,
    timestamp       INTEGER NOT NULL,           -- Unix 时间戳
    battery_voltage REAL NOT NULL,              -- 电池电压 (V)
    pv_voltage      REAL NOT NULL,              -- 光伏电压 (V)
    pv_charge_current REAL NOT NULL,            -- 光伏充电电流 (A)
    cumulative_energy REAL NOT NULL,            -- 累计发电量 (kWh)
    machine_temp    REAL NOT NULL,              -- 机器温度 (°C)
    fault_code      INTEGER NOT NULL,           -- 故障代码
    battery_soc     INTEGER NOT NULL,           -- 电池电量 (%)
    battery_string  INTEGER NOT NULL,           -- 电池串数
    charge_state    INTEGER NOT NULL,           -- 充电状态
    device_type     INTEGER NOT NULL,           -- 设备类型
    pv_input_power  REAL NOT NULL,              -- 光伏输入功率 (W)
    created_at      TEXT DEFAULT (datetime('now', 'localtime'))
);

索引

CREATE INDEX IF NOT EXISTS idx_history_timestamp ON history_data(timestamp);

8.2 存储流程

Modbus 读取成功 → 更新共享数据 → 检查存储间隔
                                    │
                    ┌───────────────┴───────────────┐
                    │ 距上次存储 >= interval_sec?    │
                    │                               │
                    ▼ Yes                           ▼ No
              插入 SQLite                      跳过
              更新 last_store_time

8.3 查询 API

GET /api/history

参数 类型 必填 说明
start_time string 否 起始时间,格式 YYYY-MM-DDTHH:MM:SS 或 YYYY-MM-DD HH:MM:SS
end_time string 否 结束时间,格式同上
page int 否 页码,默认 1
page_size int 否 每页条数,默认取 config.web.page_size,最大 500
sort string 否 排序方式:ASC 或 DESC(默认)

响应示例:

{
  "total": 150,
  "page": 1,
  "page_size": 50,
  "total_pages": 3,
  "records": [
    {
      "id": 150,
      "timestamp": "2026-08-04 16:30:00",
      "timestamp_unix": 1785832200,
      "battery_voltage": 26.8,
      "pv_voltage": 37.2,
      "pv_charge_current": 2.2,
      "pv_input_power": 81.84,
      "cumulative_energy": 0.8,
      "machine_temp": 45,
      "fault_code": 20,
      "fault_desc": "Normal",
      "battery_soc": 96,
      "charge_state": 1,
      "charge_state_desc": "Charging (Bulk)",
      "device_type": 60
    }
  ]
}

九、安全考虑

方面 措施
网络隔离 Modbus TCP 仅出站连接,不监听外部端口
HTTP 访问 当前无认证,建议通过反向代理添加 Basic Auth
数据完整性 Modbus CRC-16 校验确保数据正确性
异常输入 HTTP 路由严格匹配,未匹配返回 404
内存安全 使用 cJSON 安全 API,无缓冲区溢出风险
SQL 注入 使用 SQLite3 参数化查询(? 占位符),杜绝注入风险
配置安全 config.ini 解析使用 snprintf 防溢出,非法值回退默认

十、DM Series ModBus Protocol V2.1 完整寄存器表

10.1 Input Registers (功能码 0x04 - 只读实时数据)

PLC地址 寄存器地址 寄存器名 值范围 换算 说明
30001 0x0000 电池电压 0-65535 1=0.1V 实时电池电压
30002 0x0001 光伏电压 0-65535 1=0.1V 光伏板输入电压
30003 0x0002 光伏充电电流 0-65535 1=0.1A 当前充电电流
30004 0x0003 累计发电量 0-65535 1=0.1KWH 总发电量
30005 0x0004 机器温度 0-255 1=1°C 0xFF=故障
30006 0x0005 故障代码 0-255 见下表 设备故障状态
30007 0x0006 电池电量 0-100 % SOC
30008 0x0007 电池串数 0-8 保留
30009 0x0008 充电状态 0-1 0=未充电,1=充电
30010 0x0009 设备类型 0-255 设备型号代码
30011 0x000A 软件版本 0-255 固件版本号

10.2 Output Registers (功能码 0x03 - 可读配置参数)

PLC地址 寄存器地址 寄存器名 值范围 换算 读写 说明
40001 0x0000 电池类型 0-5 见下表 R/W
40002 0x0001 电池等级 0-6 见下表 R/W
40003 0x0002 光伏充电电流限制 5-100 % R/W
40004 0x0003 电池过放电压 80-600 1=0.1V 只读
40005 0x0004 电池提升电压 80-600 1=0.1V R/W
40006 0x0005 电池充满电压 80-600 1=0.1V R/W
40007 0x0006 过放恢复电压 80-600 1=0.1V 只读
40008 0x0007 设备485地址 0-247 R/W
40009 0x0008 充电运行模式 0-1 0=MPPT,1=DCDC R/W

10.3 电池类型对照表

值 类型 提升电压 过充电压 恢复电压 过放电压
0 胶体电池 14.2V 13.6V 11.5V 11.0V
1 密封电池 14.4V 13.6V 11.5V 11.0V
2 磷酸铁锂 14.4V 14.4V 11.5V 11.0V
3 三元锂电 12.6V 12.6V 9.5V 9.0V
4 自定义 - - - -
5 加水电池 14.6V 13.6V 11.5V 11.0V

10.4 故障代码对照表

代码 故障描述 严重程度
20 正常 -
30 光伏板超压 高
31 光伏充电过流 高
32 电池电压低 中
33 电池超压 高
38 设备温度高 中
50 温度传感器故障 中
88 未解密 低

10.5 电池等级对照表

值 电压等级 说明
0 自动识别 自动检测电池电压
1 12V
2 24V
3 36V
4 48V
5 60V
6 72V

十一、扩展方向

  1. 告警通知: 温度过高、电压异常时发送邮件/微信通知
  2. HTTPS 支持: 已预留 OpenSSL 编译选项
  3. MQTT 上报: 将数据发布到 MQTT Broker 供其他系统消费
  4. Web 认证: 添加 HTTP Basic Auth 或 Token 认证
  5. 数据导出: 支持 CSV/Excel 格式导出历史数据
  6. 统计聚合: 按小时/天/月聚合统计数据(平均、最大、最小)
  7. 写参数功能: 通过 Web 界面远程修改设备配置(0x10 功能码)

最后更新: 2026-08-05 (v2.0.0)