meter_download.h
源文件路径:
net/meter_download.h所属模块:net(网络应用层 / 设备固件升级下载) 代码行数:21
1. 文件职责
本文件是 net/meter_download.c 的对外接口头文件,声明电表(Meter)固件升级流程的 6 个接口:文件掩码查询、升级对象(电网表 / 光伏表 / 正泰无线表)的读写、强制下载标志、下载百分比,以及一个无实现的旧接口 Get_Meter_Ver_From_Server。
它在工程中承担一个特殊职责——暴露"本次升级对象"这一状态。因为工程里多种电表型号共用同一个 UPDT_Meter 升级槽位,get_meter_updt_object() 的返回值被 net/ems.c、net/server.c 与 midware/meter/* 大量用于把对象编号翻译成机型串与硬件版本,从而让云端能够正确匹配固件。
本文件不含逻辑与状态,只含 include guard、一个 include 和 6 个函数原型。
2. 关键数据结构与宏
| 名称 | 类型 | 说明 |
|---|---|---|
__METER_DOWNLOAD_H__ | 宏 | include guard(第 9-10 行) |
Get_Meter_Ver_From_Server | 函数原型 | char *Get_Meter_Ver_From_Server(void),工程内无定义、无调用点(见第 7 节备注 1) |
get_Meter_Updt_File_Mask | 函数原型 | char* get_Meter_Updt_File_Mask(void),定义于 meter_download.c:40 |
set_meter_updt_object | 函数原型 | void set_meter_updt_object(u8 object),定义于 meter_download.c:58 |
get_meter_updt_object | 函数原型 | u8 get_meter_updt_object(void),定义于 meter_download.c:69 |
IsDownloadMeter | 函数原型 | u8 IsDownloadMeter(void),定义于 meter_download.c:80 |
GetPercentDownloadMeter | 函数原型 | u8 GetPercentDownloadMeter(void),定义于 meter_download.c:91 |
本文件不定义结构体、枚举、联合体、位域,也没有除 include guard 外的宏常量。u8 来自第 12 行 #include <includes.h>。
与本头文件接口配套的枚举 METER_SITE_E(midware/meter/meter.h:163)定义了 u8_upgrade_object 的合法取值范围:GRID_METER = 1、PV_METER、CHNT_WIRELESS、MID_METER、MAX_METER_SITE。本头文件没有引用该枚举,因此接口无法在类型层面约束对象编号。
3. 函数清单
| 函数名 | 作用域 | 说明 |
|---|---|---|
Get_Meter_Ver_From_Server | 全局(原型声明) | 语义应为“取服务器下发的电表版本”,全工程无定义、无调用点,属死声明(电表硬版本实际由 midware/meter/meter.h:488 的 meter_read_hard_version(u8 site) 提供) |
get_Meter_Updt_File_Mask | 全局(原型声明) | 返回 stUpt[UPDT_Meter].as8FileMask,空串时回退 FILE_MASK_DEFAULT("00000000"),定义于 meter_download.c:40 |
set_meter_updt_object | 全局(原型声明) | 写入 stUpt[UPDT_Meter].u8_upgrade_object(无范围校验),定义于 meter_download.c:58 |
get_meter_updt_object | 全局(原型声明) | 读取 stUpt[UPDT_Meter].u8_upgrade_object,定义于 meter_download.c:69 |
IsDownloadMeter | 全局(原型声明) | 查询云端是否下发过电表强制下载标志,定义于 meter_download.c:80 |
GetPercentDownloadMeter | 全局(原型声明) | 查询电表固件下载百分比(0~100),定义于 meter_download.c:91 |
共 6 个原型声明:5 个有实现、1 个无实现。无 static 函数、无函数指针、无回调、无宏函数。
4. 核心逻辑解析
本文件是纯声明文件,不含可执行逻辑。接口契约要点:
4.1 升级对象接口是"带外"状态,类型不受约束
set_meter_updt_object(u8 object) 的参数是裸 u8,而不是 METER_SITE_E(midware/meter/meter.h:163)。合法值是 GRID_METER(1) ~ MID_METER(4),小于 MAX_METER_SITE(5)。写侧唯一调用点是:
set_meter_updt_object(atoi((char *)g_au8FWBuf)); // net/server.c:2434,来自云端 JSON 的 PARA3
set_meter_updt_object(GRID_METER); // net/server.c:2440,BB 升级固定为电网表
由于 atoi 对非法输入返回 0、对超长数字可能回绕,本接口无法保证写入值是合法站点编号。后续该值被直接当作 meter_read_hard_version(site)(midware/meter/meter.h:488)与 meter_get_meter_modle(site)(midware/meter/meter.h:485)的 site 参数使用,共 15 处调用点(见 meter_download.c.md 第 4.1 节表格)。建议签名改为 void set_meter_updt_object(METER_SITE_E object) 并在实现中校验。
4.2 文件掩码的空串兜底语义
get_Meter_Updt_File_Mask() 在 as8FileMask 为空串时返回 FILE_MASK_DEFAULT("00000000")。该返回值参与 8 处掩码匹配(net/ems.c:2977、:3007、:3088;net/server.c:3299、:3469、:3708、:3764、:3803),而没有任何分支匹配 "00000000",因此兜底的实际效果是"不匹配任何升级类型",即丢包重来。调用方无法区分"云端未下发掩码"与"掩码确实全 0"。
4.3 进度与标志的契约
IsDownloadMeter():返回u8,取值仅 0 / 1(底层BOOLEAN提升)。仅当云端下发强制升级时才为真;net/server.c:2410-2411对UPDT_Meter没有显式的清零分支(该分支只覆盖UPDT_INV3/UPDT_BMS/UPDT_EVC),因此非强制升级时该标志保持上一轮的值——这是一个需要调用方自行重置的隐式契约。GetPercentDownloadMeter():返回u8,语义 0~100;分母u32LenFile在文件信息到达前为 0,存在除零窗口(详见meter_download.c.md备注 3)。
4.4 通信协议 / 定时 / uCOS-II
均不涉及。本文件不定义帧格式、起始码、长度、命令字、校验方式或超时重试参数,不声明信号量、消息邮箱或任务,也不引用 uCOS-II API。所声明的函数由调用方在自己的任务上下文同步调用。
5. 对外接口
导出(供外部使用):
| 名称 | 使用方 |
|---|---|
get_Meter_Updt_File_Mask | net/ems.c:2977、:3007、:3088;net/server.c:3299、:3469、:3708、:3764、:3803 |
set_meter_updt_object | net/server.c:2434、:2440(唯一调用者) |
get_meter_updt_object | net/ems.c:2979、:3009、:3090;net/server.c:3299、:3708;midware/meter/meter.c:5731/5745/5759/6838/6851/6864;midware/meter/meter_upgrade.c:294/298/302/436/442 |
IsDownloadMeter | hmi/ui/ui_main.c:862、net/ems_download.c:259 |
GetPercentDownloadMeter | hmi/ui/ui_main.c:868 |
Get_Meter_Ver_From_Server | 无(无定义、无调用) |
被调用(本文件引用的外部符号):
| 名称 | 来源 |
|---|---|
includes.h | 第 12 行 #include <includes.h>,提供 u8 等基础类型,并间接引入 uCOS-II 与 GD32 头文件 |
本文件不导出全局变量,也不引用外部全局变量。
6. 依赖关系
依赖:
UCOSII/uCOS-CONFIG/includes.h(第 12 行,尖括号形式)——唯一依赖,仅用于取得基础类型;- 不依赖
ems.h/server.h/upd_download.h/meter.h,因此任何模块都能以极低耦合代价引入它。副作用是:接口用到的METER_SITE_E与FILE_MASK_DEFAULT都来自别处,调用方必须自行 include(FILE_MASK_DEFAULT在net/server.h:82,METER_SITE_E在midware/meter/meter.h:163)。
被依赖(include 本头文件的文件,共 9 处):
net/meter_download.c:14、net/ems.c:21、net/ems_download.c:20(写成了"Meter_download.h",见备注 5)、net/server.c:23hmi/ui/ui_main.c:25midware/meter/meter.c:29、midware/meter/meter_upgrade.c:17、midware/meter/bb_update.c:17midware/interface/modbus/modbus.c:35
7. 备注与风险点
Get_Meter_Ver_From_Server声明无实现:全工程(.c/.h)中该标识符只出现于本文件第 15 行,既无定义也无调用。电表硬版本当前由midware/meter/meter.h:488的meter_read_hard_version(u8 site)提供(net/ems.c:2979使用),midware/meter/meter.h:485的meter_get_meter_modle(u8 site)提供机型串。这两个函数都要求传入站点编号,而本文件把站点编号状态的读写接口暴露出来正是为此。该声明应删除。- 文件头
@file与真实文件名不符 +@author不一致:第 2 行写meter_download.h(此处一致),但第 3 行@author是Alpha g_stEMSInfo Team,与meter_download.c的Alpha EMS Team不一致(推测是历史上把标识符EMS批量替换为g_stEMSInfo时误改了注释);@date为2017/05/18,与bms/evc/inv三个 download 文件同源。 get_Meter_Updt_File_Mask返回char*而非const char*:函数既可能返回内部数组stUpt[UPDT_Meter].as8FileMask的地址,也可能返回字符串字面量FILE_MASK_DEFAULT的地址(只读段)。调用方若尝试写入返回值,前者会破坏升级状态、后者会写入只读内存触发 HardFault。加const修饰可让编译器拦截这类误用。set_meter_updt_object缺少参数类型约束与范围校验:签名用裸u8(见 4.1),实现(meter_download.c:58-61)也不校验范围。唯一写侧来自atoi的不可信输入(net/server.c:2434),非法值会被无告警地存入,随后 15 处调用点以它为索引/参数使用meter_read_hard_version()/meter_get_meter_modle()。net/ems_download.c以错误大小写包含本头文件:net/ems_download.c:20写的是#include "Meter_download.h"(首字母大写),真实文件名是全小写。Windows / Keil MDK 文件系统不区分大小写,能正常编译;迁移到区分大小写的工具链(Linux GCC、大小写敏感检出)会报"找不到文件"。对比同文件:30的afci_download.h用小写,可判定是笔误。- 接口未暴露"下载完成"状态:与
bms_download.h(IsUpgradeBMS)、afci_download.h(is_afci_firm_download_finished)、inv_download.h(is_inverter_firm_download_finished)相比,本文件没有对应接口,电表的下载完成状态只能通过通用接口Get_Status_Is_Updated_From_Server(UPDT_Meter)读取,与同族文件风格不统一。HMI 的"upgrade Meter"分支用的是midware/meter的IsUpgradeMeter()/GetPercentUpgradeMeter()(hmi/ui/ui_main.c:871、:877),属于刷写阶段而非下载阶段。 - 升级对象状态的隐式生命周期:
u8_upgrade_object只由net/server.c:2434/2440写入,且从不清零;上电初值为 0(不在METER_SITE_E合法范围内)。若在收到过升级对象之前就有代码调用get_meter_updt_object(),会拿到 0 并传给meter_read_hard_version(0)/meter_get_meter_modle(0)。net/ems.c:2979等读点全部在"掩码已匹配get_Meter_Updt_File_Mask()"的条件下才执行,实际很难命中 0,但这依赖调用顺序而非显式保护。