ems/ems_c/logic/logic_main.c

385 lines
12 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*****************************************************************************
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
* @file logic_main.c
* @brief xxxx
* @author Gary
* @date 2024/09/29
* @remark 初修订
*****************************************************************************/
#include "logic_main.h"
logic_pthread_t stlogic = {0};
tast_register_execute *task_group[E_TACTIC_MODE_END] = {0}; // MAX_TASK_NUM改用枚举
// 用于log打印 与 work_mode_e 强绑定
const char *workModeNames[] = {
"",
"调试模式",
"削峰填谷模式",
"需求响应模式",
"负载跟踪模式",
"需量控制",
"功率因数",
"null"};
/*********************************************************************
* @brief 初始化任务参数
* @param[in] 无
* @return 0sucessful1fault
*********************************************************************/
static int initTaskParam()
{
logic_getProtectParam();
logic_getPowerDistrParam();
work_mode_set_t tempMode;
if (0 == kit_get_work_mode_set(&tempMode))
{
stlogic.para_delivery.mode = tempMode.workMode;
}
else if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
{
KITLOG(LOG_MODBUS_EN, INFO_EN, "获取调试配置失败 %s ==> %s", workModeNames[stlogic.para_delivery.mode], workModeNames[tempMode.workMode]);
KITPTF(LOG_MODBUS_EN, INFO_EN, "获取调试配置失败 %s ==> %s", workModeNames[stlogic.para_delivery.mode], workModeNames[tempMode.workMode]);
return 1;
}
else
{
return 1;
}
// 读取参数值
switch (stlogic.para_delivery.mode)
{
case E_TACTIC_MODE_DEBUG: // 调试模式
logic_debugParamUpdate();
break;
case E_TACTIC_MODE_PEAKVALLY: // 削峰填谷模式
logic_peakValleyUpdate();
break;
case E_TACTIC_MODE_DEMANDRES: // 需求响应模式
/* 暂未实现 */
break;
case E_TACTIC_MODE_LOADTRACK: // 负载跟踪模式
/* 暂未实现 */
break;
case E_TACTIC_MODE_DMDCTRL: // 需量控制模式
/* 暂未实现 */
break;
case E_TACTIC_MODE_PFCTRL: // 功率因数模式
/* 暂未实现 */
break;
default:
/*无模式*/
break;
}
return 0;
}
/*********************************************************************
* @brief 注册并初始化一个新的任务节点
* @param[in] task_func 任务的函数指针
* @return 成功时返回指向新任务节点的指针;失败时返回 NULL
*********************************************************************/
// 初始化任务链表节点
tast_register_execute *register_task(task_func_t task_func)
{
tast_register_execute *new_task = (tast_register_execute *)malloc(sizeof(tast_register_execute));
if (new_task == NULL)
{
printf("Memory allocation failed!\n");
return NULL;
}
// new_task->taskPeriod = period;
new_task->task = task_func;
new_task->next = NULL;
return new_task;
}
/*********************************************************************
* @brief 初始化任务链表,支持多个任务函数指针
* @param[in] count 任务数量
* @param[in] ... 可变参数,任务函数指针
* @return 成功时返回指向链表头部的指针;失败时返回 NULL
*********************************************************************/
tast_register_execute *init_task_list(int count, ...)
{
if (count <= 0)
return NULL; // 确保任务数量合法
va_list args; // 用于处理可变参数
va_start(args, count); // 初始化可变参数列表
tast_register_execute *head = NULL, *current = NULL;
// 循环遍历每个任务函数
for (int i = 0; i < count; i++)
{
task_func_t task_func = va_arg(args, task_func_t); // 获取当前任务函数指针
tast_register_execute *new_task = register_task(task_func);
if (new_task == NULL)
{
// 内存分配失败时,清理已分配的节点并返回 NULL
// free_task_list(head);
va_end(args); // 清理可变参数列表
return NULL;
}
if (head == NULL)
{
// 第一个任务作为头节点
head = new_task;
}
else
{
// 将新任务链接到链表末尾
current->next = new_task;
}
current = new_task; // 更新当前任务
}
va_end(args); // 结束可变参数处理
return head;
}
/*********************************************************************
* @brief 初始化任务注册信息
* @param[in] 无
* @return 0sucessful1fault
*********************************************************************/
static int logic_initTaskRegister()
{
INIT_TASK_GROUP();
for (int i = 0; i < E_TACTIC_MODE_END; i++)
{
if (task_group[i] == NULL)
{
printf("Failed to initialize task group 0.\n");
return 1; // 错误返回
}
}
return 0;
}
/*********************************************************************
* @brief 创建任务线程
* @param[in] 无
* @return 无
*********************************************************************/
static int creatLogicTaskEntry()
{
if (pthread_create(&stlogic.tfd, NULL, creatLogicTaskThread, (void *)&stlogic.para_delivery) == 0)
{
KITPTF(LOG_LOGIC_EN, INFO_EN, "task线程创建成功");
KITLOG(LOG_LOGIC_EN, INFO_EN, "task线程创建成功");
return 0;
}
else
{
return 1;
}
}
/*********************************************************************
* @brief 新建任务模块的初始化工作
* @param[in] 无
* @return 0sucessful1fault
*********************************************************************/
int creatLogicCtrTaskEntry()
{
initTaskParam();
if (logic_initTaskRegister() != 0)
{
return 1;
}
if (creatLogicTaskEntry() != 0)
{
return 1;
}
return 0;
}
/*********************************************************************
* @brief 任务触发,读取数据库入参
* @param[in] 无
* @return
*********************************************************************/
void logic_taskTrigger()
{
int modeChange = 0;
// 读取是否参数更新
for (u_int16_t i = kSign_Logic_Start; i < kSign_Logic_End; i++)
{
stlogic.para_delivery.ParaChangeSign.ParaChangeUnion |= ((readWebSign(kSign_ShMem, i) == LOGIC_SIGN_MESSAGE) << i);
}
// 读取是否切换模式
if (LOGIC_SIGN_MESSAGE == readWebSign(kSign_ShMem, kSign_LogicMode))
{
writeWebSign(kSign_ShMem, kSign_LogicMode, 0);
modeChange = 1;
work_mode_set_t tempMode;
if (0 != kit_get_work_mode_set(&tempMode))
{
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
{
KITLOG(LOG_LOGIC_EN, INFO_EN, "获取调试配置失败 模式切换失败!!! %s ==> %s",workModeNames[stlogic.para_delivery.mode],workModeNames[tempMode.workMode]);
KITPTF(LOG_LOGIC_EN, INFO_EN, "获取调试配置失败 模式切换失败!!! %s ==> %s",workModeNames[stlogic.para_delivery.mode],workModeNames[tempMode.workMode]);
return;
}
}
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
{
KITLOG(LOG_LOGIC_EN, INFO_EN, "模式切换 %s ==> %s",workModeNames[stlogic.para_delivery.mode],workModeNames[tempMode.workMode]);
KITPTF(LOG_LOGIC_EN, INFO_EN, "模式切换 %s ==> %s",workModeNames[stlogic.para_delivery.mode],workModeNames[tempMode.workMode]);
return;
}
stlogic.para_delivery.mode = tempMode.workMode;
}
stlogic.para_delivery.task_params.protect.protectSign = (readWebSign(kSign_ShMem, kSign_Protect) == LOGIC_SIGN_MESSAGE);
stlogic.para_delivery.task_params.distr.powerSign = (readWebSign(kSign_ShMem, kSign_ActivePower) == LOGIC_SIGN_MESSAGE);
//数据库获取参数
/****保护****/
if (LOGIC_SIGN_MESSAGE == stlogic.para_delivery.task_params.protect.protectSign)
{
if (1 == logic_getProtectParam())
{
KITLOG(LOG_LOGIC_EN, INFO_EN, "保护参数错误");
KITPTF(LOG_LOGIC_EN, INFO_EN, "保护参数错误");
return;
}
stlogic.para_delivery.task_params.protect.protectSign = LOGIC_SIGN_UPLOAD;
}
/****功率分配****/
if (LOGIC_SIGN_MESSAGE == stlogic.para_delivery.task_params.distr.powerSign)
{
if (1 == logic_getPowerDistrParam())
{
KITLOG(LOG_LOGIC_EN, INFO_EN, "分配参数错误");
KITPTF(LOG_LOGIC_EN, INFO_EN, "分配参数错误");
return;
}
// 成功读完清除标志
stlogic.para_delivery.task_params.distr.powerSign = LOGIC_SIGN_UPLOAD;
}
//判定是否模式和参数统一
switch (stlogic.para_delivery.mode)
{
case E_TACTIC_MODE_DEBUG: // 调试模式
if (stlogic.para_delivery.ParaChangeSign.bits.debug || modeChange)
{
writeWebSign(kSign_ShMem, kSign_LogicDebug, LOGIC_SIGN_NONE);
if (1 == logic_debugParamUpdate())
{
KITLOG(LOG_LOGIC_EN, INFO_EN, "调试参数错误");
KITPTF(LOG_LOGIC_EN, INFO_EN, "调试参数错误");
}
// 成功读完清除标志
stlogic.para_delivery.ParaChangeSign.bits.debug = LOGIC_SIGN_NONE;
}
break;
case E_TACTIC_MODE_PEAKVALLY: // 削峰填谷模式
if (stlogic.para_delivery.ParaChangeSign.bits.peakValley || modeChange)
{
writeWebSign(kSign_ShMem, kSign_LogicPeakValley, LOGIC_SIGN_NONE);
if (1 == logic_peakValleyUpdate())
{
KITLOG(LOG_LOGIC_EN, INFO_EN, "削峰填谷参数错误");
KITPTF(LOG_LOGIC_EN, INFO_EN, "削峰填谷参数错误");
}
// 成功读完清除标志
stlogic.para_delivery.ParaChangeSign.bits.peakValley = LOGIC_SIGN_NONE;
}
break;
case E_TACTIC_MODE_DEMANDRES: // 需求响应模式
/* 暂未实现 */
break;
case E_TACTIC_MODE_LOADTRACK: // 负载跟踪模式
/* 暂未实现 */
break;
case E_TACTIC_MODE_DMDCTRL: // 需量控制
/* 暂未实现 */
break;
case E_TACTIC_MODE_PFCTRL: // 功率因数
/* 暂未实现 */
break;
default:
/*无模式*/
stlogic.para_delivery.task_params.distr.power = 0;
stlogic.para_delivery.task_params.protect.power = 0;
break;
}
}
/*********************************************************************
* @brief 调度函数,根据收到的指令执行对应任务链
* @param[in] task_param 任务参数
* @return 0: 成功, 1: 错误(如索引无效)
*********************************************************************/
int logic_taskExe(work_mode_e mode)
{
if (mode >= E_TACTIC_MODE_END)
{
// printf("Invalid task group index!\n");
return 1; // 返回错误
}
tast_register_execute *current = task_group[mode];
// 遍历并执行任务链表中的所有任务
while (current != NULL)
{
current->task(); // 执行当前任务
current = current->next; // 移动到下一个任务
}
return 0; // 成功
}
/*****************************************************************************
* @brief 创建任务调度线程
* @param[in] 无
* @return 无
*****************************************************************************/
void *creatLogicTaskThread(void *arg)
{
task_params_t *task_param_in = (task_params_t *)arg;
while (stlogic.exitTaskFlag == 0)
{
logic_taskTrigger();
logic_getRTDBParams();
if (0 != logic_taskExe(task_param_in->mode))
{
// 处理调度错误,可以记录日志
KITLOG(LOG_LOGIC_EN, ERROR_EN, "任务调度失败,参数无效");
usleep(50000); // 50ms sleep
continue;
}
logic_paramUpload();
usleep(20000); // 20ms sleep
}
pthread_exit(NULL);
}
void example_task1()
{
;
}