EMS 知识库
首页 / knowledge/代码解析/logic

dispatch.h

源文件路径: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_enableu8调频调度总使能
u8_mppt_enableu8本文件与 .c 中均无引用点,疑似遗留
u8_dispatch_modeu8调频模式,取值 FCAS_* / FFR_*
u16_charge_power / u16_discharge_poweru16满额充电/放电功率
u16_db / u16_sbu16阶跃模式的死区(deadband)与饱和(saturation band)判据(0.01 Hz)
u16_ldb / u16_hdbu16低/高侧死区(droop 线性段外沿)
u16_lsb / u16_hsbu16低/高侧饱和带(droop 满出力点)
u32_dispatch_ticku32指令下发时刻,用于 u32_dispatch_run_time 超时退出
u32_dispatch_run_timeu32指令有效时长(秒)
u8_freq_dispatch_flagu8调频动作标志,供 logic.c 决定是否接管控制
s32_ac_dispatch_powers32调频计算出的目标交流功率,正=放电、负=充电
t_fm_debugFM_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 存在两处刻意的数值跳跃,是版本演进的痕迹:

这意味着 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 配合

本文件不声明任务、信号量或邮箱,但两个时间字段是调度超时的核心:

调度的触发来自事件标志组 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 层一直到 data 持久化层,说明 g_t_dispatch_t 事实上是一个跨层共享的全局状态块。

7. 备注与风险点

  1. 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 的备注)。
  2. 枚举存在空洞且 SMART_CONTROL 与 ENModeControl 混用:21-25、31 未定义,但 dispatch_set_mode() 只校验上界。传入空洞值时 get_dispatch_running_mode() / excute_system_dispatch_command() 会静默落到 default/NO_DISPATCH_CONTROL,既不报错也不上报,故障定位困难。
  3. 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% 单位再做一次缩放,三处口径不一致。
  4. 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)——同一对字段在三种模式下有三种完全不同的物理含义,是典型的多路复用风险点。
  5. u32_runtime 无单位注释:STEverGenCmdTab.u32_runtime 与 FREQ_DISPATCH_T.u32_dispatch_run_time 在 .c 中按秒参与 * 1000 运算,但头文件里没有任何单位说明;DISPATCH_CMD_T.u32_runtime 也是同样问题。dispatch.c:809 里还有一处硬编码 = 90。
  6. 全局状态块无锁保护: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 后、清空前被网络任务改写,可能产生半旧半新的组合。头文件对此没有任何说明。
  7. get_dispatch_set_power() 的返回值语义未在头文件说明:返回 65535 表示"无效值"(dispatch.c:1565),但原型写的是 s32,而 65535 作为 s32 是正数。net/ems.c:773 直接把它塞进 printf,net/ems.c:1490 等同。该"魔法返回值"是关键契约,却没有任何注释。
  8. 文件头信息为空:@version、@date、@brief 均为空,与工程内部分文件的填写规范不一致。无功能影响。