dispatch.h
POSITIVE_VALUE_OFFSET = 32000)4.2 模式枚举的槽位不连续4.3 定时与 uCOS-II 配合4.4 通信协议帧格式5. 对外接口6. 依赖关系7. 备注与风险点源文件路径:
logic/dispatch.h所属模块:logic(能量调度核心 —— 云端/调频调度指令解析与执行) 代码行数:181
1. 文件职责
本文件是 logic/dispatch.c 的对外契约,定义 EMS「调度」子系统的两套模式枚举(云端 EverGen 系统调度 ENModeControl、调频状态 FM_BAND_E)与老化测试枚举,并给出三张运行表的结构体(系统调度表 STEverGenCmdTab、调频调度表 FREQ_DISPATCH_T、老化模式表 AGINGMODE_TABLE_T)以及它们的聚合体 DISPATCH_TABLE_T。它导出的 g_t_dispatch_t 是全局调度状态中枢:网络层(net/server.c 下行指令、net/ems.c 上报)与设备层(midware/interface/dry_node、modbus、inverter/parallel)都直接读写其中字段。本文件还声明了 23 个访问与控制函数(dispatch.h:152-178),是 logic/logic.c 主循环接入调度功能的唯一入口。
2. 关键数据结构与宏
| 名称 | 类型 | 说明 | ||
|---|---|---|---|---|
__DISPATCH_H | 宏 | include guard | ||
POSITIVE_VALUE_OFFSET | 宏 | 值 32000。云端下发功率的零偏置:f_para[0]/u16ActivePower == 32000 表示 0 W,小于为充电、大于为放电,实际功率 = `\ | value - 32000\ | ` |
NEGATIVE_VALUE_OFFSET | 宏 | 值 -32000。本文件及其 .c 中均无实际引用点,属遗留宏 | ||
FORCE_SOC_MULT | 宏 | 值 4。云端下发的 u8ForceSOC 放大倍数,SOC 判据用 u8ForceSOC * 4 ± 4(单位 0.1%,即 4 → 1.6%) | ||
EVERGEN_FUNC_START | 宏 | 值 1,调度使能 | ||
EVERGEN_FUNC_STOP | 宏 | 值 0,调度关闭 | ||
DISPATCH_POWER_MAX_SET | 宏 | 值 64000。西澳 CHARGE_CONTROL_2 模式下 DC/AC 参数的有效值上界(开区间) | ||
DISPATCH_POWER_MIN_SET | 宏 | 值 0。有效值下界(开区间);配合 64000 把 0/65535(云端 -1)排除在有效值之外 | ||
ENModeControl | 枚举 | 调度控制模式。NO_DISPATCH_CONTROL=0x00、BAT_CHARGE_FROM_PV=0x01、CHARGE_CONTROL=2、LOAD_FOLLOWING=3、MAX_OUTPUT=4、NORMAL_MODE=5、OPTIMISE_CONSUME=6、MAX_CONSUME=7、ECO_MODE=8、FCAS_STEP_MODE=9、FCAS_DROOP_MODE=10、FFR_PRIMARY_MODE=11、FFR_SECONDARY_MODE=12、FFR_HIGE_MODE=13、FFR_STEP_TEST1_MODE=14、FFR_STEP_TEST2_MODE=15、FFR_Response_Test1_MODE=16、FFR_Response_Test2_MODE=17、FFR_Live_Test_MODE=18、BAT_NO_CHARGE=19、AGING_MODE=20、VERY_FAST_FCAS_STEP_MODE=26、VERY_FAST_FCAS_DROOP_MODE=27、FAST_FCAS_STEP_MODE=28、FAST_FCAS_DROOP_MODE=29、SFFR_MODE=30、CHARGE_CONTROL_2=32(西澳调度)、SMART_CONTROL=33、SUNSPECT_ACTIVE_MODE=34、DISPATCH_MAX_MODE=35。注意 21-25 与 31 号位未定义,是刻意留空的历史槽位 | ||
FM_BAND_E | 枚举 | 调频阶跃状态:NORMAL_FREQ_E(0) 正常、OVER_FREQ_E(1) 高频、UNDER_FREQ_E(2) 低频 | ||
AGING_STATE_E | 枚举 | 老化测试结果:AGING_FAILURE、AGING_SUCCEED、AGING_ERROR、AGING_COMPLETE、AGING_ONGOING | ||
AGING_MODE_E | 枚举 | 老化子模式:AGING_END(0)、PV_TO_GRID(1)、PV_TO_BAT(2)、BAT_TO_GRID(3)、GRID_TO_BAT(4)、BAT_TO_GRID_2(5)、AGING_EXIT(6)、AGING_START = 0xff | ||
DISPATCH_CMD_T | 结构体 | 云端下行指令的中间载体:u8_enable、f_para[8](8 个参数)、u32_runtime(持续时间,秒) | ||
STEverGenCmdTab | 结构体 | 系统调度运行表:u8Dispatch、u8ControlMode、u8AgingMode、u8ForceSOC、u8_pv_on_off、u16ActivePower、u16ReactivePower、u32CmdGetTick、u32_runtime | ||
FM_DEBUG_T | 结构体 | 调频调试注入:u8_debug_enable、u16_debug_freq(人工设定频率,用于产线验证) | ||
FREQ_DISPATCH_T | 结构体 | 调频调度运行表,字段见下表 | ||
AGINGMODE_TABLE_T | 结构体 | 老化上报表:u8_agingmode_en、u8_aging_result、u8_aging_status、u8_flip_status | ||
DISPATCH_TABLE_T | 结构体 | 顶层聚合:t_stsystemcmdinfo + t_freq_dispatch_rundata + t_agingmode_info | ||
g_t_dispatch_t | 全局变量(extern) | DISPATCH_TABLE_T 实例,定义于 logic/dispatch.c:30 |
FREQ_DISPATCH_T 字段分解(调频核心):
| 字段 | 类型 | 说明 |
|---|---|---|
u8_dispatch_enable | u8 | 调频调度总使能 |
u8_mppt_enable | u8 | 本文件与 .c 中均无引用点,疑似遗留 |
u8_dispatch_mode | u8 | 调频模式,取值 FCAS_* / FFR_* |
u16_charge_power / u16_discharge_power | u16 | 满额充电/放电功率 |
u16_db / u16_sb | u16 | 阶跃模式的死区(deadband)与饱和(saturation band)判据(0.01 Hz) |
u16_ldb / u16_hdb | u16 | 低/高侧死区(droop 线性段外沿) |
u16_lsb / u16_hsb | u16 | 低/高侧饱和带(droop 满出力点) |
u32_dispatch_tick | u32 | 指令下发时刻,用于 u32_dispatch_run_time 超时退出 |
u32_dispatch_run_time | u32 | 指令有效时长(秒) |
u8_freq_dispatch_flag | u8 | 调频动作标志,供 logic.c 决定是否接管控制 |
s32_ac_dispatch_power | s32 | 调频计算出的目标交流功率,正=放电、负=充电 |
t_fm_debug | FM_DEBUG_T | 调试频率注入 |
3. 函数清单
本文件为声明文件,共 23 个函数原型(dispatch.h:152-178),全部对应 logic/dispatch.c 中的全局定义;无 static 声明、无函数指针类型、无回调。
| 函数名 | 作用域 | 说明 |
|---|---|---|
set_dispatch_parameter | 全局(原型) | 解析并落库一条云端调度指令(定义于 dispatch.c:98) |
get_dispatch_running_mode | 全局(原型) | 返回当前生效的调度模式(dispatch.c:128) |
dispatch_regulation_flag | 全局(原型) | 返回"是否正在被调度调节"(调频优先,否则看并网状态)(dispatch.c:160) |
dispatch_api_data_interval | 全局(原型) | 返回上报采样间隔 ms(dispatch.c:178) |
frequency_regulation_detection | 全局(原型) | 调频检测状态机主函数(dispatch.c:235) |
excute_frequency_regulation_command | 全局(原型) | 执行调频功率指令(dispatch.c:529) |
get_freq_dispatch_enable | 全局(原型) | 读 t_freq_dispatch_rundata.u8_dispatch_enable(dispatch.c:576) |
frequency_regulation_flag | 全局(原型) | 读 t_freq_dispatch_rundata.u8_freq_dispatch_flag(dispatch.c:587) |
get_dispatch_running_freq | 全局(原型) | 读取当前电网频率 ×100(dispatch.c:598) |
get_fast_dispatch_running_freq | 全局(原型) | 读取快速调频频率 ×1000(dispatch.c:620) |
get_fcas_running_flag | 全局(原型) | 是否处于 FCAS(标准速率)模式(dispatch.c:642) |
get_fast_fcas_running_flag | 全局(原型) | 是否处于 FAST_FCAS 模式(dispatch.c:667) |
get_very_fast_fcas_running_flag | 全局(原型) | 是否处于 VERY_FAST_FCAS 模式(dispatch.c:692) |
get_ffr_running_flag | 全局(原型) | 是否处于 FFR 任一模式(dispatch.c:716) |
dectect_api_dispatch_comm | 全局(原型) | 检测云端调度通信与超时退出、老化结果维护(dispatch.c:748) |
excute_system_dispatch_command | 全局(原型) | 按 u8ControlMode 分派到各 handle_* 执行体(dispatch.c:1392) |
get_dispatch_enable | 全局(原型) | 读 u8Dispatch(dispatch.c:1506) |
get_dispatch_mode | 全局(原型) | 读 u8ControlMode,智能控制模式下返回 SMART_CONTROL(dispatch.c:1528) |
aging_mode_send_data_flag | 全局(原型) | 老化数据是否有变化待上报(dispatch.c:1582) |
aging_mode_data_sync | 全局(原型) | 上报成功后同步老化数据影子副本(dispatch.c:1593) |
get_dispatch_set_power | 全局(原型) | 返回调度设定功率(已减 POSITIVE_VALUE_OFFSET)(dispatch.c:1544) |
dispatch_set_mode | 全局(原型) | 设置 u8ControlMode(dispatch.c:1605) |
set_dispatch_enable | 全局(原型) | 设置 u8Dispatch(dispatch.c:1517) |
注意:dispatch.c 实际实现了 40 个函数,其中 16 个(dispatch_api_maxfeedin_priority、handle_aging_mode、handle_bat_charge_from_pv、handle_charge_control、handle_parallel_charge_control、handle_load_following、handle_max_output、handle_normal_mode、handle_optimise_consume、handle_max_consume、handle_eco_mode、handle_bat_no_charge、handle_charge_control_2_dc、handle_charge_control_2_ac、handle_charge_control_2、dispatch_Sunspec_ative_power_mode)未在本头文件登记,属编译单元内部实现(详见 dispatch.c.md 备注)。
4. 核心逻辑解析
本文件不含可执行逻辑,但对实现有强约束的几个设计要点如下。
4.1 功率零偏置编码(POSITIVE_VALUE_OFFSET = 32000)
云端下行功率一律以 0..64000 的无符号区间编码,32000 为原点。本头文件用成对的 POSITIVE_VALUE_OFFSET(32000) / NEGATIVE_VALUE_OFFSET(-32000) 表达这一约定,但 NEGATIVE_VALUE_OFFSET 从未被使用。DISPATCH_POWER_MAX_SET = 64000 正是 32000 + 32000,即功率绝对值不超过 32000(单位 W 或 0.1 kW 由上层定义),这同时把云端用 -1(u16 解析为 65535)表示"无效"的语义与合法值区分开——CHARGE_CONTROL_2 模式下用开区间 (0, 64000) 判定有效(dispatch.c:1351-1357、:1552-1558)。
4.2 模式枚举的槽位不连续
ENModeControl 存在两处刻意的数值跳跃,是版本演进的痕迹:
BAT_NO_CHARGE = 19、AGING_MODE = 20之后直接跳到VERY_FAST_FCAS_STEP_MODE = 26,中间 21-25 未定义。SFFR_MODE = 30之后跳到CHARGE_CONTROL_2 = 32,31 未定义。
这意味着 21-25、31 这些值从云端下发时不会被任何 switch 分支命中,会落到 excute_system_dispatch_command 的 default 分支(执行自发自用)。同时 dispatch_set_mode() 的合法性检查只有 u8_dispatch_mode < DISPATCH_MAX_MODE(35),因此调用方可以传入 21-25、31 等空洞值而不报错。
4.3 定时与 uCOS-II 配合
本文件不声明任务、信号量或邮箱,但两个时间字段是调度超时的核心:
STEverGenCmdTab.u32CmdGetTick+u32_runtime:dispatch.c:767用(OSTimeGet() - u32CmdGetTick) > (u32_runtime * 1000)判定指令过期,随后清空调度状态回到自发自用。u32_runtime下限在net/server.c:823被强制为 90 秒。FREQ_DISPATCH_T.u32_dispatch_tick+u32_dispatch_run_time:dispatch.c:248同构判定,过期后memset整张调频表。
调度的触发来自事件标志组 g_t_fast_dispatch_flag(user/main.c:62 创建,user/main.h:62 导出):net/server.c:838-839 在写入调度参数后 OSFlagPost(..., POST_PEND_FAST_ENABLE, ...) 并 OSTimeDlyResume(TASK_LOGIC_CONTROL_PRIO) 立即唤醒 logic 任务——本头文件不涉及这个机制,但调用方必须知道 set_dispatch_parameter() 之后才会发生。
4.4 通信协议帧格式
本文件不定义帧格式。但它承载的调度参数来自 net/server.c 的 TCP/JSON 下行:server.c:803-818 用 parse_dispatch_para() 从 Parameter2 字段解析出 8 / 7 / 4 个十进制数字填入 f_para[8],Parameter3 解析为 u32_runtime。字段个数决定了指令是调频指令还是系统指令——这个"以参数字段个数区分指令类型"的约定在 dispatch.c 里由 set_freq_dispatch_parameter() 的返回值间接实现,本头文件的 DISPATCH_CMD_T 结构(三字段:u8_enable + f_para[8] + u32_runtime)没有把这一区分表达出来。
5. 对外接口
导出(供外部使用):
| 名称 | 类型 | 主要使用方 |
|---|---|---|
g_t_dispatch_t | 全局变量 | net/ems.c(上报 u8Dispatch、u8ForceSOC、u8ControlMode)、net/server.c、midware/interface/dry_node、midware/interface/modbus、midware/inverter/parallel、data/resume_data/flash/flash_data_store.c |
set_dispatch_parameter | 函数 | net/server.c:835 |
get_dispatch_running_mode / dispatch_api_data_interval / dispatch_regulation_flag | 函数 | net/ems.c:6492/6508/6537 等上报路径 |
frequency_regulation_flag | 函数 | logic/logic.c:2241、logic/logic.c:3501、midware/interface/modbus/modbus.c:3604/4513、net/ems.c:6355/6404/6453 |
get_freq_dispatch_enable | 函数 | midware/inverter/parallel.c:788/959 |
get_fcas_running_flag / get_fast_fcas_running_flag / get_very_fast_fcas_running_flag / get_ffr_running_flag | 函数 | net/ems.c:6321/6370/6419/6573 |
get_dispatch_running_freq | 函数 | midware/interface/modbus/modbus.c:3612、net/ems.c:6349/6589 |
get_fast_dispatch_running_freq | 函数 | net/ems.c:6398/6447/6531 |
get_dispatch_enable | 函数 | logic/logic.c:2245、midware/bms/bms.c:2225 |
get_dispatch_mode / get_dispatch_set_power | 函数 | net/ems.c:773/774、net/ems.c:1490/1491、net/ems.c:1557 |
aging_mode_send_data_flag / aging_mode_data_sync | 函数 | net/ems.c:5092、net/server.c:7021 |
set_dispatch_enable / dispatch_set_mode | 函数 | midware/interface/modbus/sunspec_business.c:1113/1114 |
frequency_regulation_detection / dectect_api_dispatch_comm / excute_frequency_regulation_command / excute_system_dispatch_command | 函数 | logic/logic.c:2928/2929/2314/2318 |
ENModeControl / DISPATCH_CMD_T / DISPATCH_TABLE_T 等类型 | 类型 | midware/interface/modbus/modbus.h:10、net/server.h:13 通过 include 本头文件间接使用 |
被调用(本文件引用的符号):仅 #include "includes.h"(dispatch.h:13)。
6. 依赖关系
依赖:includes.h(基础类型与 TRUE/FALSE)。无其他 include。
被依赖(全部 include 点,来自 grep -rn "dispatch.h"):
logic/dispatch.c:13logic/logic.c:15logic/csip_aus.c:16net/ems.c:23net/server.c:33、net/server.h:13(server.h的引入把本文件扩散到所有 includeserver.h的文件)midware/interface/modbus/modbus.c:23、midware/interface/modbus/modbus.h:10midware/interface/dry_node/dry_node.c:22midware/inverter/parallel.c:25data/resume_data/flash/flash_data_store.c:16
覆盖面从 logic 层一直到 data 持久化层,说明 g_t_dispatch_t 事实上是一个跨层共享的全局状态块。
7. 备注与风险点
NEGATIVE_VALUE_OFFSET是死宏:定义为-32000但全工程(含dispatch.c)无引用。属版本遗留。FM_DEBUG_T、AGING_STATE_E、AGING_MODE_E中的AGING_EXIT、FREQ_DISPATCH_T.u8_mppt_enable、DISPATCH_CMD_T也无明确对应使用(详见各.c的备注)。- 枚举存在空洞且
SMART_CONTROL与ENModeControl混用:21-25、31 未定义,但dispatch_set_mode()只校验上界。传入空洞值时get_dispatch_running_mode()/excute_system_dispatch_command()会静默落到default/NO_DISPATCH_CONTROL,既不报错也不上报,故障定位困难。 FORCE_SOC_MULT的注释缺失导致语义不明:值为 4,唯一用法是u8ForceSOC * FORCE_SOC_MULT ± 4(dispatch.c:1018/1035/1041)。也就是说"目标 SOC 上下各 4 个单位"形成死区。± 4这两个字面量与FORCE_SOC_MULT的倍数关系没有任何注释解释,外部读者无法判断±4是 0.4% 还是 4%。net/ems.c:774上报时又写u8ForceSOC * FORCE_SOC_MULT / 10,把同一字段按 0.1% 单位再做一次缩放,三处口径不一致。u16ActivePower/u16ReactivePower的命名与用途不符:在CHARGE_CONTROL_2(西澳调度)模式下,u16ReactivePower被当作 AC 侧有功功率设定值使用(dispatch.c:1356-1359),而u16ActivePower被当作 DC 侧有功功率。命名误导性很强,且handle_aging_mode()又把它们解释为最大充电/放电 SOC(u16ActivePower * 10、u16ReactivePower * 10,dispatch.c:880-881)——同一对字段在三种模式下有三种完全不同的物理含义,是典型的多路复用风险点。u32_runtime无单位注释:STEverGenCmdTab.u32_runtime与FREQ_DISPATCH_T.u32_dispatch_run_time在.c中按秒参与* 1000运算,但头文件里没有任何单位说明;DISPATCH_CMD_T.u32_runtime也是同样问题。dispatch.c:809里还有一处硬编码= 90。- 全局状态块无锁保护:
g_t_dispatch_t被logic任务写、被net任务写(net/server.c:835→set_dispatch_parameter)、被ems任务读(net/ems.c:774等)。虽然有g_t_fast_dispatch_flag事件标志做粗粒度同步,但事件标志只保证"logic 任务会被唤醒",并不对结构体本身做互斥。例如dectect_api_dispatch_comm()会在读取u8ControlMode后、清空前被网络任务改写,可能产生半旧半新的组合。头文件对此没有任何说明。 get_dispatch_set_power()的返回值语义未在头文件说明:返回65535表示"无效值"(dispatch.c:1565),但原型写的是s32,而65535作为s32是正数。net/ems.c:773直接把它塞进 printf,net/ems.c:1490等同。该"魔法返回值"是关键契约,却没有任何注释。- 文件头信息为空:
@version、@date、@brief均为空,与工程内部分文件的填写规范不一致。无功能影响。