删除无效文件
This commit is contained in:
parent
ea4d11107a
commit
23f43f43a5
|
@ -52,8 +52,6 @@ add_executable(${ProjectName}
|
|||
|
||||
bsp/bsp_data_mode.c
|
||||
|
||||
bsp/bsp_mqttClient.c
|
||||
bsp/bsp_mqttAsync.c
|
||||
bsp/bsp_msgQueue.c
|
||||
|
||||
driver/drv_tcp_client.c
|
||||
|
@ -70,17 +68,6 @@ add_executable(${ProjectName}
|
|||
kernel/kit_core.c
|
||||
|
||||
mw/mw_schedule_handle.c
|
||||
|
||||
logic/logic_main.c
|
||||
logic/logic_peakvalley.c
|
||||
logic/logic_protected.c
|
||||
logic/logic_demandctrl.c
|
||||
logic/logic_debug.c
|
||||
logic/logic_power_distr.c
|
||||
logic/logic_task_data.c
|
||||
logic/logic_dido.c
|
||||
logic/logic_bcu2bsu.c
|
||||
logic/logic_tempCtrl.c
|
||||
)
|
||||
|
||||
# 添加编译选项
|
||||
|
|
|
@ -462,19 +462,19 @@ void regeditThreadEntry(void *map_t) // 创建线程入口
|
|||
creatGetLocalParamTaskEntry(100); // 100*50 ms 换算5秒执行一次
|
||||
|
||||
/* 创建各种转发任务 */
|
||||
creatNetMqttTaskEntry();
|
||||
//creatNetMqttTaskEntry();
|
||||
|
||||
/*创建存储任务*/
|
||||
creatScheduledStorageTask();
|
||||
|
||||
/*创建gpio任务*/
|
||||
creatGpioModTaskEntry(10); // 初始化 GPIO模块 10*50 ms 换算500ms执行一次
|
||||
//creatGpioModTaskEntry(10); // 初始化 GPIO模块 10*50 ms 换算500ms执行一次
|
||||
|
||||
/*创建温控任务*/
|
||||
creatLogicTempCtrlEntry();
|
||||
//creatLogicTempCtrlEntry();
|
||||
|
||||
/*创建策略任务*/
|
||||
creatLogicCtrTaskEntry();
|
||||
//creatLogicCtrTaskEntry();
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
|
|
|
@ -27,8 +27,7 @@
|
|||
#include "bsp_ntp.h"
|
||||
#include "kit_log.h"
|
||||
#include "app_parse.h"
|
||||
#include "bsp_mqttClient.h"
|
||||
#include "logic_main.h"
|
||||
|
||||
#include "drv_gpio.h"
|
||||
|
||||
#define THREAD_PRIORITY_MAX 90
|
||||
|
|
|
@ -1,153 +0,0 @@
|
|||
|
||||
#include "bsp_mqttAsync.h"
|
||||
|
||||
volatile int finished = 0;
|
||||
Queue g_qMsg;
|
||||
Queue g_qHistory;
|
||||
// 当连接成功时的回调函数
|
||||
void onConnect(void *context, MQTTAsync_successData *response)
|
||||
{
|
||||
|
||||
printf("Connected successfully\n");
|
||||
MQTTAsync client = (MQTTAsync)context;
|
||||
int rc;
|
||||
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
|
||||
|
||||
// 设置响应选项
|
||||
opts.onSuccess = NULL;
|
||||
opts.onFailure = NULL;
|
||||
opts.context = client;
|
||||
|
||||
// 订阅指定的主题
|
||||
if ((rc = MQTTAsync_subscribe(client, TOPIC, QOS, &opts)) != MQTTASYNC_SUCCESS)
|
||||
{
|
||||
printf("Failed to start subscribe, return code %d\n", rc);
|
||||
}
|
||||
|
||||
printf("Subscribed to topic %s with QOS %d\n", TOPIC, QOS);
|
||||
}
|
||||
|
||||
// 当连接失败时的回调函数
|
||||
void onConnectFailure(void *context, MQTTAsync_failureData *response)
|
||||
{
|
||||
// 创建一个新的断点记录
|
||||
|
||||
// 尝试重新连接
|
||||
|
||||
while (1)
|
||||
{
|
||||
// 尝试重新连接
|
||||
|
||||
// 将存储的历史数据入数据库
|
||||
}
|
||||
}
|
||||
|
||||
// 当成功断开连接时的回调函数
|
||||
void onDisconnect(void *context, MQTTAsync_successData *response)
|
||||
{
|
||||
printf("Disconnected successfully\n");
|
||||
finished = 1; // 设置完成标志以终止任务
|
||||
}
|
||||
|
||||
// 当订阅失败时的回调函数
|
||||
void onSubscribeFailure(void *context, MQTTAsync_failureData *response)
|
||||
{
|
||||
printf("Subscribe failed, rc %d\n", response ? response->code : 0);
|
||||
finished = 1; // 设置完成标志以终止任务
|
||||
}
|
||||
|
||||
// 当消息到达时的回调函数
|
||||
int messageArrived(void *context, char *topicName, int topicLen, MQTTAsync_message *message)
|
||||
{
|
||||
printf("Message arrived on topic %s\n", topicName);
|
||||
printf("Message: %.*s\n", message->payloadlen, (char *)message->payload);
|
||||
|
||||
// 释放消息和主题名内存
|
||||
MQTTAsync_freeMessage(&message);
|
||||
MQTTAsync_free(topicName);
|
||||
return 1; // 消息处理成功
|
||||
}
|
||||
|
||||
// 发布消息的函数
|
||||
void publishMessage(MQTTAsync client)
|
||||
{
|
||||
MQTTAsync_responseOptions opts = MQTTAsync_responseOptions_initializer;
|
||||
MQTTAsync_message pubmsg = MQTTAsync_message_initializer;
|
||||
Queue *pNode = (Queue *)&g_qMsg;
|
||||
while (!isQueueEmpty(pNode))
|
||||
{
|
||||
|
||||
// 设置消息参数
|
||||
pubmsg.payload = pNode->head->data;
|
||||
pubmsg.payloadlen = (int)strlen(pNode->head->data);
|
||||
pubmsg.qos = QOS;
|
||||
pubmsg.retained = 0;
|
||||
opts.onSuccess = NULL;
|
||||
opts.onFailure = NULL;
|
||||
opts.context = client;
|
||||
|
||||
int rc = 0;
|
||||
// 发送消息
|
||||
if ((rc = MQTTAsync_sendMessage(client, pNode->head->topic, &pubmsg, &opts)) != MQTTASYNC_SUCCESS)
|
||||
{
|
||||
// 发送成功,则将消息出队
|
||||
dequeue(pNode);
|
||||
printf("Failed to publish message, return code %d\n", rc);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 修改主题为历史数据,入历史数据队列,并将元素出队
|
||||
pNode->head->topic;
|
||||
enqueue(&g_qHistory, pNode->head);
|
||||
dequeue(pNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 主任务函数,管理MQTT连接、订阅和发布
|
||||
int MQTTAsyncTask(int argc, char *argv[])
|
||||
{
|
||||
initQueue(&g_qMsg);
|
||||
initQueue(&g_qHistory);
|
||||
MQTTAsync client;
|
||||
MQTTAsync_connectOptions conn_opts = MQTTAsync_connectOptions_initializer;
|
||||
|
||||
// 创建MQTT客户端
|
||||
MQTTAsync_create(&client, ADDRESS, CLIENTID, MQTTCLIENT_PERSISTENCE_NONE, NULL);
|
||||
|
||||
// 设置回调函数
|
||||
MQTTAsync_setCallbacks(client, NULL, NULL, messageArrived, NULL);
|
||||
|
||||
// 设置连接选项
|
||||
conn_opts.keepAliveInterval = 20; // 保持连接的心跳间隔
|
||||
conn_opts.cleansession = 1; // 创建一个会话
|
||||
conn_opts.onSuccess = onConnect; // 设置连接成功的回调
|
||||
conn_opts.onFailure = onConnectFailure; // 设置连接失败的回调
|
||||
conn_opts.context = client;
|
||||
|
||||
// 发起连接
|
||||
if (MQTTAsync_connect(client, &conn_opts) != MQTTASYNC_SUCCESS)
|
||||
{
|
||||
printf("Failed to start connect\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// 等待任务完成
|
||||
while (!finished)
|
||||
{
|
||||
usleep(10000L); // 微小延迟,用以减少CPU占用
|
||||
}
|
||||
//void *msg = NULL;
|
||||
// 发布消息到主题
|
||||
publishMessage(client);
|
||||
|
||||
MQTTAsync_disconnectOptions disc_opts = MQTTAsync_disconnectOptions_initializer;
|
||||
disc_opts.onSuccess = onDisconnect; // 设置断开成功的回调
|
||||
|
||||
// 断开连接
|
||||
MQTTAsync_disconnect(client, &disc_opts);
|
||||
|
||||
// 销毁MQTT客户端
|
||||
MQTTAsync_destroy(&client);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include "MQTTAsync.h"
|
||||
#include "bsp_msgQueue.h"
|
||||
#define ADDRESS "tcp://broker.hivemq.com:1883"
|
||||
#define CLIENTID "ExampleMQTTAsyncClient"
|
||||
#define TOPIC "test/topic"
|
||||
#define PAYLOAD "Hello MQTT"
|
||||
#define QOS 1
|
||||
#define TIMEOUT 10000L
|
File diff suppressed because it is too large
Load Diff
|
@ -1,367 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 1997-2050, . POWER SUPPLY CO., LTD.
|
||||
* @file bsp_mqttClient.c
|
||||
* @brief mqtt通信客户端程序
|
||||
* @author mdy
|
||||
* @date 2024-09-29
|
||||
* @remark
|
||||
*****************************************************************************/
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
#include "MQTTClient.h"
|
||||
#include "MQTTAsync.h"
|
||||
#include <cjson/cJSON.h>
|
||||
#include "bsp_rtdb.h"
|
||||
#include "bsp_comm.h"
|
||||
#include <semaphore.h>
|
||||
#include <signal.h>
|
||||
#include "kit_db.h"
|
||||
#include "kit_core.h"
|
||||
#include "logic_bcu2bsu.h"
|
||||
#include "logic_main.h"
|
||||
#include "logic_dido.h"
|
||||
|
||||
#define D_MAX_MQTT_DEV_POINT_NUM (2000) // 每类设备最大的上云测点个数
|
||||
#define D_MAX_DEV_NUM (100) // 子设备最大数量
|
||||
#define D_MAX_DEV_NAME_LEN (100)
|
||||
#define D_MAX_DEV_KEYWORD (11)
|
||||
#define D_MAX_IPV4_LENGTH (16)
|
||||
#define D_MAX_USERNAME_LENGTH (20)
|
||||
#define D_MAX_PASSWORD_LENGTH (20)
|
||||
#define QOS 1
|
||||
#define TIMEOUT 10000L
|
||||
#define MQTT_ROOT_TOPIC_KEY "root"
|
||||
#define MQTT_PERIOD_TOPIC_KEY "period"
|
||||
#define MQTT_CHANGE_TOPIC_KEY "change"
|
||||
#define MQTT_HISTORY_TOPIC_KEY "history"
|
||||
#define MQTT_CONTROL_TOPIC_KEY "control"
|
||||
#define MQTT_READ_TOPIC_KEY "read"
|
||||
#define MQTT_REPLY_TOPIC_KEY "reply"
|
||||
#define MQTT_PAYLOAD_MAX_LEN (1024 * 1024) // 能源云限制报文长度最大为1MB
|
||||
#define MQTT_PERIOD_SEND_FAIL_WORDS "period send fail." // 周期发送失败
|
||||
#define D_MAX_TOPIC_NUM (7)
|
||||
#define MQTT_STATUS_DONT_TRANS -100 // 还未执行完策略,当前的配置参数不上传
|
||||
#define MQTT_STATUS_CFG_UPLOADED 100 // 策略配置传送完毕
|
||||
#define MAX_MQTT_HISTORY_MSG_NUM 1000
|
||||
#define D_PERIODSEND_T_SEQ (0)
|
||||
#define D_HISTORY_T_SEQ (1)
|
||||
#define D_DATACHK_T_SEQ (2)
|
||||
#define D_MAX_THREAD_NUM (3)
|
||||
#define D_STR_CONNECT_WORD "已连接"
|
||||
#define D_STR_DISCONN_WORD "已断开"
|
||||
#define RECORDNETSTATUS(word) kit_insert_lost_contact_record(word);
|
||||
|
||||
// MQTT主题枚举定义
|
||||
typedef enum
|
||||
{
|
||||
kEmsTopicType_Start,
|
||||
kEmsTopicType_root = kEmsTopicType_Start, // 初始化主题
|
||||
kEmsTopicType_period, // 周期上报主题
|
||||
kEmsTopicType_change, // 突变上报主题
|
||||
kEmsTopicType_history, // 历史数据上报主题
|
||||
kEmsTopicType_control, // 控制指令下发主题
|
||||
kEmsTopicType_read, // 读参数主题
|
||||
kEmsTopicType_reply_control, // 回复控制指令下发主题
|
||||
kEmsTopicType_reply_read, // 回复读参数主题
|
||||
kEmsTopicType_End = kEmsTopicType_reply_read,
|
||||
} ems_topic_type_e;
|
||||
|
||||
// 数据变化事件分类
|
||||
typedef enum
|
||||
{
|
||||
kEvent_topo_send = 1, // 拓扑发送完成
|
||||
kEvent_has_history_record = 2, // 存在历史记录record
|
||||
kEvent_change_devTopo = 4, // 设备列表变化
|
||||
kEvent_rename_anydev = 8, // 重命名子设备
|
||||
kEvent_int_change = 16, // 子设备整型测点值变化越死区
|
||||
kEvent_float_change = 32, // 子设备浮点型测点值变化越死区
|
||||
kEvent_pointlistcfg_change = 64, // 设备测点配置改变
|
||||
kEvent_Reconnect_success = 128, // MQTT重连成功
|
||||
kEvent_Reconnect_failed = 256, // MQTT重连失败
|
||||
kEvent_Period_Task_begin = 512, // 周期发送任务启动完成
|
||||
|
||||
} kEvent_ems_data;
|
||||
|
||||
// EMS总的工作模式
|
||||
typedef enum
|
||||
{
|
||||
KEms_cfg_Start, // 无
|
||||
KEms_cfg_DEBUG, // 调试模式
|
||||
KEms_cfg_PEAKVALLY, // 削峰填谷模式
|
||||
KEms_cfg_DEMANDRES, // 需求响应模式
|
||||
KEms_cfg_LOADTRACK, // 负载跟踪模式
|
||||
KEms_cfg_DMDCTRL, // 需量控制
|
||||
KEms_cfg_PFCTRL, // 功率因数
|
||||
KEms_cfg_Protect, // 保护策略
|
||||
KEms_cfg_END,
|
||||
} cfgType_e;
|
||||
typedef enum
|
||||
{
|
||||
kQos_0,//最多交付一次
|
||||
kQos_1,//至少交付一次
|
||||
kQos_2,//只交付一次
|
||||
}Qos_e;
|
||||
// 拓扑结构结构体
|
||||
typedef struct
|
||||
{
|
||||
int dbId; // 键:数据库中的 ID
|
||||
topology_t *topology; // 值:指向 topology_t 结构体的指针
|
||||
UT_hash_handle hh; // uthash 处理句柄,使结构体可哈希
|
||||
} topology_hash_entry_t;
|
||||
|
||||
// MQTT单个测点的db查找表
|
||||
typedef struct
|
||||
{
|
||||
// 取测点使用参数
|
||||
rtdb_type_e dbType; // 数据库类型
|
||||
uint16_t devType; // 设备类型
|
||||
uint16_t devId; // 区分同类型不同设备实体的标识
|
||||
uint16_t pointId; // 测点id
|
||||
up_dis_config_type_e txOrRx; // 是上传的测点还是接收云端指令0-仅上报 1-下发
|
||||
bool whether; // 接收用户输入,1-上传:0-不上传
|
||||
double value; // 该测点值的备份用于检测变化事件
|
||||
bool ifchg; // 是否需要变化上送
|
||||
} mqtt2db_t;
|
||||
typedef mqtt2db_t mqttGetDBElem;
|
||||
typedef mqtt2db_t mqttSetDBElem;
|
||||
|
||||
void pointListener(mqtt2db_t *tab);
|
||||
// 一个设备实体的测点信息表结构体
|
||||
typedef struct
|
||||
{
|
||||
mqttGetDBElem rtdbGetTab[D_MAX_MQTT_DEV_POINT_NUM]; // 实时数据库查找表,对应上传点位
|
||||
mqttSetDBElem rtdbSetTab[D_MAX_MQTT_DEV_POINT_NUM]; // 实时数据库查找表,对应相应云端控制的下发点位,云端写RTDB操作只能操作该表中的点
|
||||
bool bChgFlag; // 变化标志
|
||||
int txcount; // 记录加入payload的测点数量
|
||||
int rxcount;
|
||||
} payloadlist_t;
|
||||
|
||||
// mqtt通信参数结构体
|
||||
typedef struct
|
||||
{
|
||||
char stationName[100]; // 站点名称
|
||||
char stationID[20]; // 站点id
|
||||
dev_type_e devType; // 设备类别
|
||||
char *devName[D_MAX_DEV_NAME_LEN]; // 设备名称
|
||||
char sn[D_MAX_DEV_NUM][60]; // 设备SN
|
||||
char identifier[60]; // 消息服务标识
|
||||
int devNum; // 设备数量
|
||||
payloadlist_t pllist[D_MAX_DEV_NUM]; // 该类设备下,每个设备实体一张mqtt2db关联表,依据该表中的元素操作RTDB
|
||||
bool bChgFlag;
|
||||
} mqtt_option_map_t;
|
||||
// payloadlists
|
||||
|
||||
// 保留给回调函数的上下文结构体
|
||||
typedef struct
|
||||
{
|
||||
MQTTClient client;
|
||||
MQTTClient_connectOptions connopts;
|
||||
mqtt_lib_t mlib;
|
||||
int modeword;
|
||||
} ConnContext;
|
||||
|
||||
//所有算法配置的联合体
|
||||
typedef union
|
||||
{
|
||||
peakvalley_zone_tab_t pkvly; // 削峰填谷参数 IN
|
||||
demandRes_params_t demand; // 需求响应参数
|
||||
loadTrack_params_t loadTrack; // 负载跟踪参数
|
||||
debug_params_t debug; // 调试参数 IN
|
||||
protect_params_t protect; // 保护参数 IN
|
||||
power_distr_t distr; // 功率分配参数 IN
|
||||
} logic_Params;
|
||||
|
||||
//中断记录与历史数据数组关联的结构体
|
||||
typedef struct
|
||||
{
|
||||
break_record_t record; // 中断记录
|
||||
UT_array *dataArray; // 其关联的数据存储集合
|
||||
} break_record_with_data_t;
|
||||
|
||||
//从云端MQTT报文返回的信息结构体
|
||||
typedef struct
|
||||
{
|
||||
char *transaction;
|
||||
int modeWord;
|
||||
} arvcfgInfo_ret_t;
|
||||
typedef void (*setCfgCB)(void *);
|
||||
void setdbgCB(void *arg);
|
||||
void setPkvlCB(void *arg);
|
||||
void setDmdRspCB(void *arg);
|
||||
void setLoadTrackCB(void *arg);
|
||||
void setDmdCtrlCB(void *arg);
|
||||
void setPFCtrlCB(void *arg);
|
||||
/*****************************************************************************
|
||||
* @brief 消息传送成功触发的回调函数
|
||||
* @param[in] context: MQTT上下文结构体
|
||||
* @param[in] dt: 标识符
|
||||
* @return NONE
|
||||
*****************************************************************************/
|
||||
void deliveredCB(void *context, MQTTClient_deliveryToken dt);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 消息接收成功触发的回调函数
|
||||
* @param[in] context: MQTT上下文结构体
|
||||
* @param[in] topicName:主题
|
||||
* @param[in] topicLen:主题长度
|
||||
* @return
|
||||
*****************************************************************************/
|
||||
int msgarrvdCB(void *context, char *topicName, int topicLen, MQTTClient_message *message);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 连接丢失触发的回调函数
|
||||
* @param[in] context: MQTT上下文结构体
|
||||
* @param[in] cause:中断原因
|
||||
* @return NONE
|
||||
*****************************************************************************/
|
||||
void connlostCB(void *context, char *cause);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 更新MQTT参数
|
||||
* @param[in] mlt: MQTT连接配置
|
||||
* @param[in] map:测点配置表
|
||||
* @return NONE
|
||||
*****************************************************************************/
|
||||
void updateMqttPara(mqtt_lib_t *mlt, mqtt_option_map_t *map);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 更新MQTT参数
|
||||
* @param[in] mlt: MQTT连接配置
|
||||
* @param[in] map:测点配置表
|
||||
* @return NONE
|
||||
*****************************************************************************/
|
||||
int chkDataChange(mqtt_option_map_t *now, mqtt_option_map_t *old);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief MQTT周期发送线程
|
||||
* @param[in] arg: 可选参数
|
||||
* @return NONE
|
||||
*****************************************************************************/
|
||||
void *periodSendTask(void *arg);
|
||||
/*****************************************************************************
|
||||
* @brief 数据变化监视器
|
||||
* @param[in] arg: 可选参数
|
||||
* @return NONE
|
||||
************************************************************************/
|
||||
void *dataChgMonitor(void *arg);
|
||||
/*****************************************************************************
|
||||
* @brief 从MQTT字符串中获取关键字返回主题类型
|
||||
* @param[in] topic: MQTT主题字符串
|
||||
* @return 主题类型枚举值
|
||||
*****************************************************************************/
|
||||
int getKeywordsByTopic(char *topic);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 根据设备大类组包
|
||||
* @param[in] payload:目标字符串指针
|
||||
* @param[in] type:设备类型
|
||||
* @param[in] tot:设备点表结构体
|
||||
* @return NONE
|
||||
*****************************************************************************/
|
||||
void genDevGrpPeriodPayload(char *payload, dev_type_e type, mqtt_option_map_t *tot);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 递归添加子节点到 JSON 结构中
|
||||
* @param[in] parentArray: 父节点的 JSON 数组
|
||||
* @param[in] parentId: 父节点的 ID
|
||||
* @param[in] topologyById: 存储拓扑信息的哈希表
|
||||
* @return 无
|
||||
*****************************************************************************/
|
||||
void addChildrenToJson(cJSON *parentArray, int parentId, topology_hash_entry_t *topologyById);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 将数据库中的 EMS 设备拓扑结构数据转换为 JSON 字符串
|
||||
* @param[out] json: 用于存储生成的 JSON 字符串的缓冲区。确保该缓冲区有足够的空间容纳生成的 JSON 字符串。
|
||||
* @return 0-成功 1-失败
|
||||
*****************************************************************************/
|
||||
int getTopologyJsonByDb(char **json);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 将设备类型枚举值转换为与云端通信协议中的字符串
|
||||
* @param[out] type:设备类型枚举值
|
||||
* @return 设备类型缩写字符串
|
||||
*****************************************************************************/
|
||||
char *devTypeToString(dev_type_e type);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 比较两个设备节点是否相同
|
||||
* @param[in] a:左操作数
|
||||
* @param[in] b:左操作数
|
||||
* @return 0-不同,1-相同
|
||||
*****************************************************************************/
|
||||
bool ifSameTopoElem(const topology_t *a, const topology_t *b);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 比较两个设备拓扑是否相同
|
||||
* @param[in] arr1:左操作数
|
||||
* @param[in] arr2:左操作数
|
||||
* @return 0-不同,1-相同
|
||||
*****************************************************************************/
|
||||
bool chkTopoDiff(UT_array *arr1, UT_array *arr2);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 获得当前时间戳字符串
|
||||
* @return 当前时间戳字符串
|
||||
*****************************************************************************/
|
||||
char *getTmstr2();
|
||||
/*****************************************************************************
|
||||
* @brief 解析云端消息
|
||||
* @param[in] jsonString:云端消息json串
|
||||
* @param[in] arr:指向配置参数的指针
|
||||
* @return 0-成功;1-失败
|
||||
*****************************************************************************/
|
||||
arvcfgInfo_ret_t parseEmsCfgJson(const char *jsonString, logic_Params *lP);
|
||||
/*****************************************************************************
|
||||
* @brief 单个设备测点值是否改变
|
||||
* @param[in] tot: mqtt_lib_t中的主题字符串指针
|
||||
* @return false-未改变 true-改变
|
||||
*****************************************************************************/
|
||||
bool ifSingledevPointsChg(payloadlist_t *list);
|
||||
/*****************************************************************************
|
||||
* @brief 单个设备测点值是否改变
|
||||
* @param[in] map: 设备组测点列表
|
||||
* @return false-未改变 true-改变
|
||||
*****************************************************************************/
|
||||
bool ifDevGrpPointsChg(mqtt_option_map_t *map);
|
||||
/*****************************************************************************
|
||||
* @brief 装载不同设备组变化上送主题有效载荷
|
||||
* @param[in] topic: mqtt_lib_t中的主题字符串指针
|
||||
* @param[in] payload:主题类型枚举,枚举与mqtt_lib_t中的成员应对应,请确保payload的缓冲区长度足够
|
||||
* @return NONE
|
||||
*****************************************************************************/
|
||||
int genChgDevGrpPeriodPayload(char *payload, dev_type_e type, mqtt_option_map_t *tot);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 根据云端下发的配置信息,将参数写入联合体
|
||||
* @return 设备类型字符串
|
||||
*****************************************************************************/
|
||||
int parseStrategyJsonObject(cJSON *json, int modeword, logic_Params *lp);
|
||||
/*****************************************************************************
|
||||
* @brief 根据配置信息和模式组装成 JSON 字符串,并包含额外的顶层字段
|
||||
* @param[in] arvcfgInfo_ret_t cfg 结构包含模式字、交易标识等信息
|
||||
* void *arg 指向配置数据的指针(例如,指向 logic_Params 的指针)
|
||||
* @return char* 表示 JSON 字符串(需要调用者释放)
|
||||
*****************************************************************************/
|
||||
char *createStrategyCfgJsonString(arvcfgInfo_ret_t cfg, const void *arg, int rw);
|
||||
/*****************************************************************************
|
||||
* @brief 判断通信是否断开
|
||||
* @param[in] arg:tcp连接上下文
|
||||
* @return 0-中断;1-正常
|
||||
*****************************************************************************/
|
||||
bool is_mqtt_connected();
|
||||
/*****************************************************************************
|
||||
* @brief MQTT主函数
|
||||
* @param[in] arg: 可选参数
|
||||
* @return NONE
|
||||
*****************************************************************************/
|
||||
void *MqttTask(void *arg);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief MQTT转发任务入口
|
||||
* @return NONE
|
||||
*****************************************************************************/
|
||||
void creatNetMqttTaskEntry();
|
|
@ -1,91 +0,0 @@
|
|||
|
||||
|
||||
#include "logic_bcu2bsu.h"
|
||||
#define MAX_BSU_MQTT_POINTNUM (24)
|
||||
// 定义哈希表的结构
|
||||
|
||||
// 声明全局变量
|
||||
#if 1
|
||||
// 初始化全局哈希表
|
||||
void init_bcu_bsu_map(BcuBsuMap **bsu_map)
|
||||
{
|
||||
// 原始映射数组
|
||||
bcu2bsu_t g_transBcu[] =
|
||||
{
|
||||
|
||||
{kBsu_SysVolt, kBcu_TotalVolt},
|
||||
{kBsu_SysCur, kBcu_TotalCur},
|
||||
{kBsu_SOC, kBcu_SOC},
|
||||
{kBsu_SOH, kBcu_SOH},
|
||||
{kBsu_MaxCellTemp, kBcu_MaxCellTemp},
|
||||
{kBsu_MinCellTemp, kBcu_MinCellTemp},
|
||||
{kBsu_TotalChgE, kBcu_TotalChgCap},
|
||||
{kBsu_TotalDChgE, kBcu_TotalDisChgCap},
|
||||
};
|
||||
for (int i = 0; i < sizeof(g_transBcu) / sizeof(g_transBcu[0]); i++)
|
||||
{
|
||||
BcuBsuMap *entry = (BcuBsuMap *)malloc(sizeof(BcuBsuMap));
|
||||
if (entry == NULL)
|
||||
{
|
||||
// 处理内存分配失败
|
||||
perror("无法为 BcuBsuMap 分配内存");
|
||||
return;
|
||||
}
|
||||
entry->bsupointId = g_transBcu[i].bsupointId;
|
||||
entry->bcupointId = g_transBcu[i].bcupointId;
|
||||
HASH_ADD_INT(*bsu_map, bsupointId, entry);
|
||||
}
|
||||
}
|
||||
|
||||
// 清理全局哈希表
|
||||
void free_bcu_bsu_map(BcuBsuMap *bsu_map)
|
||||
{
|
||||
BcuBsuMap *current_entry, *tmp;
|
||||
|
||||
HASH_ITER(hh, bsu_map, current_entry, tmp)
|
||||
{
|
||||
HASH_DEL(bsu_map, current_entry);
|
||||
free(current_entry);
|
||||
}
|
||||
}
|
||||
|
||||
// 使用哈希表
|
||||
int bcuTransbsuPoint(BcuBsuMap *hash_table, uint16_t key)
|
||||
{
|
||||
int value = 0;
|
||||
// BcuBsuMap *element = NULL;
|
||||
// if (element != NULL)
|
||||
// {
|
||||
// value = element->bcupointId; // 找到值
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// value = -1;
|
||||
// }
|
||||
BcuBsuMap *current;
|
||||
for (current = hash_table; current != NULL; current = current->hh.next)
|
||||
{
|
||||
if(current->bsupointId==key)
|
||||
{
|
||||
value = current->bcupointId;
|
||||
break;
|
||||
}
|
||||
value = -1;
|
||||
}
|
||||
|
||||
return value; // 未找到
|
||||
}
|
||||
|
||||
double getBsuRTDBPointValue(BcuBsuMap *bsu_map, rtdb_type_e type, uint16_t devType, uint16_t devId, uint16_t pointId)
|
||||
{
|
||||
if (devType == kDev_Type_BSU && bcuTransbsuPoint(bsu_map, pointId) != -1)
|
||||
{
|
||||
return getRtdbPointValue(type, kDev_Type_BCU, 0, bcuTransbsuPoint(bsu_map, pointId));
|
||||
}
|
||||
else
|
||||
{
|
||||
return getRtdbPointValue(type, devType, devId, pointId);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,36 +0,0 @@
|
|||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
#include "bsp_rtdb.h"
|
||||
#include "kit_math.h"
|
||||
#include "kit_data.h"
|
||||
#include "kit_db.h"
|
||||
#include "utextend.h"
|
||||
#include "uthash.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t bsupointId;
|
||||
uint16_t bcupointId;
|
||||
} bcu2bsu_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t bsupointId; // key
|
||||
int bcupointId; // value
|
||||
UT_hash_handle hh; // makes this structure hashable
|
||||
} BcuBsuMap;
|
||||
|
||||
// 初始化全局哈希表
|
||||
void init_bcu_bsu_map(BcuBsuMap **bsu_map);
|
||||
|
||||
// 清理全局哈希表
|
||||
void free_bcu_bsu_map(BcuBsuMap *bsu_map);
|
||||
|
||||
// 使用哈希表
|
||||
int bcuTransbsuPoint(BcuBsuMap *bsu_map, uint16_t bsupointId);
|
||||
|
||||
double getBsuRTDBPointValue(BcuBsuMap *bsu_map, rtdb_type_e type, uint16_t devType, uint16_t devId, uint16_t pointId);
|
|
@ -1,210 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_comm.h
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/09/20
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#ifndef __LOGIC_COMMON_H__
|
||||
#define __LOGIC_COMMON_H__
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
#include <stdatomic.h>
|
||||
#include "bsp_rtdb.h"
|
||||
#include "kit_math.h"
|
||||
#include "kit_data.h"
|
||||
#include "kit_db.h"
|
||||
#include "../kernel/kit_log.h"
|
||||
#include "utextend.h"
|
||||
#include "logic_debug.h"
|
||||
#include "logic_demandctrl.h"
|
||||
#include "logic_peakvalley.h"
|
||||
#include "logic_power_distr.h"
|
||||
#include "logic_protected.h"
|
||||
|
||||
#define LOGIC_SIGN_NONE 0
|
||||
#define LOGIC_SIGN_MESSAGE 1
|
||||
#define LOGIC_SIGN_UPLOAD 2
|
||||
|
||||
#define _PCS // 华三PCS目前 开关是两个点需要特殊处理
|
||||
// #define OTHER ;
|
||||
|
||||
// 系统状态
|
||||
typedef enum
|
||||
{
|
||||
kState_Start, // 无
|
||||
kState_Charging, // 充电
|
||||
kState_Discharging, // 放电
|
||||
kState_Standby, // 待机
|
||||
kState_Shutdown, // 停机
|
||||
kState_Fault, // 故障
|
||||
kState_end
|
||||
} state_e;
|
||||
|
||||
// 用于log打印 与 枚举state_e 强绑定
|
||||
extern const char* workModeNames[];
|
||||
|
||||
// 任务
|
||||
typedef enum
|
||||
{
|
||||
kTask_Start, // 无
|
||||
kTask_Debug, // 调试
|
||||
kTask_Peakvalley, // 削峰填谷
|
||||
kTask_DemdRespond, // 需求侧相应
|
||||
kTask_PowerTrace, // 负载跟踪
|
||||
kTask_demandCtrl, // 需量控制
|
||||
kTask_PFCtrl, // 功率因数
|
||||
kTask_end
|
||||
} task_e;
|
||||
|
||||
// 保护
|
||||
typedef enum
|
||||
{
|
||||
kProtect_start,
|
||||
kProtect_backFlow, // 逆流保护
|
||||
kProtect_freqAdj, // 调频保护
|
||||
kProtect_demand, // 需量保护
|
||||
kProtect_end
|
||||
} protect_e;
|
||||
|
||||
// 下发
|
||||
typedef struct
|
||||
{
|
||||
int runPeriod; // 运行周期 ms
|
||||
float_t power; // 目标功率 INOUT
|
||||
// 可配参数(未知)
|
||||
|
||||
} demandRes_params_t; // 需求响应参数(未实现 暂放在这里)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int runPeriod; // 运行周期 ms
|
||||
float_t power; // 目标功率 INOUT
|
||||
// 可配参数
|
||||
float_t percent; // 负载跟踪百分比 (10% = 0.1)
|
||||
} loadTrack_params_t; // 负载跟踪参数(未实现 暂放在这里)
|
||||
typedef struct
|
||||
{
|
||||
peakvalley_params_t pkvly; // 削峰填谷参数 IN
|
||||
demandRes_params_t demand; // 需求响应参数
|
||||
loadTrack_params_t loadTrack; // 负载跟踪参数
|
||||
debug_params_t debug; // 调试参数 IN
|
||||
|
||||
protect_params_t protect; // 保护参数 IN
|
||||
power_distr_t distr; // 功率分配参数 IN
|
||||
} logic_paramIn_t;
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned int Res1 : 9; // 预留位
|
||||
unsigned int debug : 1; // 调试模式
|
||||
unsigned int peakValley : 1; // 削峰填谷模式
|
||||
unsigned int demandRes : 1; // 需求响应模式
|
||||
unsigned int loadTrack : 1; // 负载跟踪模式
|
||||
unsigned int dmdCtrl : 1; // 需量控制
|
||||
unsigned int pfCtrl : 1; // 功率因数控制
|
||||
unsigned int Res2 : 17; // 预留位
|
||||
} bits;
|
||||
unsigned int ParaChangeUnion; // 用于一次性访问所有位的整型变量
|
||||
} SignFlags;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
work_mode_e mode; // 总工作模式 IN
|
||||
SignFlags ParaChangeSign; // 总参数更新标志
|
||||
logic_paramIn_t task_params; // 入参数据 IN
|
||||
} task_params_t; // 调试函数传参结构体
|
||||
|
||||
/*modbus客户端信息*/
|
||||
typedef struct
|
||||
{
|
||||
/*线程属性*/
|
||||
pthread_t tfd; // 线程fd
|
||||
uint8_t exitTaskFlag; // 退出线程标记
|
||||
uint8_t taskStateFlag; // 处理任务标志,0-无需处理,1-更新参数,2-参数上传
|
||||
task_params_t para_delivery; // 参数传递
|
||||
} logic_pthread_t;
|
||||
extern logic_pthread_t stlogic;
|
||||
|
||||
// 实时库获取数据
|
||||
typedef struct
|
||||
{
|
||||
uint16_t No;
|
||||
dev_type_e devType;
|
||||
uint16_t pointId;
|
||||
} ParamFromRTDB;
|
||||
|
||||
// 实时库参数枚举
|
||||
typedef enum
|
||||
{
|
||||
e_Logic_RTDB_start,
|
||||
e_Logic_totalAcPower = e_Logic_RTDB_start, // 总电表总有功功率
|
||||
e_Logic_emsActivePower, // 储能测总有功功率
|
||||
e_Logic_bmsSoc, // 实时每个柜子的BMS的SOC
|
||||
e_Logic_pcsMaxChaPower, // 最大充电功率
|
||||
e_Logic_pcsMaxDiscPower, // 最大放电功率
|
||||
e_Logic_nowBmsPower, // bms当前实时功率
|
||||
e_Logic_nowActiveDemand, // 实时需量
|
||||
e_Logic_distrPower, // 下发功率
|
||||
e_Logic_pcsSwitch, // PCS开关
|
||||
e_Logic_pcsState, // pcs在线状态
|
||||
e_Logic_bmsState, // bms在线状态
|
||||
e_Logic_emsMode, // ems运行模式
|
||||
// e_Logic_emsStat, // ems运行状态
|
||||
e_Logic_bsuMaxCellTemp, // BMS单体最高温度
|
||||
e_Logic_bsuMinCellTemp, // BMS单体最低温度
|
||||
// e_Logic_AcLiquidSwitch, // 液冷机组开关
|
||||
// e_Logic_AcLiquidHeatTemp, // 液冷机组制热温度
|
||||
// e_Logic_AcLiquidColdTemp, // 液冷机组制冷温度
|
||||
e_Logic_RTDB_end
|
||||
} ParamFromRTDB_e;
|
||||
|
||||
// 需量超阈值防护 负载预测
|
||||
void logic_protect_demandCtrl(protect_params_t *charge_params);
|
||||
|
||||
// 获取需执行的命令以及策略运行的所以参数
|
||||
void logic_getRTDBParams();
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 获取RTDB参数
|
||||
* @param[in] 枚举序号,参数指针,数据类型
|
||||
* @return 无
|
||||
*****************************************************************************/
|
||||
void logic_getValue(int No, void *value, data_type_e dataType);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 写入RTDB参数
|
||||
* @param[in] No 枚举序号(对应 RTDBtable 中的索引)
|
||||
* @param[in] value 参数指针,表示要写入的数据
|
||||
* @param[in] dataType 数据类型,表示写入的数据类型(Uint8、Int16 等)
|
||||
* @return 无
|
||||
*****************************************************************************/
|
||||
void logic_setValue(int No, void *value, uint16_t num, data_type_e dataType);
|
||||
|
||||
// 初始化 GPIO模块 任务入口
|
||||
void creatGpioModTaskEntry(uint16_t time);
|
||||
|
||||
/*********************************************************************
|
||||
* @brief 新建温控的初始化工作
|
||||
* @param[in] 无
|
||||
* @return 0:sucessful;1:fault
|
||||
*********************************************************************/
|
||||
int creatLogicTempCtrlEntry();
|
||||
|
||||
/*********************************************************************
|
||||
* @brief 数据返回实时库
|
||||
* @param[in] 无
|
||||
* @return
|
||||
*********************************************************************/
|
||||
int logic_paramUpload();
|
||||
|
||||
// 更新系统状态函数 (内部带互斥锁)
|
||||
void updateState(state_e newState, bool enOrDisable);
|
||||
#endif
|
|
@ -1,60 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_debug.c
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/09/27
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#include "logic_comm.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 获取调试模式运行参数接口 (暂时没有额外功能)
|
||||
* @return 0 更新成功 -1 失败 1 无更新
|
||||
*****************************************************************************/
|
||||
int logic_debugParamUpdate()
|
||||
{
|
||||
static debug_params_t *debug_params = &stlogic.para_delivery.task_params.debug;
|
||||
if (NULL == debug_params)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
// 配置变化标志
|
||||
debug_algorithm_t p_debugAlgo = {0, 0, 0};
|
||||
if (1 == kit_get_debug_algorithm(&p_debugAlgo))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
debug_params->activePower = p_debugAlgo.activePower;
|
||||
debug_params->reactivePower = p_debugAlgo.reactivePower;
|
||||
debug_params->pcsSwitch = p_debugAlgo.pcsSwitch;
|
||||
debug_params->protectSwitch = p_debugAlgo.protectSwitch;
|
||||
//debug_params->protectSwitch =1;
|
||||
|
||||
if(debug_params->pcsSwitch)
|
||||
{
|
||||
stlogic.para_delivery.task_params.protect.power = debug_params->activePower;
|
||||
stlogic.para_delivery.task_params.protect.rePower = debug_params->reactivePower;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_params->activePower = 0;
|
||||
debug_params->reactivePower = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 获取调试模式运行参数接口 (暂时没有额外功能)
|
||||
* @return -1 失败 0 成功
|
||||
*****************************************************************************/
|
||||
int logicFun_debug()
|
||||
{
|
||||
debug_params_t *debug_params = &stlogic.para_delivery.task_params.debug;
|
||||
if(NULL == debug_params)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
stlogic.para_delivery.task_params.protect.power = debug_params->activePower;
|
||||
return 0;
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_debug.h
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/09/21
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#ifndef __LOGIC_DEBUG_H__
|
||||
#define __LOGIC_DEBUG_H__
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// 用户可配参数
|
||||
float_t activePower; // 目标有功功率
|
||||
float_t reactivePower; // 目标无功功率 kw
|
||||
bool pcsSwitch; // 充放电开关 1 开 0 关
|
||||
uint8_t protectSwitch; // 保护算法开关 1 开 0 跳过
|
||||
// 中间变量
|
||||
int runPeriod; // 运行周期 ms
|
||||
} debug_params_t; // 调试函数传参结构体
|
||||
|
||||
// 获取调试模式运行参数接口
|
||||
int logicFun_debug();
|
||||
int logic_debugParamUpdate();
|
||||
#endif
|
|
@ -1,172 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_demandctrl.c
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/09/27
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#include "logic_comm.h"
|
||||
|
||||
// static sliding_window_t g_window; //滑差结构体
|
||||
|
||||
void initSlidingWindow(sliding_window_t *window)
|
||||
{
|
||||
window->pccCount = 0;
|
||||
window->pccIndex = 0;
|
||||
window->pccSum = 0;
|
||||
|
||||
window->loadCount = 0;
|
||||
window->loadIndex = 0;
|
||||
window->loadSum = 0;
|
||||
|
||||
window->foreCount = 0;
|
||||
window->foreIndex = 0;
|
||||
}
|
||||
|
||||
int updateSlidingWindow(sliding_window_t *window, double_t pcc, double_t load)
|
||||
{
|
||||
// 如果窗口尚未填满,直接添加数据并更新总和
|
||||
if (window->pccCount < 450)
|
||||
{
|
||||
window->pccDemand[window->pccCount] = pcc;
|
||||
window->pccSum += pcc;
|
||||
window->pccCount++;
|
||||
|
||||
window->loadDemand[window->loadCount] = load;
|
||||
window->loadSum += load;
|
||||
window->loadCount++;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果窗口已经填满,移除最早的数据并添加新数据
|
||||
window->pccSum -= window->pccDemand[window->pccIndex];
|
||||
window->pccDemand[window->pccIndex] = pcc;
|
||||
window->pccSum += pcc;
|
||||
window->pccIndex = (window->pccIndex + 1) % 450; // 更新索引
|
||||
|
||||
window->loadSum -= window->loadDemand[window->loadIndex];
|
||||
window->loadDemand[window->loadIndex] = load;
|
||||
window->loadSum += load;
|
||||
window->loadIndex = (window->loadIndex + 1) % 450; // 更新索引
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int UpdateForeDemand(sliding_window_t *window, double_t fore)
|
||||
{
|
||||
// 如果窗口尚未填满,直接添加数据并更新总和
|
||||
if (window->foreCount < 15)
|
||||
{
|
||||
window->foreDemand[window->foreCount] = fore;
|
||||
window->foreCount++;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果窗口已经填满,移除最早的数据并添加新数据
|
||||
window->foreDemand[window->foreIndex] = fore;
|
||||
window->foreIndex = (window->foreIndex + 1) % 15; // 更新索引
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 拟合二次方程
|
||||
double_t fitQuadraticEquation(double_t *loadDemand)
|
||||
{
|
||||
// 拟合二次方程:y = ax^2 + bx + c
|
||||
double sum_x = 0, sum_x2 = 0, sum_x3 = 0, sum_x4 = 0;
|
||||
double sum_y = 0, sum_xy = 0, sum_x2y = 0;
|
||||
|
||||
for (int i = 0; i < 15; ++i)
|
||||
{
|
||||
double x = i + 1; // 每分钟对应的时间
|
||||
double y = loadDemand[i]; // 对应的数据点
|
||||
|
||||
sum_x += x;
|
||||
sum_x2 += x * x;
|
||||
sum_x3 += x * x * x;
|
||||
sum_x4 += x * x * x * x;
|
||||
sum_y += y;
|
||||
sum_xy += x * y;
|
||||
sum_x2y += x * x * y;
|
||||
}
|
||||
|
||||
// 计算二次方程系数
|
||||
double a = (sum_x2y * sum_x2 - sum_xy * sum_x3) / (sum_x2 * sum_x4 - sum_x3 * sum_x3);
|
||||
double b = (sum_xy - a * sum_x3) / sum_x2;
|
||||
double c = (sum_y - a * sum_x4 - b * sum_x3) / sum_x2;
|
||||
|
||||
printf("拟合的二次方程为: y = %.2fx^2 + %.2fx + %.2f\n", a, b, c);
|
||||
return a * 15 * 15 + b * 15 + c;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 获取实际需量 但是不能超过变压器器容量
|
||||
* @param[in] float_t aimDemand 目标需量 float_t nowDemand 实时电表需量
|
||||
* float_t maxActivePower 变压器容量
|
||||
* @return float_t 实际需量
|
||||
*****************************************************************************/
|
||||
float_t getActiveDemand(float_t aimDemand, float_t nowDemand, float_t maxActivePower)
|
||||
{
|
||||
return float_min(float_max(aimDemand, nowDemand), maxActivePower);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 需量超阈值防护判断及处理
|
||||
* @param[in] protect_demand_t demandParams 运行参数
|
||||
* @return 参数指针返回
|
||||
*****************************************************************************/
|
||||
void logic_protect_demandCtrl(protect_params_t *charge_params)
|
||||
{
|
||||
float_t demand = getActiveDemand(charge_params->aimActiveDemand, charge_params->nowActiveDemand, charge_params->maxActivePower);
|
||||
float_t tmp_active_demand = demand - charge_params->demandCtrlCloseLimt; // 预留
|
||||
if (tmp_active_demand >= charge_params->totalActivePower) // 关机判断
|
||||
{
|
||||
float_t load_active_power = charge_params->totalActivePower - charge_params->emsActivePower; // 算出负载功率
|
||||
tmp_active_demand = demand - charge_params->demandCtrlLowLimt; // 限流值
|
||||
if (tmp_active_demand >= charge_params->totalActivePower) // 限流判断
|
||||
{
|
||||
float_t tmp_power = tmp_active_demand - load_active_power - charge_params->demandCtrlLowLimt / 10;
|
||||
if (tmp_power > 0)
|
||||
{
|
||||
charge_params->power = -float_min(abs(charge_params->power), tmp_power);
|
||||
}
|
||||
else
|
||||
{
|
||||
charge_params->power = 0;
|
||||
}
|
||||
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
|
||||
{
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "触发需量保护!!! 并网点功率:%.2f kw 目标需量:%.2f kw 实时需量:%.2f kw 新的目标功率:%.2f kw",
|
||||
charge_params->totalActivePower, charge_params->aimActiveDemand, charge_params->nowActiveDemand, charge_params->power);
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "触发需量保护!!! 并网点功率:%.2f kw 目标需量:%.2f kw 实时需量:%.2f kw 新的目标功率:%.2f kw",
|
||||
charge_params->totalActivePower, charge_params->aimActiveDemand, charge_params->nowActiveDemand, charge_params->power);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float_t tmp_power = tmp_active_demand - load_active_power - charge_params->demandCtrlLowLimt / 2;
|
||||
if (tmp_power > 0)
|
||||
{
|
||||
charge_params->power = -float_min(abs(charge_params->power), tmp_power);
|
||||
}
|
||||
else
|
||||
{
|
||||
charge_params->power = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
charge_params->power = 0;
|
||||
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
|
||||
{
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "触发需量关机!!! 并网点功率:%.2f kw 目标需量:%.2f kw 实时需量:%.2f kw 新的目标功率:%.2f kw",
|
||||
charge_params->totalActivePower, charge_params->aimActiveDemand, charge_params->nowActiveDemand, charge_params->power);
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "触发需量关机!!! 并网点功率:%.2f kw 目标需量:%.2f kw 实时需量:%.2f kw 新的目标功率:%.2f kw",
|
||||
charge_params->totalActivePower, charge_params->aimActiveDemand, charge_params->nowActiveDemand, charge_params->power);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_demandctrl.h
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/09/27
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#ifndef __LOGIC_DEMANDCTRL_H__
|
||||
#define __LOGIC_DEMANDCTRL_H__
|
||||
|
||||
// 滑差窗口结构体
|
||||
typedef struct
|
||||
{
|
||||
double_t pccDemand[450]; // 实时需量
|
||||
int pccCount; // 当前实时需量的数量
|
||||
int pccIndex; // 当前实时需量的索引
|
||||
double_t pccSum; // 窗口内实时需量的总和
|
||||
|
||||
double_t loadDemand[450]; // 负荷实时需量
|
||||
int loadCount; // 当前负荷实时需量的数量
|
||||
int loadIndex; // 当前负荷实时需量的索引
|
||||
double_t loadSum; // 窗口内负荷实时需量的总和
|
||||
|
||||
double_t foreDemand[15]; // 负荷预测需量
|
||||
int foreCount; // 当前负荷预测需量的数量
|
||||
int foreIndex; // 当前负荷预测需量的索引
|
||||
} sliding_window_t;
|
||||
|
||||
|
||||
#endif
|
|
@ -1,920 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_dido.C
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/10/18
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#include "logic_comm.h"
|
||||
#include "logic_dido.h"
|
||||
|
||||
// dido任务数组
|
||||
static gpio_func_t gpioDiTask[MAX_NUM_CABINT][DI_End - DI_Start] = {NULL};
|
||||
static gpio_func_t gpioDoTask[MAX_NUM_CABINT][DO_End - DO_Start] = {NULL};
|
||||
|
||||
static gpio_rtdb_data_parsing_t gpioRtdbData = {0};
|
||||
|
||||
pthread_mutex_t stateMutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
// 开启对应功能的led闪烁
|
||||
uint8_t ledFucSwitch[kLedFuc_End] = {0};
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 更新系统状态函数 (内部带互斥锁)
|
||||
* @param[in] state_e newState 需要更新的状态
|
||||
* @param[in] 状态使能 enOrDisable 0 不使能 1 使能 (仅用于故障状态恢复)
|
||||
* @return 无
|
||||
*****************************************************************************/
|
||||
void updateState(state_e newState, bool enOrDisable)
|
||||
{
|
||||
static state_e currentState = kState_Start;
|
||||
pthread_mutex_lock(&stateMutex);
|
||||
|
||||
if (currentState == kState_Fault)
|
||||
{
|
||||
if (newState == kState_Fault)
|
||||
{
|
||||
if (enOrDisable)
|
||||
{
|
||||
// 故障状态再次被调用,保持故障状态
|
||||
pthread_mutex_unlock(&stateMutex);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 故障解除 切为停机
|
||||
currentState = kState_Shutdown;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 非故障状态调用,忽略
|
||||
pthread_mutex_unlock(&stateMutex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (currentState == newState)
|
||||
{
|
||||
// 非故障状态再次被调用,保持故障状态
|
||||
pthread_mutex_unlock(&stateMutex);
|
||||
return;
|
||||
}
|
||||
else // 所有状态的更新
|
||||
{
|
||||
if (enOrDisable)
|
||||
{
|
||||
currentState = newState;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 防止多次调用故障解除
|
||||
pthread_mutex_unlock(&stateMutex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 系统状态写入实时库
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_RunState, (double)currentState);
|
||||
pthread_mutex_unlock(&stateMutex);
|
||||
return;
|
||||
}
|
||||
|
||||
// RTDB数据获取
|
||||
void faultDataGet()
|
||||
{
|
||||
uint8_t loop = 0;
|
||||
// DI值获取
|
||||
for (loop = 0; loop < (DI_End - DI_Start); loop++)
|
||||
{
|
||||
gpioRtdbData.diValue[loop] = (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Di_Start + loop));
|
||||
}
|
||||
// 获取联网状态
|
||||
ledFucSwitch[kLedFuc_wlan] = (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_netStatus);
|
||||
|
||||
gpioRtdbData.pccmeterStatus = (uint8_t)(0 == (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_Pccmeter, 0, kPCC_IsOnline));
|
||||
gpioRtdbData.bsmeterStatus = (uint8_t)(0 == (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_Bsmeter, 0, kBs_IsOnline));
|
||||
|
||||
for (loop = 0; loop < gpioRtdbData.pcsSum; loop++)
|
||||
{
|
||||
gpioRtdbData.pcsStatus[loop] = 0;
|
||||
gpioRtdbData.pcsStatus[loop] += (uint8_t)(0 == (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_PCS, loop, kPcs_IsOnline));
|
||||
gpioRtdbData.pcsStatus[loop] += (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_PCS, loop, kPcs_TotalFault);
|
||||
}
|
||||
|
||||
for (loop = 0; loop < gpioRtdbData.bsuNum; loop++)
|
||||
{
|
||||
gpioRtdbData.bsuStatus[loop] = 0;
|
||||
gpioRtdbData.bsuStatus[loop] += (uint8_t)(0 == (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_BSU, loop, kBsu_IsOnline));
|
||||
gpioRtdbData.bsuStatus[loop] += (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_BSU, loop, kBsu_TotalAlarm);
|
||||
gpioRtdbData.bsuStatus[loop] += (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_BSU, loop, kBsu_TotalFault);
|
||||
}
|
||||
|
||||
for (loop = 0; loop < gpioRtdbData.bcuNum; loop++)
|
||||
{
|
||||
gpioRtdbData.bcuStatus[loop] = 0;
|
||||
gpioRtdbData.bcuStatus[loop] += (uint8_t)(0 == (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_BCU, loop, kBcu_IsOnline));
|
||||
gpioRtdbData.bcuStatus[loop] += (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_BCU, loop, kBsu_TotalAlarm);
|
||||
gpioRtdbData.bcuStatus[loop] += (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_BCU, loop, kBsu_TotalFault);
|
||||
}
|
||||
|
||||
for (loop = 0; loop < gpioRtdbData.thsensorNum; loop++)
|
||||
{
|
||||
gpioRtdbData.thsensorStatus[loop] = (uint8_t)(0 == (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_Thsensor, loop, kTHSenor_IsOnline));
|
||||
gpioRtdbData.tmp[loop] = (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_Thsensor, loop, kTHSenor_Temp);
|
||||
}
|
||||
|
||||
for (loop = 0; loop < gpioRtdbData.upsNum; loop++)
|
||||
{
|
||||
gpioRtdbData.upsStatus[loop] = (uint8_t)(0 == (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_UPS, loop, kUps_IsOnline));
|
||||
}
|
||||
|
||||
for (loop = 0; loop < gpioRtdbData.airCondNum; loop++)
|
||||
{
|
||||
gpioRtdbData.airCondStatus[loop] = (uint8_t)(0 == (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_AirCond_LiquidCool, loop, kAcLiquidMac_IsOnline));
|
||||
}
|
||||
#if 0
|
||||
printf("******************************************************** tmp %d 度\r\n",(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_Thsensor, 0, kTHSenor_Temp));
|
||||
printf("输入:\r\n 水浸传感器低:%d\r\n水浸传感器高:%d\r\n急停:%d\r\n烟感:%d\r\n温感:%d\r\n消防触发反馈:%d\r\n门禁传感器:%d\r\n交流断路器反馈:%d\r\n",
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Di1),
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Di1+1),
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Di1+2),
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Di1+3),
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Di1+4),
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Di1+5),
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Di1+6),
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Di1+7));
|
||||
|
||||
printf("\r\n输入:\r\n运行灯:%d\r\n故障灯:%d\r\n交流断路器分励脱扣:%d\r\n机柜风扇:%d\r\n消防一级准备:%d\r\n消防二级触发:%d\r\n",
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Do1),
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Do1+1),
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Do1+2),
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Do1+3),
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Do1+4),
|
||||
(uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_Do1+5));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// RTDB数据写入
|
||||
void faultDataSet(uint8_t cabt)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 水浸低(常闭)
|
||||
void diWaterLowGetOn(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.waterLow[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.waterLow[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
// 水浸低(常开)
|
||||
void diWaterLowGetOff(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.waterLow[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.waterLow[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
}
|
||||
|
||||
// 水浸高(常闭)
|
||||
void diWaterHighGetOn(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.waterHigh[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.waterHigh[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
// 水浸高(常开)
|
||||
void diWaterHighGetOff(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.waterHigh[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.waterHigh[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
}
|
||||
|
||||
// 急停(常闭)
|
||||
void diEmergSignalGetOn(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.emergStop[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.emergStop[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
// 急停(常开)
|
||||
void diEmergSignalGetOff(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.emergStop[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.emergStop[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
}
|
||||
|
||||
// 烟感(常闭)
|
||||
void diSmokeSignalGetOn(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.smokeDetec[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.smokeDetec[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
// 烟感(常开)
|
||||
void diSmokeSignalGetOff(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.smokeDetec[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.smokeDetec[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
}
|
||||
|
||||
// 温感(常闭)
|
||||
void diTempSignalGetOn(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.tempSensor[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.tempSensor[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
|
||||
// 温感(常开)
|
||||
void diTempSignalGetOff(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.tempSensor[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.tempSensor[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
}
|
||||
|
||||
// 消防触发反馈(常闭)
|
||||
void diFireFeedbackSignalGetOn(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.fireFeedback[cabt] = kGpioSwitch_off; // 消防触发
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.fireFeedback[cabt] = kGpioSwitch_on; // 消防未触发
|
||||
}
|
||||
}
|
||||
// 消防触发反馈(常开)
|
||||
void diFireFeedbackSignalGetOff(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.fireFeedback[cabt] = kGpioSwitch_on; // 消防触发
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.fireFeedback[cabt] = kGpioSwitch_off; // 消防未触发
|
||||
}
|
||||
}
|
||||
|
||||
// 门禁传感器(常闭)
|
||||
void diAccessSignalGetOn(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.accessSensor[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.accessSensor[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
// 门禁传感器(常开)
|
||||
void diAccessSignalGetOff(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.accessSensor[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.accessSensor[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
}
|
||||
|
||||
// 交流断路器反馈(常闭)
|
||||
void diCircuitFeedGetOn(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.circuitFeed[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.circuitFeed[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
// 交流断路器反馈(常开)
|
||||
void diCircuitFeedGetOff(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.circuitFeed[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.circuitFeed[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
}
|
||||
|
||||
// 气溶胶触发反馈(常闭)
|
||||
void diFireAerosolGetOn(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.fireAerosol[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.fireAerosol[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
// 气溶胶触发反馈(常开)
|
||||
void diFireAerosolGetOff(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.fireAerosol[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.fireAerosol[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
}
|
||||
|
||||
// 浪涌辅助触点(常闭)
|
||||
void diSurgeGetOn(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.surge[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.surge[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
// 浪涌辅助触点(常开)
|
||||
void diSurgeGetOff(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.surge[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.surge[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
}
|
||||
|
||||
// 消防故障(常闭)
|
||||
void diFireFaultGetOn(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.fireFault[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.fireFault[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
// 消防故障(常开)
|
||||
void diFireFaultGetOff(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.diValue[indx])
|
||||
{
|
||||
gpioRtdbData.fireFault[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
else
|
||||
{
|
||||
gpioRtdbData.fireFault[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
}
|
||||
|
||||
// LED闪烁模式
|
||||
void doRunLedBliCtrl(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
static int rtLedStat[MAX_NUM_CABINT] = {kGpioSwitch_off};
|
||||
// 本机LED闪烁与DIDO策略无关仅用于开发
|
||||
ledFucSwitch[kLedFuc_on] = kGpioSwitch_on;
|
||||
if (rtLedStat[cabt])
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_on);
|
||||
// drvGpioWrite(DO_Start + indx, kGpioSwitch_on);
|
||||
rtLedStat[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
else
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_off);
|
||||
// drvGpioWrite(DO_Start + indx, kGpioSwitch_off);
|
||||
rtLedStat[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// LED常亮常灭模式
|
||||
void doRunLedContnCtrl(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
static gpioSwitch_e rtLedStat[MAX_NUM_CABINT] = {kGpioSwitch_off};
|
||||
if (kGpioSwitch_on) // 待获取开灯条件
|
||||
{
|
||||
if (1 != rtLedStat[cabt])
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_on);
|
||||
drvGpioWrite(DO_Start + indx, kGpioSwitch_on); // 写DO任务暂时在这里
|
||||
rtLedStat[cabt] = kGpioSwitch_on;
|
||||
|
||||
// 本机LED闪烁与DIDO策略无关仅用于开发
|
||||
ledFucSwitch[kLedFuc_on] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
else if (kGpioSwitch_off)
|
||||
{
|
||||
if (0 != rtLedStat[cabt])
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_off);
|
||||
drvGpioWrite(DO_Start + indx, kGpioSwitch_off); // 写DO任务暂时在这里
|
||||
rtLedStat[cabt] = kGpioSwitch_off;
|
||||
|
||||
// 本机LED闪烁与DIDO策略无关仅用于开发
|
||||
ledFucSwitch[kLedFuc_on] = kGpioSwitch_off;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 故障LED闪烁模式
|
||||
void doFaultLedBliCtrl(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
static int rtLedStat[MAX_NUM_CABINT] = {kGpioSwitch_off}, flag = 0;
|
||||
// 告警
|
||||
if (gpioRtdbData.thsensorStatus[cabt] || gpioRtdbData.upsStatus[cabt] || gpioRtdbData.airCondStatus[cabt])
|
||||
{
|
||||
// EMS自带告警灯闪烁
|
||||
ledFucSwitch[kLedFuc_alarm] = kGpioSwitch_on;
|
||||
}
|
||||
else
|
||||
{
|
||||
ledFucSwitch[kLedFuc_alarm] = kGpioSwitch_off;
|
||||
}
|
||||
// 故障
|
||||
if (gpioRtdbData.pccmeterStatus || gpioRtdbData.bsmeterStatus || gpioRtdbData.pcsStatus[cabt] ||
|
||||
gpioRtdbData.bsuStatus[cabt] || gpioRtdbData.bcuStatus[cabt])
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_off); // 关灯 // 控灯
|
||||
// 故障上报
|
||||
updateState(kState_Fault, true);
|
||||
flag = 1;
|
||||
// EMS自带故障灯闪烁
|
||||
ledFucSwitch[kLedFuc_fault] = kGpioSwitch_on;
|
||||
}
|
||||
else if (flag)
|
||||
{
|
||||
// 故障恢复上报
|
||||
updateState(kState_Fault, false);
|
||||
flag = 0; // 恢复只能调用一次
|
||||
drvGpioWrite(DO_Start + indx, kGpioSwitch_off);
|
||||
ledFucSwitch[kLedFuc_fault] = kGpioSwitch_off;
|
||||
return;
|
||||
}
|
||||
if (rtLedStat[cabt])
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_on);
|
||||
// drvGpioWrite(DO_Start + indx, kGpioSwitch_on);
|
||||
rtLedStat[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
else
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_off);
|
||||
// drvGpioWrite(DO_Start + indx, kGpioSwitch_off);
|
||||
rtLedStat[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 故障和告警LED常亮常灭模式
|
||||
void doFaultLedContnCtrl(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
static gpioSwitch_e rtLedStat[MAX_NUM_CABINT] = {kGpioSwitch_off};
|
||||
if (gpioRtdbData.pccmeterStatus || gpioRtdbData.bsmeterStatus || gpioRtdbData.pcsStatus[cabt] ||
|
||||
gpioRtdbData.bsuStatus[cabt] || gpioRtdbData.bcuStatus[cabt])
|
||||
{
|
||||
if (kGpioSwitch_on != rtLedStat[cabt])
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_on);
|
||||
drvGpioWrite(DO_Start + indx, kGpioSwitch_on); // 写DO任务暂时在这里
|
||||
rtLedStat[cabt] = kGpioSwitch_on;
|
||||
// 故障上报
|
||||
updateState(kState_Fault, true);
|
||||
|
||||
// 本机LED闪烁与DIDO策略无关仅用于开发
|
||||
ledFucSwitch[kLedFuc_fault] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (kGpioSwitch_off != rtLedStat[cabt])
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_off);
|
||||
drvGpioWrite(DO_Start + indx, kGpioSwitch_off); // 写DO任务暂时在这里
|
||||
rtLedStat[cabt] = kGpioSwitch_off;
|
||||
// 故障恢复上报
|
||||
updateState(kState_Fault, false);
|
||||
|
||||
// 本机LED闪烁与DIDO策略无关仅用于开发
|
||||
ledFucSwitch[kLedFuc_fault] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
// 告警
|
||||
if (gpioRtdbData.thsensorStatus[cabt] || gpioRtdbData.upsStatus[cabt] || gpioRtdbData.airCondStatus[cabt])
|
||||
{
|
||||
// EMS自带告警灯闪烁
|
||||
ledFucSwitch[kLedFuc_alarm] = kGpioSwitch_on;
|
||||
}
|
||||
else
|
||||
{
|
||||
ledFucSwitch[kLedFuc_alarm] = kGpioSwitch_off;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 交流断路器分励脱扣
|
||||
void doCircuitTrippingCtrl(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
static gpioSwitch_e rtDoStat[MAX_NUM_CABINT] = {kGpioSwitch_off};
|
||||
if (gpioRtdbData.emergStop[cabt] || (gpioRtdbData.waterHigh[cabt] && gpioRtdbData.waterHigh[cabt]) ||
|
||||
gpioRtdbData.tempSensor[cabt] || gpioRtdbData.smokeDetec[cabt] || gpioRtdbData.fireFeedback[cabt])
|
||||
{
|
||||
if (kGpioSwitch_on != gpioRtdbData.circuitFeed[cabt] && kGpioSwitch_on != rtDoStat[cabt])
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_on);
|
||||
drvGpioWrite(DO_Start + indx, kGpioSwitch_on); // 写DO任务暂时在这里
|
||||
rtDoStat[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
if (1 != stlogic.para_delivery.task_params.protect.scramButton)
|
||||
{
|
||||
stlogic.para_delivery.task_params.protect.scramButton = 1;
|
||||
}
|
||||
// 不仅仅是交流脱扣 还有 PCS 停机 BMS脱扣
|
||||
}
|
||||
else
|
||||
{
|
||||
if (0 != stlogic.para_delivery.task_params.protect.scramButton)
|
||||
{
|
||||
stlogic.para_delivery.task_params.protect.scramButton = 0;
|
||||
}
|
||||
if (kGpioSwitch_off != rtDoStat[cabt])
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_off);
|
||||
drvGpioWrite(DO_Start + indx, kGpioSwitch_off); // 写DO任务暂时在这里
|
||||
rtDoStat[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 机柜风扇控制
|
||||
void doFanCtrl(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
static gpioSwitch_e rtFanStat[MAX_NUM_CABINT] = {kGpioSwitch_off};
|
||||
if (gpioRtdbData.tmp[cabt] >= 35) // 判断风扇开启条件
|
||||
{
|
||||
if (rtFanStat[cabt] != kGpioSwitch_on) // 开启
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_on);
|
||||
drvGpioWrite(DO_Start + indx, kGpioSwitch_on);
|
||||
rtFanStat[cabt] = kGpioSwitch_on;
|
||||
}
|
||||
}
|
||||
else if (gpioRtdbData.tmp[cabt] < 30 && 1 == rtFanStat[cabt]) // 回差判断
|
||||
{
|
||||
if (rtFanStat[cabt] != kGpioSwitch_off) // 关闭
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_off);
|
||||
drvGpioWrite(DO_Start + indx, kGpioSwitch_off);
|
||||
rtFanStat[cabt] = kGpioSwitch_off;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 消防一级准备 暂时不启用
|
||||
void multiCondTrigFire1(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.smokeDetec[cabt] && gpioRtdbData.tempSensor[cabt])
|
||||
{
|
||||
if (kGpioSwitch_off == gpioRtdbData.fireFeedback[cabt])
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_on);
|
||||
// drvGpioWrite(DO_Start + indx, kGpioSwitch_on);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_off);
|
||||
// drvGpioWrite(DO_Start + indx, kGpioSwitch_off);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 消防二级触发 暂时不启用
|
||||
void multiCondTrigFire2(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
if (gpioRtdbData.smokeDetec[cabt] && gpioRtdbData.tempSensor[cabt])
|
||||
{
|
||||
if (kGpioSwitch_off == gpioRtdbData.fireFeedback[cabt])
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_on);
|
||||
// drvGpioWrite(DO_Start + indx, kGpioSwitch_on);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_off);
|
||||
// drvGpioWrite(DO_Start + indx, kGpioSwitch_off);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// 对应DO口输出高电平
|
||||
void doPutHigh(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_on);
|
||||
drvGpioWrite(DO_Start + indx, kGpioSwitch_on);
|
||||
return;
|
||||
}
|
||||
|
||||
// 对应DO口输出低电平
|
||||
void doPutLow(uint8_t cabt, uint16_t indx)
|
||||
{
|
||||
setRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, (kEms_Do_Start + indx), kGpioSwitch_off);
|
||||
drvGpioWrite(DO_Start + indx, kGpioSwitch_off);
|
||||
return;
|
||||
}
|
||||
static gpio_func_t diFuc[kDiFuc_End] =
|
||||
{
|
||||
NULL,
|
||||
diWaterLowGetOn, // 水浸传感器低常闭0
|
||||
diWaterLowGetOff, // 水浸传感器低常开1
|
||||
diWaterHighGetOn, // 水浸传感器高常闭2
|
||||
diWaterHighGetOff, // 水浸传感器高常开3
|
||||
diEmergSignalGetOn, // 急停常闭4
|
||||
diEmergSignalGetOff, // 急停常开5
|
||||
diSmokeSignalGetOn, // 烟感常闭6
|
||||
diSmokeSignalGetOff, // 烟感常开7
|
||||
diTempSignalGetOn, // 温感常闭8
|
||||
diTempSignalGetOff, // 温感常开9
|
||||
diFireFeedbackSignalGetOn, // 消防触发反馈常闭10
|
||||
diFireFeedbackSignalGetOff, // 消防触发反馈常开11
|
||||
diAccessSignalGetOn, // 门禁传感器常闭12
|
||||
diAccessSignalGetOff, // 门禁传感器常开13
|
||||
diCircuitFeedGetOn, // 交流断路器反馈常闭14
|
||||
diCircuitFeedGetOff, // 交流断路器反馈常开15
|
||||
diFireAerosolGetOn, // 气溶胶触发反馈常闭16
|
||||
diFireAerosolGetOff, // 气溶胶触发反馈常开17
|
||||
diSurgeGetOn, // 浪涌辅助触点常闭18
|
||||
diSurgeGetOff, // 浪涌辅助触点常开19
|
||||
diFireFaultGetOn, // 消防故障常闭20
|
||||
diFireFaultGetOff // 消防故障常开21
|
||||
};
|
||||
|
||||
static gpio_func_t doFuc[kDoFuc_End] =
|
||||
{
|
||||
NULL,
|
||||
doRunLedContnCtrl, // 运行灯 常亮 0
|
||||
doRunLedBliCtrl, // 运行灯 闪烁 1
|
||||
doFaultLedContnCtrl, // 故障灯 常亮 2
|
||||
doFaultLedBliCtrl, // 故障灯 闪烁 3
|
||||
doCircuitTrippingCtrl, // 交流断路器分励脱扣 4
|
||||
doFanCtrl, // 机柜风扇 5
|
||||
multiCondTrigFire1, // 消防一级准备 6
|
||||
multiCondTrigFire2, // 消防二级触发 一级二级同时置高电平才真的喷洒 7
|
||||
doPutHigh, // 对应DO口输出高电平8
|
||||
doPutLow // 对应DO口输出低电平9
|
||||
};
|
||||
|
||||
// 从sq获取配置用于初始化DIDO定义
|
||||
int didoConfigInit()
|
||||
{
|
||||
// 初始化
|
||||
memset(&gpioRtdbData, 0, sizeof(gpio_rtdb_data_parsing_t));
|
||||
UT_array *didoInfoArr = NULL;
|
||||
// 测试使用默认配置
|
||||
#if 0
|
||||
gpioDiTask[0][0] = diFuc[0];
|
||||
gpioDiTask[0][1] = diFuc[1];
|
||||
gpioDiTask[0][2] = diFuc[2];
|
||||
gpioDiTask[0][3] = diFuc[3];
|
||||
gpioDiTask[0][4] = diFuc[4];
|
||||
gpioDiTask[0][5] = diFuc[5];
|
||||
gpioDiTask[0][6] = diFuc[6];
|
||||
gpioDiTask[0][7] = diFuc[7];
|
||||
|
||||
gpioDoTask[0][0] = doFuc[0];
|
||||
gpioDoTask[0][1] = doFuc[2];
|
||||
gpioDoTask[0][2] = doFuc[4];
|
||||
gpioDoTask[0][3] = doFuc[5];
|
||||
gpioDoTask[0][4] = doFuc[6];
|
||||
gpioDoTask[0][5] = doFuc[7];
|
||||
#endif
|
||||
// 获取数据库ID、设备类型、设备编号、协议类型
|
||||
if (0 != kit_get_di_do_set_arr(&didoInfoArr))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
// 遍历设备
|
||||
utarray_foreach(didoInfoArr, di_do_logic_set_t *, p_didoInfo)
|
||||
{
|
||||
if (kDi == p_didoInfo->dIDOType)
|
||||
{
|
||||
gpioDiTask[p_didoInfo->cabinetCode][p_didoInfo->dIDOseq] = diFuc[p_didoInfo->strategySeqDi];
|
||||
}
|
||||
else if (kDo == p_didoInfo->dIDOType)
|
||||
{
|
||||
gpioDoTask[p_didoInfo->cabinetCode][p_didoInfo->dIDOseq] = doFuc[p_didoInfo->strategySeqDo];
|
||||
}
|
||||
}
|
||||
utarray_free(didoInfoArr); // 释放 UT_array
|
||||
gpioDoTask[0][0] = doFuc[1];
|
||||
gpioDoTask[0][1] = doFuc[3];
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 初始化rtdb 固定的的数据
|
||||
void gpioRtdbDataInit()
|
||||
{
|
||||
// 设备数量读取
|
||||
gpioRtdbData.pccmeterNum = (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_PccmeterNum);
|
||||
gpioRtdbData.bsmeterNum = (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_BsmeterNum);
|
||||
gpioRtdbData.pcsSum = (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_PCSNum);
|
||||
gpioRtdbData.bsuNum = (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_BSUNum);
|
||||
gpioRtdbData.bcuNum = (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_BCUNum);
|
||||
gpioRtdbData.thsensorNum = (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_ThsensorNum);
|
||||
// gpioRtdbData.didoNum = (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_DI_Num);
|
||||
gpioRtdbData.upsNum = (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_UPSNum);
|
||||
gpioRtdbData.airCondNum = (uint8_t)getRtdbPointValue(kSign_ShMem, kDev_Type_EMS, 0, kEms_AirCondNum);
|
||||
return;
|
||||
}
|
||||
|
||||
// 模块主循环
|
||||
void *taskGpioProduce(void *itime)
|
||||
{
|
||||
uint16_t cnt = 0;
|
||||
uint16_t time = *(uint16_t *)itime;
|
||||
uint8_t loop = 0, cabt = 0;
|
||||
if (time == 0)
|
||||
{
|
||||
KITPTF(LOG_MODBUS_EN, INFO_EN, "EMS本地DIDO处理 线程 延时参数有误!!");
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "EMS本地DIDO处理 线程 延时参数有误!!");
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
if (0 == cnt % time)
|
||||
{
|
||||
faultDataGet(); // 故障数据刷新
|
||||
for (cabt = 0; cabt < MAX_NUM_CABINT; cabt++)
|
||||
{
|
||||
for (loop = 0; loop < (DI_End - DI_Start); loop++)
|
||||
{
|
||||
if (NULL != gpioDiTask[cabt][loop])
|
||||
{
|
||||
(*gpioDiTask[cabt][loop])(cabt, loop);
|
||||
}
|
||||
}
|
||||
|
||||
for (loop = 0; loop < (DO_End - DO_Start); loop++)
|
||||
{
|
||||
if (NULL != gpioDoTask[cabt][loop])
|
||||
{
|
||||
(*gpioDoTask[cabt][loop])(cabt, loop);
|
||||
}
|
||||
}
|
||||
// 维护RTDB故障
|
||||
faultDataSet(cabt);
|
||||
}
|
||||
cnt = 0;
|
||||
}
|
||||
cnt++;
|
||||
usleep(50000);
|
||||
}
|
||||
}
|
||||
|
||||
void *led_blink_thread(void *arg)
|
||||
{
|
||||
uint8_t led_status = kGpioSwitch_on;
|
||||
ledFuc_e step = 0;
|
||||
while (1)
|
||||
{
|
||||
// 运行灯必然会闪烁
|
||||
if (ledFucSwitch[kLedFuc_on])
|
||||
{
|
||||
led_status = (led_status == kGpioSwitch_on) ? kGpioSwitch_off : kGpioSwitch_on;
|
||||
|
||||
for (step = 0; step < kLedFuc_End; step++)
|
||||
{
|
||||
switch (step)
|
||||
{
|
||||
case kLedFuc_on:
|
||||
drvGpioWrite(LED1, (int)(led_status && ledFucSwitch[step])); // 开机控灯
|
||||
break;
|
||||
case kLedFuc_alarm:
|
||||
drvGpioWrite(LED2, (int)ledFucSwitch[step]); // 告警控灯
|
||||
break;
|
||||
case kLedFuc_wlan:
|
||||
drvGpioWrite(LED3, (int)(led_status && ledFucSwitch[step])); // 连网控灯
|
||||
break;
|
||||
case kLedFuc_fault:
|
||||
drvGpioWrite(LED4, (int)ledFucSwitch[step]); // 故障控灯
|
||||
break;
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sleep(1);
|
||||
}
|
||||
usleep(50000);
|
||||
}
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
/*********************************************************************
|
||||
* @brief 初始化 GPIO模块 任务入口
|
||||
* @param[in] time 运行周期
|
||||
* @return 无
|
||||
*********************************************************************/
|
||||
void creatGpioModTaskEntry(uint16_t time)
|
||||
{
|
||||
// GPIO配置只在启动时读一遍 修改需要重启
|
||||
if (0 != didoConfigInit())
|
||||
{
|
||||
KITPTF(LOG_MODBUS_EN, ERROR_EN, "EMS获取DIDO配置失败");
|
||||
KITLOG(LOG_MODBUS_EN, ERROR_EN, "EMS获取DIDO配置失败");
|
||||
return;
|
||||
}
|
||||
// 一些固定数据获取
|
||||
gpioRtdbDataInit();
|
||||
static uint16_t itime = 10;
|
||||
itime = time;
|
||||
pthread_t pfd, led_thread;
|
||||
if (pthread_create(&pfd, NULL, taskGpioProduce, (void *)&itime))
|
||||
{
|
||||
KITPTF(LOG_MODBUS_EN, INFO_EN, "EMS本地DIDO处理 线程 创建成功");
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "EMS本地DIDO处理 线程 创建成功");
|
||||
}
|
||||
|
||||
// 创建LED闪烁线程
|
||||
if (pthread_create(&led_thread, NULL, led_blink_thread, NULL) != 0)
|
||||
{
|
||||
KITPTF(LOG_MODBUS_EN, INFO_EN, "LED闪烁 线程 创建成功");
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "LED闪烁 线程 创建成功");
|
||||
}
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_dido.h
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/10/18
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#ifndef __LOGIC_DIDO_H__
|
||||
#define __LOGIC_DIDO_H__
|
||||
|
||||
#include "../driver/drv_gpio.h"
|
||||
// 开关
|
||||
typedef enum
|
||||
{
|
||||
kGpioSwitch_Start = 0, // 起始
|
||||
kGpioSwitch_off = kGpioSwitch_Start, // 关 0
|
||||
kGpioSwitch_on, // 开 1
|
||||
kLedSwitch_End // 结束
|
||||
} gpioSwitch_e;
|
||||
|
||||
// LED功能
|
||||
typedef enum
|
||||
{
|
||||
kLedFuc_Start = 0, // 起始
|
||||
kLedFuc_on, // 开机自启灯(绿)
|
||||
kLedFuc_alarm, // 告警(红)
|
||||
kLedFuc_wlan, // 联网灯(绿)
|
||||
kLedFuc_fault, // 故障灯(红)
|
||||
kLedFuc_End // 结束
|
||||
} ledFuc_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t pccmeterNum; // PCC电表数量
|
||||
uint8_t bsmeterNum; // 储能电表数量
|
||||
uint8_t pcsSum; // PCS 数量
|
||||
uint8_t bsuNum; // 电池堆数量
|
||||
uint8_t bcuNum; // 电池簇数量
|
||||
uint8_t thsensorNum; // 温湿度传感器数量
|
||||
uint8_t upsNum; // UPS设备数量
|
||||
uint8_t airCondNum; // 空调组数量
|
||||
|
||||
uint8_t pccmeterStatus; // PCC电表状态 1 故障 0 正常
|
||||
uint8_t bsmeterStatus; // 储能电表状态 1 故障 0 正常
|
||||
uint8_t pcsStatus[MAX_NUM_CABINT]; // pcs状态 1 故障 0 正常
|
||||
uint8_t bsuStatus[MAX_NUM_CABINT]; // 电池堆状态 1 故障 0 正常
|
||||
uint8_t bcuStatus[MAX_NUM_CABINT]; // 电池簇状态 1 故障 0 正常
|
||||
uint8_t thsensorStatus[MAX_NUM_CABINT]; // 温湿度传感器状态 1 故障 0 正常
|
||||
uint8_t tmp[MAX_NUM_CABINT]; // 柜内温度 ℃
|
||||
uint8_t upsStatus[MAX_NUM_CABINT]; // UPS设备状态 1 故障 0 正常
|
||||
uint8_t airCondStatus[MAX_NUM_CABINT]; // 空调组状态 1 故障 0 正常
|
||||
|
||||
// DI1-DI40 (可配所以都是未知包括柜号)
|
||||
uint8_t diValue[DI_End - DI_Start]; // DI值
|
||||
|
||||
// DI 根据配置已知
|
||||
uint8_t waterLow[MAX_NUM_CABINT]; // 水浸传感器低
|
||||
uint8_t waterHigh[MAX_NUM_CABINT]; // 水浸传感器高
|
||||
uint8_t emergStop[MAX_NUM_CABINT]; // 急停
|
||||
uint8_t smokeDetec[MAX_NUM_CABINT]; // 烟感
|
||||
uint8_t tempSensor[MAX_NUM_CABINT]; // 温感
|
||||
uint8_t fireFeedback[MAX_NUM_CABINT]; // 消防喷洒触发反馈
|
||||
|
||||
uint8_t fireAerosol[MAX_NUM_CABINT]; // 消防气溶胶触发反馈
|
||||
uint8_t surge[MAX_NUM_CABINT]; // 浪涌辅助触点
|
||||
uint8_t fireFault[MAX_NUM_CABINT]; // 消防故障
|
||||
|
||||
uint8_t accessSensor[MAX_NUM_CABINT]; // 门禁传感器
|
||||
uint8_t circuitFeed[MAX_NUM_CABINT]; // 交流断路器反馈
|
||||
|
||||
} gpio_rtdb_data_parsing_t; // 解析rtdb的数据用于GPIO
|
||||
|
||||
extern uint8_t ledFucSwitch[kLedFuc_End];
|
||||
typedef void (*gpio_func_t)(uint8_t cabt, uint16_t indx); // 定义函数指针类型,无返回值
|
||||
#endif
|
|
@ -1,384 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @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 0:sucessful;1:fault
|
||||
*********************************************************************/
|
||||
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 0:sucessful;1:fault
|
||||
*********************************************************************/
|
||||
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 0:sucessful;1:fault
|
||||
*********************************************************************/
|
||||
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()
|
||||
{
|
||||
;
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_main.h
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/09/29
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#pragma once
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "logic_comm.h"
|
||||
|
||||
|
||||
#define MAX_TASK_NUM 10
|
||||
|
||||
// 在头文件中配置任务链
|
||||
#define INIT_TASK_GROUP() \
|
||||
{ \
|
||||
task_group[E_TACTIC_MODE_START] = init_task_list(1, example_task1); \
|
||||
task_group[E_TACTIC_MODE_DEBUG] = init_task_list(2, logicFun_protect,logicFun_powerDistr); \
|
||||
task_group[E_TACTIC_MODE_PEAKVALLY] = init_task_list(3, logicFun_peakValley,logicFun_protect,logicFun_powerDistr); \
|
||||
task_group[E_TACTIC_MODE_DEMANDRES] = init_task_list(1, example_task1); \
|
||||
task_group[E_TACTIC_MODE_LOADTRACK] = init_task_list(1, example_task1); \
|
||||
task_group[E_TACTIC_MODE_DMDCTRL] = init_task_list(1, example_task1); \
|
||||
task_group[E_TACTIC_MODE_PFCTRL] = init_task_list(1, example_task1); \
|
||||
}
|
||||
|
||||
typedef int (*task_func_t)(); // 定义函数指针类型,返回值为int
|
||||
|
||||
typedef enum
|
||||
{
|
||||
E_RUN_ONCE, //单次运行
|
||||
E_RUN_period //周期运行
|
||||
} task_run_type;
|
||||
|
||||
typedef struct tast_register_execute
|
||||
{
|
||||
// protocol_type_master_e protocolType; // 任务
|
||||
// task_run_type taskType; // 任务类型
|
||||
// uint16_t taskPeriod; // 任务间隔 ms
|
||||
task_func_t task; // 任务指针
|
||||
struct tast_register_execute* next; // 指向下一个任务
|
||||
} tast_register_execute;
|
||||
|
||||
extern tast_register_execute* task_group[E_TACTIC_MODE_END];
|
||||
|
||||
void example_task1();
|
||||
|
||||
//初始化任务链表,支持多个任务函数指针
|
||||
tast_register_execute* init_task_list(int count, ...);
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 创建任务调度线程
|
||||
* @param[in] 无
|
||||
* @return 无
|
||||
*****************************************************************************/
|
||||
void* creatLogicTaskThread(void* arg);
|
||||
|
||||
/*********************************************************************
|
||||
* @brief 新建任务模块的初始化工作
|
||||
* @param[in] 无
|
||||
* @return 0:sucessful;1:fault
|
||||
*********************************************************************/
|
||||
int creatLogicCtrTaskEntry();
|
|
@ -1,230 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_peakvalley.c
|
||||
* @brief 削峰填谷控制策略
|
||||
* @author Gary
|
||||
* @date 2024/09/21
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#include "logic_comm.h"
|
||||
|
||||
// 削峰填谷参数数据库配置
|
||||
peakvalley_zone_tab_t zone_tab_obj = {0}; // 定义一个结构体变量
|
||||
peakvalley_zone_tab_t* zone_tab = &zone_tab_obj; // 使指针指向该变量
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 将日期字符串转换为月份和日的整数表示
|
||||
* @param[in] char* dateStr 日期字符串,例如 "MM-DD"
|
||||
* @param[out] int* month 指向月份的指针
|
||||
* @param[out] int* day 指向日期的指针
|
||||
* @return 0: 成功 其它值:失败
|
||||
*****************************************************************************/
|
||||
static int parseDate(const char* dateStr, int* month, int* day)
|
||||
{
|
||||
int result = sscanf(dateStr, "%d-%d", month, day); // 解析字符串获取月份和日期
|
||||
return (result == 2) ? 0 : -1; // 返回0表示成功,其他值表示失败
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 获取削峰平谷实时运行参数接口
|
||||
* @param[in] pv_time_config_t *ret_params(功率计划时间表) u_int16_t slotTabLen (实际表长)
|
||||
* @return 目标功率
|
||||
*****************************************************************************/
|
||||
static float_t getPeakValleyPower(pv_time_config_t* ret_params, u_int16_t slotTabLen)
|
||||
{
|
||||
// 获取当前时间
|
||||
time_t current_time;
|
||||
struct tm* timeinfo;
|
||||
time(¤t_time); // 获取当前时间戳
|
||||
timeinfo = localtime(¤t_time); // 将时间戳转换为当地时间
|
||||
uint32_t now_seconds = timeinfo->tm_hour * 3600 + timeinfo->tm_min * 60 + timeinfo->tm_sec; // 计算当前秒数
|
||||
|
||||
// EMS要求最小的时间间隔不得小于15分钟,换算之后一天不可大于96个时段
|
||||
if (slotTabLen > MAX_TIME_SEGMENTS)
|
||||
{
|
||||
// 检查传入的时间段表长度是否合法
|
||||
KITLOG(LOG_LOGIC_EN, WARN_EN, "获取时段表的长度非法 len:%d\n", slotTabLen);
|
||||
return 0; // 返回0表示未能获取有效功率
|
||||
}
|
||||
for (int loop = 0; loop < slotTabLen; loop++)
|
||||
{
|
||||
// 跳过开始时间和结束时间相同的时间段
|
||||
if (ret_params[loop].startTime == ret_params[loop].endTime)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查当前时间是否在时间段内
|
||||
if (now_seconds >= ret_params[loop].startTime &&
|
||||
now_seconds <= ret_params[loop].endTime)
|
||||
{
|
||||
return ret_params[loop].power; // 返回当前时间段的功率值
|
||||
}
|
||||
}
|
||||
// 未命中任意时段则停机,返回0
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 判断日期是否在给定时间段内
|
||||
* @param[in] int dateMonth(当前月)
|
||||
* @param[in] int dateDay(当前日)
|
||||
* @param[in] const char* startDateStr(开始日期字符串)
|
||||
* @param[in] const char* endDateStr(结束日期字符串)
|
||||
* @return 1 在时间段内 0 不在时间段内 -1参数异常解析失败
|
||||
*****************************************************************************/
|
||||
static int isDateInRange(int dateMonth, int dateDay, const char* startDateStr, const char* endDateStr)
|
||||
{
|
||||
if (NULL == startDateStr || NULL == endDateStr)
|
||||
{
|
||||
// 检查开始和结束日期指针是否为空
|
||||
KITLOG(LOG_LOGIC_EN, ERROR_EN, "入参指针为空");
|
||||
return -1; // 返回-1表示参数异常
|
||||
}
|
||||
|
||||
int startMonth, startDay, endMonth, endDay;
|
||||
|
||||
if (0 != parseDate(startDateStr, &startMonth, &startDay))
|
||||
{
|
||||
// 解析开始日期字符串失败
|
||||
KITLOG(LOG_LOGIC_EN, ERROR_EN, "开始日期字符串匹配失败");
|
||||
return -1; // 返回-1表示参数解析失败
|
||||
}
|
||||
if (0 != parseDate(endDateStr, &endMonth, &endDay))
|
||||
{
|
||||
// 解析结束日期字符串失败
|
||||
KITLOG(LOG_LOGIC_EN, ERROR_EN, "结束日期字符串匹配失败");
|
||||
return -1; // 返回-1表示参数解析失败
|
||||
}
|
||||
// 日期保护,确保开始日期在结束日期之前
|
||||
if (startMonth > endMonth || (startMonth == endMonth && startDay > endDay))
|
||||
{
|
||||
return 0; // 返回0表示不在范围内
|
||||
}
|
||||
// 判断是否在日期内
|
||||
if (dateMonth > startMonth || (dateMonth == startMonth && dateDay >= startDay))
|
||||
{
|
||||
if (dateMonth < endMonth || (dateMonth == endMonth && dateDay <= endDay))
|
||||
{
|
||||
return 1; // 返回1表示在时间段内
|
||||
}
|
||||
}
|
||||
return 0; // 返回0表示不在范围内
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 更新时区时段表
|
||||
* @return 0 更新成功 -1 失败
|
||||
*****************************************************************************/
|
||||
int logic_peakValleyUpdate()
|
||||
{
|
||||
UT_array* pvDateConfigs;
|
||||
|
||||
// 清空之前的时段表
|
||||
if (zone_tab->peakItem != NULL)
|
||||
{
|
||||
for (int j = 0; j < zone_tab->zoneTabLen; ++j)
|
||||
{
|
||||
if (zone_tab->peakItem[j].timeCfgTab != NULL)
|
||||
free(zone_tab->peakItem[j].timeCfgTab);
|
||||
zone_tab->peakItem[j].timeCfgTab = NULL;
|
||||
}
|
||||
free(zone_tab->peakItem);
|
||||
zone_tab->peakItem = NULL;
|
||||
}
|
||||
|
||||
// 从数据库获取新的削峰填谷时段表数据
|
||||
if (kit_get_pv_date_cfg_db_data(&pvDateConfigs) != 0)
|
||||
{
|
||||
KITLOG(LOG_LOGIC_EN, ERROR_EN, "获取削峰填谷时段表失败");
|
||||
return 1; // 返回错误码
|
||||
}
|
||||
|
||||
// 获取数据个数
|
||||
size_t numConfigs = utarray_len(pvDateConfigs);
|
||||
|
||||
// 检查时段表长度是否合法
|
||||
if (MAX_DATA_SEGMENTS < numConfigs || numConfigs <= 0)
|
||||
{
|
||||
KITLOG(LOG_LOGIC_EN, ERROR_EN, "时区表表长异常: %zu", numConfigs);
|
||||
utarray_free(pvDateConfigs); // 释放资源
|
||||
return 1; // 返回错误码
|
||||
}
|
||||
|
||||
// 分配空间
|
||||
zone_tab->peakItem = (pv_date_config_t*)calloc(numConfigs, sizeof(pv_date_config_t));
|
||||
if (zone_tab->peakItem == NULL)
|
||||
{
|
||||
KITLOG(LOG_LOGIC_EN, ERROR_EN, "内存分配失败");
|
||||
utarray_free(pvDateConfigs); // 释放资源
|
||||
return 1; // 返回错误码
|
||||
}
|
||||
// 更新日期配置个数
|
||||
zone_tab->zoneTabLen = numConfigs;
|
||||
|
||||
// 遍历并复制数据 使用 memcpy 整体复制结构体
|
||||
for (int i = 0; i < numConfigs; ++i)
|
||||
{
|
||||
pv_date_config_t* srcConfig = (pv_date_config_t*)utarray_eltptr(pvDateConfigs, i);
|
||||
pv_date_config_t* dstConfig = &zone_tab->peakItem[i]; // 直接访问数组元素
|
||||
|
||||
// 复制 timeCfgTab 前先分配内存
|
||||
dstConfig->timeCfgTab = (pv_time_config_t*)calloc(srcConfig->timeCfgLen, sizeof(pv_time_config_t));
|
||||
if (dstConfig->timeCfgTab == NULL)
|
||||
{
|
||||
KITLOG(LOG_LOGIC_EN, ERROR_EN, "内存分配失败");
|
||||
// 释放已分配的内存
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
free(zone_tab->peakItem[j].timeCfgTab);
|
||||
}
|
||||
free(zone_tab->peakItem);
|
||||
utarray_free(pvDateConfigs); // 释放资源
|
||||
return 1; // 返回错误码
|
||||
}
|
||||
|
||||
memcpy(dstConfig, srcConfig, sizeof(pv_date_config_t)); // 整体复制结构体
|
||||
memcpy(dstConfig->timeCfgTab, srcConfig->timeCfgTab, srcConfig->timeCfgLen * sizeof(pv_time_config_t));
|
||||
}
|
||||
|
||||
utarray_free(pvDateConfigs); // 释放 UT_array 资源
|
||||
|
||||
return 0; // 返回成功
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 获取削峰平谷实时运行参数接口
|
||||
* @param[in] bool sign 时间表是否更新标志
|
||||
* @return 0 成功 -1 失败
|
||||
*****************************************************************************/
|
||||
int logicFun_peakValley()
|
||||
{
|
||||
// 获取任务参数
|
||||
peakvalley_params_t* task_params = &stlogic.para_delivery.task_params.pkvly;
|
||||
time_t current_time;
|
||||
struct tm* timeinfo;
|
||||
time(¤t_time); // 获取当前时间
|
||||
timeinfo = localtime(¤t_time); // 转换为当地时间
|
||||
// 获取日期
|
||||
int month = timeinfo->tm_mon + 1; // 月份从0开始,需要加1
|
||||
int day = timeinfo->tm_mday; // 天
|
||||
if (zone_tab == NULL)
|
||||
{
|
||||
// 检查时段表指针是否为空
|
||||
KITLOG(LOG_LOGIC_EN, ERROR_EN, "入参指针为空");
|
||||
return -1; // 返回-1表示失败
|
||||
}
|
||||
for (int loop = 0; loop < zone_tab->zoneTabLen; loop++)
|
||||
{
|
||||
// 检查当前日期是否在时段表中
|
||||
if (1 == isDateInRange(month, day, (char*)zone_tab->peakItem[loop].startDate, (char*)zone_tab->peakItem[loop].endDate))
|
||||
{
|
||||
// 获取对应时间段的功率配置
|
||||
task_params->power = getPeakValleyPower(zone_tab->peakItem[loop].timeCfgTab, zone_tab->peakItem[loop].timeCfgLen);
|
||||
return 0; // 返回0表示成功
|
||||
}
|
||||
}
|
||||
// 没找到合适的日期,返回0
|
||||
task_params->power = 0;
|
||||
return 0;
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_peakvalley.h
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/09/20
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#ifndef __LOGIC_PEAKVALLEY_H__
|
||||
#define __LOGIC_PEAKVALLEY_H__
|
||||
|
||||
#define MAX_DATA_SEGMENTS 0x0C // 一年12个月最多分 12个时间段
|
||||
#define MAX_TIME_SEGMENTS 0x60 // 一天24小时最多分 96个时间段
|
||||
|
||||
#include "kit_data.h"
|
||||
|
||||
// // 时段类型
|
||||
// typedef enum
|
||||
// {
|
||||
// kPeakvalley_Start = 0, // 开始值
|
||||
// kPeakvalley_Valley, // 谷
|
||||
// kPeakvalley_Peak, // 峰
|
||||
// kPeakvalley_Flat, // 平
|
||||
// kPeakvalley_End // 结束值
|
||||
// } peak_valley_e;
|
||||
|
||||
// 所有时间表结构体 用于查询
|
||||
typedef struct
|
||||
{
|
||||
pv_date_config_t* peakItem; // 时区表
|
||||
int zoneTabLen; // 时区表实际表长
|
||||
} peakvalley_zone_tab_t;
|
||||
|
||||
// 削峰填谷传参结构体
|
||||
typedef struct
|
||||
{
|
||||
int runPeriod; // 运行周期 ms
|
||||
float_t power; // 最终计算的目标功率
|
||||
} peakvalley_params_t;
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 获取保护参数
|
||||
* @return 0 成功 -1 失败
|
||||
*****************************************************************************/
|
||||
int logic_getProtectParam();
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 更新时区时段表
|
||||
* @return 0 更新成功 -1 失败
|
||||
*****************************************************************************/
|
||||
int logic_peakValleyUpdate();
|
||||
|
||||
#endif
|
|
@ -1,176 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_power_distr.c
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/09/28
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#include "logic_comm.h"
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 获取功率分配参数
|
||||
*
|
||||
* @return 0 更新成功 -1 失败 1 无更新
|
||||
*****************************************************************************/
|
||||
int logic_getPowerDistrParam()
|
||||
{
|
||||
static allocate_power_t getPowerBuff;
|
||||
if (0 != kit_get_allocate_power(&getPowerBuff))
|
||||
{
|
||||
// INLOG(Log_LOGIC_EN, ERROR_EN, "获取保护配置失败\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
stlogic.para_delivery.task_params.distr.cabintCont = getPowerBuff.pcsNum;
|
||||
stlogic.para_delivery.task_params.distr.chgDirection = getPowerBuff.chgDirection;
|
||||
stlogic.para_delivery.task_params.distr.allocateMode = getPowerBuff.allocateMode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 分配的期望功率下发
|
||||
* @param[in] power_distr_t distPower 运行参数
|
||||
* @return -1:下发失败 0:下发成功
|
||||
*****************************************************************************/
|
||||
void logic_PowerCal(power_distr_t *distPower, float_t tempPower, int loop)
|
||||
{
|
||||
float_t finalPower = 0;
|
||||
// if (distPower->nowDistPower[loop] < 0) // 充电
|
||||
if (tempPower < 0) // 充电
|
||||
{
|
||||
finalPower = -float_min(abs(tempPower), distPower->pcsMaxChaPower[loop]);
|
||||
if (float_diff(distPower->nowBmsPower[loop], finalPower)) // 实时功率比较 差距大再下发
|
||||
{
|
||||
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
|
||||
{
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "柜 %d 功率变化 %.2f kw ==> %.2f kw", loop, distPower->nowDistPower[loop], finalPower * distPower->chgDirection);
|
||||
KITPTF(LOG_MODBUS_EN, INFO_EN, "柜 %d 功率变化 %.2f kw ==> %.2f kw", loop, distPower->nowDistPower[loop], finalPower * distPower->chgDirection);
|
||||
}
|
||||
distPower->nowDistPower[loop] = finalPower * distPower->chgDirection;
|
||||
}
|
||||
// 调试模式PCS开关由指令决定
|
||||
if (stlogic.para_delivery.mode == E_TACTIC_MODE_DEBUG)
|
||||
{
|
||||
distPower->pcsSwitch[loop] = stlogic.para_delivery.task_params.debug.pcsSwitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
// distPower->pcsSwitch[loop] = distPower->pcsOn; // pcs 功能码可定制 在这里
|
||||
distPower->pcsSwitch[loop] = 1;
|
||||
}
|
||||
|
||||
// 系统状态更新
|
||||
updateState(kState_Charging, true);
|
||||
}
|
||||
else if (tempPower > 0) // 放电
|
||||
{
|
||||
finalPower = float_min(tempPower, distPower->pcsMaxDiscPower[loop]);
|
||||
if (float_diff(distPower->nowBmsPower[loop], finalPower)) // 与实时功率比较 差距大再下发
|
||||
{
|
||||
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
|
||||
{
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "柜 %d 功率变化 %.2f kw ==> %.2f kw", loop, distPower->nowDistPower[loop], finalPower * distPower->chgDirection);
|
||||
KITPTF(LOG_MODBUS_EN, INFO_EN, "柜 %d 功率变化 %.2f kw ==> %.2f kw", loop, distPower->nowDistPower[loop], finalPower * distPower->chgDirection);
|
||||
}
|
||||
distPower->nowDistPower[loop] = finalPower * distPower->chgDirection;
|
||||
}
|
||||
// 调试模式PCS开关由指令决定
|
||||
if (stlogic.para_delivery.mode == E_TACTIC_MODE_DEBUG)
|
||||
{
|
||||
distPower->pcsSwitch[loop] = stlogic.para_delivery.task_params.debug.pcsSwitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
// distPower->pcsSwitch[loop] = distPower->pcsOn; // pcs 功能码可定制 在这里
|
||||
distPower->pcsSwitch[loop] = 1;
|
||||
}
|
||||
|
||||
// 系统状态更新
|
||||
updateState(kState_Discharging, true);
|
||||
}
|
||||
else // 待机
|
||||
{
|
||||
// distPower->pcsSwitch[loop] = distPower->pcsOff;
|
||||
if (0 != distPower->nowDistPower[loop])
|
||||
{
|
||||
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
|
||||
{
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "柜 %d 功率变化 %.2f kw ==> 0 kw", loop, distPower->nowDistPower[loop]);
|
||||
KITPTF(LOG_MODBUS_EN, INFO_EN, "柜 %d 功率变化 %.2f kw ==> 0 kw", loop, distPower->nowDistPower[loop]);
|
||||
}
|
||||
}
|
||||
distPower->nowDistPower[loop] = 0;
|
||||
// 调试模式PCS开关由指令决定
|
||||
if (stlogic.para_delivery.mode == E_TACTIC_MODE_DEBUG)
|
||||
{
|
||||
distPower->pcsSwitch[loop] = stlogic.para_delivery.task_params.debug.pcsSwitch;
|
||||
}
|
||||
else
|
||||
{
|
||||
// distPower->pcsSwitch[loop] = distPower->pcsOn; // pcs 功能码可定制 在这里
|
||||
distPower->pcsSwitch[loop] = 0;
|
||||
}
|
||||
// 系统状态更新
|
||||
updateState(kState_Standby, true);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 期望功率分配计算并下发
|
||||
*
|
||||
* @return -1:数据处理失败 0:数据处理成功
|
||||
*****************************************************************************/
|
||||
void logicFun_powerDistr()
|
||||
{
|
||||
power_distr_t *charge_params = &stlogic.para_delivery.task_params.distr;
|
||||
float_t tempPower = 0;
|
||||
int loop = 0, closePrtc = 0;
|
||||
if (charge_params == NULL)
|
||||
{
|
||||
// INLOG(Log_LOGIC_EN, ERROR_EN, "入参指针为空!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// 把保护计算完的的功率拿出来分配
|
||||
charge_params->power = stlogic.para_delivery.task_params.protect.power;
|
||||
|
||||
if (E_TACTIC_MODE_DEBUG == stlogic.para_delivery.mode && stlogic.para_delivery.task_params.debug.protectSwitch)
|
||||
{
|
||||
closePrtc = 1;
|
||||
}
|
||||
// 计算每个柜子分多少功率
|
||||
for (loop = 0; loop < charge_params->cabintCont; loop++)
|
||||
{
|
||||
if (charge_params->power < 0 && charge_params->sumSoc != 0) // 充电
|
||||
{
|
||||
if (closePrtc || (charge_params->pcsMaxChaPower[loop] != 0 && charge_params->pcsState[loop] != 0 && charge_params->bmsState[loop] != 0))
|
||||
{
|
||||
tempPower = charge_params->power * (SOCMAX - charge_params->bmsSoc[loop]) / charge_params->sumSoc;
|
||||
logic_PowerCal(charge_params, tempPower, loop);
|
||||
}
|
||||
else
|
||||
{
|
||||
charge_params->nowDistPower[loop] = 0;
|
||||
}
|
||||
}
|
||||
else if (charge_params->power > 0 && charge_params->sumSoc != 0) // 放电
|
||||
{
|
||||
if (closePrtc || (charge_params->pcsMaxDiscPower[loop] != 0 && charge_params->pcsState[loop] != 0 && charge_params->bmsState[loop] != 0))
|
||||
{
|
||||
tempPower = charge_params->power * (charge_params->bmsSoc[loop]) / charge_params->sumSoc;
|
||||
logic_PowerCal(charge_params, tempPower, loop);
|
||||
}
|
||||
else
|
||||
{
|
||||
charge_params->nowDistPower[loop] = 0;
|
||||
}
|
||||
}
|
||||
else // 待机
|
||||
{
|
||||
charge_params->nowDistPower[loop] = 0;
|
||||
logic_PowerCal(charge_params, tempPower, loop);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
|
||||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_power_issue.h
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/09/28
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#ifndef __LOGIC_POWERISSUE_H__
|
||||
#define __LOGIC_POWERISSUE_H__
|
||||
|
||||
#define MAX_NUM_CABINT 3 // 默认最大柜体个数为3(RTDB预留)
|
||||
#define SOCMAX 100
|
||||
|
||||
extern int g_iPcsChargeDirection; // PCS充放电方向 1(正放 负充) -1(负放 正充) 默认:1
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kBms_State_Start = 0,
|
||||
kBms_State_Normal, // 正常(rack可以放电, 可以充电)
|
||||
kBms_State_NoCharge, // 禁充(rack可以放电, 不能充电)
|
||||
kBms_State_NoDischarge, // 禁放(rack可以充电, 不能放电)
|
||||
kBms_State_Down, // 停机(rack不能充放)
|
||||
kBms_state_end
|
||||
} bms_state_e;
|
||||
|
||||
// // 充放电模式
|
||||
// typedef enum
|
||||
// {
|
||||
// kCharge_Mode_Start = 0, // 开始值
|
||||
// kCharge_Mode_charge ,
|
||||
// kCharge_Mode_discharge,
|
||||
// kCharge_Mode_rest,
|
||||
// kCharge_Mode_End // 结束值
|
||||
|
||||
// } charge_mode_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// charge_mode_e issueMod; // 本次下发充放电模式 ps:模式暂时不用 充放电方向: 默认1(正放 负充)
|
||||
// bms_state_e rackRunState[MAX_NUM_CABINT]; // 实时每个柜子的BMS的状态 IN
|
||||
|
||||
// 从实时库获取
|
||||
float_t bmsSoc[MAX_NUM_CABINT]; // 实时每个柜子的BMS的SOC IN
|
||||
float_t pcsMaxChaPower[MAX_NUM_CABINT]; // 最大充电功率 kw IN
|
||||
float_t pcsMaxDiscPower[MAX_NUM_CABINT]; // 最大放电功率 kw IN
|
||||
float_t nowBmsPower[MAX_NUM_CABINT]; // bms当前实时功率 kw IN
|
||||
uint8_t pcsState[MAX_NUM_CABINT]; // pcs在线状态
|
||||
uint8_t bmsState[MAX_NUM_CABINT]; // bms在线状态
|
||||
|
||||
// 可配置参数
|
||||
uint16_t cabintCont; // 当前实际并柜数量 IN
|
||||
int chgDirection; // 充放电方向 1(正放 负充) -1(正充 负放)
|
||||
uint8_t allocateMode; // 下发功率开关:总功率(0),分相功率(1)
|
||||
uint16_t pcsOn; // PCS开机字 功能码可定制
|
||||
uint16_t pcsOff; // PCS关机字 功能码可定制
|
||||
|
||||
int runPeriod; // 运行周期 ms
|
||||
uint8_t powerSign; // 功率分配配置修改标志
|
||||
|
||||
// 中间参数
|
||||
float_t stationBmsSoc; // 站级SOC OUT
|
||||
float_t sumSoc; // SOC累加
|
||||
float_t power; // 总的目标功率 kw IN
|
||||
float_t nowDistPower[MAX_NUM_CABINT]; // 分配后下发的目标功率 kw OUT
|
||||
uint16_t pcsSwitch[MAX_NUM_CABINT]; // PCS开关
|
||||
} power_distr_t;
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 获取功率分配参数
|
||||
*
|
||||
* @return 0 更新成功 -1 失败 1 无更新
|
||||
*****************************************************************************/
|
||||
int logic_getPowerDistrParam();
|
||||
|
||||
// 功率分发接口
|
||||
void logicFun_powerDistr();
|
||||
|
||||
#endif
|
|
@ -1,293 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_protected.c
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/09/21
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#include "logic_comm.h"
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 获取保护参数
|
||||
* @return 0 成功 -1 失败
|
||||
*****************************************************************************/
|
||||
int logic_getProtectParam()
|
||||
{
|
||||
static protect_algorithm_t getProtectBuff = {0.0f, 0.0f, 0.0f, 0.0f, 0, 0.0f, 0.0f, 0.0f, 0, 0.0f, 0.0f};
|
||||
static protect_params_t *tmpProtectBuff = &stlogic.para_delivery.task_params.protect;
|
||||
|
||||
if (0 != kit_get_protect_algorithm(&getProtectBuff))
|
||||
{
|
||||
// INLOG(Log_LOGIC_EN, ERROR_EN, "获取保护配置失败\n");
|
||||
return 1;
|
||||
}
|
||||
// 防过载和功率限制
|
||||
tmpProtectBuff->maxActivePower = getProtectBuff.transCapacity;
|
||||
tmpProtectBuff->overFlowLowLimt = getProtectBuff.olWarnLimitVal;
|
||||
tmpProtectBuff->overFlowCloseLimt = getProtectBuff.olShutdownVal;
|
||||
tmpProtectBuff->maxPower = getProtectBuff.maxPower;
|
||||
|
||||
// 防需和防逆流
|
||||
tmpProtectBuff->demandCtl = getProtectBuff.demandSwitch;
|
||||
tmpProtectBuff->aimActiveDemand = getProtectBuff.targetDemand;
|
||||
tmpProtectBuff->demandCtrlLowLimt = getProtectBuff.deWarnLimitVal;
|
||||
tmpProtectBuff->demandCtrlCloseLimt = getProtectBuff.deShutdownVal;
|
||||
|
||||
tmpProtectBuff->backFlow = getProtectBuff.backflowSwitch;
|
||||
tmpProtectBuff->backFlowLowLimt = getProtectBuff.bfWarnLimitVal;
|
||||
tmpProtectBuff->backFlowCloseLimt = getProtectBuff.bfShutdownVal;
|
||||
|
||||
// soc 保护
|
||||
tmpProtectBuff->socForbidCharge = getProtectBuff.socForbidChg;
|
||||
tmpProtectBuff->socForbidDischarge = getProtectBuff.socForbidDischg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 过载保护判断及处理
|
||||
* @param[inout] protect_params_t *charge_params 运行参数
|
||||
* @return 参数指针返回
|
||||
*****************************************************************************/
|
||||
void logic_protect_overload(protect_params_t *charge_params)
|
||||
{
|
||||
float_t tmp_max_power = charge_params->maxActivePower - charge_params->overFlowCloseLimt; // 计算关机功率点
|
||||
if (tmp_max_power >= charge_params->totalActivePower) // 关机判断
|
||||
{
|
||||
float_t load_active_power = charge_params->totalActivePower - charge_params->emsActivePower; // 算出负载功率
|
||||
tmp_max_power = charge_params->maxActivePower - charge_params->overFlowLowLimt;
|
||||
|
||||
if (tmp_max_power >= charge_params->totalActivePower) // 限流判断
|
||||
{
|
||||
float_t tmp_power = tmp_max_power - load_active_power - charge_params->overFlowLowLimt / 10;
|
||||
if (tmp_power > 0)
|
||||
{
|
||||
charge_params->power = -float_min(abs(charge_params->power), tmp_power);
|
||||
}
|
||||
else
|
||||
{
|
||||
charge_params->power = 0;
|
||||
}
|
||||
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
|
||||
{
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "触发过载保护!!! 并网点功率:%.2f kw 新的目标功率:%.2f kw", charge_params->totalActivePower, charge_params->power);
|
||||
KITPTF(LOG_MODBUS_EN, INFO_EN, "触发过载保护!!! 并网点功率:%.2f kw 新的目标功率:%.2f kw", charge_params->totalActivePower, charge_params->power);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float_t tmp_power = tmp_max_power - load_active_power - charge_params->overFlowLowLimt / 2;
|
||||
if (tmp_power > 0)
|
||||
{
|
||||
charge_params->power = -float_min(abs(charge_params->power), tmp_power);
|
||||
}
|
||||
else
|
||||
{
|
||||
charge_params->power = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
charge_params->power = 0;
|
||||
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
|
||||
{
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "触发过载保护!!! 并网点功率:%.2f kw 新的目标功率:%.2f kw", charge_params->totalActivePower, charge_params->power);
|
||||
KITPTF(LOG_MODBUS_EN, INFO_EN, "触发过载保护!!! 并网点功率:%.2f kw 新的目标功率:%.2f kw", charge_params->totalActivePower, charge_params->power);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 逆流防护判断及处理
|
||||
* @param[in] protect_backflow_t backflowParams 运行参数
|
||||
* @return 参数指针返回
|
||||
*****************************************************************************/
|
||||
void logic_protect_backflow(protect_params_t *charge_params)
|
||||
{
|
||||
float_t load_active_power = charge_params->totalActivePower - charge_params->emsActivePower; // 算出负载功率
|
||||
if (charge_params->totalActivePower > charge_params->backFlowCloseLimt) // 关机判断
|
||||
{
|
||||
if (load_active_power > charge_params->backFlowLowLimt) // 限流判断
|
||||
{
|
||||
float_t tmp_power = load_active_power - charge_params->backFlowLowLimt * 1.10;
|
||||
if (tmp_power > 0)
|
||||
{
|
||||
charge_params->power = float_min(charge_params->power, tmp_power);
|
||||
}
|
||||
else
|
||||
{
|
||||
charge_params->power = 0;
|
||||
}
|
||||
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
|
||||
{
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "触发逆流保护!!! 并网点功率:%.2f kw 新的目标功率:%.2f kw", charge_params->totalActivePower, charge_params->power);
|
||||
KITPTF(LOG_MODBUS_EN, INFO_EN, "触发逆流保护!!! 并网点功率:%.2f kw 新的目标功率:%.2f kw", charge_params->totalActivePower, charge_params->power);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
float_t tmp_power = load_active_power - charge_params->backFlowLowLimt * 1.50;
|
||||
if (tmp_power > 0)
|
||||
{
|
||||
charge_params->power = float_min(charge_params->power, tmp_power);
|
||||
}
|
||||
else
|
||||
{
|
||||
charge_params->power = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
charge_params->power = 0;
|
||||
if ((uint8_t)getRtdbPointValue(rtdbType, kDev_Type_EMS, 0, kEms_LogicLog_Enable) == 1)
|
||||
{
|
||||
KITLOG(LOG_MODBUS_EN, INFO_EN, "触发逆流关机!!! 并网点功率:%.2f kw 新的目标功率:%.2f kw", charge_params->totalActivePower, charge_params->power);
|
||||
KITPTF(LOG_MODBUS_EN, INFO_EN, "触发逆流关机!!! 并网点功率:%.2f kw 新的目标功率:%.2f kw", charge_params->totalActivePower, charge_params->power);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 最大充放电功率防护判断及处理
|
||||
* @param[in] protect_backflow_t backflowParams 运行参数
|
||||
* @return 参数指针返回
|
||||
*****************************************************************************/
|
||||
void logic_protect_maxPower(protect_params_t *charge_params)
|
||||
{
|
||||
if (charge_params->power < 0) // 充电
|
||||
{
|
||||
charge_params->power = -float_min(abs(charge_params->power), abs(charge_params->maxPower));
|
||||
}
|
||||
else if (charge_params->power > 0) // 放电
|
||||
{
|
||||
charge_params->power = float_min(charge_params->power, abs(charge_params->maxPower));
|
||||
}
|
||||
}
|
||||
/*****************************************************************************
|
||||
* @brief 策略数据计算及保护接口
|
||||
* @return -1:数据处理失败 0:数据处理成功
|
||||
*****************************************************************************/
|
||||
int logicFun_protect()
|
||||
{
|
||||
protect_params_t *charge_params = &stlogic.para_delivery.task_params.protect;
|
||||
if (charge_params->scramButton)
|
||||
{
|
||||
charge_params->power = 0;
|
||||
return 0;
|
||||
}
|
||||
switch (stlogic.para_delivery.mode)
|
||||
{
|
||||
case E_TACTIC_MODE_DEBUG: // 调试模式
|
||||
charge_params->power = stlogic.para_delivery.task_params.debug.activePower;
|
||||
charge_params->rePower = stlogic.para_delivery.task_params.debug.reactivePower;
|
||||
break;
|
||||
case E_TACTIC_MODE_PEAKVALLY: // 削峰填谷模式
|
||||
|
||||
charge_params->power = stlogic.para_delivery.task_params.pkvly.power;
|
||||
|
||||
break;
|
||||
case E_TACTIC_MODE_DEMANDRES: // 需求响应模式
|
||||
/* 暂未实现 */
|
||||
charge_params->power = stlogic.para_delivery.task_params.demand.power;
|
||||
|
||||
break;
|
||||
case E_TACTIC_MODE_LOADTRACK: // 负载跟踪模式
|
||||
/* 暂未实现 */
|
||||
charge_params->power = stlogic.para_delivery.task_params.loadTrack.power;
|
||||
break;
|
||||
default:
|
||||
/*未知模式*/
|
||||
stlogic.para_delivery.task_params.distr.power = 0;
|
||||
stlogic.para_delivery.task_params.protect.power = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// 统计总SOC
|
||||
int bmsOlineNum = 0;
|
||||
stlogic.para_delivery.task_params.distr.sumSoc = 0; // 参数清零
|
||||
if (charge_params->power < 0) // 充电
|
||||
{
|
||||
stlogic.para_delivery.task_params.distr.stationBmsSoc = 0;
|
||||
for (int loop = 0; loop < stlogic.para_delivery.task_params.distr.cabintCont; loop++)
|
||||
{
|
||||
if (!float_equal(stlogic.para_delivery.task_params.distr.pcsMaxChaPower[loop], 0) &&
|
||||
stlogic.para_delivery.task_params.distr.pcsState[loop] != 0 && stlogic.para_delivery.task_params.distr.bmsState[loop] != 0)
|
||||
{
|
||||
stlogic.para_delivery.task_params.distr.sumSoc += (SOCMAX - stlogic.para_delivery.task_params.distr.bmsSoc[loop]);
|
||||
bmsOlineNum++;
|
||||
}
|
||||
}
|
||||
if (bmsOlineNum)
|
||||
{
|
||||
stlogic.para_delivery.task_params.distr.stationBmsSoc = (((SOCMAX * bmsOlineNum) - stlogic.para_delivery.task_params.distr.sumSoc) / (SOCMAX * bmsOlineNum)) * 100.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
stlogic.para_delivery.task_params.distr.stationBmsSoc = 0.0;
|
||||
}
|
||||
}
|
||||
else if (charge_params->power > 0) // 放电
|
||||
{
|
||||
stlogic.para_delivery.task_params.distr.stationBmsSoc = 0;
|
||||
for (int loop = 0; loop < stlogic.para_delivery.task_params.distr.cabintCont; loop++)
|
||||
{
|
||||
if (!float_equal(stlogic.para_delivery.task_params.distr.pcsMaxDiscPower[loop], 0) &&
|
||||
stlogic.para_delivery.task_params.distr.pcsState[loop] != 0 && stlogic.para_delivery.task_params.distr.bmsState[loop] != 0)
|
||||
{
|
||||
stlogic.para_delivery.task_params.distr.sumSoc += stlogic.para_delivery.task_params.distr.bmsSoc[loop];
|
||||
bmsOlineNum++;
|
||||
}
|
||||
}
|
||||
if (bmsOlineNum)
|
||||
{
|
||||
stlogic.para_delivery.task_params.distr.stationBmsSoc = (stlogic.para_delivery.task_params.distr.sumSoc / (SOCMAX * bmsOlineNum)) * 100.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
stlogic.para_delivery.task_params.distr.stationBmsSoc = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
if (E_TACTIC_MODE_DEBUG == stlogic.para_delivery.mode && stlogic.para_delivery.task_params.debug.protectSwitch)
|
||||
{
|
||||
charge_params = NULL;
|
||||
return 0; // 调试模式保护跳过
|
||||
}
|
||||
|
||||
if (charge_params->power < 0) // 充电
|
||||
{
|
||||
if (stlogic.para_delivery.task_params.distr.stationBmsSoc >= charge_params->socForbidCharge)
|
||||
{
|
||||
// 到达禁充SOC
|
||||
charge_params->power = 0;
|
||||
return 0;
|
||||
}
|
||||
logic_protect_overload(charge_params); // 防过载
|
||||
if (charge_params->demandCtl)
|
||||
{
|
||||
logic_protect_demandCtrl(charge_params); // 需量控制
|
||||
}
|
||||
}
|
||||
else if (charge_params->power > 0) // 放电
|
||||
{
|
||||
if (stlogic.para_delivery.task_params.distr.stationBmsSoc <= charge_params->socForbidDischarge)
|
||||
{
|
||||
// 到达禁放SOC
|
||||
charge_params->power = 0;
|
||||
return 0;
|
||||
}
|
||||
if (charge_params->backFlow)
|
||||
{
|
||||
logic_protect_backflow(charge_params); // 防逆流
|
||||
}
|
||||
}
|
||||
else // 待机
|
||||
{
|
||||
// 待机目前考虑不用保护
|
||||
}
|
||||
logic_protect_maxPower(charge_params); // 限制功率
|
||||
charge_params = NULL;
|
||||
return 0; // 处理结束
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_protected.h
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/09/21
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#ifndef __LOGIC_PROTECTED_H__
|
||||
#define __LOGIC_PROTECTED_H__
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// 中间参数
|
||||
float_t power; // 目标功率 INOUT
|
||||
float_t rePower; // 目标无功功率 INOUT
|
||||
float_t nowActiveDemand; // 实时需量
|
||||
int runPeriod; // 运行周期 ms
|
||||
uint8_t protectSign; // 保护配置更新标志
|
||||
|
||||
// 读实时库
|
||||
float_t totalActivePower; // 变压器下总电表总有功功率 IN
|
||||
float_t emsActivePower; // 储能测总有功功率 IN
|
||||
|
||||
// 可配置参数
|
||||
float_t maxActivePower; // 变压器总容量 IN
|
||||
float_t overFlowLowLimt; // 过载预警限流值 IN
|
||||
float_t overFlowCloseLimt; // 过载关机值 IN
|
||||
float_t maxPower; // 充放电功率上限(一律为正值)
|
||||
bool demandCtl; // 防需量开关 IN
|
||||
float_t aimActiveDemand; // 目标需量 IN
|
||||
float_t demandCtrlLowLimt; // 防需预警限流值 IN
|
||||
float_t demandCtrlCloseLimt; // 防需关机值 IN
|
||||
bool backFlow; // 防逆流开关 IN
|
||||
float_t backFlowLowLimt; // 逆流预警限流值 IN
|
||||
float_t backFlowCloseLimt; // 逆流关机值 IN
|
||||
uint16_t socForbidCharge; // 禁充SOC [55%-100%]
|
||||
uint16_t socForbidDischarge; // 禁放SOC [0%-45%]
|
||||
|
||||
// DIDO接口
|
||||
uint16_t scramButton; // 急停开关,1打开
|
||||
} protect_params_t; // 保护函数传参结构体
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 获取削峰平谷实时运行参数接口
|
||||
* @param[in] bool sign 时间表是否更新标志
|
||||
* @return 0 成功 -1 失败
|
||||
*****************************************************************************/
|
||||
int logicFun_peakValley();
|
||||
|
||||
// 策略数据计算及保护接口
|
||||
int logicFun_protect();
|
||||
|
||||
#endif
|
|
@ -1,398 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_task_schedu.c
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/09/28
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#include <pthread.h>
|
||||
#include "logic_comm.h"
|
||||
|
||||
// 各模块任务函数注册
|
||||
// static task_funcPoint_t g_taskUnitSet;
|
||||
|
||||
// 设置任务的固定参数和初始参数
|
||||
// static task_params_t g_defaultParams;
|
||||
|
||||
// 序号,设备号,点位ID
|
||||
ParamFromRTDB RTDBtable[e_Logic_RTDB_end] =
|
||||
{
|
||||
{e_Logic_totalAcPower, kDev_Type_Pccmeter, kPCC_TotalActivePwr },
|
||||
{e_Logic_emsActivePower, kDev_Type_Bsmeter, kBs_TotalActivePwr },
|
||||
{e_Logic_bmsSoc, kDev_Type_BCU, kBcu_SOC },
|
||||
{e_Logic_pcsMaxChaPower, kDev_Type_PCS, kPcs_MaxAllowedChgPwr },
|
||||
{e_Logic_pcsMaxDiscPower, kDev_Type_PCS, kPcs_MaxAllowedDisChgPwr },
|
||||
{e_Logic_nowBmsPower, kDev_Type_PCS, kPcs_TotalActivePwr },
|
||||
{e_Logic_nowActiveDemand, kDev_Type_Pccmeter, kPCC_MaxDemandActiveFwd },
|
||||
{e_Logic_distrPower, kDev_Type_PCS, kPcs_ConstantActivePwrSet },
|
||||
{e_Logic_pcsSwitch, kDev_Type_PCS, kPcs_DeviceSwitchCommand },
|
||||
{e_Logic_pcsState, kDev_Type_PCS, kPcs_IsOnline },
|
||||
{e_Logic_bmsState, kDev_Type_BCU, kBcu_IsOnline },
|
||||
{e_Logic_emsMode, kDev_Type_EMS, kEms_LogicMode },
|
||||
{e_Logic_bsuMaxCellTemp, kDev_Type_BSU, kBsu_MaxCellTemp },
|
||||
{e_Logic_bsuMinCellTemp, kDev_Type_BSU, kBsu_MinCellTemp }
|
||||
// {e_Logic_AcLiquidSwitch, kDev_Type_AirCond_LiquidCool, kAcLiquidMac_SetOnOff },
|
||||
// {e_Logic_AcLiquidHeatTemp, kDev_Type_AirCond_LiquidCool, kAcLiquidMac_SetHeatTemp },
|
||||
// {e_Logic_AcLiquidColdTemp, kDev_Type_AirCond_LiquidCool, kAcLiquidMac_SetCoolDiff }
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 获取RTDB参数
|
||||
* @param[in] 枚举序号,参数指针,数据类型
|
||||
* @return 无
|
||||
*****************************************************************************/
|
||||
void logic_getValue(int No, void *value, data_type_e dataType)
|
||||
{
|
||||
if (No < 0 || No >= e_Logic_RTDB_end)
|
||||
{
|
||||
// 输入的 No 无效
|
||||
return;
|
||||
}
|
||||
|
||||
// 从表格中获取对应的条目
|
||||
ParamFromRTDB entry = RTDBtable[No];
|
||||
|
||||
switch (dataType)
|
||||
{
|
||||
case Uint8:
|
||||
{
|
||||
// 对于 uint8_t 类型
|
||||
uint8_t *uint8Value = (uint8_t *)value;
|
||||
for (uint16_t i = 0; i < gStDevTypeNum[entry.devType]; i++)
|
||||
{
|
||||
uint8Value[i] = (uint8_t)getRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Int8:
|
||||
{
|
||||
// 对于 int8_t 类型
|
||||
int8_t *int8Value = (int8_t *)value;
|
||||
for (uint16_t i = 0; i < gStDevTypeNum[entry.devType]; i++)
|
||||
{
|
||||
int8Value[i] = (int8_t)getRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Uint16:
|
||||
{
|
||||
// 对于 uint16_t 类型
|
||||
uint16_t *uint16Value = (uint16_t *)value;
|
||||
for (uint16_t i = 0; i < gStDevTypeNum[entry.devType]; i++)
|
||||
{
|
||||
uint16Value[i] = (uint16_t)getRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Int16:
|
||||
{
|
||||
// 对于 int16_t 类型
|
||||
int16_t *int16Value = (int16_t *)value;
|
||||
for (uint16_t i = 0; i < gStDevTypeNum[entry.devType]; i++)
|
||||
{
|
||||
int16Value[i] = (int16_t)getRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Uint32:
|
||||
{
|
||||
// 对于 uint32_t 类型
|
||||
uint32_t *uint32Value = (uint32_t *)value;
|
||||
for (uint16_t i = 0; i < gStDevTypeNum[entry.devType]; i++)
|
||||
{
|
||||
uint32Value[i] = (uint32_t)getRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Int32:
|
||||
{
|
||||
// 对于 int32_t 类型
|
||||
int32_t *int32Value = (int32_t *)value;
|
||||
for (uint16_t i = 0; i < gStDevTypeNum[entry.devType]; i++)
|
||||
{
|
||||
int32Value[i] = (int32_t)getRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Uint64:
|
||||
{
|
||||
// 对于 uint64_t 类型
|
||||
uint64_t *uint64Value = (uint64_t *)value;
|
||||
for (uint16_t i = 0; i < gStDevTypeNum[entry.devType]; i++)
|
||||
{
|
||||
uint64Value[i] = (uint64_t)getRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Int64:
|
||||
{
|
||||
// 对于 int64_t 类型
|
||||
int64_t *int64Value = (int64_t *)value;
|
||||
for (uint16_t i = 0; i < gStDevTypeNum[entry.devType]; i++)
|
||||
{
|
||||
int64Value[i] = (int64_t)getRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Float32:
|
||||
{
|
||||
// 对于 float_t (Float32) 类型
|
||||
float_t *floatValue = (float_t *)value;
|
||||
for (uint16_t i = 0; i < gStDevTypeNum[entry.devType]; i++)
|
||||
{
|
||||
floatValue[i] = (float_t)getRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Float64:
|
||||
{
|
||||
// 对于 double (Float64) 类型
|
||||
double *doubleValue = (double *)value;
|
||||
for (uint16_t i = 0; i < gStDevTypeNum[entry.devType]; i++)
|
||||
{
|
||||
doubleValue[i] = getRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// 不支持的类型
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 判断跳过语句
|
||||
* @param[in] No 枚举序号(对应 RTDBtable 中的索引)
|
||||
* @param[in] value 参数指针,表示要写入的数据
|
||||
* @param[in] num 数量
|
||||
* @return 无
|
||||
*****************************************************************************/
|
||||
void logic_skip_judge(bool *skip, uint16_t num, int No, void *value, data_type_e dataType)
|
||||
{
|
||||
ParamFromRTDB entry = RTDBtable[No];
|
||||
|
||||
for (uint16_t i = 0; i < num; i++)
|
||||
{
|
||||
// skip[i] = false; // 默认不跳过
|
||||
if(stlogic.para_delivery.task_params.distr.allocateMode)
|
||||
{
|
||||
float_t *floatValue = (float_t *)value;
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, kPcs_APhaseAPSet, (float_t)floatValue[i]/3);
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, kPcs_BPhaseAPSet, (float_t)floatValue[i]/3);
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, kPcs_CPhaseAPSet, (float_t)floatValue[i]/3);
|
||||
skip[i] = true; // 标记跳过
|
||||
continue;
|
||||
}
|
||||
|
||||
// 根据 No 值进行不同的处理
|
||||
switch (No)
|
||||
{
|
||||
case e_Logic_pcsSwitch: // PCS开关
|
||||
// 判断 pcsState 和 bmsState
|
||||
if (stlogic.para_delivery.task_params.distr.pcsState[i] == 0 ||
|
||||
stlogic.para_delivery.task_params.distr.bmsState[i] == 0)
|
||||
{
|
||||
skip[i] = true; // 标记跳过
|
||||
}
|
||||
else
|
||||
{
|
||||
// _PCS 特殊处理
|
||||
#ifdef _PCS
|
||||
// if (dataType == Uint16 && value != NULL)
|
||||
// {
|
||||
uint16_t *uint16Value = (uint16_t *)value;
|
||||
if (uint16Value[i])
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, kPcs_DeviceStartup, 1.0);
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, kPcs_DeviceShutdown, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, kPcs_DeviceStartup, 0.0);
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, kPcs_DeviceShutdown, 1.0);
|
||||
}
|
||||
// }
|
||||
skip[i] = true; // 标记跳过
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case e_Logic_distrPower: // distrPower 为 No 的处理逻辑
|
||||
// 判断 pcsState 和 bmsState
|
||||
if (stlogic.para_delivery.task_params.distr.pcsState[i] == 0 ||
|
||||
stlogic.para_delivery.task_params.distr.bmsState[i] == 0)
|
||||
{
|
||||
// 分配电力为 No 且满足保护条件时跳过
|
||||
if (E_TACTIC_MODE_DEBUG != stlogic.para_delivery.mode ||
|
||||
!stlogic.para_delivery.task_params.debug.protectSwitch)
|
||||
{
|
||||
skip[i] = true; // 标记跳过
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// 如果 No 不符合任何已定义的条件,默认不跳过
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 写入RTDB参数
|
||||
* @param[in] No 枚举序号(对应 RTDBtable 中的索引)
|
||||
* @param[in] value 参数指针,表示要写入的数据
|
||||
* @param[in] num 数量
|
||||
* @param[in] dataType 数据类型,表示写入的数据类型(Uint8、Int16 等)
|
||||
* @return 无
|
||||
*****************************************************************************/
|
||||
void logic_setValue(int No, void *value, uint16_t num, data_type_e dataType)
|
||||
{
|
||||
if (No < 0 || No >= e_Logic_RTDB_end)
|
||||
{
|
||||
// 输入的 No 无效
|
||||
return;
|
||||
}
|
||||
|
||||
// 从表格中获取对应的条目
|
||||
ParamFromRTDB entry = RTDBtable[No];
|
||||
|
||||
bool skip[MAX_NUM_CABINT] = {false};
|
||||
// 调用跳过判断逻辑
|
||||
logic_skip_judge(skip, num, No, value, dataType);
|
||||
|
||||
for (uint16_t i = 0; i < num; i++)
|
||||
{
|
||||
if (skip[i])
|
||||
continue;
|
||||
|
||||
switch (dataType)
|
||||
{
|
||||
case Uint8:
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId, (double)((uint8_t*)value)[i]);
|
||||
break;
|
||||
case Int8:
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId, (double)((int8_t*)value)[i]);
|
||||
break;
|
||||
case Uint16:
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId, (double)((uint16_t*)value)[i]);
|
||||
break;
|
||||
case Int16:
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId, (double)((int16_t*)value)[i]);
|
||||
break;
|
||||
case Uint32:
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId, (double)((uint32_t*)value)[i]);
|
||||
break;
|
||||
case Int32:
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId, (double)((int32_t*)value)[i]);
|
||||
break;
|
||||
case Uint64:
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId, (double)((uint64_t*)value)[i]);
|
||||
break;
|
||||
case Int64:
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId, (double)((int64_t*)value)[i]);
|
||||
break;
|
||||
case Float32:
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId, (double)((float*)value)[i]);
|
||||
break;
|
||||
case Float64:
|
||||
setRtdbPointValue(Rtdb_ShMem, entry.devType, i, entry.pointId, ((double*)value)[i]);
|
||||
break;
|
||||
default:
|
||||
// 不支持的类型,返回
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 实时库获取参数
|
||||
*
|
||||
* @return 0 更新成功 -1 失败 1 无更新
|
||||
*****************************************************************************/
|
||||
void logic_getRTDBParams()
|
||||
{
|
||||
/*获取电表的数据*/
|
||||
logic_getValue(e_Logic_totalAcPower, &stlogic.para_delivery.task_params.protect.totalActivePower, Float32);
|
||||
logic_getValue(e_Logic_emsActivePower, &stlogic.para_delivery.task_params.protect.emsActivePower, Float32);
|
||||
logic_getValue(e_Logic_nowActiveDemand, &stlogic.para_delivery.task_params.protect.nowActiveDemand, Float32);
|
||||
|
||||
/*获取pcs的数据*/
|
||||
logic_getValue(e_Logic_bmsSoc, &stlogic.para_delivery.task_params.distr.bmsSoc, Float32);
|
||||
logic_getValue(e_Logic_pcsMaxChaPower, &stlogic.para_delivery.task_params.distr.pcsMaxChaPower, Float32);
|
||||
logic_getValue(e_Logic_pcsMaxDiscPower, &stlogic.para_delivery.task_params.distr.pcsMaxDiscPower, Float32);
|
||||
logic_getValue(e_Logic_nowBmsPower, &stlogic.para_delivery.task_params.distr.nowBmsPower, Float32);
|
||||
logic_getValue(e_Logic_pcsState, &stlogic.para_delivery.task_params.distr.pcsState, Uint8);
|
||||
logic_getValue(e_Logic_bmsState, &stlogic.para_delivery.task_params.distr.bmsState, Uint8);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @brief 数据返回实时库
|
||||
* @param[in] 无
|
||||
* @return
|
||||
*********************************************************************/
|
||||
int logic_paramUpload()
|
||||
{
|
||||
|
||||
if (LOGIC_SIGN_UPLOAD == stlogic.para_delivery.task_params.protect.protectSign)
|
||||
{
|
||||
stlogic.para_delivery.task_params.protect.protectSign = LOGIC_SIGN_NONE;
|
||||
writeWebSign(kSign_ShMem, kSign_Protect, LOGIC_SIGN_UPLOAD);
|
||||
}
|
||||
|
||||
if (LOGIC_SIGN_UPLOAD == stlogic.para_delivery.task_params.distr.powerSign)
|
||||
{
|
||||
stlogic.para_delivery.task_params.distr.powerSign = LOGIC_SIGN_NONE;
|
||||
writeWebSign(kSign_ShMem, kSign_ActivePower, LOGIC_SIGN_UPLOAD);
|
||||
}
|
||||
|
||||
switch (stlogic.para_delivery.mode)
|
||||
{
|
||||
case E_TACTIC_MODE_DEBUG: // 调试模式
|
||||
writeWebSign(kSign_ShMem, kSign_LogicDebug, LOGIC_SIGN_UPLOAD);
|
||||
// PCS开关机下发
|
||||
logic_setValue(e_Logic_pcsSwitch, &stlogic.para_delivery.task_params.distr.pcsSwitch, stlogic.para_delivery.task_params.distr.cabintCont, Uint16);
|
||||
// 功率下发
|
||||
logic_setValue(e_Logic_distrPower, &stlogic.para_delivery.task_params.distr.nowDistPower, stlogic.para_delivery.task_params.distr.cabintCont, Float32);
|
||||
break;
|
||||
case E_TACTIC_MODE_PEAKVALLY: // 削峰填谷模式
|
||||
writeWebSign(kSign_ShMem, kSign_LogicPeakValley, LOGIC_SIGN_UPLOAD);
|
||||
// PCS开关机下发
|
||||
logic_setValue(e_Logic_pcsSwitch, &stlogic.para_delivery.task_params.distr.pcsSwitch, stlogic.para_delivery.task_params.distr.cabintCont, Uint16);
|
||||
// 功率下发
|
||||
logic_setValue(e_Logic_distrPower, &stlogic.para_delivery.task_params.distr.nowDistPower, stlogic.para_delivery.task_params.distr.cabintCont, Float32);
|
||||
break;
|
||||
case E_TACTIC_MODE_DEMANDRES: // 需求响应模式
|
||||
/* 暂未实现 */
|
||||
// 系统状态更新为停机
|
||||
updateState(kState_Shutdown, true);
|
||||
break;
|
||||
case E_TACTIC_MODE_LOADTRACK: // 负载跟踪模式
|
||||
/* 暂未实现 */
|
||||
// 系统状态更新为停机
|
||||
updateState(kState_Shutdown, true);
|
||||
break;
|
||||
case E_TACTIC_MODE_DMDCTRL: // 需量控制
|
||||
/* 暂未实现 */
|
||||
// 系统状态更新为停机
|
||||
updateState(kState_Shutdown, true);
|
||||
break;
|
||||
case E_TACTIC_MODE_PFCTRL: // 功率因数
|
||||
/* 暂未实现 */
|
||||
// 系统状态更新为停机
|
||||
updateState(kState_Shutdown, true);
|
||||
break;
|
||||
default:
|
||||
// 系统状态更新为停机
|
||||
updateState(kState_Shutdown, true);
|
||||
break;
|
||||
}
|
||||
// 运行模式入RTDB
|
||||
logic_setValue(e_Logic_emsMode, &stlogic.para_delivery.mode, 1, Uint16);
|
||||
return 0;
|
||||
}
|
|
@ -1,723 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_tempCtrl.c
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/11/26
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#include "logic_tempCtrl.h"
|
||||
|
||||
temp_judge_mod_e logicTempState[MAX_NUM_CABINT] = {0};
|
||||
logic_pthread_t stTemp = {0};
|
||||
|
||||
logicTempEquip tempEquipCall[kTemperature_ctrl_end] =
|
||||
{
|
||||
Logic_Temp_Select_AC,
|
||||
Logic_Temp_Select_LC,
|
||||
Logic_Temp_Select_AC_Auto,
|
||||
Logic_Temp_Select_LC_Auto
|
||||
};
|
||||
|
||||
logicTempExe tempFunCall[kTemperature_ctrl_end][kTemp_Judge_end] = {
|
||||
// kTemperature_ctrl_Ac
|
||||
{
|
||||
kAC_Normal_Callback,
|
||||
kAC_OverTemp_Callback,
|
||||
kAC_OverLock_Callback,
|
||||
kAC_UnderTemp_Callback,
|
||||
kAC_UnderLock_Callback,
|
||||
kAC_Close_Callback
|
||||
},
|
||||
// kTemperature_ctrl_Lc
|
||||
{
|
||||
kLC_Normal_Callback,
|
||||
kLC_OverTemp_Callback,
|
||||
kLC_OverLock_Callback,
|
||||
kLC_UnderTemp_Callback,
|
||||
kLC_UnderLock_Callback,
|
||||
kLC_Close_Callback
|
||||
},
|
||||
// kTemperature_auto_Ac
|
||||
{
|
||||
kAC_Auto_Callback,
|
||||
},
|
||||
// kTemperature_auto_Lc
|
||||
{
|
||||
kLC_Auto_Callback,
|
||||
}
|
||||
};
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 初始化温度控制参数
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
static void Logic_Temp_initParam(temp_ctrl_algorithm_t* sqlPara,temp_params_t *para)
|
||||
{
|
||||
for (u_int16_t i = 0; i < MAX_NUM_CABINT; i++)
|
||||
{
|
||||
logicTempState[i] = kTemp_Judge_Normal;
|
||||
}
|
||||
|
||||
para->mod = sqlPara->mod;
|
||||
para->workTemp.coolTrigTemp = sqlPara->workCoolTrigTemp;
|
||||
para->workTemp.coolHys = sqlPara->workCoolHys;
|
||||
para->workTemp.heatTrigTemp = sqlPara->workHeatTrigTemp;
|
||||
para->workTemp.heatHys = sqlPara->workHeatHys;
|
||||
|
||||
para->standByTemp.coolTrigTemp = sqlPara->standbyCoolTrigTemp;
|
||||
para->standByTemp.coolHys = sqlPara->standbyCoolHys;
|
||||
para->standByTemp.heatTrigTemp = sqlPara->standbyHeatTrigTemp;
|
||||
para->standByTemp.heatHys = sqlPara->standbyHeatHys;
|
||||
|
||||
para->standByLimit.maxlimit = sqlPara->standbyMaxLimit;
|
||||
para->standByLimit.minlimit = sqlPara->standbyMinLimit;
|
||||
para->standByLimit.maxbacklimit = sqlPara->standbyMaxbackLimit;
|
||||
para->standByLimit.minbacklimit = sqlPara->standbyMinbackLimit;
|
||||
|
||||
para->tempCmd_normal = sqlPara->tempCmdNormal;
|
||||
para->tempCmd_heat = sqlPara->tempCmdHeat;
|
||||
para->tempCmd_cold = sqlPara->tempCmdCold;
|
||||
para->tempCmdOpen = sqlPara->tempCmdOpen;
|
||||
para->tempCmdClose = sqlPara->tempCmdClose;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 收集温度控制参数
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void Logic_Temp_Collect(temp_params_t *para)
|
||||
{
|
||||
logic_getValue(e_Logic_nowBmsPower, para->pcsPower, Float32);
|
||||
logic_getValue(e_Logic_bsuMaxCellTemp, para->maxCellTemp, Float32);
|
||||
logic_getValue(e_Logic_bsuMinCellTemp, para->minCellTemp, Float32);
|
||||
|
||||
// para->pcsPower[0] = 6;
|
||||
|
||||
// printf("请输入最大单元温度: ");
|
||||
// scanf("%f", ¶->maxCellTemp[0]); // 输入最大单元温度
|
||||
|
||||
// printf("请输入最小单元温度: ");
|
||||
// scanf("%f", ¶->minCellTemp[0]); // 输入最小单元温度
|
||||
|
||||
// para->maxCellTemp[0] = 41;
|
||||
// para->minCellTemp[0] = 25;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 初始化温控设备
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
static void Logic_Temp_initEquip(temp_params_t *para)
|
||||
{
|
||||
// 创建一个临时副本,防止修改影响原始数据
|
||||
temp_params_t temppara = *para; // 进行浅拷贝,副本和原始数据不同
|
||||
Logic_Temp_Collect(&temppara); // 使用副本进行操作
|
||||
|
||||
for (u_int16_t i = 0; i < gStDevTypeNum[kDev_Type_AirCond_LiquidCool]; i++)
|
||||
{
|
||||
switch (temppara.mod)
|
||||
{
|
||||
default:
|
||||
break;
|
||||
|
||||
case kTemperature_ctrl_Ac:
|
||||
// 判断是否需要开机
|
||||
// if (para->maxCellTemp[i] - temppara.workTemp.coolTrigTemp > EPSILON
|
||||
// || temppara.workTemp.heatTrigTemp - para->minCellTemp[i] < EPSILON)
|
||||
// {
|
||||
// setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff, temppara.tempCmdOpen);
|
||||
// }
|
||||
if (temppara.tempCmdClose == getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff, temppara.tempCmdOpen);
|
||||
}
|
||||
break;
|
||||
|
||||
case kTemperature_ctrl_Lc:
|
||||
if (para->maxCellTemp[i] - temppara.standByLimit.maxlimit > EPSILON
|
||||
|| temppara.standByLimit.minlimit - para->minCellTemp[i] < EPSILON)
|
||||
{
|
||||
kLC_Normal_Callback((void *)&temppara , (void *)&i);
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_RunTemp, TEMP_AC_TEMP);
|
||||
}
|
||||
break;
|
||||
|
||||
case kTemperature_auto_Ac:
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff, temppara.tempCmdOpen);
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetCoolTemp, temppara.workTemp.coolTrigTemp);
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetHeatTemp, temppara.workTemp.heatTrigTemp);
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetCoolDiff, temppara.workTemp.coolHys);
|
||||
// setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetHeatDiff, temppara.workTemp.heatHys);
|
||||
break;
|
||||
|
||||
case kTemperature_auto_Lc:
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 选择当前温控设备状态
|
||||
* @param[in] para 指向温度参数结构体的指针,包含当前温度、功率等信息
|
||||
* @param[in] No 参数编号,用于选择特定的温度控制对象
|
||||
* @return 无返回值
|
||||
*
|
||||
* @note 该函数通过温度参数来判断当前设备是否处于过温、欠温或正常工作状态,
|
||||
* 并根据不同的温度值和功率值进行状态切换。
|
||||
*****************************************************************************/
|
||||
void Logic_Temp_Select_LC(temp_params_t *para, u_int16_t No)
|
||||
{
|
||||
// 检查参数编号是否合法
|
||||
if (No >= MAX_NUM_CABINT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
temp_limit_t temp_limit;
|
||||
|
||||
// 错误数据
|
||||
if (fabs(para->maxCellTemp[No]) > 255.0f || fabs(para->minCellTemp[No]) > 255.0f)
|
||||
{
|
||||
logicTempState[No] = kTemp_Judge_Close;
|
||||
return;
|
||||
}
|
||||
|
||||
// 没有电池温度,关机
|
||||
if (para->maxCellTemp[No] < EPSILON && para->minCellTemp[No] < EPSILON)
|
||||
{
|
||||
logicTempState[No] = kTemp_Judge_Close;
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据当前功率判断使用待机温度或工作温度
|
||||
if (abs(para->pcsPower[No]) < TEMP_WORKPOWER)
|
||||
{
|
||||
temp_limit = para->standByTemp; // 使用待机温度
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_limit = para->workTemp; // 使用工作温度
|
||||
}
|
||||
|
||||
// 判断是否需要触发制冷或制热
|
||||
if (para->maxCellTemp[No] - temp_limit.coolTrigTemp > -EPSILON)
|
||||
{
|
||||
// 过温状态
|
||||
logicTempState[No] = kTemp_Judge_OverTemp;
|
||||
return;
|
||||
}
|
||||
else if (temp_limit.heatTrigTemp - para->minCellTemp[No] > -EPSILON)
|
||||
{
|
||||
// 欠温状态
|
||||
logicTempState[No] = kTemp_Judge_UnderTemp;
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据当前温度状态进行判断和状态转换
|
||||
switch (logicTempState[No])
|
||||
{
|
||||
// 过温判断
|
||||
case kTemp_Judge_OverTemp:
|
||||
case kTemp_Judge_OverLock:
|
||||
if (temp_limit.coolTrigTemp - temp_limit.coolHys - para->maxCellTemp[No] > -EPSILON)
|
||||
{
|
||||
// 恢复正常状态
|
||||
logicTempState[No] = kTemp_Judge_Normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 保持过温锁定状态
|
||||
logicTempState[No] = kTemp_Judge_OverLock;
|
||||
}
|
||||
break;
|
||||
|
||||
// 欠温判断
|
||||
case kTemp_Judge_UnderTemp:
|
||||
case kTemp_Judge_UnderLock:
|
||||
if (temp_limit.heatTrigTemp + temp_limit.heatHys - para->minCellTemp[No] < EPSILON)
|
||||
{
|
||||
// 恢复正常状态
|
||||
logicTempState[No] = kTemp_Judge_Normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 保持欠温锁定状态
|
||||
logicTempState[No] = kTemp_Judge_UnderLock;
|
||||
}
|
||||
break;
|
||||
|
||||
// 正常循环状态
|
||||
case kTemp_Judge_Normal:
|
||||
if (abs(para->pcsPower[No]) < TEMP_WORKPOWER)
|
||||
{
|
||||
// 检查是否符合待机关闭条件
|
||||
if (para->maxCellTemp[No] - (para->standByLimit.maxlimit - para->standByLimit.maxbacklimit) <= EPSILON
|
||||
&& para->standByLimit.minlimit + para->standByLimit.minbacklimit - para->minCellTemp[No] <= EPSILON)
|
||||
{
|
||||
logicTempState[No] = kTemp_Judge_Close; // 进入关闭状态
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// 关机状态
|
||||
case kTemp_Judge_Close:
|
||||
if (abs(para->pcsPower[No]) < TEMP_WORKPOWER)
|
||||
{
|
||||
// 检查是否符合恢复正常条件
|
||||
if (para->maxCellTemp[No] - para->standByLimit.maxlimit > -EPSILON
|
||||
|| para->standByLimit.minlimit - para->minCellTemp[No] > -EPSILON)
|
||||
{
|
||||
logicTempState[No] = kTemp_Judge_Normal; // 恢复正常状态
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// 其他状态,保持原有状态
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 选择当前温控设备状态
|
||||
* @param[in] para 指向温度参数结构体的指针,包含当前温度、功率等信息
|
||||
* @param[in] No 参数编号,用于选择特定的温度控制对象
|
||||
* @return 无返回值
|
||||
*
|
||||
* @note 该函数通过温度参数来判断当前设备是否处于过温、欠温或正常工作状态,
|
||||
* 并根据不同的温度值和功率值进行状态切换。
|
||||
*****************************************************************************/
|
||||
void Logic_Temp_Select_AC(temp_params_t *para, u_int16_t No)
|
||||
{
|
||||
// 检查参数编号是否合法
|
||||
if (No >= MAX_NUM_CABINT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
temp_limit_t temp_limit;
|
||||
|
||||
temp_limit = para->workTemp; // 使用工作温度
|
||||
|
||||
// 错误数据
|
||||
if (fabs(para->maxCellTemp[No]) > 255.0f || fabs(para->minCellTemp[No]) > 255.0f)
|
||||
{
|
||||
logicTempState[No] = kTemp_Judge_Close;
|
||||
return;
|
||||
}
|
||||
|
||||
// 没有电池温度,关机
|
||||
if (para->maxCellTemp[No] < EPSILON && para->minCellTemp[No] < EPSILON)
|
||||
{
|
||||
logicTempState[No] = kTemp_Judge_Close;
|
||||
return;
|
||||
}
|
||||
|
||||
// 判断是否需要触发制冷或制热
|
||||
if (para->maxCellTemp[No] - temp_limit.coolTrigTemp > EPSILON)
|
||||
{
|
||||
// 过温状态
|
||||
logicTempState[No] = kTemp_Judge_OverTemp;
|
||||
return;
|
||||
}
|
||||
else if (temp_limit.heatTrigTemp - para->minCellTemp[No] > EPSILON)
|
||||
{
|
||||
// 欠温状态
|
||||
logicTempState[No] = kTemp_Judge_UnderTemp;
|
||||
return;
|
||||
}
|
||||
|
||||
// 根据当前温度状态进行判断和状态转换
|
||||
switch (logicTempState[No])
|
||||
{
|
||||
// 过温判断
|
||||
case kTemp_Judge_OverTemp:
|
||||
case kTemp_Judge_OverLock:
|
||||
if (temp_limit.coolTrigTemp - temp_limit.coolHys - para->maxCellTemp[No] > EPSILON)
|
||||
{
|
||||
// 恢复正常状态
|
||||
logicTempState[No] = kTemp_Judge_Normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 保持过温锁定状态
|
||||
logicTempState[No] = kTemp_Judge_OverLock;
|
||||
}
|
||||
break;
|
||||
|
||||
// 欠温判断
|
||||
case kTemp_Judge_UnderTemp:
|
||||
case kTemp_Judge_UnderLock:
|
||||
if (temp_limit.heatTrigTemp + temp_limit.heatHys - para->minCellTemp[No] < EPSILON)
|
||||
{
|
||||
// 恢复正常状态
|
||||
logicTempState[No] = kTemp_Judge_Normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 保持欠温锁定状态
|
||||
logicTempState[No] = kTemp_Judge_UnderLock;
|
||||
}
|
||||
break;
|
||||
|
||||
// 其他状态,保持原有状态
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Logic_Temp_Select_AC_Auto(temp_params_t *para, u_int16_t No)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
void Logic_Temp_Select_LC_Auto(temp_params_t *para, u_int16_t No)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 创建温度控制线程
|
||||
* @param[in] 无
|
||||
* @return 无
|
||||
*****************************************************************************/
|
||||
void *creatLogicTempThread(void *arg)
|
||||
{
|
||||
temp_params_t *temp_params_in = (temp_params_t *)arg;
|
||||
|
||||
while (stTemp.exitTaskFlag == 0)
|
||||
{
|
||||
// 读取更新信号
|
||||
// if(1 == readWebSign(kSign_ShMem, kSign_TempCtrl))
|
||||
// {
|
||||
// writeWebSign(kSign_ShMem, kSign_TempCtrl, 0);
|
||||
|
||||
// temp_ctrl_algorithm_t temp_infoFromDB;
|
||||
// int ret = kit_get_temp_ctrl_algorithm(&temp_infoFromDB);
|
||||
// if (ret != 0) // 判断是否成功
|
||||
// {
|
||||
// KITLOG(LOG_KIT_EN, ERROR_EN, "读取温控配置失败");
|
||||
// stTemp.exitTaskFlag = 1;
|
||||
// continue;
|
||||
// }
|
||||
// Logic_Temp_initParam(&temp_infoFromDB, temp_params_in);
|
||||
// }
|
||||
|
||||
Logic_Temp_Collect(temp_params_in);
|
||||
for(u_int16_t i = 0;i < gStDevTypeNum[kDev_Type_AirCond_LiquidCool]; i++)
|
||||
{
|
||||
tempEquipCall[temp_params_in->mod](temp_params_in, i);
|
||||
tempFunCall[temp_params_in->mod][logicTempState[i]](temp_params_in, &i);
|
||||
}
|
||||
|
||||
usleep(1000000); // 1s sleep
|
||||
}
|
||||
free(temp_params_in); // 线程结束后释放内存
|
||||
|
||||
pthread_exit(NULL);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
* @brief 新建温控的初始化工作
|
||||
* @param[in] 无
|
||||
* @return 0:sucessful;1:fault
|
||||
*********************************************************************/
|
||||
int creatLogicTempCtrlEntry()
|
||||
{
|
||||
if(0 == gStDevTypeNum[kDev_Type_AirCond_LiquidCool])
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
temp_ctrl_algorithm_t temp_infoFromDB;
|
||||
temp_params_t *tempPara = (temp_params_t *)malloc(sizeof(temp_params_t));
|
||||
|
||||
if (tempPara == NULL) // 检查内存分配是否成功
|
||||
{
|
||||
KITLOG(LOG_KIT_EN, ERROR_EN, "内存分配失败");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ret = kit_get_temp_ctrl_algorithm(&temp_infoFromDB);
|
||||
if (ret != 0) // 判断是否成功
|
||||
{
|
||||
free(tempPara);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Logic_Temp_initParam(&temp_infoFromDB, tempPara);
|
||||
|
||||
Logic_Temp_initEquip(tempPara);
|
||||
|
||||
if (pthread_create(&stTemp.tfd, NULL, creatLogicTempThread, (void *)tempPara) != 0)
|
||||
{
|
||||
KITPTF(LOG_LOGIC_EN, ERROR_EN, "temp线程创建失败");
|
||||
KITLOG(LOG_LOGIC_EN, ERROR_EN, "temp线程创建失败");
|
||||
free(tempPara);
|
||||
return 1;
|
||||
}
|
||||
KITPTF(LOG_LOGIC_EN, INFO_EN, "temp线程创建成功");
|
||||
KITLOG(LOG_LOGIC_EN, INFO_EN, "temp线程创建成功");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 过温回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kLC_OverTemp_Callback(void *arg, void *no)
|
||||
{
|
||||
uint16_t i = *(uint16_t *)no;
|
||||
temp_params_t *temp_params_in = (temp_params_t *)arg;
|
||||
if (temp_params_in->tempCmdClose == getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_Switch))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_Switch, temp_params_in->tempCmdOpen);
|
||||
}
|
||||
if (temp_params_in->tempCmd_cold != getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_RunMode))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_RunMode, temp_params_in->tempCmd_cold);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 过温自锁回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kLC_OverLock_Callback(void *arg, void *no)
|
||||
{
|
||||
uint16_t i = *(uint16_t *)no;
|
||||
temp_params_t *temp_params_in = (temp_params_t *)arg;
|
||||
if (temp_params_in->tempCmdClose == getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_Switch))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_Switch, temp_params_in->tempCmdOpen);
|
||||
}
|
||||
if (temp_params_in->tempCmd_cold != getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_RunMode))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_RunMode, temp_params_in->tempCmd_cold);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 自循环回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kLC_Normal_Callback(void *arg, void *no)
|
||||
{
|
||||
uint16_t i = *(uint16_t *)no;
|
||||
temp_params_t *temp_params_in = (temp_params_t *)arg;
|
||||
if (temp_params_in->tempCmdClose == getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_Switch))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_Switch, temp_params_in->tempCmdOpen);
|
||||
}
|
||||
if (temp_params_in->tempCmd_normal != getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_RunMode))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_RunMode, temp_params_in->tempCmd_normal);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 欠温回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kLC_UnderTemp_Callback(void *arg, void *no)
|
||||
{
|
||||
uint16_t i = *(uint16_t *)no;
|
||||
temp_params_t *temp_params_in = (temp_params_t *)arg;
|
||||
if (temp_params_in->tempCmdClose == getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_Switch))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_Switch, temp_params_in->tempCmdOpen);
|
||||
}
|
||||
if (temp_params_in->tempCmd_heat != getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_RunMode))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_RunMode, temp_params_in->tempCmd_heat);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 欠温自锁回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kLC_UnderLock_Callback(void *arg, void *no)
|
||||
{
|
||||
uint16_t i = *(uint16_t *)no;
|
||||
temp_params_t *temp_params_in = (temp_params_t *)arg;
|
||||
if (temp_params_in->tempCmdClose == getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_Switch))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_Switch, temp_params_in->tempCmdOpen);
|
||||
}
|
||||
if (temp_params_in->tempCmd_heat != getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_RunMode))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_RunMode, temp_params_in->tempCmd_heat);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 关机回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kLC_Close_Callback(void *arg, void *no)
|
||||
{
|
||||
uint16_t i = *(uint16_t *)no;
|
||||
temp_params_t *temp_params_in = (temp_params_t *)arg;
|
||||
if (temp_params_in->tempCmdOpen == getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_Switch))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_Switch, temp_params_in->tempCmdClose);
|
||||
}
|
||||
if (temp_params_in->tempCmd_normal != getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_RunMode))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_Lc_RunMode, temp_params_in->tempCmd_normal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 过温回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kAC_OverTemp_Callback(void *arg, void *no)
|
||||
{
|
||||
uint16_t i = *(uint16_t *)no;
|
||||
temp_params_t *temp_params_in = (temp_params_t *)arg;
|
||||
if (temp_params_in->tempCmdClose == getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff, temp_params_in->tempCmdOpen);
|
||||
}
|
||||
if (temp_params_in->tempCmd_cold != getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetCoolTemp))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetCoolTemp, TEMP_AC_TEMP);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 过温自锁回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kAC_OverLock_Callback(void *arg, void *no)
|
||||
{
|
||||
uint16_t i = *(uint16_t *)no;
|
||||
temp_params_t *temp_params_in = (temp_params_t *)arg;
|
||||
if (temp_params_in->tempCmdClose == getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff, temp_params_in->tempCmdOpen);
|
||||
}
|
||||
if (temp_params_in->tempCmd_cold != getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetCoolTemp))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetCoolTemp, TEMP_AC_TEMP);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 自循环回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kAC_Normal_Callback(void *arg, void *no)
|
||||
{
|
||||
uint16_t i = *(uint16_t *)no;
|
||||
temp_params_t *temp_params_in = (temp_params_t *)arg;
|
||||
if (temp_params_in->tempCmdOpen == getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff, temp_params_in->tempCmdClose);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 欠温回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kAC_UnderTemp_Callback(void *arg, void *no)
|
||||
{
|
||||
uint16_t i = *(uint16_t *)no;
|
||||
temp_params_t *temp_params_in = (temp_params_t *)arg;
|
||||
if (temp_params_in->tempCmdClose == getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff, temp_params_in->tempCmdOpen);
|
||||
}
|
||||
if (temp_params_in->tempCmd_heat != getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetHeatTemp))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetHeatTemp, temp_params_in->tempCmd_heat);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 欠温自锁回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kAC_UnderLock_Callback(void *arg, void *no)
|
||||
{
|
||||
uint16_t i = *(uint16_t *)no;
|
||||
temp_params_t *temp_params_in = (temp_params_t *)arg;
|
||||
if (temp_params_in->tempCmdClose == getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff, temp_params_in->tempCmdOpen);
|
||||
}
|
||||
if (temp_params_in->tempCmd_heat != getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetHeatTemp))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetHeatTemp, temp_params_in->tempCmd_heat);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 关机回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kAC_Close_Callback(void *arg, void *no)
|
||||
{
|
||||
uint16_t i = *(uint16_t *)no;
|
||||
temp_params_t *temp_params_in = (temp_params_t *)arg;
|
||||
if (temp_params_in->tempCmdOpen == getRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff))
|
||||
{
|
||||
setRtdbPointValue(Rtdb_ShMem, kDev_Type_AirCond_LiquidCool, i, kAcLiquidMac_SetOnOff, temp_params_in->tempCmdClose);
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 空调自动模式回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kAC_Auto_Callback(void *arg, void *no)
|
||||
{
|
||||
;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* @brief 液冷自动模式回调
|
||||
* @param[in] para 指向温度参数结构体的指针,用于存储收集到的参数
|
||||
* @param[in] No 序号
|
||||
* @return None
|
||||
*****************************************************************************/
|
||||
void kLC_Auto_Callback(void *arg, void *no)
|
||||
{
|
||||
;
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
/*****************************************************************************
|
||||
* @copyright 2024-202, . POWER SUPPLY CO., LTD.
|
||||
* @file logic_tempCtrl.h
|
||||
* @brief xxxx
|
||||
* @author Gary
|
||||
* @date 2024/09/21
|
||||
* @remark 初修订
|
||||
*****************************************************************************/
|
||||
#ifndef __LOGIC_TEMPCTRL_H__
|
||||
#define __LOGIC_TEMPCTRL_H__
|
||||
#include "logic_comm.h"
|
||||
|
||||
#define TEMP_WORKPOWER 2
|
||||
|
||||
#define TEMP_AC_TEMP 25
|
||||
|
||||
// 温控模式
|
||||
// typedef enum
|
||||
// {
|
||||
// kTemp_ctrl_Start, // 无
|
||||
// kTemp_ctrl_Ac = kTemp_ctrl_Start, // 风冷模式
|
||||
// kTemp_ctrl_Lc, // 液冷模式
|
||||
// kTemp_ctrl_end
|
||||
// } temp_ctrl_mod_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
kTemp_Judge_Start, // 无
|
||||
kTemp_Judge_Normal = kTemp_Judge_Start, // 正常温度(自循环)
|
||||
kTemp_Judge_OverTemp, // 高温
|
||||
kTemp_Judge_OverLock, // 高温自锁
|
||||
kTemp_Judge_UnderTemp, // 低温
|
||||
kTemp_Judge_UnderLock, // 低温自锁
|
||||
kTemp_Judge_Close, // 关机
|
||||
kTemp_Judge_end
|
||||
} temp_judge_mod_e;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float_t coolTrigTemp; // 制冷触发温度
|
||||
float_t coolHys; // 制冷回差
|
||||
float_t heatTrigTemp; // 制热触发温度
|
||||
float_t heatHys; // 制热回差
|
||||
}temp_limit_t; // 温度控制参数
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float_t maxlimit; //开启自循环高温
|
||||
float_t minlimit; //开启自循环低温
|
||||
float_t maxbacklimit; //自循环高温回温
|
||||
float_t minbacklimit; //自循环低温回温
|
||||
}temp_standby_limit_t; // 温度控制参数
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*用户可配参数*/
|
||||
temperature_ctrl_mod_e mod;
|
||||
|
||||
temp_limit_t workTemp; // 工作温度
|
||||
|
||||
temp_limit_t standByTemp; // 静置温度(液冷)
|
||||
|
||||
temp_standby_limit_t standByLimit; // 静置自循环温度限制(液冷)
|
||||
|
||||
u_int16_t tempCmd_normal; //循环控制字
|
||||
u_int16_t tempCmd_heat; //制热控制字
|
||||
u_int16_t tempCmd_cold; //制冷控制字
|
||||
uint8_t tempCmdOpen; // 开控制字
|
||||
uint8_t tempCmdClose; // 关控制字
|
||||
|
||||
/*中间变量*/
|
||||
float_t pcsPower[MAX_NUM_CABINT]; // kPcs_TotalActivePwr 总有功功率
|
||||
float_t maxCellTemp[MAX_NUM_CABINT]; // kBsu_MaxCellTemp 单体最高温度
|
||||
float_t minCellTemp[MAX_NUM_CABINT]; // kBsu_MinCellTemp 单体最低温度
|
||||
|
||||
} temp_params_t; // 温度控制参数
|
||||
|
||||
extern temp_judge_mod_e logicTempState[MAX_NUM_CABINT];
|
||||
|
||||
void Logic_Temp_Select_LC(temp_params_t *para, u_int16_t No);
|
||||
void Logic_Temp_Select_AC(temp_params_t *para, u_int16_t No);
|
||||
void Logic_Temp_Select_AC_Auto(temp_params_t *para, u_int16_t No);
|
||||
void Logic_Temp_Select_LC_Auto(temp_params_t *para, u_int16_t No);
|
||||
|
||||
void kLC_OverTemp_Callback(void *arg, void *no);
|
||||
void kLC_OverLock_Callback(void *arg, void *no);
|
||||
void kLC_Normal_Callback(void *arg, void *no);
|
||||
void kLC_UnderTemp_Callback(void *arg, void *no);
|
||||
void kLC_UnderLock_Callback(void *arg, void *no);
|
||||
void kLC_Close_Callback(void *arg, void *no);
|
||||
|
||||
void kAC_OverTemp_Callback(void *arg, void *no);
|
||||
void kAC_OverLock_Callback(void *arg, void *no);
|
||||
void kAC_Normal_Callback(void *arg, void *no);
|
||||
void kAC_UnderTemp_Callback(void *arg, void *no);
|
||||
void kAC_UnderLock_Callback(void *arg, void *no);
|
||||
void kAC_Close_Callback(void *arg, void *no);
|
||||
|
||||
void kAC_Auto_Callback(void *arg, void *no);
|
||||
|
||||
void kLC_Auto_Callback(void *arg, void *no);
|
||||
|
||||
typedef void (*logicTempEquip)(temp_params_t *para, u_int16_t No);
|
||||
typedef void (*logicTempExe)(void * , void *);
|
||||
|
||||
#endif
|
|
@ -28,7 +28,7 @@
|
|||
#include "kit_db.h"
|
||||
#include "kit_log.h"
|
||||
#include "utextend.h"
|
||||
#include "logic_power_distr.h"
|
||||
|
||||
#include "mw_schedule_handle.h"
|
||||
#include "drv_4g.h"
|
||||
#include "drv_wifi.h"
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#ifndef MW_SCHEDULE_HANDLE
|
||||
#define MW_SCHEDULE_HANDLE
|
||||
|
||||
#define MAX_NUM_CABINT 3
|
||||
/*****************************************************************************
|
||||
* @brief 创建定时存储任务
|
||||
* @return void
|
||||
|
|
Loading…
Reference in New Issue