From 23f43f43a55dd6db3fc202bf356d7bcc024c369a Mon Sep 17 00:00:00 2001 From: ahu_gq <57164135+gq-hefei@users.noreply.github.com> Date: Sat, 21 Jun 2025 16:57:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=97=A0=E6=95=88=E6=96=87?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ems_c/CMakeLists.txt | 13 - ems_c/app/app_task_regedit.c | 8 +- ems_c/app/app_task_regedit.h | 3 +- ems_c/bsp/bsp_mqttAsync.c | 153 -- ems_c/bsp/bsp_mqttAsync.h | 12 - ems_c/bsp/bsp_mqttClient.c | 2897 ------------------------------- ems_c/bsp/bsp_mqttClient.h | 367 ---- ems_c/logic/logic_bcu2bsu.c | 91 - ems_c/logic/logic_bcu2bsu.h | 36 - ems_c/logic/logic_comm.h | 210 --- ems_c/logic/logic_debug.c | 60 - ems_c/logic/logic_debug.h | 26 - ems_c/logic/logic_demandctrl.c | 172 -- ems_c/logic/logic_demandctrl.h | 31 - ems_c/logic/logic_dido.c | 920 ---------- ems_c/logic/logic_dido.h | 76 - ems_c/logic/logic_main.c | 384 ---- ems_c/logic/logic_main.h | 67 - ems_c/logic/logic_peakvalley.c | 230 --- ems_c/logic/logic_peakvalley.h | 53 - ems_c/logic/logic_power_distr.c | 176 -- ems_c/logic/logic_power_distr.h | 80 - ems_c/logic/logic_protected.c | 293 ---- ems_c/logic/logic_protected.h | 54 - ems_c/logic/logic_task_data.c | 398 ----- ems_c/logic/logic_tempCtrl.c | 723 -------- ems_c/logic/logic_tempCtrl.h | 106 -- ems_c/mw/mw_schedule_handle.c | 2 +- ems_c/mw/mw_schedule_handle.h | 1 + 29 files changed, 7 insertions(+), 7635 deletions(-) delete mode 100644 ems_c/bsp/bsp_mqttAsync.c delete mode 100644 ems_c/bsp/bsp_mqttAsync.h delete mode 100644 ems_c/bsp/bsp_mqttClient.c delete mode 100644 ems_c/bsp/bsp_mqttClient.h delete mode 100644 ems_c/logic/logic_bcu2bsu.c delete mode 100644 ems_c/logic/logic_bcu2bsu.h delete mode 100644 ems_c/logic/logic_comm.h delete mode 100644 ems_c/logic/logic_debug.c delete mode 100644 ems_c/logic/logic_debug.h delete mode 100644 ems_c/logic/logic_demandctrl.c delete mode 100644 ems_c/logic/logic_demandctrl.h delete mode 100644 ems_c/logic/logic_dido.c delete mode 100644 ems_c/logic/logic_dido.h delete mode 100644 ems_c/logic/logic_main.c delete mode 100644 ems_c/logic/logic_main.h delete mode 100644 ems_c/logic/logic_peakvalley.c delete mode 100644 ems_c/logic/logic_peakvalley.h delete mode 100644 ems_c/logic/logic_power_distr.c delete mode 100644 ems_c/logic/logic_power_distr.h delete mode 100644 ems_c/logic/logic_protected.c delete mode 100644 ems_c/logic/logic_protected.h delete mode 100644 ems_c/logic/logic_task_data.c delete mode 100644 ems_c/logic/logic_tempCtrl.c delete mode 100644 ems_c/logic/logic_tempCtrl.h diff --git a/ems_c/CMakeLists.txt b/ems_c/CMakeLists.txt index 8107dfa..1975ec8 100644 --- a/ems_c/CMakeLists.txt +++ b/ems_c/CMakeLists.txt @@ -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 ) # 添加编译选项 diff --git a/ems_c/app/app_task_regedit.c b/ems_c/app/app_task_regedit.c index 4d5caf9..352ce7c 100644 --- a/ems_c/app/app_task_regedit.c +++ b/ems_c/app/app_task_regedit.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(); } /********************************************************************* diff --git a/ems_c/app/app_task_regedit.h b/ems_c/app/app_task_regedit.h index 5ffdeae..34af9c3 100644 --- a/ems_c/app/app_task_regedit.h +++ b/ems_c/app/app_task_regedit.h @@ -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 diff --git a/ems_c/bsp/bsp_mqttAsync.c b/ems_c/bsp/bsp_mqttAsync.c deleted file mode 100644 index b52de1f..0000000 --- a/ems_c/bsp/bsp_mqttAsync.c +++ /dev/null @@ -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; -} \ No newline at end of file diff --git a/ems_c/bsp/bsp_mqttAsync.h b/ems_c/bsp/bsp_mqttAsync.h deleted file mode 100644 index ce24930..0000000 --- a/ems_c/bsp/bsp_mqttAsync.h +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include -#include -#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 \ No newline at end of file diff --git a/ems_c/bsp/bsp_mqttClient.c b/ems_c/bsp/bsp_mqttClient.c deleted file mode 100644 index bc9a651..0000000 --- a/ems_c/bsp/bsp_mqttClient.c +++ /dev/null @@ -1,2897 +0,0 @@ -/***************************************************************************** - * @copyright 1997-2050, . POWER SUPPLY CO., LTD. - * @file bsp_mqttClient.h - * @brief mqtt头文件 - * @author mdy - * @date 2024-09-29 - * @remark - *****************************************************************************/ -// #pragma once -#include "bsp_mqttClient.h" - -// #define MQTTSELFTEST -// #define CLOUDCTRLPRINT -// #define MQTTPRINT -sem_t g_allowSend; // 控制发送的信号量 -sem_t g_MqttwaitAndSaveHistory; // MQTT断线后,等待重连并将数据包入库 - -static const UT_icd topology_icd = {sizeof(topology_t), NULL, NULL, NULL}; -// static const UT_icd uint16_icd = {sizeof(uint16_t), NULL, NULL, NULL}; -static const UT_icd brcd_icd = {sizeof(break_record_t), NULL, NULL, NULL}; -static const UT_icd bdst_icd = {sizeof(break_data_storage_t), NULL, NULL, NULL}; -static const UT_icd brd_icd = {sizeof(break_record_with_data_t), NULL, NULL, NULL}; -static const UT_icd pvcfg_icd = {sizeof(pv_date_config_t), NULL, NULL, NULL}; -UT_array *g_recordsWithData; -// MQTT msgid 由paho.mqtt负责维护,int类型,标识每一次消息传递的状态,在客户端和服务端之间唯一标识一条消息的交付操作。 -volatile MQTTClient_deliveryToken deliveredtoken; -UT_array *g_topology_storage; //旧的拓扑信息,用于对比数据库中的拓扑 -uint64_t g_MqttMsg;//mqtt全局消息 -pthread_mutex_t connection_status_mutex = PTHREAD_MUTEX_INITIALIZER;//连接状态互斥锁 -pthread_mutex_t record_mutex = PTHREAD_MUTEX_INITIALIZER;//中断记录互斥锁 -char emsName[MAX_NAME_BUF_LEN]; -char mainEmsSn[MAX_NAME_BUF_LEN]; -mqtt_option_map_t g_mqtt_map[kDev_Type_End]; // 接收配置信息的结构体数组 -mqtt_option_map_t g_mqtt_map_chg[kDev_Type_End]; // 配置信息的备份 -bool g_ChgSend[kDev_Type_End] = {false}; -logic_Params g_LP = {0}; -BcuBsuMap *g_bcuMap = NULL; -long g_mqttSendTag = 0; -volatile int period_thread_alive = 1; // 状态变量,监控周期任务工作线程是否活跃 -volatile int history_thread_alive = 1; // 状态变量,监控历史数据任务工作线程是否活跃 -volatile int chkdata_thread_alive = 1; // 状态变量,监控检测变化任务工作线程是否活跃 -volatile int period_thread_haveSendSig = 0; // 状态变量,监控周期任务工作线程是否持有发送资源 -volatile int history_thread_haveSendSig = 0; // 状态变量,监控历史数据任务工作线程是否持有发送资源 -volatile int chkdata_thread_haveSendSig = 0; // 状态变量,监控检测数据变化监测任务工作线程是否持有发送资源 -volatile int period_thread_haveRcdSig = 0; // 状态变量,监控周期任务工作线程是否持有断点记录读写资源 -volatile int history_thread_haveRcdSig = 0; // 状态变量,监控历史数据任务工作线程是否持有发送资源 -pthread_t g_Tids[D_MAX_THREAD_NUM] = {0}; -long long CurtimesMS() -{ - struct timeval te; - // CS104_Connection_create("local_host", 2404); - gettimeofday(&te, NULL); // 获取当前时间 - // MeasuredValueScaled_create; - long long milliseconds = te.tv_sec * 1000LL + te.tv_usec / 1000; // 将秒和微秒转换为毫秒 - return milliseconds; -} -/***************************************************************************** - * @brief 发送消息给broker时触发的回调函数 - * @param[in] context:mqtt连接上下文 - * @param[in] dt:token * @return NONE - *****************************************************************************/ -void deliveredCB(void *context, MQTTClient_deliveryToken dt) -{ - - long times = time(NULL); - deliveredtoken = dt; - long deltaT = abs(times - g_mqttSendTag); - printf("Message with token value %d delivery confirmed.msg finish timestamp=%ld,msg send success timestamp=%ld,deltaT=%ld\n", dt, g_mqttSendTag, times, deltaT); -}; -void printdeltaT() -{ - long times = CurtimesMS(NULL); - long deltaT = abs(times - g_mqttSendTag); - printf("msg finish timestamp=%ld,msg send success timestamp=%ld,deltaT=%ld\n", g_mqttSendTag, times, deltaT); -}; -/***************************************************************************** - * @brief 根据报文的写配置类型,为参数指针申请相应的内存 - * @param[in] modeWord:策略类型枚举 - * @param[in] funArg:函数参数指针 - * @return NONE - *****************************************************************************/ -int param_set_select(int modeWord, void *funArg) -{ - int lenth = 0; - switch (modeWord) - { - case E_TACTIC_MODE_DEBUG: // 调试模式 - lenth = sizeof(debug_params_t); - funArg = (debug_params_t *)malloc(lenth); - break; - case E_TACTIC_MODE_PEAKVALLY: // 削峰填谷模式 - lenth = sizeof(peakvalley_zone_tab_t); - funArg = (peakvalley_zone_tab_t *)malloc(lenth); - break; - // case E_TACTIC_MODE_LOADTRACK: // 负载跟踪模式 - // lenth = sizeof(peakvalley_zone_tab_t); - // break; - case E_TACTIC_MODE_DMDCTRL: // 需量控制 - lenth = sizeof(protect_params_t); - funArg = (protect_params_t *)malloc(lenth); - break; - case E_TACTIC_MODE_PFCTRL: // 功率因数 - break; - default: - return 1; // 失败 - } - return 0; // 成功 -} -/***************************************************************************** - * @brief 将调试模式参数写入SqliteDB - * @param[in] arg:调试模式参数结构体指针 - * @return NONE - *****************************************************************************/ -int writeDbgParaToDb(debug_algorithm_t *arg) -{ - - int rc = kit_set_debug_algorithm(arg); - return rc; -} -/***************************************************************************** - * @brief 将削峰填谷模式参数写入SqliteDB - * @param[in] arg:削峰填谷模式参数结构体指针 - * @return NONE - *****************************************************************************/ -int writePvParaToDb(UT_array *arg) -{ - int rc = 0; - rc = kit_set_pv_date_time_cfg(&arg); - return rc; -} -/***************************************************************************** - * @brief 将负荷跟踪模式参数写入SqliteDB - * @param[in] arg:负荷跟踪模式参数结构体指针 - * @return NONE - *****************************************************************************/ -int writeLoadTrckParaToDb(debug_params_t *arg) -{ - return 0; -} -/***************************************************************************** - * @brief 将需量控制模式参数写入SqliteDB - * @param[in] arg:负荷跟踪模式参数结构体指针 - * @return NONE - *****************************************************************************/ -int writeDmCtrlParaToDb(protect_params_t *arg) -{ - return 0; -} -/***************************************************************************** - * @brief 将保护参数写入SqliteDB - * @param[in] arg:负荷跟踪模式参数结构体指针 - * @return NONE - *****************************************************************************/ -int writeProtecParaToDb(protect_params_t *arg) -{ - // 此处缺失数据赋值 - protect_algorithm_t item = {0}; - int rc = kit_set_protect_algorithm(&item); - return rc; -} -/***************************************************************************** - * @brief 根据配置类型写对应的数据库表 - * @param[in] arg:配置参数结构体指针 - * @param[in] modeWord:配置类型 - * @return NONE - *****************************************************************************/ -int writeCfgToDb(logic_Params *arg, int modeWord) -{ - int rc = 0; - debug_algorithm_t dbarg = {0}; - UT_array *ua; - utarray_new(ua, &pvcfg_icd); - switch (modeWord) - { - case E_TACTIC_MODE_DEBUG: // 调试模式 - - dbarg.activePower = arg->debug.activePower; - dbarg.reactivePower = arg->debug.reactivePower; - dbarg.pcsSwitch = arg->debug.pcsSwitch; - dbarg.dbId = 1; - rc |= writeDbgParaToDb(&dbarg); - break; - case E_TACTIC_MODE_PEAKVALLY: // 削峰填谷模式 - - for (int i = 0; i < arg->pkvly.zoneTabLen; i++) - { - utarray_push_back(ua, &arg->pkvly.peakItem[i]); - } - rc |= writePvParaToDb(ua); - break; - // case E_TACTIC_MODE_LOADTRACK: // 负载跟踪模式 - // lenth = sizeof(peakvalley_zone_tab_t); - // break; - case E_TACTIC_MODE_DMDCTRL: // 需量控制 - // writeDmCtrlParaToDb((protect_params_t *)arg); - break; - case E_TACTIC_MODE_PFCTRL: // 功率因数 - break; - case 11: - // writeProtecParaToDb((protect_params_t *)arg); - break; - default: - rc = 1; - } - if (ua != NULL) - { - utarray_free(ua); - } - return rc; -} -/***************************************************************************** - * @brief 告知云端ems处于本地模式的报文 - * @param[in] info:接收消息参数结构体指针 - * @return NONE - *****************************************************************************/ -char *createLocalModeDefualtMsg(arvcfgInfo_ret_t *info) -{ - // 创建根 JSON 对象 - cJSON *root = cJSON_CreateObject(); - if (root == NULL) - { - goto end; - } - - // 添加 transaction - if (cJSON_AddStringToObject(root, "transaction", info->transaction) == NULL) - { - goto end; - } - - // 添加 respCode - if (cJSON_AddNumberToObject(root, "respCode", 1) == NULL) - { - goto end; - } - - // 添加 msg - if (cJSON_AddStringToObject(root, "msg", "ERROR:ems is running at local mode!") == NULL) - { - goto end; - } - - // 添加毫秒时间戳 - if (cJSON_AddNumberToObject(root, "timestamp", CurtimesMS(NULL)) == NULL) - { - goto end; - } - - // 打印成JSON字符串 - char *json_string = cJSON_Print(root); - if (json_string == NULL) - { - goto end; - } - - // 释放 JSON 对象 - cJSON_Delete(root); - return json_string; - -end: - cJSON_Delete(root); - return NULL; -} -/***************************************************************************** - * @brief 告知云端ems处于本地模式 - * @param[in] client: mqtt客户端句柄 - * @param[in] info:接收消息参数结构体指针 - * @return 0-成功 - *****************************************************************************/ -int sendLocalStatus(MQTTClient client, arvcfgInfo_ret_t *arg) -{ - signal(SIGPIPE, SIG_IGN); - int rc = 0; - int cnt = 0; - char *msg = (char *)malloc(MAX_MQTT_MSG_LEN * sizeof(char)); - MQTTClient_message pubmsg = MQTTClient_message_initializer; - msg = createLocalModeDefualtMsg(arg); - pubmsg.payload = msg; - pubmsg.payloadlen = strlen(msg); - pubmsg.qos = kQos_2; - pubmsg.retained = 0; - char *topic = (char *)NorthProtoTable[kProto_MQTT_Slave].northProtocol.mqttLib.rootTopic; -retry:; - if (0 == sem_trywait(&g_allowSend)) - { - rc = MQTTClient_publishMessage(client, topic, &pubmsg, &deliveredtoken); - if (MQTTCLIENT_SUCCESS == rc) - { - rc = MQTTClient_waitForCompletion(client, deliveredtoken, TIMEOUT); - } - sem_post(&g_allowSend); - } - else if (cnt > 10) - { - rc = 1; - } - else - { - usleep(50000); - cnt++; - goto retry; - } - if (msg != NULL) - { - free(msg); - msg = NULL; - } - return rc; -}; - -int msgarrvdCB(void *context, char *topicName, int topicLen, MQTTClient_message *message) -{ - // printf("Message arrived\n"); - // printf("Topic: %s\n", topicName); - // printf("Message: "); - ConnContext *ct = (ConnContext *)context; - // 解析消息主题 - int msgtype = getKeywordsByTopic(topicName); - char *msgstr = message->payload; - memset(&g_LP, 0, sizeof(logic_Params)); - arvcfgInfo_ret_t cfgInfo = parseEmsCfgJson(msgstr, &g_LP); - if (cfgInfo.modeWord < E_TACTIC_MODE_DEBUG || cfgInfo.modeWord > E_TACTIC_MODE_PFCTRL) - { - return -1; - } - // 打印消息内容 -#ifdef MQTTPRINT - printf("recv msg is\n%s\n", msgstr); -#endif - int rc = 0; - // 根据modeWord解析云端下发的配置信息,解析后的参数放入结构体指针arg中 - MQTTClient_message pubmsg = MQTTClient_message_initializer; - - // 根据模式从数据库读取对应的配置信息 - void *stArg = NULL; // 策略参数 - char *ans = NULL; - int ifremote = AdvancedSettingTable[kEms_Mode].value; // 读取本地远程设置 - // rc = kit_get_localRemote(&ifremote); -retry_label:; - switch (msgtype) - { - case kEmsTopicType_control: - // while (stlogic.exitTaskFlag != 2) - // { - // usleep(50000); - // } - if (ifremote) - { - rc = writeCfgToDb(&g_LP, cfgInfo.modeWord); - if (0 == rc) - { - // 如果写数据库成功,写算法配置改变信号 - writeWebSign(Rtdb_ShMem, kSign_LogicDebug + cfgInfo.modeWord - 1, 1); - work_mode_set_t setting; - setting.workMode = cfgInfo.modeWord; - rc = kit_set_work_mode(&setting); - if (0 == rc) - { - // 如果工作模式写入数据库成功,写工作模式切换信号 - writeWebSign(Rtdb_ShMem, kSign_LogicMode, 1); - } - } - - getCfgBymodeWord(stArg, cfgInfo.modeWord); - ans = createStrategyCfgJsonString(cfgInfo, stArg, 1); - pubmsg.payload = ans; - pubmsg.payloadlen = strlen(ans); - pubmsg.qos = kQos_2; - pubmsg.retained = 0; - if ((0 == sem_trywait(&g_allowSend)) && MQTTClient_isConnected(ct->client)) - { - rc = MQTTClient_publishMessage(ct->client, (char *)ct->mlib.replycontrolTopic, &pubmsg, &deliveredtoken); - if (MQTTCLIENT_SUCCESS == rc) - { - rc = MQTTClient_waitForCompletion(ct->client, &deliveredtoken, TIMEOUT); - } - sem_post(&g_allowSend); - } - else - { - goto retry_label; - } - } - else - { - sendLocalStatus(ct->client, &cfgInfo); - } - break; - case kEmsTopicType_read: - while (stlogic.exitTaskFlag != 2) - { - usleep(50000); - } - if ((0 == sem_trywait(&g_allowSend)) && MQTTClient_isConnected(ct->client)) - { - getCfgBymodeWord(stArg, cfgInfo.modeWord); - ans = createStrategyCfgJsonString(cfgInfo, stArg, 0); - pubmsg.payload = ans; - pubmsg.payloadlen = strlen(ans); - pubmsg.qos = kQos_2; - pubmsg.retained = 0; - rc = MQTTClient_publishMessage(ct->client, (char *)ct->mlib.replyreadTopic, &pubmsg, &deliveredtoken); - if (MQTTCLIENT_SUCCESS == rc) - { - rc = MQTTClient_waitForCompletion(ct->client, &deliveredtoken, TIMEOUT); - } - sem_post(&g_allowSend); - } - else - { - goto retry_label; - } - break; - default: - rc = 1; - break; - } - - MQTTClient_freeMessage(&message); - MQTTClient_free(topicName); - return rc; -} -int updateBreakRcd(break_record_t *rcd) -{ - // 一次通信中断触发时,更新插入断点数据库的dbid和break_record_t - long long id = kit_insert_break_record(rcd); - rcd->dbId = id; - rcd->isUploaded = 0; - strcpy((char *)rcd->reason, MQTT_PERIOD_SEND_FAIL_WORDS); - - return 0; -} -int initBreakRcd(break_record_t *rcd) -{ - if (rcd == NULL) - { - return 1; - } - rcd->dbId = 0; - rcd->isUploaded = 0; - strcpy((char *)rcd->reason, MQTT_PERIOD_SEND_FAIL_WORDS); - return 0; -} -/***************************************************************************** - * @brief 与broker连接丢失时触发的回调函数 - * @param[in] context:mqtt连接上下文 - * @param[in] cause:错误信息 - * @return NONE - *****************************************************************************/ -// 假设的方法,用于重连MQTT客户端 -int attemptReconnect(MQTTClient client, MQTTClient_connectOptions *connopts) -{ - int rc; - // 这里执行重连逻辑 - rc = MQTTClient_connect(client, connopts); - if (MQTTCLIENT_SUCCESS != rc) - { - KITPTF(LOG_MQTT_EN, INFO_EN, "MQTT重新连接失败,返回值%d。", rc); - return rc; - } - return rc; -} - -/***************************************************************************** - * @brief 从北向配置表的点表中读取单个测点的rtdb查找信息 - * @param[in] tar:mqtt2db_t查找表指针 - * @param[in] cfg:测点配置信息 - * @return NONE - *****************************************************************************/ -void loadRtdbFindTabByCfg(mqtt2db_t *tar, up_dis_point_t cfg) -{ - tar->dbType = Rtdb_ShMem; - tar->devType = cfg.devType; - tar->devId = cfg.devId; - tar->pointId = cfg.pointId; -} -/***************************************************************************** - * @brief 将EMS测点rtdb参数存入结构体 - * @param[in] tar:待写入mqtt查找表 - * @param[in] p:源测点 - * @return NONE - *****************************************************************************/ -void loadEmsPoints(mqtt_option_map_t *map) -{ - if (map == NULL) - { - return; - } - map[kDev_Type_EMS].devNum++; - // strncpy(map[kDev_Type_EMS].sn[0],) - for (int i = 0; i < kEms_DataEnd; i++) - { - map[kDev_Type_EMS].pllist[0].rtdbGetTab[i].dbType = kSign_ShMem; - map[kDev_Type_EMS].pllist[0].rtdbGetTab[i].devId = 0; - map[kDev_Type_EMS].pllist[0].rtdbGetTab[i].devType = kDev_Type_EMS; - map[kDev_Type_EMS].pllist[0].rtdbGetTab[i].pointId = i; - map[kDev_Type_EMS].pllist[0].txcount++; - } -}; -/***************************************************************************** - * @brief 从自定义配置表的点表中读取mqtt单个测点的rtdb查找信息 - * @param[in] tar:mqtt2db_t查找表指针 - * @param[in] cfg:测点配置信息 - * @return NONE - *****************************************************************************/ -void loadNorthCfgBySet(mqtt_option_map_t *map) // 配置的测点 -{ - loadEmsPoints(map); - if (0 == NorthProtoTable[kProto_MQTT_Slave].disDevNum + NorthProtoTable[kProto_MQTT_Slave].upDevNum) - { - return; // 若北向协议中的测点列表为空 - } - for (int i = 0; i < NorthProtoTable[kProto_MQTT_Slave].upDevNum; i++) - { - dev_type_e type = NorthProtoTable[kProto_MQTT_Slave].upDevArr[i].devType; - int n = map[type].devNum; - // map[type].devName[n] = NorthProtoTable[kProto_MQTT_Slave].upDevArr[i]; - for (int k = 0; k < NorthProtoTable[kProto_MQTT_Slave].upDevArr[i].upDisPointNum; k++) - { - loadRtdbFindTabByCfg(&map[type].pllist[n].rtdbGetTab[map[type].pllist[n].txcount++], NorthProtoTable[kProto_MQTT_Slave].upDevArr[i].upDisPointArr[k]); - } - } - for (int i = 0; i < NorthProtoTable[kProto_MQTT_Slave].disDevNum; i++) - { - dev_type_e type = NorthProtoTable[kProto_MQTT_Slave].disDevArr[i].devType; - int n = map[type].devNum; - // map[type].devName[n] = NorthProtoTable[kProto_MQTT_Slave].upDevArr[i]; - for (int k = 0; k < NorthProtoTable[kProto_MQTT_Slave].disDevArr[i].upDisPointNum; k++) - { - loadRtdbFindTabByCfg(&map[type].pllist[n].rtdbSetTab[map[type].pllist[n].rxcount++], NorthProtoTable[kProto_MQTT_Slave].disDevArr[i].upDisPointArr[k]); - } - } -} -/***************************************************************************** - * @brief 初始化mqtt表结构 - * @param[in] map:mqtt总表指针 - * @return NONE - *****************************************************************************/ -void initMqttMap(mqtt_option_map_t *map) -{ - for (int i = 0; i < kDev_Type_End; i++) - { - map[i].devNum = 0; - map[i].devType = i; - for (int k = 0; k < D_MAX_DEV_NUM; k++) - { - map[i].pllist[k].rxcount = 0; - map[i].pllist[k].txcount = 0; - for (int j = 0; j < D_MAX_MQTT_DEV_POINT_NUM; j++) - { - map[i].pllist[k].rtdbGetTab[j].dbType = 0; - map[i].pllist[k].rtdbGetTab[j].devId = 0; - map[i].pllist[k].rtdbGetTab[j].devType = 0; - map[i].pllist[k].rtdbGetTab[j].pointId = 0; - map[i].pllist[k].rtdbGetTab[j].value = 0; - map[i].pllist[k].rtdbGetTab[j].ifchg = 0; - - map[i].pllist[k].rtdbSetTab[j].dbType = 0; - map[i].pllist[k].rtdbSetTab[j].devId = 0; - map[i].pllist[k].rtdbSetTab[j].devType = 0; - map[i].pllist[k].rtdbSetTab[j].pointId = 0; - map[i].pllist[k].rtdbSetTab[j].value = 0; - map[i].pllist[k].rtdbSetTab[j].ifchg = 0; - } - } - } -} -/***************************************************************************** - * @brief 将测点rtdb参数存入结构体 - * @param[in] tar:待写入mqtt查找表 - * @param[in] p:源测点 - * @return NONE - *****************************************************************************/ -int loadRtdbFindTabBySouthCfg(mqtt2db_t *tar, point_t p) -{ - - if (tar == NULL) - { - return -1; - } - tar->dbType = Rtdb_ShMem; - tar->devType = p.devType; - tar->devId = p.devId; - tar->pointId = p.pointId; - // printf("dbtype=%d,devType=%d,devId=%d,pointId=%d\n",tar->dbType,tar->devType,tar->devId,tar->pointId); - return 0; -} -/***************************************************************************** - * @brief 将测点rtdb参数存入结构体 - * @param[in] tar:待写入mqtt查找表 - * @param[in] p:源测点 - * @return NONE - *****************************************************************************/ -void loadNorthCfgAllptsByProtocol(mqtt_option_map_t *map, proto_dev_point_map_t proto) -{ - if (proto.devNum == 0) - { - return; - } - - char *str = {0}; - for (int k = 0; k < proto.devNum; k++) - { - dev_type_e devType = proto.devPointMapArr[k].devType; - - if (devType < 0 || devType > kDev_Type_End) - { - continue; - } - str = (char *)proto.devPointMapArr[k].devName; - // 其他设备的测点从数据库读取配置 - int index = map[devType].devNum; - if (map[devType].devName[index] != NULL) - { - free(map[devType].devName[index]); - map[devType].devName[index] = NULL; - } - map[devType].devName[index] = (char *)malloc(strlen(str)); - strncpy(map[devType].devName[index], str, strlen(str)); - - for (int p = 0; p < proto.devPointMapArr[k].pointNum; p++) - { - map[devType].pllist[index].txcount++; - loadRtdbFindTabBySouthCfg(&map[devType].pllist[index].rtdbGetTab[p], proto.devPointMapArr[k].pointArr[p]); - map[devType].pllist[index].rtdbGetTab[p].value = getRtdbPointValue(map[devType].pllist[index].rtdbGetTab[p].dbType, - map[devType].pllist[index].rtdbGetTab[p].devType, - map[devType].pllist[index].rtdbGetTab[p].devId, - map[devType].pllist[index].rtdbGetTab[p].pointId); - } - map[devType].devNum++; - } -} - -void loadvBsuPoints(mqtt_option_map_t *map) -{ - if (gStDevTypeNum[kDev_Type_BSU] == 0 && gStDevTypeNum[kDev_Type_BCU] != 0) - { - map[kDev_Type_BSU].devNum = 1; - init_bcu_bsu_map(&g_bcuMap); // 初始化哈希表 - - map[kDev_Type_BSU].devName[0] = "1#bsu_v"; - - int i = 0; - BcuBsuMap *current; - map[kDev_Type_BSU].pllist[0].txcount = 0; - for (current = g_bcuMap; current != NULL; current = current->hh.next) - { - map[kDev_Type_BSU].pllist[0].rtdbGetTab[i].dbType = Rtdb_ShMem; - map[kDev_Type_BSU].pllist[0].rtdbGetTab[i].devType = kDev_Type_BSU; - map[kDev_Type_BSU].pllist[0].rtdbGetTab[i].devId = 0; - map[kDev_Type_BSU].pllist[0].rtdbGetTab[i].pointId = current->bsupointId; - i++; - map[kDev_Type_BSU].pllist[0].txcount++; - } - } -}; -void loadNorthCfgAllPts(mqtt_option_map_t *map) // 全量测点上传 -{ - initMqttMap(map); -#ifdef MQTTPRINT - for (int i = 0; i < kDev_Type_End; i++) - { - if (gStDevTypeNum[i] > 0 && i != kDev_Type_EMS) - { - printf("devType[%d]=%d\n", i, gStDevTypeNum[i]); - } - } - for (int i = 0; i < kProto_Master_End; i++) - { - printf("porotodev[%d]=%d\n", i, protoTable[i].devNum); - } - - for (int t = 0; t < protoTable[kProto_ModbusTCP_Master].devNum; t++) - { - printf("devtype[%d] is %d", t, protoTable[kProto_ModbusTCP_Master].devPointMapArr[t].devType); - } -#endif - loadEmsPoints(map); - loadvBsuPoints(map); // 加载虚拟bsu节点测点参数 - for (int i = 0; i < kProto_Master_End; i++) - { - loadNorthCfgAllptsByProtocol(map, protoTable[i]); - } -} -/***************************************************************************** - * @brief 将北向配置表中的信息(上传/下发)读入mqtt_option_map_t结构体 - * @param[in] map:mqttClient使用的测点配置表 - * @return NONE - *****************************************************************************/ -void loadNorthCfg(mqtt_option_map_t *map) -{ - if (map == NULL) - { - return; - } - switch (NorthProtoTable[kProto_MQTT_Slave].configType) - { - case kNorth_Config_Default: - loadNorthCfgAllPts(map); // 从南向设备表读取所有MQTT测点配置 - break; - case kNorth_Config_Up: - loadNorthCfgBySet(map); // 根据北向配置读取MQTT测点配置 - break; - default: - break; - } -} -/***************************************************************************** - * @brief 初始化mqttClient参数和mqtt测点配置表 - * @param[in] mlt:存放mqtt_lib_t参数 - * @param[in] map:存放北向测点配置的map,一般为全局变量 - * @return NONE - *****************************************************************************/ -void setEMSsn() -{ - char serial[128]; - int rc = kit_get_ems_sn(serial); - if (0 == rc) - { - strncpy(mainEmsSn, serial, MAX_NAME_BUF_LEN); - mainEmsSn[MAX_NAME_BUF_LEN - 1] = '\0'; - } -} -int getMQTTCfg(mqtt_lib_t *mlt) -{ - if (mlt == NULL) - { - return 1; - } - // 读取连接配置 - memcpy(mlt, &NorthProtoTable[kProto_MQTT_Slave].northProtocol.mqttLib, sizeof(mqtt_lib_t)); - return 0; -} -/***************************************************************************** - * @brief 初始化mqttClient参数和mqtt测点配置表 - * @param[in] mlt:存放mqtt_lib_t参数 - * @param[in] map:存放北向测点配置的map,一般为全局变量 - * @return NONE - *****************************************************************************/ -void updateMqttPara(mqtt_lib_t *mlt, mqtt_option_map_t *map) -{ - - // 读取连接配置 - getMQTTCfg(mlt); - // 将北向协议里的测点读到mqtt结构体中 - loadNorthCfg(map); - // 设置EMS 的sn号 - setEMSsn(); -} -/***************************************************************************** - * @brief 历史数据处理 - * @param[in] arg:tcp连接上下文 - * @return NONE - *****************************************************************************/ -void updateConnectionStatus(bool is_connected) -{ - setRtdbPointValue(Rtdb_ShMem, kDev_Type_EMS, 0, kEms_netStatus, is_connected); - // 这里可以利用一个全局变量如 g_MqttMsg 来编码连接状态 - pthread_mutex_lock(&connection_status_mutex); // 假设此互斥锁存在 - if (is_connected) - { - g_MqttMsg &= ~kEvent_Reconnect_failed; - } - else - { - g_MqttMsg |= kEvent_Reconnect_failed; - } - pthread_mutex_unlock(&connection_status_mutex); -} -/***************************************************************************** - * @brief 判断通信是否断开 - * @param[in] arg:tcp连接上下文 - * @return 0-中断;1-正常 - *****************************************************************************/ -bool is_mqtt_connected() -{ - pthread_mutex_lock(&connection_status_mutex); - bool connected = !(g_MqttMsg & kEvent_Reconnect_failed); - pthread_mutex_unlock(&connection_status_mutex); - return connected; -} -/***************************************************************************** - * @brief 处理MQTT连接丢失的回调函数 - * - * @param[in] context 指向 `ConnContext` 的指针,代表当前连接的上下文信息 - * @param[in] cause 导致连接丢失的原因字符串 - * - * @return NONE - * - * @details 函数在MQTT连接丢失时被调用。该函数执行以下操作: - * 1. 将连接状态更新为断开状态。 - * 2. 记录连接丢失的信息,创建一个新的断开记录,并将其加入全局记录数组。 - * 3. 执行重连逻辑,直到成功连接为止。 - * 4. 在重新连接成功后更新连接状态。 - *****************************************************************************/ -long g_teststart = 0; -int record_is_updated = 0; -void updateBrkRcd(char *cause) -{ - pthread_mutex_lock(&record_mutex); - // 创建一个新的 `break_record_with_data_t` - break_record_with_data_t newRecord; - memset(&newRecord, 0, sizeof(break_record_with_data_t)); - strcpy((char *)newRecord.record.reason, cause ? cause : "Unknown reason"); - - // 插入断开记录到数据库并获取其ID - newRecord.record.isUploaded = false; - newRecord.record.dbId = kit_insert_break_record(&(newRecord.record)); - - // 初始化数据存储数组 - utarray_new(newRecord.dataArray, &bdst_icd); - // 将新的记录添加到全局数组 - // 首先,确保 g_recordsWithData 中仅有一个元素 - if (utarray_len(g_recordsWithData) == 1) - { - // 用 newRecord 替换现有的唯一一条记录 - void *p = utarray_eltptr(g_recordsWithData, 0); // 获取指向第一条记录的指针 - if (p != NULL) - { - memcpy(p, &newRecord, sizeof(break_record_with_data_t)); // 通过内存复制进行替换 - } - } - else - { - // 如果数组里面不止一条记录,可以选择清空数组并添加 newRecord - utarray_clear(g_recordsWithData); // 清空数组 - utarray_push_back(g_recordsWithData, &newRecord); // 添加 newRecord - } - pthread_mutex_unlock(&record_mutex); -} - -void connlostCB(void *context, char *cause) -{ - // 记录网络断开 - RECORDNETSTATUS(D_STR_DISCONN_WORD) - // pthread_t lockPipefd; - // int lock = 0; - // pthread_create(&lockPipefd, NULL, lockPipe, &lock); - ConnContext *ct = (ConnContext *)context; - // 立即更新连接状态为断开 - updateConnectionStatus(false); - g_MqttMsg &= ~kEvent_has_history_record; - if (utarray_len(g_recordsWithData) == 0) - { - // 创建一个中断记录 - cause = "MQTT连接中断"; - updateBrkRcd(cause); - g_MqttMsg |= kEvent_has_history_record; - } - // 重连逻辑 - int rc = 0; - while ((rc = attemptReconnect(ct->client, &ct->connopts)) != MQTTCLIENT_SUCCESS) - { - KITLOG(LOG_MQTT_EN, WARN_EN, "Reconnection attempt failed, retrying...", NULL); - // 重新连接成功,如果尾部记录还有未插入数据库的 数据,插入,且清理尾部记录的内存空间 - break_record_with_data_t *record = utarray_back(g_recordsWithData); - if (utarray_len(record->dataArray) > 0) - { - int rc = kit_insert_break_data_storage(record->record.dbId, &record->dataArray); - if (1 == rc) - { - KITLOG(LOG_MQTT_EN, ERROR_EN, "insert history data to DB failed...", NULL); - } - else if (utarray_len(record->dataArray) > 0) - { - utarray_clear(record->dataArray); - } - } - sleep(10); // 重试间隔 - } - // 记录网络恢复 - RECORDNETSTATUS(D_STR_CONNECT_WORD) - KITLOG(LOG_MQTT_EN, INFO_EN, "Reconnected to the broker successfully.", NULL); - // 更新连接状态,连接恢复 - // if (utarray_len(g_recordsWithData) > 0) - // { - // utarray_clear(g_recordsWithData); - // } - updateConnectionStatus(true); -} -/***************************************************************************** - * @brief MQTT周期发送任务 - * @param[in] arg:MQTT连接上下文 - * @return NONE - *****************************************************************************/ -void *periodSendTask(void *arg) -{ - while (!(g_MqttMsg & kEvent_topo_send)) - { - usleep(50000); - } - ConnContext *ct = (ConnContext *)arg; - int period = ct->mlib.tSendTaskPeriod; - if (period == 0) - { - period = 5; // 默认周期为5秒 - } - // 忽略 SIGPIPE 信号 - signal(SIGPIPE, SIG_IGN); - MQTTClient_message pubmsg = MQTTClient_message_initializer; - char *msg = (char *)malloc(MAX_MQTT_MSG_LEN * sizeof(char)); - if (msg == NULL) - { - return NULL; - } - int rc = 0; - int cnt = 0; - while (1) - { - cnt++; - - // if (stlogic.taskStateFlag == LOGIC_SIGN_UPLOAD) - // { - // } - readWebSign(kSign_ShMem, kSign_LogicDebug); - for (int i = 0; i < kDev_Type_End; i++) - { - if (i != kDev_Type_EMS && g_mqtt_map[i].devNum == 0) - { - usleep(50000); - continue; - } - genDevGrpPeriodPayload(msg, i, &g_mqtt_map[i]); - pubmsg.payload = msg; - pubmsg.payloadlen = strlen(msg); - pubmsg.qos = kQos_0; - pubmsg.retained = 0; - retry: - if ((0 == sem_trywait(&g_allowSend))) - { - period_thread_haveSendSig = 1; - rc = MQTTClient_publishMessage(ct->client, (char *)ct->mlib.periodTopic, &pubmsg, &deliveredtoken); - if (rc != MQTTCLIENT_SUCCESS) - { - sem_post(&g_allowSend); - break_record_with_data_t *test = (break_record_with_data_t *)utarray_back(g_recordsWithData); - // 获取或创建当前的中断记录 - if (!(g_MqttMsg & kEvent_has_history_record)) - { - KITLOG(LOG_MQTT_EN, INFO_EN, "MQTT:no historydata record existed!\n", NULL); - continue; - } - - break_record_with_data_t *record = (break_record_with_data_t *)utarray_back(g_recordsWithData); - if (record != NULL) - { - if (0 == sem_trywait(&g_MqttwaitAndSaveHistory)) - { - period_thread_haveRcdSig = 1; - break_data_storage_t newData; - newData.breakDbId = record->record.dbId; - strncpy((char *)newData.content, msg, MAX_JSON_STR_LEN - 1); - newData.content[MAX_JSON_STR_LEN - 1] = '\0'; - newData.isUploaded = false; - utarray_push_back(record->dataArray, &newData); - sem_post(&g_MqttwaitAndSaveHistory); - } - } - usleep(50000); - } - else - { - rc = MQTTClient_waitForCompletion(ct->client, deliveredtoken, TIMEOUT); - sem_post(&g_allowSend); - if (MQTTCLIENT_SUCCESS == rc) - { -#ifdef MQTTPRINT - printdeltaT(); -#endif - } - usleep(50000); - } - } - else - { - usleep(50000); - goto retry; - } - } - - if (!(g_MqttMsg & kEvent_Period_Task_begin) && cnt < 2) // 周期上送运行2次之后再检测变化 - { - g_MqttMsg |= kEvent_Period_Task_begin; - } - sleep(period); - } - - free(msg); - return NULL; -} - -/***************************************************************************** - * @brief MQTT历史数据处理任务 - * @param[in] arg:MQTT连接上下文 - * @return NONE - *****************************************************************************/ -void *historyDataHandle(void *arg) -{ - while (!(g_MqttMsg & kEvent_topo_send)) - { - usleep(50000); - } - ConnContext *ct = (ConnContext *)arg; - MQTTClient_message pubmsg = MQTTClient_message_initializer; - UT_array *breakRcds; - UT_array *dataSets; - utarray_new(breakRcds, &brcd_icd); - utarray_new(dataSets, &bdst_icd); - int rc = 0; - // 忽略 SIGPIPE 信号 - signal(SIGPIPE, SIG_IGN); - while (1) - { - if (0 == sem_trywait(&g_MqttwaitAndSaveHistory)) - { - period_thread_haveRcdSig = 1; - break_record_with_data_t *record = (break_record_with_data_t *)utarray_back(g_recordsWithData); - if (record != NULL) - { - if (utarray_len(record->dataArray) > 0) - { - int rc = kit_insert_break_data_storage(record->record.dbId, &record->dataArray); - if (1 == rc) - { - KITLOG(LOG_MQTT_EN, ERROR_EN, "insert history data to DB failed...", NULL); - } - else - { - utarray_clear(record->dataArray); - } - } - } - sem_post(&g_MqttwaitAndSaveHistory); - } - // if (!is_mqtt_connected()) // 如果连接为断开状态,历史数据线程不工作 - // { - // continue; - // } - rc = kit_query_break_records(false, &breakRcds); - if (1 == rc) // 如果查询数据库失败,等待10s再操作数据库 - { - history_thread_alive = 1; - sleep(10); - continue; - } - else if (0 == utarray_len(breakRcds)) // 如果短点记录,不运行 - { - sleep(1); - history_thread_alive = 1; - continue; - } - utarray_foreach(breakRcds, break_record_t *, p_rcd) - { - if (p_rcd->isUploaded == true) - { - continue; - } - rc = kit_query_break_data(p_rcd->dbId, &dataSets); - if (1 == rc && utarray_len(dataSets) > 0) - { - utarray_clear(dataSets); - continue; - } - p_rcd->isUploaded = true; // 先将标记位设置为true,一旦有消息发送失败,is_Uploaded就会置为false - int length = 0; - uint64_t ids[100] = {0}; - int retry_cnt = 0; - utarray_foreach(dataSets, break_data_storage_t *, p_contents) - { - if (p_contents == NULL) - { - continue; - } - retry_cnt = 0; - pubmsg.payload = p_contents->content; - pubmsg.payloadlen = strlen((char *)p_contents->content); - pubmsg.qos = kQos_0; - pubmsg.retained = true; - retry_label:; - if ((0 == sem_trywait(&g_allowSend))) - { - history_thread_haveSendSig = 1; - rc = MQTTClient_publishMessage(ct->client, (char *)ct->mlib.historyTopic, &pubmsg, &deliveredtoken); - if (rc == MQTTCLIENT_SUCCESS) - { - rc = MQTTClient_waitForCompletion(ct->client, deliveredtoken, TIMEOUT); - ids[length] = p_contents->breakDbId; - length++; - } - else - { - p_rcd->isUploaded = false; - } - sem_post(&g_allowSend); - history_thread_haveSendSig = 0; - usleep(50000); - } - // else if (retry_cnt > 10) - // { - // continue; - // } - else - { - retry_cnt++; - goto retry_label; - } - } - if (utarray_len(dataSets) > 0) - { - utarray_clear(dataSets); - } - kit_update_break_record(p_rcd); - kit_update_break_data(p_rcd->dbId, ids, length); - } - history_thread_alive = 1; - sleep(ct->mlib.tSendTaskPeriod > 0 ? ct->mlib.tSendTaskPeriod : 5); - } - - return NULL; -} - -/***************************************************************************** - * @brief - * @param[in] json: json对象 - * @param[in] key:键 - * @param[in] value:值 - * @return NONE - *****************************************************************************/ -void appendJsonKeyValue(cJSON *json, const char *key, double value) -{ - cJSON_AddNumberToObject(json, key, value); -} -/***************************************************************************** - * @brief 装载周期上送主题有效载荷 - * @param[in] topic: mqtt_lib_t中的主题字符串指针 - * @param[in] payload:主题类型枚举,枚举与mqtt_lib_t中的成员应对应,请确保payload的缓冲区长度足够 - * @return 主题类型枚举 - *****************************************************************************/ -int getKeywordsByTopic(char *topic) -{ - - if (strstr(topic, MQTT_ROOT_TOPIC_KEY)) - { - return kEmsTopicType_root; - } - else if (strstr(topic, MQTT_PERIOD_TOPIC_KEY)) - { - return kEmsTopicType_period; - } - else if (strstr(topic, MQTT_CHANGE_TOPIC_KEY)) - { - return kEmsTopicType_change; - } - else if (strstr(topic, MQTT_HISTORY_TOPIC_KEY)) - { - return kEmsTopicType_history; - } - else if (strstr(topic, MQTT_CONTROL_TOPIC_KEY)) - { - return kEmsTopicType_control; - } - else if (strstr(topic, MQTT_READ_TOPIC_KEY)) - { - return kEmsTopicType_read; - } - else if (strstr(topic, MQTT_CONTROL_TOPIC_KEY) && strstr(topic, MQTT_REPLY_TOPIC_KEY)) - { - return kEmsTopicType_reply_control; - } - else if (strstr(topic, MQTT_READ_TOPIC_KEY) && strstr(topic, MQTT_REPLY_TOPIC_KEY)) - { - return kEmsTopicType_reply_read; - } - else - { - return -1; - } -} -/***************************************************************************** - * @brief 获取浮点数变化死区 - * @return 浮点数变化死区 - *****************************************************************************/ -double getFpDeadZone() -{ - return 1e-6; -}; -/***************************************************************************** - * @brief 获取整型数变化死区 - * @return 整型数变化死区 - *****************************************************************************/ -int getIntDeadZone() -{ - return 1; -} -/***************************************************************************** - * @brief mqtt查找db表结构 - * @return 目标测点值 - *****************************************************************************/ -double mqttFindDB(mqtt2db_t m) -{ - return getRtdbPointValue(m.dbType, m.devType, m.devId, m.pointId); -} -/***************************************************************************** - * @brief mqtt查找db表结构 - * @return 目标测点值 - *****************************************************************************/ -bool isSamePoint(mqtt2db_t l, mqtt2db_t r) -{ - if (l.devType == r.devType && l.devId == r.devType && l.pointId == r.pointId) - { - return true; - } - return false; -} -/***************************************************************************** - * @brief 检测payloadlist的变化事件 - * @param[in] now: 当前的mqtt_map_t结构体 - * @param[in] old: 存储的mqtt_map_t结构体 - * @return 变化事件类型,后期可与装载部分优化成mqtt客户端状态机 - *****************************************************************************/ -int chkDataChange(mqtt_option_map_t *now, mqtt_option_map_t *old) -{ - return 0; - // int rt = 0; - // if(0!=strcmp(now->stationName,old->stationName)) - // { - // rt |= kEvent_rename_station; - // } - // if(0!=strcmp(now->stationID,old->stationID)) - // { - // rt |= kEvent_reset_id; - // } - // if(now->devNum != old->devNum) - // { - // rt |= kEvent_change_devTopo; - // } - // for(int i=0;i < D_MAX_DEV_NUM; i++) - // { - - // if((0 != strcmp(now->devType,old->devType))&&(0 != strcmp(now->devName[i],old->devName[i]))) - // { - // rt |= kEvent_change_devTopo; - // break; - // } - - // } - // for(int devSeq = 0 ;devSeqpllist[devSeq].txcount != old->pllist[devSeq].txcount) - // { - // rt |= kEvent_pointlistcfg_change; - // } - // for(int pointSeq = 0;pointSeqpllist[devSeq].rtdbGetTab[pointSeq],old->pllist[devSeq].rtdbGetTab[pointSeq])) - // { - // double lval = mqttFindDB(now->pllist[devSeq].rtdbGetTab[pointSeq]); - // double rval = mqttFindDB(old->pllist[devSeq].rtdbGetTab[pointSeq]); - // if(abs(lval-rval)>getIntDeadZone()) - // { - // rt |= kEvent_int_change; - // } - // else if(abs(lval-rval)>getFpDeadZone()) - // { - // rt |= kEvent_float_change; - // } - - // } - // } - // } - // return rt; -} -/***************************************************************************** - * @brief 打印所有类型设备的数量 - * @return NONE - *****************************************************************************/ -int judgeNodev() -{ - int rc = 1; - for (int i = kDev_Type_Start + 1; i < kDev_Type_End; i++) - { - if (gStDevTypeNum[i] > 0) - rc = 0; -#ifdef MQTTPRINT -// printf("%s:%d台\n", devTypeToString(i), gStDevTypeNum[i]); -#endif - } - return rc; -} -/***************************************************************************** - * @brief 单个设备测点值是否改变 - * @param[in] list: 测点列表 - * @return false-未改变 true-改变 - *****************************************************************************/ -bool ifSingledevPointsChg(payloadlist_t *list) -{ - bool res = false; - for (int i = 0; i < list->txcount; i++) - { - res |= list->rtdbGetTab[i].ifchg; - } - return res; -} -/***************************************************************************** - * @brief 单个设备测点值是否改变 - * @param[in] map: 设备组测点列表 - * @return false-未改变 true-改变 - *****************************************************************************/ -bool ifDevGrpPointsChg(mqtt_option_map_t *map) -{ - bool res = false; - for (int i = 0; i < map->devNum; i++) - { - res |= map->bChgFlag; - } - return res; -} - -/***************************************************************************** - * @brief 装载不同设备组周期上送主题有效载荷 - * @param[in] topic: mqtt_lib_t中的主题字符串指针 - * @param[in] payload:主题类型枚举,枚举与mqtt_lib_t中的成员应对应,请确保payload的缓冲区长度足够 - * @return NONE - *****************************************************************************/ -void genDevGrpPeriodPayload(char *payload, dev_type_e type, mqtt_option_map_t *map) -{ -#ifdef MQTTPRINT -#endif - cJSON *root = cJSON_CreateObject(); - cJSON *devDataArray = cJSON_CreateArray(); - char *str_type = devTypeToString(type); - uint16_t devN[kDev_Type_End] = {0}; - memcpy(devN, gStDevTypeNum, sizeof(gStDevTypeNum)); - devN[kDev_Type_EMS] = 1; - devN[kDev_Type_BSU] = g_mqtt_map[kDev_Type_BSU].devNum; - // bool res = false; - for (int i = 0; i < devN[type]; i++) - { - if (map->pllist[i].txcount == 0) - { - continue; - } - // 检查设备类型是否匹配给定的类型 - if (map->devType == type) - { - cJSON *devData = cJSON_CreateObject(); - cJSON_AddItemToObject(devData, "devType", cJSON_CreateNumber(type)); - if (type == kDev_Type_EMS) - { - cJSON_AddItemToObject(devData, "devName", cJSON_CreateString(emsName)); - } - else - { - cJSON_AddItemToObject(devData, "devName", cJSON_CreateString(map->devName[i])); - } - - char *sn_tmp = (char *)malloc(50 * sizeof(char)); - if (sn_tmp == NULL) - { - usleep(50000); - continue; - } - sprintf(sn_tmp, "%s00%d", str_type, i); - cJSON_AddItemToObject(devData, "sn", cJSON_CreateString(sn_tmp)); - free(sn_tmp); - cJSON *data = cJSON_CreateObject(); - for (int j = 0; j < map->pllist[i].txcount; j++) - { - - char tag[128]; - uint16_t a = map->pllist[i].rtdbGetTab[j].pointId; - // printf("a=%hu\n",a); - snprintf(tag, sizeof(tag), "%s_%hu", str_type, a); - // 生成tag名称 - double value = 0; - if (type == kDev_Type_BSU) - { - value = getBsuRTDBPointValue(g_bcuMap, - map->pllist[i].rtdbGetTab[j].dbType, - map->pllist[i].rtdbGetTab[j].devType, - map->pllist[i].rtdbGetTab[j].devId, - map->pllist[i].rtdbGetTab[j].pointId); - } - else - { - value = mqttFindDB(map->pllist[i].rtdbGetTab[j]); // 根据测点查找表的参数,将value写入到匹配的key - } - cJSON_AddItemToObject(data, tag, cJSON_CreateNumber(value)); // 预留值 - } - cJSON_AddItemToObject(devData, "data", data); - cJSON_AddItemToArray(devDataArray, devData); - } - } - long t = CurtimesMS(NULL); - cJSON_AddItemToObject(root, "timeStamp", cJSON_CreateNumber(t)); // 时间戳 - g_mqttSendTag = t; - cJSON_AddItemToObject(root, "devData", devDataArray); - - // 打印生成的JSON - char *jsonString = cJSON_Print(root); - strcpy(payload, jsonString); // 将生成的JSON字符串复制到payload - free(jsonString); - cJSON_Delete(root); -} -/***************************************************************************** - * @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 *map) -{ -#ifdef MQTTPRINT -#endif - int rc = 0; - cJSON *root = cJSON_CreateObject(); - cJSON *devDataArray = cJSON_CreateArray(); - char *str_type = devTypeToString(type); - uint16_t devN[kDev_Type_End] = {0}; - memcpy(devN, gStDevTypeNum, sizeof(gStDevTypeNum)); - devN[kDev_Type_EMS] = 1; - devN[kDev_Type_BSU] = g_mqtt_map[kDev_Type_BSU].devNum; - if (map->bChgFlag == false) // 该类设备无数据变化 - { - rc = 1; - } - bool isNULL = true; - for (int i = 0; i < devN[type]; i++) - { - if (map->pllist[i].txcount == 0 || map->pllist[i].bChgFlag == false) - { - continue; - } - // 检查设备类型是否匹配给定的类型 - if (map->devType == type) - { - cJSON *devData = cJSON_CreateObject(); - cJSON_AddItemToObject(devData, "devType", cJSON_CreateNumber(type)); - if (type == kDev_Type_EMS) - { - cJSON_AddItemToObject(devData, "devName", cJSON_CreateString(emsName)); - } - else - { - cJSON_AddItemToObject(devData, "devName", cJSON_CreateString(map->devName[i])); - } - - char *sn_tmp = (char *)malloc(50 * sizeof(char)); - if (sn_tmp == NULL) - { - - continue; - } - sprintf(sn_tmp, "%s00%d", str_type, i); - cJSON_AddItemToObject(devData, "sn", cJSON_CreateString(sn_tmp)); - free(sn_tmp); - cJSON *data = cJSON_CreateObject(); - for (int j = 0; j < map->pllist[i].txcount; j++) - { - if (map->pllist[i].rtdbGetTab[j].ifchg == false) - { - continue; - } - char tag[128]; - uint16_t a = map->pllist[i].rtdbGetTab[j].pointId; - // printf("a=%hu\n",a); - snprintf(tag, sizeof(tag), "%s_%hu", str_type, a); - // 生成tag名称 - double value = 0; - // double old, new = 0; - if (type == kDev_Type_BSU) - { - value = getBsuRTDBPointValue(g_bcuMap, - map->pllist[i].rtdbGetTab[j].dbType, - map->pllist[i].rtdbGetTab[j].devType, - map->pllist[i].rtdbGetTab[j].devId, - map->pllist[i].rtdbGetTab[j].pointId); - } - else - { - value = mqttFindDB(map->pllist[i].rtdbGetTab[j]); // 根据测点查找表的参数,将value写入到匹配的key - } - map->pllist[i].rtdbGetTab[j].value = value; - // printf("dbtype=%d,devType=%d,devId=%d,pointId=%d,old=%f,new=%f\n", map->pllist[i].rtdbGetTab[j].dbType, - // map->pllist[i].rtdbGetTab[j].devType, - // map->pllist[i].rtdbGetTab[j].devId, - // map->pllist[i].rtdbGetTab[j].pointId, old, new); - cJSON_AddItemToObject(data, tag, cJSON_CreateNumber(value)); // 预留值 - isNULL = false; - } - - cJSON_AddItemToObject(devData, "data", data); - cJSON_AddItemToArray(devDataArray, devData); - } - } - long t = CurtimesMS(NULL); - cJSON_AddItemToObject(root, "timeStamp", cJSON_CreateNumber(t)); // 时间戳 - g_mqttSendTag = t; - cJSON_AddItemToObject(root, "devData", devDataArray); - - // 打印生成的JSON - char *jsonString = cJSON_Print(root); - strcpy(payload, jsonString); // 将生成的JSON字符串复制到payload - if (isNULL == true) - { - rc = 1; - } - free(jsonString); - cJSON_Delete(root); - return rc; -} -// 将dev_type_e转换为字符串 -char *devTypeToString(dev_type_e type) -{ - char *str; - switch (type) - { - case kDev_Type_EMS: - str = "ems"; - break; - case kDev_Type_Pccmeter: - str = "pcc"; - break; - case kDev_Type_Bsmeter: - str = "bsm"; - break; - case kDev_Type_PCS: - str = "pcs"; - break; - case kDev_Type_BSU: - str = "bsu"; - break; - case kDev_Type_BCU: - str = "bcu"; - break; - case kDev_Type_Thsensor: - str = "thss"; - break; - case kDev_Type_DI_DO_Device: - str = "dido"; - break; - case kDev_Type_UPS: - str = "ups"; - break; - case kDev_Type_AirCond_LiquidCool: - str = "airlqd"; - break; - case kDev_Type_WaterThsensor: - str = "wlsd"; - break; - case kDev_Type_Reserve2: - str = "Reserve2"; - break; - case kDev_Type_Reserve3: - str = "Reserve3"; - break; - case kDev_Type_Reserve4: - str = "Reserve4"; - break; - case kDev_Type_Reserve5: - str = "Reserve5"; - break; - default: - return "Unknown"; - break; - } - return str; -} -/***************************************************************************** - * @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) -{ - topology_hash_entry_t *entry; - for (entry = topologyById; entry != NULL; entry = entry->hh.next) - { // 遍历整个哈希表 - if (entry->topology->parentId == parentId) - { - cJSON *child = cJSON_CreateObject(); // 创建一个子节点的 JSON 对象 - cJSON_AddNumberToObject(child, "menuTree", entry->topology->menuTree); // 添加 menuTree 属性 - cJSON_AddStringToObject(child, "name", (char *)entry->topology->name); // 添加 name 属性 - cJSON_AddNumberToObject(child, "devType", entry->topology->devType); // 添加 devType 属性 - cJSON_AddStringToObject(child, "sn", (char *)entry->topology->sn); // 添加 sn 属性 - - cJSON *grandchildren = cJSON_CreateArray(); // 创建子节点的子节点数组 - cJSON_AddItemToObject(child, "child", grandchildren); // 将子节点数组添加到子节点对象 - cJSON_AddItemToArray(parentArray, child); // 将子节点添加到父节点数组 - - addChildrenToJson(grandchildren, entry->topology->dbId, topologyById); // 递归调用,处理子节点的子节点 - } - } -} -/***************************************************************************** - * @brief 将数据库中的 EMS 设备拓扑结构数据转换为 JSON 字符串 - * @param[out] json: 用于存储生成的 JSON 字符串的缓冲区。确保该缓冲区有足够的空间容纳生成的 JSON 字符串。 - * @return 0-成功 1-失败 - *****************************************************************************/ -int getTopologyJsonByDb(char **json) -{ - UT_array *topologies = NULL; // 初始化 UT_array 指针 - topology_hash_entry_t *topologyById = NULL; // 初始化哈希表 - - // 从数据库获取拓扑数据 - if (kit_get_topology_db_data(&topologies) != 0) - { // 注意这里需要传递 topologies 的地址 - // 处理数据库查询错误 - // if (topologies != NULL) - // utarray_free(topologies); // 释放内存 - return 1; - } - // 如果拓扑信息发生了改变,发送消息给全局变量 - if (false == chkTopoDiff(g_topology_storage, topologies)) - { - g_MqttMsg |= kEvent_change_devTopo; - } - else - { - g_MqttMsg &= ~(1 << 2); - } - if (g_topology_storage != NULL) - { - utarray_clear(g_topology_storage); - } - utarray_new(g_topology_storage, &topology_icd); - // 存储当前的拓扑信息,用于检测拓扑发生了变化 - utarray_concat(g_topology_storage, topologies); - // 将拓扑数据填充到哈希表中,使用 dbId 作为键 - for (int i = 0; i < utarray_len(topologies); i++) - { - topology_t *p_topology = (topology_t *)utarray_eltptr(topologies, i); - topology_hash_entry_t *entry = (topology_hash_entry_t *)malloc(sizeof(topology_hash_entry_t)); - if (entry == NULL) - { // 内存分配失败处理 - fprintf(stderr, "内存分配失败!\n"); - utarray_free(topologies); - return 1; - } - entry->dbId = p_topology->dbId; - entry->topology = p_topology; - HASH_ADD_INT(topologyById, dbId, entry); // 将条目添加到哈希表 - } - - cJSON *root = cJSON_CreateObject(); // 创建根 JSON 对象 - cJSON *structure = cJSON_CreateObject(); // 创建 structure JSON 对象 -// test -#ifdef MQTTPRINT - for (int i = 0; i < utarray_len(topologies); i++) - { - // test,打印设备拓扑列表 - - topology_t *p_topology = (topology_t *)utarray_eltptr(topologies, i); - int parentId = p_topology->parentId; - printf("dev%d.parent_Id=%d\n", i, parentId); - } -#endif - - // 遍历拓扑数据以查找顶级节点 - for (int i = 0; i < utarray_len(topologies); i++) - { - topology_t *p_topology = (topology_t *)utarray_eltptr(topologies, i); - int parentId = p_topology->parentId; - if (parentId == -999) - { // 顶级节点 - cJSON_AddNumberToObject(structure, "menuTree", p_topology->menuTree); // 添加 menuTree 属性 - cJSON_AddStringToObject(structure, "name", (char *)p_topology->name); // 添加 name 属性 - strncpy(emsName, (char *)p_topology->name, MAX_NAME_BUF_LEN - 1); // ems设备名称 - emsName[MAX_NAME_BUF_LEN - 1] = '\0'; // 确保最后一个字符是空字符 - cJSON_AddNumberToObject(structure, "devType", p_topology->devType); // 添加 devType 属性 - cJSON_AddStringToObject(structure, "sn", mainEmsSn); // 添加 sn 属性 - cJSON *children = cJSON_CreateArray(); // 创建顶级节点的子节点数组 - cJSON_AddItemToObject(structure, "child", children); // 将子节点数组添加到顶级节点对象 - - addChildrenToJson(children, p_topology->dbId, topologyById); // 调用递归函数添加子节点 - break; - } - } - cJSON_AddItemToObject(root, "structure", structure); // 将 structure 添加到 root 对象 - - // 将 cJSON 对象转换为字符串 - char *jsonString = cJSON_Print(root); - if (jsonString == NULL) - { - cJSON_Delete(root); - utarray_free(topologies); - // 释放哈希表 - topology_hash_entry_t *current_entry, *tmp; - HASH_ITER(hh, topologyById, current_entry, tmp) - { - HASH_DEL(topologyById, current_entry); - free(current_entry); - } - return 1; // 处理 cJSON 打印错误 - } - *json = (char *)malloc((strlen(jsonString) + 1) * sizeof(char)); - strncpy(*json, jsonString, strlen(jsonString)); // 将 JSON 字符串复制到输出缓冲区 - json[strlen(jsonString)] = '\0'; - - // printf("%s\n",*json); - int lenth = strlen(jsonString); - free(jsonString); // 释放 cJSON_Print 分配的字符串 - - cJSON_Delete(root); // 释放 cJSON 对象 - utarray_free(topologies); // 释放 UT_array - g_mqttSendTag = CurtimesMS(NULL); - // 释放哈希表 - topology_hash_entry_t *current_entry, *tmp; - HASH_ITER(hh, topologyById, current_entry, tmp) - { - HASH_DEL(topologyById, current_entry); - free(current_entry); - } - - return lenth; // 成功返回 -} -// 按类型解析策略配置 -int parseStrategyJsonObject(cJSON *strategyCfg, int mode, logic_Params *lP) -{ - if (strategyCfg == NULL) - { - return 1; - } - switch (mode) - { - case E_TACTIC_MODE_START: - { - // 暂未实现 - break; - } - case E_TACTIC_MODE_DEBUG: - { - cJSON *activepower = cJSON_GetObjectItem(strategyCfg, "P"); - cJSON *reactivepower = cJSON_GetObjectItem(strategyCfg, "Q"); - cJSON *onoff = cJSON_GetObjectItem(strategyCfg, "onOff"); -#ifdef MQTTPRINT - printf("Active power: %s, Reactive power: %s, On/Off: %s\n", - cJSON_GetStringValue(activepower), // 有功功率 - cJSON_GetStringValue(reactivepower), // 无功功率 - cJSON_GetStringValue(onoff)); // 开关机 -#endif - lP->debug.activePower = activepower->valuedouble; - lP->debug.reactivePower = reactivepower->valuedouble; - lP->debug.pcsSwitch = onoff->valueint; - break; - } - case E_TACTIC_MODE_PEAKVALLY: - { - if (cJSON_IsObject(strategyCfg)) - { - cJSON *peakValleyTimeTables = cJSON_GetObjectItem(strategyCfg, "pvTab"); - if (cJSON_IsObject(peakValleyTimeTables)) - { - cJSON *timeTableLength = cJSON_GetObjectItem(peakValleyTimeTables, "dTabN"); - lP->pkvly.zoneTabLen = timeTableLength->valueint; -#ifdef CLOUDCTRLPRINT - printf("Time Table Length: %d\n", lP->pkvly.zoneTabLen); -#endif - cJSON *peakItem = cJSON_GetObjectItem(peakValleyTimeTables, "dTab"); - if (cJSON_IsArray(peakItem)) - { - int peakItemCount = cJSON_GetArraySize(peakItem); - lP->pkvly.peakItem = (pv_date_config_t *)malloc(peakItemCount * sizeof(pv_date_config_t)); - for (int i = 0; i < peakItemCount; i++) - { - cJSON *peak = cJSON_GetArrayItem(peakItem, i); - if (cJSON_IsObject(peak)) - { - cJSON *startDateTime = cJSON_GetObjectItem(peak, "sDay"); - cJSON *endDateTime = cJSON_GetObjectItem(peak, "eDay"); - memcpy(lP->pkvly.peakItem[i].startDate, (uint8_t *)startDateTime->valuestring, 6); - memcpy(lP->pkvly.peakItem[i].endDate, (uint8_t *)endDateTime->valuestring, 6); -#ifdef CLOUDCTRLPRINT - printf("Start DateTime: %s, End DateTime: %s\n", - cJSON_IsString(startDateTime) ? startDateTime->valuestring : "null", - cJSON_IsString(endDateTime) ? endDateTime->valuestring : "null"); -#endif - -#ifdef CLOUDCTRLPRINT - cJSON *timeSlotTableLength = cJSON_GetObjectItem(peak, "sTabN"); - printf("Time Slot Table Length: %d\n", cJSON_IsNumber(timeSlotTableLength) ? timeSlotTableLength->valueint : 0); -#endif - - cJSON *timeSlotTable = cJSON_GetObjectItem(peak, "sTab"); - if (cJSON_IsArray(timeSlotTable)) - { - int timeSlotCount = cJSON_GetArraySize(timeSlotTable); - lP->pkvly.peakItem[i].timeCfgTab = (pv_time_config_t *)malloc(timeSlotCount * sizeof(pv_time_config_t)); - lP->pkvly.peakItem[i].timeCfgLen = timeSlotCount; - for (int j = 0; j < timeSlotCount; j++) - { - cJSON *timeSlot = cJSON_GetArrayItem(timeSlotTable, j); - if (cJSON_IsObject(timeSlot)) - { - cJSON *startTime = cJSON_GetObjectItem(timeSlot, "sSec"); - cJSON *endTime = cJSON_GetObjectItem(timeSlot, "eSec"); - cJSON *powerKW = cJSON_GetObjectItem(timeSlot, "pwrKw"); - lP->pkvly.peakItem[i].timeCfgTab[j].startTime = atoi(startTime->valuestring); - lP->pkvly.peakItem[i].timeCfgTab[j].endTime = atoi(endTime->valuestring); - lP->pkvly.peakItem[i].timeCfgTab[j].power = powerKW->valuedouble; -#ifdef CLOUDCTRLPRINT - printf("Time Slot [%d]: Start: %d, End: %d, Power: %.2f kW\n", - j, - atoi(startTime->valuestring), - atoi(endTime->valuestring), - powerKW->valuedouble); -#endif - } - } - // 释放资源 - if (lP->pkvly.peakItem[i].timeCfgTab != NULL) - { - free(lP->pkvly.peakItem[i].timeCfgTab); - lP->pkvly.peakItem[i].timeCfgTab = NULL; - } - } - } - } - } - } - } - 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; - } - case KEms_cfg_Protect: - { - cJSON *transCapacity = cJSON_GetObjectItem(strategyCfg, "transCapacity"); - cJSON *olWarnLimitVal = cJSON_GetObjectItem(strategyCfg, "olWarnLimitVal"); - cJSON *maxPower = cJSON_GetObjectItem(strategyCfg, "maxPower"); - cJSON *olShutdownVal = cJSON_GetObjectItem(strategyCfg, "olShutdownVal"); - cJSON *demandSwitch = cJSON_GetObjectItem(strategyCfg, "demandSwitch"); - cJSON *targetDemand = cJSON_GetObjectItem(strategyCfg, "targetDemand"); - cJSON *deWarnLimitVal = cJSON_GetObjectItem(strategyCfg, "deWarnLimitVal"); - cJSON *deShutdownVal = cJSON_GetObjectItem(strategyCfg, "deShutdownVal"); - cJSON *backflowSwitch = cJSON_GetObjectItem(strategyCfg, "backflowSwitch"); - cJSON *bfWarnLimitVal = cJSON_GetObjectItem(strategyCfg, "bfWarnLimitVal"); - cJSON *bfShutdownVal = cJSON_GetObjectItem(strategyCfg, "bfShutdownVal"); - cJSON *socForbidCharge = cJSON_GetObjectItem(strategyCfg, "socForbidCharge"); - cJSON *socForbidDischarge = cJSON_GetObjectItem(strategyCfg, "socForbidDischarge"); - lP->protect.maxActivePower = transCapacity->valuedouble; - lP->protect.overFlowLowLimt = olWarnLimitVal->valuedouble; - lP->protect.overFlowCloseLimt = olShutdownVal->valuedouble; - lP->protect.maxPower = maxPower->valuedouble; - lP->protect.demandCtl = demandSwitch->valueint; - lP->protect.aimActiveDemand = targetDemand->valuedouble; - lP->protect.demandCtrlLowLimt = deWarnLimitVal->valuedouble; - lP->protect.demandCtrlCloseLimt = deShutdownVal->valuedouble; - lP->protect.backFlow = backflowSwitch->valueint; - lP->protect.backFlowLowLimt = bfWarnLimitVal->valueint; - lP->protect.backFlowCloseLimt = bfShutdownVal->valuedouble; - lP->protect.socForbidCharge = socForbidCharge->valuedouble; - lP->protect.socForbidDischarge = socForbidDischarge->valuedouble; - - break; - } - case KEms_cfg_END: - { - - break; - } - default: - { - printf("Unknown mode: %d\n", mode); - break; - } - } - return 0; -} - -/***************************************************************************** - * @brief 根据配置信息和模式组装成 JSON 字符串,并包含额外的顶层字段 - * @param[in] arvcfgInfo_ret_t cfg 结构包含模式字、事务标识等信息 - * @param[in] arg 指向配置数据的指针(例如,指向 logic_Params 的指针) - * @param[in] rw 0-read,1-conrtol - * @return char* 表示 JSON 字符串(需要调用者释放) - *****************************************************************************/ -char *createStrategyCfgJsonString(arvcfgInfo_ret_t cfg, const void *arg, int rw) -{ - int mode = cfg.modeWord; - char *transaction = cfg.transaction; - int rc = 0; - char *msg = NULL; - work_mode_set_t curmode = {0}; - rc = kit_get_work_mode_set(&curmode); - if (1 == rc) - { - msg = "db fault"; - } - // 如果是控制指令且参数为空 - if (arg == NULL && rw == 1) - { - rc = 1; - msg = "param Analysis failed!"; // 参数解析失败 - } - - // 获取当前时间戳 - time_t timeStamp = time(NULL); - - // 创建一个新的 JSON 对象来包含所有信息 - cJSON *root = cJSON_CreateObject(); - cJSON *strategyCfg = cJSON_CreateObject(); - if (strategyCfg == NULL) - { - rc = 1; - msg = "program fault"; // 内存错误 - } - debug_algorithm_t p1 = {0}; - protect_params_t p7 = {0}; - UT_array *pvDateConfigs; - - // 添加顶层字段 - cJSON_AddStringToObject(root, "transaction", transaction); - cJSON_AddNumberToObject(root, "timeStamp", CurtimesMS(NULL)); - cJSON_AddNumberToObject(root, "curMode", curmode.workMode); - cJSON_AddNumberToObject(root, "modeWord", mode); - - cJSON_AddItemToObject(root, "strategyCfg", strategyCfg); - switch (mode) - { - case E_TACTIC_MODE_START: - // 暂未实现,如有需要,可以在这里设置相关字段 - break; - - case E_TACTIC_MODE_DEBUG: - rc = kit_get_debug_algorithm(&p1); - if (rc == 1) - { - msg = "db fault"; - break; - } - cJSON_AddNumberToObject(strategyCfg, "activepower", p1.activePower); - cJSON_AddNumberToObject(strategyCfg, "reactivepower", p1.reactivePower); - cJSON_AddNumberToObject(strategyCfg, "onOff", p1.pcsSwitch); - break; - - case E_TACTIC_MODE_PEAKVALLY: - rc = kit_get_pv_date_cfg_db_data(&pvDateConfigs); - if (rc == 1) - { - msg = "db fault"; - break; - } - // pv_date_config_t *pv_elem = (pv_date_config_t *)malloc(sizeof(pv_date_config_t)); - cJSON *peakValleyTimeTables = cJSON_CreateObject(); - cJSON_AddItemToObject(strategyCfg, "pvTab", peakValleyTimeTables); - cJSON_AddNumberToObject(peakValleyTimeTables, "dTabN", utarray_len(pvDateConfigs)); - - cJSON *peakItem = cJSON_CreateArray(); - cJSON_AddItemToObject(peakValleyTimeTables, "dTab", peakItem); - - utarray_foreach(pvDateConfigs, pv_date_config_t *, pv_elem) - { - cJSON *peak = cJSON_CreateObject(); - cJSON_AddItemToArray(peakItem, peak); - - cJSON_AddStringToObject(peak, "sDay", (char *)pv_elem->startDate); - cJSON_AddStringToObject(peak, "eDay", (char *)pv_elem->endDate); - cJSON_AddNumberToObject(peak, "sTabN", pv_elem->timeCfgLen); - cJSON *timeSlotTable = cJSON_CreateArray(); - cJSON_AddItemToObject(peak, "sTab", timeSlotTable); - - for (int j = 0; j < pv_elem->timeCfgLen; j++) - { - cJSON *timeSlot = cJSON_CreateObject(); - cJSON_AddItemToArray(timeSlotTable, timeSlot); - cJSON_AddNumberToObject(timeSlot, "sSec", pv_elem->timeCfgTab[j].startTime); - cJSON_AddNumberToObject(timeSlot, "eSec", pv_elem->timeCfgTab[j].endTime); - cJSON_AddNumberToObject(timeSlot, "pwrKw", pv_elem->timeCfgTab[j].power); - } - } - 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; - case KEms_cfg_Protect: - if (rw == 0) - { - // rc = kit_get_protect_algorithm(&p7); - if (rc == 1) - { - msg = "db fault"; - } - } - else - { - memcpy(&p7, arg, sizeof(protect_params_t)); - } - - cJSON_AddNumberToObject(strategyCfg, "transCapacity", p7.maxActivePower); - cJSON_AddNumberToObject(strategyCfg, "olWarnLimitVal", p7.overFlowLowLimt); - cJSON_AddNumberToObject(strategyCfg, "maxPower", p7.maxPower); - cJSON_AddNumberToObject(strategyCfg, "olShutdownVal", p7.overFlowCloseLimt); - cJSON_AddNumberToObject(strategyCfg, "demandSwitch", p7.demandCtl); - cJSON_AddNumberToObject(strategyCfg, "targetDemand", p7.aimActiveDemand); - cJSON_AddNumberToObject(strategyCfg, "deWarnLimitVal", p7.demandCtrlLowLimt); - cJSON_AddNumberToObject(strategyCfg, "deShutdownVal", p7.demandCtrlCloseLimt); - cJSON_AddNumberToObject(strategyCfg, "backflowSwitch", p7.backFlow); - cJSON_AddNumberToObject(strategyCfg, "bfWarnLimitVal", p7.backFlowLowLimt); - cJSON_AddNumberToObject(strategyCfg, "bfShutdownVal", p7.backFlowCloseLimt); - cJSON_AddNumberToObject(strategyCfg, "socForbidCharge", p7.socForbidCharge); - cJSON_AddNumberToObject(strategyCfg, "socForbidDischarge", p7.socForbidDischarge); - - // 暂未实现,如有需要,可以在这里设置相关字段 - break; - - case KEms_cfg_END: - // 暂未实现,如有需要,可以在这里设置相关字段 - break; - - default: - printf("Unknown mode: %d\n", mode); - cJSON_Delete(strategyCfg); - return NULL; - } - cJSON_AddNumberToObject(root, "respCode", rc); - if (rc == 0) - { - msg = "success"; - } - cJSON_AddStringToObject(root, "respMsg", msg); - char *jsonString = cJSON_Print(strategyCfg); - cJSON_Delete(strategyCfg); // 清理 JSON 对象 - return jsonString; // 返回生成的 JSON 字符串 -} - -/***************************************************************************** - * @brief 解析云端的配置消息 - * @param[in] jsonString:云端消息字符串 - * @param[in] lP:算法配置联合体指针 - * @return 事务符、mode - *****************************************************************************/ -arvcfgInfo_ret_t parseEmsCfgJson(const char *jsonString, logic_Params *lP) -{ - arvcfgInfo_ret_t rc = {0}; - cJSON *json = cJSON_Parse(jsonString); - if (json == NULL) - { - printf("JSON parsing failed.\n"); - return rc; - } - cJSON *transaction = cJSON_GetObjectItem(json, "transaction"); - cJSON *timeStamp = cJSON_GetObjectItem(json, "timeStamp"); - cJSON *modeWord = cJSON_GetObjectItem(json, "modeWord"); - cJSON *strategyCfg = cJSON_GetObjectItem(json, "strategyCfg"); - rc.transaction = transaction->valuestring; - rc.modeWord = modeWord->valueint; - if (transaction && timeStamp && modeWord && strategyCfg) - { - printf("Transaction: %s, Timestamp: %s\n", - cJSON_GetStringValue(transaction), - timeStamp->valuedouble); - // 跟据算法枚举值解析json中的startegy元素,解析后的算法参数放入logic_Params中 - parseStrategyJsonObject(strategyCfg, rc.modeWord, lP); - } - - cJSON_Delete(json); - return rc; -} -/***************************************************************************** - * @brief 获取时间戳 - * @return NONE - *****************************************************************************/ -char *getTmstr2() -{ - time_t t = time(NULL); - struct tm *tm = localtime(&t); - char *time_str = malloc(20); // 动态分配内存 - - if (time_str == NULL) - { - return NULL; // 检查内存分配是否成功 - } - - strftime(time_str, 20, "%Y-%m-%d %H:%M:%S", tm); - return time_str; -} -/***************************************************************************** - * @brief 获取时间戳 - * @return NONE - *****************************************************************************/ -time_t strToTimeT(char *time_str) -{ - struct tm tm; - // 初始化tm结构体 - memset(&tm, 0, sizeof(struct tm)); - - // 解析日期时间字符串 - if (strftime(time_str, strlen(time_str), "%Y-%m-%d %H:%M:%S", &tm) == 0) - { - // 解析失败 - return (time_t)-1; - } - - // 转换为time_t - return mktime(&tm); -} -/***************************************************************************** - * @brief 从时间戳获取距离当前的时间差 - * @return NONE - *****************************************************************************/ -void getTmDiffByStr(char *strdate) -{ - time_t past_time = strToTimeT(strdate); - - if (past_time == (time_t)-1) - { - printf("Failed to convert string to time_t\n"); - } - - time_t current_time = time(NULL); - double difference = difftime(current_time, past_time); - - // 计算差异的天数、小时数、分钟数和秒数 - int days = difference / (60 * 60 * 24); - int hours = ((int)difference % (60 * 60 * 24)) / (60 * 60); - int minutes = ((int)difference % (60 * 60)) / 60; - int seconds = (int)difference % 60; - printf("Time difference: %d days, %d hours, %d minutes, %d seconds\n", days, hours, minutes, seconds); -} -/***************************************************************************** - * @brief 比较两个设备节点是否相同 - * @param[in] a:左操作数 - * @param[in] b:左操作数 - * @return 0-不同,1-相同 - *****************************************************************************/ -bool ifSameTopoElem(const topology_t *a, const topology_t *b) -{ - bool result = true; - - if (a->menuTree != b->menuTree) - { - // printf("menuTree differs: %d vs %d\n", a->menuTree, b->menuTree); - result = false; - } - - if (memcmp(a->name, b->name, MAX_NAME_BUF_LEN) != 0) - { - // printf("name differs: %s vs %s\n", a->name, b->name); - result = false; - } - - if (memcmp(a->sn, b->sn, MAX_CODE_BUF_LEN) != 0) - { - // printf("sn differs: %s vs %s\n", a->sn, b->sn); - result = false; - } - - if (a->dbId != b->dbId) - { - // printf("dbId differs: %d vs %d\n", a->dbId, b->dbId); - result = false; - } - - if (a->parentId != b->parentId) - { - // printf("parentId differs: %d vs %d\n", a->parentId, b->parentId); - result = false; - } - - if (a->sortOrder != b->sortOrder) - { - // printf("sortOrder differs: %d vs %d\n", a->sortOrder, b->sortOrder); - result = false; - } - - if (a->devType != b->devType) - { - // printf("devType differs: %d vs %d\n", a->devType, b->devType); - result = false; - } - - return result; -} -/***************************************************************************** - * @brief 比较两个设备拓扑是否相同 - * @param[in] arr1:左操作数 - * @param[in] arr2:左操作数 - * @return 0-不同,1-相同 - *****************************************************************************/ -bool chkTopoDiff(UT_array *arr1, UT_array *arr2) -{ - if (arr1 == NULL || arr2 == NULL) - { - return false; - } - if (utarray_len(arr1) != utarray_len(arr2)) - { - return false; - } - - topology_t *el1, *el2; - for (el1 = (topology_t *)utarray_front(arr1), el2 = (topology_t *)utarray_front(arr2); - el1 != NULL && el2 != NULL; - el1 = (topology_t *)utarray_next(arr1, el1), el2 = (topology_t *)utarray_next(arr2, el2)) - { - - if (!ifSameTopoElem(el1, el2)) - { - return false; - } - } - - return true; -} -int getCfgBymodeWord(void *arg, int modeWord) -{ - - debug_algorithm_t *pDbA = (debug_algorithm_t *)malloc(sizeof(debug_algorithm_t)); - debug_params_t *pDbg = (debug_params_t *)malloc(sizeof(debug_params_t)); - int rc = 0; - switch (modeWord) - { - case E_TACTIC_MODE_DEBUG: // 调试模式 - - rc = kit_get_debug_algorithm(pDbA); - if (rc != 0) - { - return 1; - } - pDbg->activePower = pDbA->activePower; - pDbg->reactivePower = pDbA->reactivePower; - pDbg->pcsSwitch = pDbA->pcsSwitch; - arg = (debug_params_t *)malloc(sizeof(debug_params_t)); - memcpy(arg, pDbg, sizeof(debug_params_t)); - break; - case E_TACTIC_MODE_PEAKVALLY: // 削峰填谷模式 - - break; - // case E_TACTIC_MODE_LOADTRACK: // 负载跟踪模式 - // lenth = sizeof(peakvalley_zone_tab_t); - // break; - case E_TACTIC_MODE_DMDCTRL: // 需量控制 - - break; - case E_TACTIC_MODE_PFCTRL: // 功率因数 - break; - default: - break; // 失败 - } - if (pDbA != NULL) - { - free(pDbA); - } - if (pDbg != NULL) - { - free(pDbg); - } - return 0; -} -/***************************************************************************** - * @brief 更新上云测点的变化状态 - * @param[in] map:mqtt测点配置表 - * @return NONE - *****************************************************************************/ -void updatePointsChgStat(mqtt_option_map_t *map) -{ - map->bChgFlag = false; - for (int i = 0; i < map->devNum; i++) - { - map->pllist->bChgFlag = false; - for (int j = 0; j < map->pllist[i].txcount; j++) - { - double old = map->pllist[i].rtdbGetTab[j].value; - double new = 0; - - if (map->devType == kDev_Type_BSU) - { - new = getBsuRTDBPointValue(g_bcuMap, - map->pllist[i].rtdbGetTab[j].dbType, - map->pllist[i].rtdbGetTab[j].devType, - map->pllist[i].rtdbGetTab[j].devId, - map->pllist[i].rtdbGetTab[j].pointId); - } - else - { - new = mqttFindDB(map->pllist[i].rtdbGetTab[j]); - } - map->pllist[i].rtdbGetTab[j].value = new; - if (double_equal(old, new)) - { - map->pllist[i].rtdbGetTab[j].ifchg = false; - } - else - { - map->pllist[i].rtdbGetTab[j].ifchg = true; -#ifdef MQTTPRINT - printf("dbtype=%d,devType=%d,devId=%d,pointId=%d,old=%f,new=%f\n", map->pllist[i].rtdbGetTab[j].dbType, - map->pllist[i].rtdbGetTab[j].devType, - map->pllist[i].rtdbGetTab[j].devId, - map->pllist[i].rtdbGetTab[j].pointId, old, new); -#endif - } - map->pllist[i].bChgFlag |= map->pllist[i].rtdbGetTab[j].ifchg; - } - map->bChgFlag |= map->pllist[i].bChgFlag; - } -} -char *getDbgLocalSetMsg(debug_algorithm_t *dbg, work_mode_set_t *wm) -{ - // 为字符串申请内存 - char *jsonStr = malloc(256); - if (jsonStr == NULL) - { - return NULL; - } - - // 构建json - snprintf(jsonStr, 256, - "{" - "\"timeStamp\":0," - "\"transaction\":\"0\"," - "\"curMode\":\"%d\"," - "\"modeWord\":\"1\"," - "\"strategyCfg\":{" - "\"activePower\":\"%f\"," - "\"reactivePower\":\"%f\"," - "\"switch\":\"%d\"" - "}" - "}", - wm->workMode, dbg->activePower, dbg->reactivePower, dbg->pcsSwitch); - - return jsonStr; -} -void setdbgCB(void *arg) -{ - // 忽略 SIGPIPE 信号 - signal(SIGPIPE, SIG_IGN); - ConnContext *ct = (ConnContext *)arg; - int rc = 0; - MQTTClient_message pubmsg = MQTTClient_message_initializer; - char *msg = (char *)malloc(MAX_MQTT_MSG_LEN * sizeof(char)); - debug_algorithm_t dbgArg = {0}; - rc = kit_get_debug_algorithm(&dbgArg); - work_mode_set_t workmode = {0}; - kit_get_work_mode_set(&workmode); - if (0 == rc) - { - msg = getDbgLocalSetMsg(&dbgArg, &workmode); - pubmsg.payload = msg; - pubmsg.payloadlen = strlen(msg); - pubmsg.qos = kQos_2; - pubmsg.retained = 0; - retry:; - if (0 == sem_trywait(&g_allowSend)) - { - rc = MQTTClient_publishMessage(ct->client, (char *)ct->mlib.changeTopic, &pubmsg, NULL); - if (MQTTCLIENT_SUCCESS == rc) - { - rc = MQTTClient_waitForCompletion(ct->client, deliveredtoken, TIMEOUT); - sem_post(&g_allowSend); - } - else - { - sem_post(&g_allowSend); - goto retry; - } - } - else - { - usleep(50000); - goto retry; - } - } - return NULL; -}; -void setPkvlCB(void *arg) -{ - return; -}; -void setDmdRspCB(void *arg) -{ - return; -}; -void setLoadTrackCB(void *arg) -{ - return; -}; -void setDmdCtrlCB(void *arg) -{ - return; -}; -void setPFCtrlCB(void *arg) -{ - return; -}; - -setCfgCB setCfgCBGrp[] = - { - setdbgCB, - setPkvlCB, - setDmdRspCB, - setLoadTrackCB, - setDmdCtrlCB, - setPFCtrlCB, -}; - -void *dataChgMonitor(void *arg) -{ - while (!(g_MqttMsg & kEvent_topo_send)) - { - usleep(50000); - } - // 忽略 SIGPIPE 信号 - signal(SIGPIPE, SIG_IGN); - ConnContext *ct = (ConnContext *)arg; - int rc = 0; - MQTTClient_message pubmsg = MQTTClient_message_initializer; - char *msg = (char *)malloc(MAX_MQTT_MSG_LEN * sizeof(char)); - if (msg == NULL) - { - return NULL; - } - while (1) - { - for (int cfgN = kSign_LogicDebug; cfgN < kSign_Logic_End; cfgN++) - { - rc = readWebSign(kSign_ShMem, cfgN); - if (true == rc) - { - setCfgCBGrp[cfgN - kSign_Logic_Start - 1](ct); - } - } - if (g_MqttMsg & kEvent_Period_Task_begin) - { - for (int i = 0; i < kDev_Type_End; i++) - { - if (g_mqtt_map[i].bChgFlag == false) - { - updatePointsChgStat(&g_mqtt_map[i]); - usleep(50000); - continue; - } - else - { - - rc = genChgDevGrpPeriodPayload(msg, i, &g_mqtt_map[i]); - updatePointsChgStat(&g_mqtt_map[i]); - if (0 == strlen(msg) || g_mqtt_map[i].devNum < 1 || 1 == rc) // rc==1代表该包数据无测点信息 - { - continue; - } - pubmsg.payload = msg; - pubmsg.payloadlen = strlen(msg); - pubmsg.qos = kQos_2; - pubmsg.retained = 0; - retry_label:; - if (0 == sem_trywait(&g_allowSend)) - { - chkdata_thread_haveSendSig = 1; - rc = MQTTClient_publishMessage(ct->client, (char *)ct->mlib.changeTopic, &pubmsg, NULL); - if (MQTTCLIENT_SUCCESS == rc) - { - rc = MQTTClient_waitForCompletion(ct->client, deliveredtoken, TIMEOUT); - sem_post(&g_allowSend); - chkdata_thread_haveSendSig = 0; - } - else - { - sem_post(&g_allowSend); - chkdata_thread_haveSendSig = 0; - } - } - else - { - usleep(50000); - goto retry_label; - } - updatePointsChgStat(&g_mqtt_map[i]); - } - } - chkdata_thread_alive = 1; - usleep(50000); - } - else - { - usleep(50000); - } - } -} -void pointListener(mqtt2db_t *tab) -{ - double old = tab->value; - double new = mqttFindDB(*tab); - if (!double_equal(old, new)) - { - tab->ifchg = 1; - } -} -/***************************************************************************** - * @brief 线程监视函数 - * @param[in] arg: 可选参数 - * @return NONE - *****************************************************************************/ -void *threadGuard(void *arg) -{ - pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); - pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL); - pthread_t worker = 0; - mqtt_lib_t mlt = {0}; - getMQTTCfg(&mlt); - // 传递给重连回调函数的结构体 - ConnContext connContext; - MQTTClient_connectOptions connopts_tmp = MQTTClient_connectOptions_initializer; - memcpy(&connContext.mlib, &mlt, sizeof(mqtt_lib_t)); - connContext.connopts = connopts_tmp; - connContext.connopts.username = (char *)mlt.username; - connContext.connopts.password = (char *)mlt.password; - connContext.connopts.keepAliveInterval = 60; // 设置心跳间隔为 60 秒 - connContext.connopts.cleansession = 0; - int period = connContext.mlib.tSendTaskPeriod > 0 ? 2 * connContext.mlib.tSendTaskPeriod : 10; - int cnt = 0; - while (1) - { - - sleep(period); // 检查频率,为2倍周期线程的周期 - cnt = 0; - periodT_rechk:; - if (!period_thread_alive) - { - if (cnt < 20) - { - cnt++; - goto periodT_rechk; - } - if (period_thread_haveSendSig) - { - sem_post(&g_allowSend); - } - - if (period_thread_haveRcdSig) - { - sem_post(&g_MqttwaitAndSaveHistory); - } - pthread_cancel(g_Tids[D_PERIODSEND_T_SEQ]); // 尝试取消阻塞或无响应的线程 - pthread_create(&worker, NULL, periodSendTask, &connContext); // 创建新的线程 - - g_Tids[D_PERIODSEND_T_SEQ] = worker; // 存储新的线程id - } - worker = 0; - cnt = 0; - history_rechk:; - if (!history_thread_alive) - { - if (cnt < 20) - { - cnt++; - goto history_rechk; - } - if (history_thread_haveSendSig) - { - sem_post(&g_allowSend); - } - if (history_thread_haveRcdSig) - { - sem_post(&g_MqttwaitAndSaveHistory); - } - pthread_cancel(g_Tids[D_HISTORY_T_SEQ]); // 尝试取消阻塞或无响应的线程 - pthread_create(&worker, NULL, historyDataHandle, &connContext); // 创建新的线程 - g_Tids[D_HISTORY_T_SEQ] = worker; // 存储新的线程id - } - worker = 0; - chg_rechk:; - if (!chkdata_thread_alive) - { - if (cnt < 20) - { - cnt++; - goto chg_rechk; - } - if (chkdata_thread_haveSendSig) - { - sem_post(&g_allowSend); - } - pthread_cancel(g_Tids[D_DATACHK_T_SEQ]); // 尝试取消阻塞或无响应的线程 - pthread_create(&worker, NULL, dataChgMonitor, &connContext); // 创建新的线程 - g_Tids[D_DATACHK_T_SEQ] = worker; // 存储新的线程id - } - - period_thread_alive = 0; // 重置 - history_thread_alive = 0; - chkdata_thread_alive = 0; - } - return NULL; -} -/***************************************************************************** - * @brief 本地设置调试模式的参数 - * @param[in] onoff:开关机 - * @param[in] actiePower:有功功率 - * @param[in] reactivePower:无功功率 - * @return 控制报文json串 - *****************************************************************************/ -char *LocalCtrlDebugParam(int onoff, float activePower, float reactivePower) -{ - // 为字符串申请内存 - char *jsonStr = malloc(256); - if (jsonStr == NULL) - { - return NULL; - } - - // 构建json - snprintf(jsonStr, 256, - "{" - "\"transaction\":\"0\"," - "\"timeStamp\":\"0\"," - "\"modeWord\":\"1\"," - "\"strategyCfg\":{" - "\"P\":%f," - "\"Q\":%f," - "\"onOff\":%d" - "}" - "}", - activePower, reactivePower, onoff); - - return jsonStr; -} -/***************************************************************************** - * @brief 本地设置削峰填谷模式的参数 - * @return 控制报文json串 - *****************************************************************************/ -char *LocalPkvlyParams() -{ - char *json_string = "{\n" - " \"transaction\": \"0\",\n" - " \"timeStamp\": \"0\",\n" - " \"modeWord\": 2,\n" - " \"strategyCfg\": {\n" - " \"pvTab\": {\n" - " \"dTabN\": 2,\n" - " \"dTab\": [\n" - " {\n" - " \"sDay\": \"2024-09-24\",\n" - " \"eDay\": \"2024-09-30\",\n" - " \"sTabN\": 3,\n" - " \"sTab\": [\n" - " {\n" - " \"sSec\": 1000,\n" - " \"eSec\": 1000,\n" - " \"pwrKw\": 7.0\n" - " },\n" - " {\n" - " \"sSec\": 4000,\n" - " \"eSec\": 10000,\n" - " \"pwrKw\": 9\n" - " },\n" - " {\n" - " \"sSec\": 1000,\n" - " \"eSec\": 20000,\n" - " \"pwrKw\": 18\n" - " }\n" - " ]\n" - " },\n" - " {\n" - " \"sDay\": \"2024-10-01\",\n" - " \"eDay\": \"2024-10-07\",\n" - " \"sTabN\": 2,\n" - " \"sTab\": [\n" - " {\n" - " \"sSec\": 1500,\n" - " \"eSec\": 2500,\n" - " \"pwrKw\": 45\n" - " },\n" - " {\n" - " \"sSec\": 2500,\n" - " \"eSec\": 3500,\n" - " \"pwrKw\": -55\n" - " }\n" - " ]\n" - " }\n" - " ]\n" - " }\n" - " }\n" - "}"; - return json_string; -} -/***************************************************************************** - * @brief 发送拓扑结构的函数 - * @param[in] client:客户端句柄 - * @return none - *****************************************************************************/ -void sendDevTopo(MQTTClient client) -{ - signal(SIGPIPE, SIG_IGN); - static int finish = 0; - if (finish == 1) - { - return; - } - int rc = 0; - char *msg = (char *)malloc(MAX_MQTT_MSG_LEN * sizeof(char)); - if ((g_MqttMsg & kEvent_change_devTopo) || (finish == 0)) - { - g_MqttMsg &= ~kEvent_topo_send; - MQTTClient_message pubmsg = MQTTClient_message_initializer; - getTopologyJsonByDb(&msg); - pubmsg.payload = msg; - pubmsg.payloadlen = strlen(msg); - pubmsg.qos = kQos_2; - pubmsg.retained = 0; - char *topic = (char *)NorthProtoTable[kProto_MQTT_Slave].northProtocol.mqttLib.rootTopic; - retry:; - if (0 == sem_trywait(&g_allowSend)) - { - rc = MQTTClient_publishMessage(client, topic, &pubmsg, &deliveredtoken); - if (MQTTCLIENT_SUCCESS == rc) - { - rc = MQTTClient_waitForCompletion(client, deliveredtoken, TIMEOUT); - sem_post(&g_allowSend); - if (MQTTCLIENT_SUCCESS == rc) - { - g_MqttMsg |= kEvent_topo_send; - finish = 1; - } - else - { - finish = 0; - } - } - else - { - sem_post(&g_allowSend); - finish = 0; - } - } - else - { - usleep(50000); - goto retry; - } - } - return; -}; -/***************************************************************************** - * @brief mqtt主函数 - * @param[in] arg: 可选参数 - * @return NONE - *****************************************************************************/ -void *MqttTask(void *arg) -{ - - // 忽略 SIGPIPE 信号 - signal(SIGPIPE, SIG_IGN); - // printf("mqtt task begin!\n"); - int rc; - g_MqttMsg = 0; - mqtt_lib_t mlt; -retry: - updateMqttPara(&mlt, g_mqtt_map); - // 初始化历史数据数组 - utarray_new(g_recordsWithData, &brd_icd); - MQTTClient_connectOptions connopts_tmp = MQTTClient_connectOptions_initializer; - // 传递给重连回调函数的结构体 - ConnContext connContext; - memcpy(&connContext.mlib, &mlt, sizeof(mqtt_lib_t)); - connContext.connopts = connopts_tmp; - connContext.connopts.username = (char *)mlt.username; - connContext.connopts.password = (char *)mlt.password; - connContext.connopts.keepAliveInterval = 10; // 设置心跳间隔为 10 秒 - connContext.connopts.cleansession = 0; - // connContext.connopts.retryInterval = 1; - // 创建MQTT客户端 - rc = MQTTClient_create(&connContext.client, (char *)mlt.url, (char *)mlt.clientId, MQTTCLIENT_PERSISTENCE_NONE, NULL); - // 设置回调函数 - rc = MQTTClient_setCallbacks(connContext.client, (void *)&connContext, connlostCB, msgarrvdCB, NULL); - - // 连接到MQTT代理 - if ((rc = MQTTClient_connect(connContext.client, &connContext.connopts)) != MQTTCLIENT_SUCCESS) - { - char *cause = "MQTT Broker连接失败。"; - updateBrkRcd(cause); - updateConnectionStatus(false); - KITPTF(LOG_MQTT_EN, INFO_EN, "Failed to connect, return code%d\n.", rc); - KITLOG(LOG_MQTT_EN, INFO_EN, "MQTT Broker连接失败。", NULL); - // 记录网络断开 - RECORDNETSTATUS(D_STR_DISCONN_WORD) - goto retry; - } - else - { - updateConnectionStatus(true); - KITPTF(LOG_MQTT_EN, INFO_EN, "successfully connected to MQTT broker!\n.", rc); - KITLOG(LOG_MQTT_EN, INFO_EN, "successfully connected to MQTT broker!\n", NULL); - // 记录网络连接成功 - RECORDNETSTATUS(D_STR_CONNECT_WORD) - } - - // 订阅EMS control/read主题以接收消息 - rc = MQTTClient_subscribe(connContext.client, (char *)mlt.controlTopic, mlt.qos); - if (MQTTCLIENT_SUCCESS == rc) - { - // printf("Successfully subscribed to the %s topic!\n", mlt.controlTopic); - } - - rc = MQTTClient_subscribe(connContext.client, (char *)mlt.readTopic, mlt.qos); - if (MQTTCLIENT_SUCCESS == rc) - { - // printf("Successfully subscribed to the %s topic!\n", mlt.readTopic); - } - // 初始化消息发送互斥信号量 - sem_init(&g_allowSend, 0, 1); - // 初始化历史数据存储和发送互斥量 - sem_init(&g_MqttwaitAndSaveHistory, 0, 1); - pthread_t periodfd; - pthread_create(&periodfd, NULL, periodSendTask, &connContext); // 创建周期发送线程 - g_Tids[D_PERIODSEND_T_SEQ] = periodfd; - pthread_t historyHandlefd; - pthread_create(&historyHandlefd, NULL, historyDataHandle, &connContext); // 创建历史数据处理线程 - g_Tids[D_HISTORY_T_SEQ] = historyHandlefd; - pthread_t dataChgMonitorfd; - pthread_create(&dataChgMonitorfd, NULL, dataChgMonitor, &connContext); // 创建变化检测处理线程 - g_Tids[D_DATACHK_T_SEQ] = dataChgMonitorfd; - // pthread_t thread_guardfd; - // pthread_create(&thread_guardfd, NULL,threadGuard, &connContext); // 创建线程管理线程 - while (1) - { - // 在首次开始发送任务或者设备拓扑改动时,发送设备拓扑 - sendDevTopo(connContext.client); - sleep(1); - } - // 断开连接并销毁客户端 - MQTTClient_disconnect(connContext.client, 10000); - MQTTClient_destroy(&connContext.client); -} -/***************************************************************************** - * @brief 创建MQTT线程函数 - * @return NONE - *****************************************************************************/ -void creatNetMqttTaskEntry() -{ - int nodevToSend = judgeNodev(); - if (NorthProtoTable[kProto_MQTT_Slave].configType == 0) - { - if (nodevToSend == 1) - { - KITPTF(LOG_MQTT_EN, INFO_EN, "MQTT:failed to get mqtt config!\n.", NULL); - KITLOG(LOG_MQTT_EN, INFO_EN, "MQTT:failed to get mqtt config!\n", NULL); - return; - } - } - else if (NorthProtoTable[kProto_MQTT_Slave].configType == 1) - { - if (NorthProtoTable[kProto_MQTT_Slave].upDevNum + NorthProtoTable[kProto_MQTT_Slave].disDevNum == 0) - { - KITPTF(LOG_MQTT_EN, INFO_EN, "MQTT:failed to get mqtt config!\n.", NULL); - KITLOG(LOG_MQTT_EN, INFO_EN, "MQTT:failed to get mqtt config!\n", NULL); - return; - } - } - pthread_t mqttfd; - if (pthread_create(&mqttfd, NULL, MqttTask, NULL) != 0) - { - KITPTF(LOG_MQTT_EN, INFO_EN, "MQTT任务创建失败。", NULL); - KITLOG(LOG_MQTT_EN, INFO_EN, "MQTT任务创建失败。", NULL); - // printf("fail to connect!"); - } - else - { - KITPTF(LOG_MQTT_EN, INFO_EN, "MQTT任务创建成功。", NULL); - KITLOG(LOG_MQTT_EN, INFO_EN, "MQTT任务创建成功。", NULL); - // printf("success to connect!\n"); - } -}; diff --git a/ems_c/bsp/bsp_mqttClient.h b/ems_c/bsp/bsp_mqttClient.h deleted file mode 100644 index 255393e..0000000 --- a/ems_c/bsp/bsp_mqttClient.h +++ /dev/null @@ -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 -#include -#include -#include -#include -#include "MQTTClient.h" -#include "MQTTAsync.h" -#include -#include "bsp_rtdb.h" -#include "bsp_comm.h" -#include -#include -#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(); \ No newline at end of file diff --git a/ems_c/logic/logic_bcu2bsu.c b/ems_c/logic/logic_bcu2bsu.c deleted file mode 100644 index 1ef715e..0000000 --- a/ems_c/logic/logic_bcu2bsu.c +++ /dev/null @@ -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 \ No newline at end of file diff --git a/ems_c/logic/logic_bcu2bsu.h b/ems_c/logic/logic_bcu2bsu.h deleted file mode 100644 index fbef929..0000000 --- a/ems_c/logic/logic_bcu2bsu.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once -#include -#include -#include -#include -#include -#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); diff --git a/ems_c/logic/logic_comm.h b/ems_c/logic/logic_comm.h deleted file mode 100644 index 037570e..0000000 --- a/ems_c/logic/logic_comm.h +++ /dev/null @@ -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 -#include -#include -#include -#include -#include -#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 diff --git a/ems_c/logic/logic_debug.c b/ems_c/logic/logic_debug.c deleted file mode 100644 index bfed017..0000000 --- a/ems_c/logic/logic_debug.c +++ /dev/null @@ -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; -} \ No newline at end of file diff --git a/ems_c/logic/logic_debug.h b/ems_c/logic/logic_debug.h deleted file mode 100644 index 817c87c..0000000 --- a/ems_c/logic/logic_debug.h +++ /dev/null @@ -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 \ No newline at end of file diff --git a/ems_c/logic/logic_demandctrl.c b/ems_c/logic/logic_demandctrl.c deleted file mode 100644 index 0160006..0000000 --- a/ems_c/logic/logic_demandctrl.c +++ /dev/null @@ -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); - } - } -} \ No newline at end of file diff --git a/ems_c/logic/logic_demandctrl.h b/ems_c/logic/logic_demandctrl.h deleted file mode 100644 index 0db9e81..0000000 --- a/ems_c/logic/logic_demandctrl.h +++ /dev/null @@ -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 \ No newline at end of file diff --git a/ems_c/logic/logic_dido.c b/ems_c/logic/logic_dido.c deleted file mode 100644 index 2cd32ad..0000000 --- a/ems_c/logic/logic_dido.c +++ /dev/null @@ -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闪烁 线程 创建成功"); - } -} \ No newline at end of file diff --git a/ems_c/logic/logic_dido.h b/ems_c/logic/logic_dido.h deleted file mode 100644 index d954892..0000000 --- a/ems_c/logic/logic_dido.h +++ /dev/null @@ -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 \ No newline at end of file diff --git a/ems_c/logic/logic_main.c b/ems_c/logic/logic_main.c deleted file mode 100644 index b2a4dda..0000000 --- a/ems_c/logic/logic_main.c +++ /dev/null @@ -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() -{ - ; -} diff --git a/ems_c/logic/logic_main.h b/ems_c/logic/logic_main.h deleted file mode 100644 index 515a97c..0000000 --- a/ems_c/logic/logic_main.h +++ /dev/null @@ -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 -#include -#include -#include -#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(); diff --git a/ems_c/logic/logic_peakvalley.c b/ems_c/logic/logic_peakvalley.c deleted file mode 100644 index 943b0a7..0000000 --- a/ems_c/logic/logic_peakvalley.c +++ /dev/null @@ -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; -} \ No newline at end of file diff --git a/ems_c/logic/logic_peakvalley.h b/ems_c/logic/logic_peakvalley.h deleted file mode 100644 index b988a8b..0000000 --- a/ems_c/logic/logic_peakvalley.h +++ /dev/null @@ -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 \ No newline at end of file diff --git a/ems_c/logic/logic_power_distr.c b/ems_c/logic/logic_power_distr.c deleted file mode 100644 index 452df3c..0000000 --- a/ems_c/logic/logic_power_distr.c +++ /dev/null @@ -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); - } - } -} diff --git a/ems_c/logic/logic_power_distr.h b/ems_c/logic/logic_power_distr.h deleted file mode 100644 index 172e804..0000000 --- a/ems_c/logic/logic_power_distr.h +++ /dev/null @@ -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 \ No newline at end of file diff --git a/ems_c/logic/logic_protected.c b/ems_c/logic/logic_protected.c deleted file mode 100644 index 6f694c6..0000000 --- a/ems_c/logic/logic_protected.c +++ /dev/null @@ -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; // 处理结束 -} \ No newline at end of file diff --git a/ems_c/logic/logic_protected.h b/ems_c/logic/logic_protected.h deleted file mode 100644 index 54eadeb..0000000 --- a/ems_c/logic/logic_protected.h +++ /dev/null @@ -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 \ No newline at end of file diff --git a/ems_c/logic/logic_task_data.c b/ems_c/logic/logic_task_data.c deleted file mode 100644 index 11f6d5d..0000000 --- a/ems_c/logic/logic_task_data.c +++ /dev/null @@ -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 -#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; -} diff --git a/ems_c/logic/logic_tempCtrl.c b/ems_c/logic/logic_tempCtrl.c deleted file mode 100644 index a642aac..0000000 --- a/ems_c/logic/logic_tempCtrl.c +++ /dev/null @@ -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) -{ - ; -} \ No newline at end of file diff --git a/ems_c/logic/logic_tempCtrl.h b/ems_c/logic/logic_tempCtrl.h deleted file mode 100644 index ae3af8c..0000000 --- a/ems_c/logic/logic_tempCtrl.h +++ /dev/null @@ -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 \ No newline at end of file diff --git a/ems_c/mw/mw_schedule_handle.c b/ems_c/mw/mw_schedule_handle.c index dd1d00b..3948f61 100644 --- a/ems_c/mw/mw_schedule_handle.c +++ b/ems_c/mw/mw_schedule_handle.c @@ -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" diff --git a/ems_c/mw/mw_schedule_handle.h b/ems_c/mw/mw_schedule_handle.h index 4e1a02f..5e8e5bd 100644 --- a/ems_c/mw/mw_schedule_handle.h +++ b/ems_c/mw/mw_schedule_handle.h @@ -9,6 +9,7 @@ #ifndef MW_SCHEDULE_HANDLE #define MW_SCHEDULE_HANDLE +#define MAX_NUM_CABINT 3 /***************************************************************************** * @brief 创建定时存储任务 * @return void