From 04976dd01b41ff1cbdc7d67f6e12a58289598624 Mon Sep 17 00:00:00 2001 From: ypc <15051963820@163.com> Date: Wed, 27 May 2026 09:14:19 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E61850=E7=9A=84mms=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E7=AB=AF=E7=A8=8B=E5=BA=8F=EF=BC=9B=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E6=95=B0=E6=8D=AE=E4=B8=AD=E5=BF=83=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- release/inc/myMms_s.h | 131 ++ release/inc/mySystem.h | 20 +- release/src/protocol/libmms_s/makefile | 87 ++ release/src/protocol/makefile | 1 + release/src/system/RTU/makefile | 4 +- release/src/system/libiec61850s/makefile | 85 ++ release/src/system/makefile | 1 + src/protocol/libmms_s/inc/mms_s.h | 122 ++ src/protocol/libmms_s/inc/mms_s_control.h | 5 + src/protocol/libmms_s/inc/mms_s_file.h | 6 + src/protocol/libmms_s/inc/mms_s_icd.h | 269 ++++ src/protocol/libmms_s/inc/mms_s_model.h | 6 + src/protocol/libmms_s/inc/mms_s_param.h | 5 + src/protocol/libmms_s/inc/mms_s_setting.h | 28 + src/protocol/libmms_s/inc/mms_s_value.h | 7 + src/protocol/libmms_s/src/mms_s.cpp | 219 +++ src/protocol/libmms_s/src/mms_s_control.cpp | 251 ++++ src/protocol/libmms_s/src/mms_s_file.cpp | 70 + src/protocol/libmms_s/src/mms_s_icd.cpp | 1346 +++++++++++++++++++ src/protocol/libmms_s/src/mms_s_model.cpp | 1164 ++++++++++++++++ src/protocol/libmms_s/src/mms_s_param.cpp | 624 +++++++++ src/protocol/libmms_s/src/mms_s_setting.cpp | 523 +++++++ src/protocol/libmms_s/src/mms_s_value.cpp | 767 +++++++++++ src/system/RTU/src/app_sys.cpp | 3 +- src/system/libdatacenter/src/dc_siganl.cpp | 28 +- src/system/libiec/src/iec.cpp | 4 +- src/system/libiec61850m/src/iec61850m.cpp | 17 +- src/system/libiec61850s/inc/iec61850s.h | 5 + src/system/libiec61850s/src/iec61850s.cpp | 298 ++++ src/system/libself_ptl/src/self_ptl.cpp | 4 +- src/system/libweb_server/src/ws_method.cpp | 55 +- test/file/MMS/prj.xml | 2 +- 32 files changed, 6091 insertions(+), 66 deletions(-) create mode 100644 release/inc/myMms_s.h create mode 100644 release/src/protocol/libmms_s/makefile create mode 100644 release/src/system/libiec61850s/makefile create mode 100644 src/protocol/libmms_s/inc/mms_s.h create mode 100644 src/protocol/libmms_s/inc/mms_s_control.h create mode 100644 src/protocol/libmms_s/inc/mms_s_file.h create mode 100644 src/protocol/libmms_s/inc/mms_s_icd.h create mode 100644 src/protocol/libmms_s/inc/mms_s_model.h create mode 100644 src/protocol/libmms_s/inc/mms_s_param.h create mode 100644 src/protocol/libmms_s/inc/mms_s_setting.h create mode 100644 src/protocol/libmms_s/inc/mms_s_value.h create mode 100644 src/protocol/libmms_s/src/mms_s.cpp create mode 100644 src/protocol/libmms_s/src/mms_s_control.cpp create mode 100644 src/protocol/libmms_s/src/mms_s_file.cpp create mode 100644 src/protocol/libmms_s/src/mms_s_icd.cpp create mode 100644 src/protocol/libmms_s/src/mms_s_model.cpp create mode 100644 src/protocol/libmms_s/src/mms_s_param.cpp create mode 100644 src/protocol/libmms_s/src/mms_s_setting.cpp create mode 100644 src/protocol/libmms_s/src/mms_s_value.cpp create mode 100644 src/system/libiec61850s/inc/iec61850s.h create mode 100644 src/system/libiec61850s/src/iec61850s.cpp diff --git a/release/inc/myMms_s.h b/release/inc/myMms_s.h new file mode 100644 index 0000000..5b592c1 --- /dev/null +++ b/release/inc/myMms_s.h @@ -0,0 +1,131 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef DATA_TYPE_B +#define DATA_TYPE_B 1 +#endif /* DATA_TYPE_B */ + +#ifndef DATA_TYPE_S8 +#define DATA_TYPE_S8 43 +#endif /* DATA_TYPE_S8 */ +#ifndef DATA_TYPE_U8 +#define DATA_TYPE_U8 32 +#endif /* DATA_TYPE_U8 */ +#ifndef DATA_TYPE_S16 +#define DATA_TYPE_S16 33 +#endif /* DATA_TYPE_S16 */ +#ifndef DATA_TYPE_U16 +#define DATA_TYPE_U16 45 +#endif /* DATA_TYPE_U16 */ +#ifndef DATA_TYPE_S32 +#define DATA_TYPE_S32 2 +#endif /* DATA_TYPE_S32 */ +#ifndef DATA_TYPE_U32 +#define DATA_TYPE_U32 35 +#endif /* DATA_TYPE_U32 */ +#ifndef DATA_TYPE_L64 +#define DATA_TYPE_L64 36 +#endif /* DATA_TYPE_L64 */ +#ifndef DATA_TYPE_UL64 +#define DATA_TYPE_UL64 37 +#endif /* DATA_TYPE_UL64 */ +#ifndef DATA_TYPE_F32 +#define DATA_TYPE_F32 38 +#endif /* DATA_TYPE_F32 */ +#ifndef DATA_TYPE_D64 +#define DATA_TYPE_D64 39 +#endif /* DATA_TYPE_D64 */ +#ifndef DATA_TYPE_IP +#define DATA_TYPE_IP 100 +#endif /* DATA_TYPE_IP */ +#ifndef DATA_TYPE_MAC +#define DATA_TYPE_MAC 101 +#endif /* DATA_TYPE_MAC */ +#ifndef DATA_TYPE_C8 +#define DATA_TYPE_C8 102 +#endif /* DATA_TYPE_C8 */ +#ifndef DATA_TYPE_C32 +#define DATA_TYPE_C32 103 +#endif /* DATA_TYPE_C32 */ +#ifndef DATA_TYPE_C64 +#define DATA_TYPE_C64 104 +#endif /* DATA_TYPE_C64 */ +#ifndef DATA_TYPE_C128 +#define DATA_TYPE_C128 105 +#endif /* DATA_TYPE_C128 */ +#ifndef DATA_TYPE_C1 +#define DATA_TYPE_C1 106 +#endif /* DATA_TYPE_C1 */ +#ifndef DATA_TYPE_STR +#define DATA_TYPE_STR 107 +#endif /* DATA_TYPE_STR */ + + + +#define MMS_S_STR_LEN 64 +#define MMS_S_PARAM_MAX 16 + + + +typedef struct +{ + char saddr[MMS_S_STR_LEN]; + char desc[MMS_S_STR_LEN]; + uint8_t type; + uint8_t ctrl_model; + // float min; + // float max; + // float step; + // char unit[MMS_S_STR_LEN]; +}stru_mms_s_param_base; + + +// 定值仅支持一个参数 +typedef struct +{ + stru_mms_s_param_base base; + void *data; +}stru_mms_s_setting; + +typedef void (*mms_s_setting_cb)(stru_mms_s_setting *p_setting, const char *p_data); + +// 参数支持多个值 +typedef struct +{ + stru_mms_s_param_base base; + uint8_t param_num; + void *data[MMS_S_PARAM_MAX]; +}stru_mms_s_param; + +typedef void (*mms_s_param_cb)(stru_mms_s_param *p_param, const char *p_data, int setting_zone); + + +typedef struct +{ + char saddr[MMS_S_STR_LEN]; + char desc[MMS_S_STR_LEN]; + uint8_t ctrl_model; +}stru_mms_s_control; + +typedef void (*mms_s_control_cb)(stru_mms_s_control *p_control, uint8_t state); + +int mms_s_init(const char* icd_path, int port); +void mms_s_dbg_switch(bool on); + +int mms_s_control_register(stru_mms_s_control *p_control, uint16_t num, mms_s_control_cb cb); +int mms_s_setting_register(stru_mms_s_setting *p_setting, uint16_t num, mms_s_setting_cb cb); +int mms_s_param_register(stru_mms_s_param *p_param, uint16_t num, mms_s_param_cb cb); +int mms_s_file_path_set(const char* file_path); + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + diff --git a/release/inc/mySystem.h b/release/inc/mySystem.h index eb2d52a..33ad8a1 100644 --- a/release/inc/mySystem.h +++ b/release/inc/mySystem.h @@ -61,6 +61,7 @@ typedef enum ENUM_APP_SELF_PTL, // icp67应用 ENUM_APP_WEB_SERVER, // web服务器应用 ENUM_APP_IEC61850M, // iec61850m应用 + ENUM_APP_IEC61850S, // iec61850s应用 ENUM_APP_MAX }enum_app; @@ -225,6 +226,13 @@ extern int app_iec61850m_init1(void *arg); extern int app_iec61850m_init2(void *arg); extern void *app_iec61850m(void *arg); +// iec61850s应用初始化与线程函数声明 +extern int app_iec61850s_init1(void *arg); +extern int app_iec61850s_init2(void *arg); +extern void *app_iec61850s(void *arg); + + + // icp67线程设置通道类型 void self_ptl_set_interface(uint32_t interface); @@ -343,13 +351,13 @@ int dc_signal_out(const std::string &saddr, const std::string &desc, uint8_t dat int dc_signal_out_with_callback(const std::string &saddr, const std::string &desc, uint8_t data_type, void *p_data, out_signal_change_cb cb); // 数据中心in信号注册并链接out信号接口 -int dc_signal_in(const std::string &saddr, const std::string &desc, const std::string &link_saddr, uint8_t data_type, void **p_data); +int dc_signal_in(const std::string &saddr, const std::string &desc, const std::string &link_saddr, void **p_data); -int dc_signal_in_with_callback(const std::string &saddr, const std::string &desc, const std::string &link_saddr, uint8_t data_type, void **p_data, out_signal_change_cb cb); +int dc_signal_in_with_callback(const std::string &saddr, const std::string &desc, const std::string &link_saddr, void **p_data, out_signal_change_cb cb); int dc_signal_ao(const std::string &saddr, const std::string &desc, uint8_t data_type, const stru_signal_param ¶m, uint8_t ctrl_type, void *p_data, void *p_default_data, signal_change_cb cb); -int dc_signal_ao_link_with_callback(const std::string &saddr, uint8_t data_type, void **p_data, signal_change_cb cb); +int dc_signal_ao_link_with_callback(const std::string &saddr, void **p_data, signal_change_cb cb); int dc_signal_ao_set_val(const std::string &saddr, SIGNAL_CTRL_STEP step, stru_signal_ctrl &ctrl, void *p_data); @@ -359,7 +367,7 @@ int dc_signal_ao_set_val_without_check(const std::string &saddr, uint8_t data_ty int dc_signal_param(const std::string &saddr, const std::string &desc, uint8_t data_type, const stru_signal_param ¶m, uint8_t ctrl_type, std::vector &vec_p_data, std::vector &vec_p_default_data, signal_change_cb cb); // 数据中心参数链接信号接口 -int dc_signal_param_link_with_callback(const std::string &saddr, uint8_t data_type, std::vector &vec_p_data, signal_change_cb cb); +int dc_signal_param_link_with_callback(const std::string &saddr, std::vector &vec_p_data, signal_change_cb cb); // 数据中心参数设置接口 int dc_signal_param_set_val(const std::string &saddr, SIGNAL_CTRL_STEP step, stru_signal_ctrl &ctrl, uint8_t setting_zone, void *p_data); @@ -370,7 +378,7 @@ int dc_signal_param_set_val_without_check(const std::string &saddr, uint8_t data int dc_signal_yk(const std::string &saddr, const std::string &desc, uint8_t data_type, uint8_t ctrl_type, void *p_data, signal_change_cb cb); // 数据中心遥控信号链接接口 -int dc_signal_yk_link_with_callback(const std::string &saddr, uint8_t data_type, void **p_data, signal_change_cb cb); +int dc_signal_yk_link_with_callback(const std::string &saddr, void **p_data, signal_change_cb cb); // 数据中心遥控控制接口(校验前置,调用前需先调 dc_yk_ctrl_valid) int dc_signal_yk_set_status(const std::string &saddr, SIGNAL_CTRL_STEP step, stru_signal_ctrl &ctrl, void *p_data); @@ -381,7 +389,7 @@ int dc_get_out_signal_info(const std::string &saddr, std::string &desc, uint8_t // 数据中心获取in信号信息接口 int dc_get_in_signal_info(const std::string &saddr, std::string &desc, uint8_t &data_type, std::vector &vec_p_data); -int dc_get_ao_siganl_info(const std::string &saddr, std::string &desc, uint8_t &data_type, stru_signal_param ¶m, uint8_t &ctrl_type, std::vector &vec_p_data, std::vector &vec_p_default_data); +int dc_get_ao_signal_info(const std::string &saddr, std::string &desc, uint8_t &data_type, stru_signal_param ¶m, uint8_t &ctrl_type, std::vector &vec_p_data, std::vector &vec_p_default_data); // 数据中心获取参数信号信息接口 int dc_get_param_signal_info(const std::string &saddr, std::string &desc, uint8_t &data_type, stru_signal_param ¶m, uint8_t &ctrl_type, std::vector &vec_p_data, std::vector &vec_p_default_data); diff --git a/release/src/protocol/libmms_s/makefile b/release/src/protocol/libmms_s/makefile new file mode 100644 index 0000000..f7e7123 --- /dev/null +++ b/release/src/protocol/libmms_s/makefile @@ -0,0 +1,87 @@ +# 包含外部Makefile +include ./../../../linux.mk + +ProjectName := libmms_s + + +DIR := $(realpath $(CURDIR)/..) +LAST_DIR := $(notdir $(DIR)) + + +# 静态库文件目标 +OutputFile := $(LIB_REL)/$(ProjectName).a +ArchiveCommand := ar rcs # 静态库打包命令 + +MakeDirCommand := mkdir -p + +OBJ := $(DIR)/$(ProjectName)/obj +SRC := $(SRC_ROOT_DIR)/$(LAST_DIR)/$(ProjectName)/src +INC := $(SRC_ROOT_DIR)/$(LAST_DIR)/$(ProjectName)/inc +INC += $(REL_INC)/iec61850_inc + +# print_dir: +# @echo "Shell层面打印DIR: $(SRC_ROOT_DIR) $(OBJ) $(SRC) $(INC) " + +# 定义源文件和对象文件 +SOURCES := $(wildcard $(SRC)/*.c) $(wildcard $(SRC)/*.cpp) +OBJECTS := $(patsubst $(SRC)/%.c, $(OBJ)/%.o,$(filter %.c,$(SOURCES))) +OBJECTSCPP := $(patsubst $(SRC)/%.cpp, $(OBJ)/%.o,$(filter %.cpp,$(SOURCES))) + +ALL_OBJECTS := $(OBJECTS) $(OBJECTSCPP) + +# 编译选项 +APP_C_FLAGS := $(C_FLAGS) +APP_C_FLAGS += -I $(INC) -g + +APP_C_FLAGS += -O0 + +# 伪目标 +.PHONY : all clean veryclean rebuild + +# 默认目标 +all: $(OutputFile) + +# 构建静态库 +$(OutputFile): $(ALL_OBJECTS) + @$(MakeDirCommand) $(dir $@) + $(ArchiveCommand) $@ $^ + @echo "Static library built: $@" + +# 重新构建 +rebuild: veryclean all + +# 清理 +clean: + rm -f $(OBJ)/*.o + rm -f $(OBJ)/*.d + rm -f $(OutputFile) + rm -f ./out/*.* + +# 非常彻底的清理 +veryclean: clean + rm -f ./out/$(OutputFile) + rm -f $(SRC)/*.bak + rm -f $(INC)/*.bak + +# C对象文件规则 +$(OBJECTS): $(OBJ)/%.o: $(SRC)/%.c + @mkdir -p $(dir $@) + $(CC) $(APP_C_FLAGS) -o $@ -c $< + +# C++对象文件规则 +$(OBJECTSCPP): $(OBJ)/%.o: $(SRC)/%.cpp + @mkdir -p $(dir $@) + $(CPP) $(APP_C_FLAGS) -o $@ -c $< + +# 可选:生成依赖文件(用于自动重新编译) +# -include $(ALL_OBJECTS:.o=.d) + +# C依赖文件规则 +$(OBJ)/%.d: $(SRC)/%.c + @mkdir -p $(dir $@) + $(CC) $(APP_C_FLAGS) -MM -MT '$(OBJ)/$*.o' $< > $@ + +# C++依赖文件规则 +$(OBJ)/%.d: $(SRC)/%.cpp + @mkdir -p $(dir $@) + $(CPP) $(APP_C_FLAGS) -MM -MT '$(OBJ)/$*.o' $< > $@ \ No newline at end of file diff --git a/release/src/protocol/makefile b/release/src/protocol/makefile index 84ed952..aa27fe1 100644 --- a/release/src/protocol/makefile +++ b/release/src/protocol/makefile @@ -5,6 +5,7 @@ SUBDIRS += ./libicp67 SUBDIRS += ./libmms_m +SUBDIRS += ./libmms_s SUBDIRS += ./libmoongoose diff --git a/release/src/system/RTU/makefile b/release/src/system/RTU/makefile index 63c6325..51f20d5 100644 --- a/release/src/system/RTU/makefile +++ b/release/src/system/RTU/makefile @@ -15,8 +15,8 @@ MakeDirCommand := mkdir -p # 静态库链接(注意顺序很重要,被依赖的库放在后面) # Libs := -lcom_channel -lcom_scan -liec -lself_ptl -lfunc -ltask -lcomm -lshell -lpthread -Libs := -lcom_channel -lcom_scan -liec -liec61850m -lself_ptl -lweb_server -ldatacenter -Libs += -l60870 -licp67 -lmms_m -lmoongoose +Libs := -lcom_channel -lcom_scan -liec -liec61850m -liec61850s -lself_ptl -lweb_server -ldatacenter +Libs += -l60870 -licp67 -lmms_m -lmms_s -lmoongoose Libs += -liec61850 Libs += -lmy_xxhash -lcmd -lmd5 -lxml -lcJSON -lcomm -ltask -lfunc Libs += -lpthread diff --git a/release/src/system/libiec61850s/makefile b/release/src/system/libiec61850s/makefile new file mode 100644 index 0000000..b78f98b --- /dev/null +++ b/release/src/system/libiec61850s/makefile @@ -0,0 +1,85 @@ +# 包含外部Makefile +include ./../../../linux.mk + +ProjectName := libiec61850s + +DIR := $(realpath $(CURDIR)/..) +LAST_DIR := $(notdir $(DIR)) + + +# 静态库文件目标 +OutputFile := $(LIB_REL)/$(ProjectName).a +ArchiveCommand := ar rcs # 静态库打包命令 + +MakeDirCommand := mkdir -p + +OBJ := $(DIR)/$(ProjectName)/obj +SRC := $(SRC_ROOT_DIR)/$(LAST_DIR)/$(ProjectName)/src +INC := $(SRC_ROOT_DIR)/$(LAST_DIR)/$(ProjectName)/inc +INC += $(REL_INC)/iec61850_inc +# print_dir: +# @echo "Shell层面打印DIR: $(SRC_ROOT_DIR) $(OBJ) $(SRC) $(INC) " + +# 定义源文件和对象文件 +SOURCES := $(wildcard $(SRC)/*.c) $(wildcard $(SRC)/*.cpp) +OBJECTS := $(patsubst $(SRC)/%.c, $(OBJ)/%.o,$(filter %.c,$(SOURCES))) +OBJECTSCPP := $(patsubst $(SRC)/%.cpp, $(OBJ)/%.o,$(filter %.cpp,$(SOURCES))) + +ALL_OBJECTS := $(OBJECTS) $(OBJECTSCPP) + +# 编译选项 +APP_C_FLAGS := $(C_FLAGS) +APP_C_FLAGS += -I $(INC) -g + +APP_C_FLAGS += -O0 + +# 伪目标 +.PHONY : all clean veryclean rebuild + +# 默认目标 +all: $(OutputFile) + +# 构建静态库 +$(OutputFile): $(ALL_OBJECTS) + @$(MakeDirCommand) $(dir $@) + $(ArchiveCommand) $@ $^ + @echo "Static library built: $@" + +# 重新构建 +rebuild: veryclean all + +# 清理 +clean: + rm -f $(OBJ)/*.o + rm -f $(OBJ)/*.d + rm -f $(OutputFile) + rm -f ./out/*.* + +# 非常彻底的清理 +veryclean: clean + rm -f ./out/$(OutputFile) + rm -f $(SRC)/*.bak + rm -f $(INC)/*.bak + +# C对象文件规则 +$(OBJECTS): $(OBJ)/%.o: $(SRC)/%.c + @mkdir -p $(dir $@) + $(CC) $(APP_C_FLAGS) -o $@ -c $< + +# C++对象文件规则 +$(OBJECTSCPP): $(OBJ)/%.o: $(SRC)/%.cpp + @mkdir -p $(dir $@) + $(CPP) $(APP_C_FLAGS) -o $@ -c $< + +# 可选:生成依赖文件(用于自动重新编译) +# -include $(ALL_OBJECTS:.o=.d) + +# C依赖文件规则 +$(OBJ)/%.d: $(SRC)/%.c + @mkdir -p $(dir $@) + $(CC) $(APP_C_FLAGS) -MM -MT '$(OBJ)/$*.o' $< > $@ + +# C++依赖文件规则 +$(OBJ)/%.d: $(SRC)/%.cpp + @mkdir -p $(dir $@) + $(CPP) $(APP_C_FLAGS) -MM -MT '$(OBJ)/$*.o' $< > $@ \ No newline at end of file diff --git a/release/src/system/makefile b/release/src/system/makefile index 0268bd3..fe5a88e 100644 --- a/release/src/system/makefile +++ b/release/src/system/makefile @@ -8,6 +8,7 @@ SUBDIRS += ./libcom_scan SUBDIRS += ./libdatacenter SUBDIRS += ./libiec SUBDIRS += ./libiec61850m +SUBDIRS += ./libiec61850s SUBDIRS += ./libself_ptl SUBDIRS += ./libweb_server diff --git a/src/protocol/libmms_s/inc/mms_s.h b/src/protocol/libmms_s/inc/mms_s.h new file mode 100644 index 0000000..ad114ca --- /dev/null +++ b/src/protocol/libmms_s/inc/mms_s.h @@ -0,0 +1,122 @@ +/** + * @file mms_s.h + * @brief libmms_s 核心头文件,包含日志宏、全局接口声明 + * + * @details 本文件定义了: + * - 终端彩色打印宏(COLOR_RESET / COLOR_RED / COLOR_WHITE) + * - 带时间戳的日志宏(LOG / LOG_I / LOG_E) + * - LOCAL 静态函数宏 + * - IED 服务器全局访问接口 + * - MMS 数据类型与自定义类型之间的字符串转换函数 + */ + +#pragma once + +#include +#include +#include +#include +#include +#include "mms_s_icd.h" + +/* 终端颜色控制 —— 重置 */ +#ifndef COLOR_RESET +#define COLOR_RESET "\033[0m" +#endif + +/* 终端颜色控制 —— 红色(错误信息) */ +#ifndef COLOR_RED +#define COLOR_RED "\033[31m" +#endif + +/* 终端颜色控制 —— 白色(普通信息) */ +#ifndef COLOR_WHITE +#define COLOR_WHITE "\033[37m" +#endif + + +/* 获取当前时间字符串,格式:YYYY-MM-DD HH:MM:SS.mmm */ +#ifndef __CURRENT_TIME__ +#define __CURRENT_TIME__ \ + ({ \ + struct timeval __tv; \ + gettimeofday(&__tv, NULL); \ + struct tm *__tm = localtime(&__tv.tv_sec); \ + static char __buf[84]; \ + snprintf(__buf, sizeof(__buf), "%04d-%02d-%02d %02d:%02d:%02d.%03d", \ + __tm->tm_year + 1900, __tm->tm_mon + 1, __tm->tm_mday, \ + __tm->tm_hour, __tm->tm_min, __tm->tm_sec, (int)(__tv.tv_usec / 1000)); \ + __buf; \ + }) +#endif + +/* 从 __FILE__ 宏中提取不含路径的短文件名 */ +#ifndef __SHORT_FILE__ +#define __SHORT_FILE__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) +#endif + +/* + * 通用日志宏 + * @param color 终端颜色(COLOR_WHITE / COLOR_RED) + * @param level 日志级别字符串("INFO" / "ERROR") + * @param fmt 格式化字符串 + * @param ... 可变参数 + * 输出格式:[level] [时间: 文件名, 行号] 消息内容 + */ +#ifndef LOG +#define LOG(color, level, fmt, ...) \ + do{\ + printf("%s[%s] [%s: %s, %u] " fmt COLOR_RESET "\n", \ + color, level, __CURRENT_TIME__, __SHORT_FILE__, __LINE__, ##__VA_ARGS__); \ + }while (0) +#endif + +/* 信息级别日志(白色) */ +#ifndef LOG_I +#define LOG_I(fmt, ...) LOG(COLOR_WHITE, "INFO", fmt, ##__VA_ARGS__) +#endif + +/* 错误级别日志(红色) */ +#ifndef LOG_E +#define LOG_E(fmt, ...) LOG(COLOR_RED, "ERROR", fmt, ##__VA_ARGS__) +#endif + +/* 将函数声明为局部(static)的简便写法 */ +#ifndef LOCAL +#define LOCAL static +#endif + + +/** + * 获取全局 ICD 数据结构指针 + * @return stru_icd* ICD 数据结构指针,未初始化时返回 NULL + */ +stru_icd *mms_s_get_icd_ptr(); + +/** + * 获取全局 IED 服务器指针 + * @return IedServer IED 服务器指针,未初始化时返回 NULL + */ +IedServer mms_s_get_ied_server_ptr(); + +/** + * 获取调试开关状态 + * @return true 已开启调试,false 未开启 + */ +bool mms_s_dbg_get(); + +/** + * 将 MMS 类型数据转换为字符串(按 MMS 类型码转换) + * @param p_data 数据指针 + * @param type MMS 类型码(MMS_BOOLEAN / MMS_INTEGER / MMS_UNSIGNED / MMS_FLOAT / MMS_VISIBLE_STRING 等) + * @return 转换后的字符串,不支持的类型返回空串 + */ +std::string mms_s_get_string_by_mms_type(void *p_data, int type); + +/** + * 将数据转换为字符串(按自定义 DATA_TYPE_ 类型码转换) + * @param p_data 数据指针 + * @param type 自定义类型码(DATA_TYPE_B / DATA_TYPE_S32 / DATA_TYPE_F32 / DATA_TYPE_STR 等) + * @return 转换后的字符串,不支持的类型返回空串 + */ +std::string mms_s_get_string_by_type(void *p_data, int type); \ No newline at end of file diff --git a/src/protocol/libmms_s/inc/mms_s_control.h b/src/protocol/libmms_s/inc/mms_s_control.h new file mode 100644 index 0000000..97446f6 --- /dev/null +++ b/src/protocol/libmms_s/inc/mms_s_control.h @@ -0,0 +1,5 @@ +#pragma once + +#include "mms_s_icd.h" + +int control_init(IedServer server, stru_icd &icd); \ No newline at end of file diff --git a/src/protocol/libmms_s/inc/mms_s_file.h b/src/protocol/libmms_s/inc/mms_s_file.h new file mode 100644 index 0000000..2fd9665 --- /dev/null +++ b/src/protocol/libmms_s/inc/mms_s_file.h @@ -0,0 +1,6 @@ +#pragma once + +#include "mms_s.h" + +int file_init(IedServer server); + diff --git a/src/protocol/libmms_s/inc/mms_s_icd.h b/src/protocol/libmms_s/inc/mms_s_icd.h new file mode 100644 index 0000000..6a016e6 --- /dev/null +++ b/src/protocol/libmms_s/inc/mms_s_icd.h @@ -0,0 +1,269 @@ +#pragma once + +#include +#include +#include + +#include "iec61850_server.h" + + +typedef struct +{ + std::string desc; + std::string type; +}stru_DO; + +typedef struct +{ + std::string lnClass; + std::vector vec_do; + std::map map_do; // key:name +}stru_LNodeType; + + +typedef struct +{ + std::string bType; + std::string type; + std::string dchg; + std::string qchg; + std::string fc; + std::string text; +}stru_DA; + +typedef struct +{ + std::string cdc; + std::vector vec_da; + std::map map_da; // key:name + std::vector vec_sdo; + std::map map_sdo; // key:name +}stru_DOType; + + +typedef struct +{ + std::string bType; + std::string type; + std::string fc; + std::string dchg; + std::string qchg; +}stru_BDA; + +typedef struct +{ + std::vector vec_bda; + std::map map_bda; // key:name +}stru_DAType; + + +typedef struct +{ + std::vector vec_ord; + std::map map_enumVal; // key:ord +}stru_EnumType; + + + + + + +typedef struct _all_DA +{ + DataAttribute *DA; + std::string bType; + std::string type; + std::string fc; + std::string dchg; + std::string qchg; + std::string text; + + std::string sAddr; + std::string val; + std::map map_all_da; // key:name +}stru_all_DA; + + + +typedef struct _all_DO +{ + DataObject *DO; + std::map map_all_sdo; // key:name + std::map map_all_da; // key:name +}stru_all_DO; + + +typedef struct _DAI +{ + std::string sAddr; + std::string val; +}stru_DAI; + + +typedef struct _SDI +{ + std::vector vec_sdI; + std::map map_sdI; // key:name + std::vector vec_daI; + std::map map_daI; // key:name +}stru_SDI; + +typedef struct _DOI +{ + std::string desc; + std::vector vec_sdI; + std::map map_sdI; // key:name + std::vector vec_daI; + std::map map_daI; // key:name +}stru_DOI; + +typedef struct +{ + std::string ldevice_inst; + std::string ln_type; + std::string ln_class; + std::string ln_inst; + std::string ln_prefix; + std::string do_name; + stru_all_DO *p_all_do; +}stru_contorl_DO; + + +typedef struct +{ + LogicalNode *LN; + std::string lnType; + std::string lnClass; + std::string desc; + std::string inst; + std::string prefix; + std::vector vec_doI; + std::map map_doI; // key:name + std::map map_all_do; // key:name +}stru_LN; + +typedef struct +{ + DataSetEntry *fcda; + std::string ldInst; + std::string lnClass; + std::string lnInst; + std::string prefix; + std::string doName; + std::string daName; + std::string fc; +}stru_FCDA; + + +typedef struct +{ + DataSet *dataset; + std::string desc; + std::vector vec_fcda; +}stru_DataSet; + +typedef struct +{ + bool dchg; + bool qchg; + bool dupd; + bool period; +}stru_TrgOps; + +typedef struct +{ + bool seqNum; + bool timeStamp; + bool dataSet; + bool reasonCode; + bool dataRef; + bool entryID; + bool configRef; +}stru_OptFields; + +typedef struct +{ + ReportControlBlock *Rcb; + std::string datSet; + int intgPd; + std::string rptID; + int confRev; + bool buffered; + int bufTime; + stru_TrgOps trgOps; + stru_OptFields optFields; + int RptEnabled_max; +}stru_ReportControl; + +typedef struct +{ + uint8_t actSG; + uint8_t numOfSGs; +}stru_SettingControl; + +typedef struct +{ + LogicalNode *LLN0; + std::string lnType; + std::string lnClass; + std::vector vec_dataset; + std::map map_dataset; // key:name + std::vector vec_reportControl; + std::map map_reportControl; // key:name + std::vector vec_doI; + std::map map_doI; // key:name + std::map map_all_do; // key:name + stru_SettingControl settingControl; +}stru_LN0; + +typedef struct +{ + LogicalDevice *Ldevice; + SettingGroupControlBlock* sgcb; + stru_LN0 ln0; + std::vector vec_ln; +}stru_LDevice; + +typedef struct +{ + ModelNode *node; +}stru_saddr_point; + +typedef struct +{ + DataAttribute *DA; + DataAttributeType type; + std::string str_val; + int val; +}stru_setting_info; + +typedef struct +{ + IedModel *model; + std::string name; + std::string desc; + std::string type; + std::vector vec_ldevice; + std::map map_ldevice; // key:inst + std::vector vec_control_do; + std::vector vec_saddr; + std::map map_saddr_point; // key:saddr + std::map map_setting_info; // key:name +}stru_ied; + +typedef struct +{ + stru_ied ied; + std::vector vec_lnType; + std::map map_lnType; // key:id + std::vector vec_doType; + std::map map_doType; // key:id + std::vector vec_daType; + std::map map_daType; // key:id + std::vector vec_enumType; + std::map map_enumType; // key:id +}stru_icd; + + +stru_icd *icd_parse(const char *icd_path); +void icd_show(stru_icd &icd); \ No newline at end of file diff --git a/src/protocol/libmms_s/inc/mms_s_model.h b/src/protocol/libmms_s/inc/mms_s_model.h new file mode 100644 index 0000000..ff75a44 --- /dev/null +++ b/src/protocol/libmms_s/inc/mms_s_model.h @@ -0,0 +1,6 @@ +#pragma once + +#include "iec61850_server.h" +#include "mms_s_icd.h" + +int model_init(stru_icd &icd); diff --git a/src/protocol/libmms_s/inc/mms_s_param.h b/src/protocol/libmms_s/inc/mms_s_param.h new file mode 100644 index 0000000..4ab563a --- /dev/null +++ b/src/protocol/libmms_s/inc/mms_s_param.h @@ -0,0 +1,5 @@ +#pragma once + +#include "mms_s.h" + +int param_init(IedServer server, stru_icd &icd); diff --git a/src/protocol/libmms_s/inc/mms_s_setting.h b/src/protocol/libmms_s/inc/mms_s_setting.h new file mode 100644 index 0000000..967fc03 --- /dev/null +++ b/src/protocol/libmms_s/inc/mms_s_setting.h @@ -0,0 +1,28 @@ +/** + * @file mms_s_setting.h + * @brief IEC 61850 定值(SP)管理初始化接口 + * + * @details 定值(Setting,FC=SP)区别于参数(FC=SG/SE),定值不参与定值组切换。 + * 本模块负责: + * - 将外部注册的定值数据初始化到 SP 数据属性 + * - 安装写访问回调,接收客户端下发的定值修改 + * - 写操作时进行范围检查和步长校验 + * - 设置 SP 的默认写权限为 DENY,仅注册的 sAddr 允许写入 + */ + +#pragma once + +#include "mms_s.h" + +/** + * 初始化定值管理功能 + * + * 1. 将注册的定值初始值写入对应 SP DA + * 2. 设置 SP 写权限为 ACCESS_POLICY_DENY + * 3. 为每个注册 sAddr 的 DA 安装写访问处理器(writeAccessHandler) + * + * @param server IED 服务器指针 + * @param icd ICD 数据结构引用 + * @return 0 成功,-1 失败 + */ +int setting_init(IedServer server, stru_icd &icd); \ No newline at end of file diff --git a/src/protocol/libmms_s/inc/mms_s_value.h b/src/protocol/libmms_s/inc/mms_s_value.h new file mode 100644 index 0000000..28226a5 --- /dev/null +++ b/src/protocol/libmms_s/inc/mms_s_value.h @@ -0,0 +1,7 @@ +#pragma once + +#include "mms_s_icd.h" +#include "mms_s.h" + +void mms_s_values_init(); +void mms_s_values_update(); diff --git a/src/protocol/libmms_s/src/mms_s.cpp b/src/protocol/libmms_s/src/mms_s.cpp new file mode 100644 index 0000000..9c625c9 --- /dev/null +++ b/src/protocol/libmms_s/src/mms_s.cpp @@ -0,0 +1,219 @@ +#include + + +#include "myMms_s.h" +#include "mms_s.h" +#include "mms_s_model.h" +#include "mms_s_value.h" +#include "mms_s_control.h" +#include "mms_s_param.h" +#include "mms_s_setting.h" +#include "mms_s_file.h" + +#include "hal_thread.h" + +LOCAL int g_running = 0; + +LOCAL stru_icd *gp_icd = NULL; +LOCAL IedServer gp_iedServer = NULL; +LOCAL bool g_dbg_switch = false; + +LOCAL void sigint_handler(int signum) +{ + g_running = 0; +} + +stru_icd *mms_s_get_icd_ptr() +{ + return gp_icd; +} + +IedServer mms_s_get_ied_server_ptr() +{ + return gp_iedServer; +} + +void mms_s_dbg_switch(bool on) +{ + g_dbg_switch = on; +} + +bool mms_s_dbg_get() +{ + return g_dbg_switch; +} + + + +std::string mms_s_get_string_by_mms_type(void *p_data, int type) +{ + if(nullptr == p_data) + { + LOG_E("p_data is null"); + return ""; + } + + switch(type) + { + case MMS_BOOLEAN: + return (*(uint8_t *)p_data) ? "true" : "false"; + case MMS_INTEGER: + return std::to_string(*(int *)p_data); + case MMS_UNSIGNED: + return std::to_string(*(uint32_t *)p_data); + case MMS_FLOAT: + return std::to_string(*(float *)p_data); + case MMS_VISIBLE_STRING: + case MMS_STRING: + return std::string((char *)p_data); + default: + LOG_E("type %d is not supported", type); + return ""; + } +} + +std::string mms_s_get_string_by_type(void *p_data, int type) +{ + if(nullptr == p_data) + { + LOG_E("p_data is null"); + return ""; + } + + switch(type) + { + case DATA_TYPE_B: + return (*(uint8_t *)p_data) ? "true" : "false"; + case DATA_TYPE_S8: + return std::to_string(*(int8_t *)p_data); + case DATA_TYPE_U8: + return std::to_string(*(uint8_t *)p_data); + case DATA_TYPE_S16: + return std::to_string(*(int16_t *)p_data); + case DATA_TYPE_U16: + return std::to_string(*(uint16_t *)p_data); + case DATA_TYPE_S32: + return std::to_string(*(int32_t *)p_data); + case DATA_TYPE_U32: + return std::to_string(*(uint32_t *)p_data); + case DATA_TYPE_L64: + return std::to_string(*(int64_t *)p_data); + case DATA_TYPE_UL64: + return std::to_string(*(uint64_t *)p_data); + case DATA_TYPE_F32: + return std::to_string(*(float *)p_data); + case DATA_TYPE_D64: + return std::to_string(*(double *)p_data); + case DATA_TYPE_C1: + return std::string((char *)p_data, 1); + case DATA_TYPE_C8: + return std::string((char *)p_data, 8); + case DATA_TYPE_C32: + return std::string((char *)p_data, 32); + case DATA_TYPE_C64: + return std::string((char *)p_data, 64); + case DATA_TYPE_C128: + case DATA_TYPE_STR: + return std::string((char *)p_data, 128); + default: + LOG_E("type %d is not supported", type); + return ""; + } +} + + +LOCAL void *mms_s_run_task(void *parameter) +{ + IedModel *iedModel = (IedModel *)parameter; + while(g_running) + { + IedServer_lockDataModel(gp_iedServer); + + IedServer_unlockDataModel(gp_iedServer); + + + + Thread_sleep(100); + } + + IedServer_stop(gp_iedServer); + + /* Cleanup - free all resources */ + IedServer_destroy(gp_iedServer); + + /* destroy dynamic data model */ + IedModel_destroy(iedModel); + + return NULL; +} + +int mms_s_init(const char *icd_path, int port) +{ + if(nullptr == icd_path) + { + LOG_E("icd_path is null"); + return -1; + } + + if(nullptr == (gp_icd = icd_parse(icd_path))) + { + LOG_E("parse icd failed"); + return -1; + } + + if(mms_s_dbg_get()) + { + icd_show(*gp_icd); + } + + if(0 != model_init(*gp_icd)) + { + LOG_E("model_init failed"); + return -1; + } + + IedModel *iedModel = gp_icd->ied.model; + if(nullptr == iedModel) + { + LOG_E("iedModel is null"); + return -1; + } + + IedServerConfig serverConfig = IedServerConfig_create(); + IedServerConfig_enableResvTmsForSGCB(serverConfig, true); + + gp_iedServer = IedServer_createWithConfig(iedModel, NULL, serverConfig); + if(nullptr == gp_iedServer) + { + LOG_E("IedServer_createWithConfig failed"); + return -1; + } + + IedServer_setTimeQuality(gp_iedServer, true, false, false, 10); + IedServerConfig_destroy(serverConfig); + + control_init(gp_iedServer, *gp_icd); + param_init(gp_iedServer, *gp_icd); + + file_init(gp_iedServer); + + IedServer_start(gp_iedServer, port); + + setting_init(gp_iedServer, *gp_icd); + + if(!IedServer_isRunning(gp_iedServer)) + { + LOG_E("IedServer_isRunning failed"); + IedServer_destroy(gp_iedServer); + gp_iedServer = NULL; + return -1; + } + + g_running = 1; + signal(SIGINT, sigint_handler); + + Thread mms_s_thread = Thread_create(mms_s_run_task, iedModel, false); + Thread_start(mms_s_thread); + + return 0; +} \ No newline at end of file diff --git a/src/protocol/libmms_s/src/mms_s_control.cpp b/src/protocol/libmms_s/src/mms_s_control.cpp new file mode 100644 index 0000000..f7e74b3 --- /dev/null +++ b/src/protocol/libmms_s/src/mms_s_control.cpp @@ -0,0 +1,251 @@ +#include "hal_time.h" + +#include "myMms_s.h" +#include "mms_s_control.h" +#include "mms_s.h" + +LOCAL std::vector vec_control; +LOCAL mms_s_control_cb cb_control = NULL; + +LOCAL ControlHandlerResult control_handler(ControlAction action, void* parameter, MmsValue* value, bool test) +{ + uint64_t timestamp = Hal_getTimeInMs(); + + LOG_I("control handler called"); + LOG_I(" ctlNum: %i", ControlAction_getCtlNum(action)); + + ClientConnection clientCon = ControlAction_getClientConnection(action); + + if (clientCon) { + LOG_I("Control from client %s", ClientConnection_getPeerAddress(clientCon)); + } + else { + LOG_E("clientCon == NULL!"); + } + + IedServer server = NULL; + stru_icd *p_icd = NULL; + + if(NULL == (server = mms_s_get_ied_server_ptr())) + { + LOG_E("server is NULL"); + return CONTROL_RESULT_FAILED; + } + + if(NULL == (p_icd = mms_s_get_icd_ptr())) + { + LOG_E("p_icd is NULL"); + return CONTROL_RESULT_FAILED; + } + + LOG_I("control handler called value: %s", MmsValue_getBoolean(value) ? "true" : "false"); + + int ret = 0; + + for(std::vector::iterator it = p_icd->ied.vec_control_do.begin(); it != p_icd->ied.vec_control_do.end(); ++it) + { + std::string ln_name = it->ln_prefix + it->ln_class + it->ln_inst; + + if(NULL == it->p_all_do) + { + LOG_E("ld:%s, ln:%s, do:%s, control all_DO is NULL", it->ldevice_inst.c_str(), ln_name.c_str(), it->do_name.c_str()); + continue; + } + + if(NULL == it->p_all_do->DO) + { + LOG_E("ld:%s, ln:%s, do:%s, control DO is NULL", it->ldevice_inst.c_str(), ln_name.c_str(), it->do_name.c_str()); + continue; + } + + if(NULL == it->p_all_do) + { + LOG_E("ld:%s, ln:%s, do:%s, control all_DO is NULL", it->ldevice_inst.c_str(), ln_name.c_str(), it->do_name.c_str()); + continue; + } + + ret = 0; + + if(it->p_all_do->DO == parameter) + { + + if(it->p_all_do->map_all_da.find("t") != it->p_all_do->map_all_da.end() && it->p_all_do->map_all_da.find("stVal") != it->p_all_do->map_all_da.end()) + { + ret = 1; + IedServer_updateUTCTimeAttributeValue(server, it->p_all_do->map_all_da["t"]->DA, timestamp); + + DataAttribute *stVal = it->p_all_do->map_all_da["stVal"]->DA; + std::string saddr = it->p_all_do->map_all_da["stVal"]->DA->sAddr; + + for(std::vector::iterator it_control = vec_control.begin(); it_control != vec_control.end(); ++it_control) + { + if(it_control->saddr == saddr) + { + if(NULL != cb_control) + { + cb_control(&*it_control, MmsValue_getBoolean(value) ? 1 : 0); + } + } + } + + if(stVal->type == IEC61850_BOOLEAN) + { + IedServer_updateAttributeValue(server, stVal, value); + } + else if(stVal->type == IEC61850_GENERIC_BITSTRING) + { + Dbpos pos = MmsValue_getBoolean(value) == true ? DBPOS_ON : DBPOS_OFF; + IedServer_updateDbposValue(server, stVal, pos); + + + LOG_I("da %s-%s, pos %d", stVal->parent->name, stVal->name, pos); + } + else + { + ret = 0; + } + } + + if(ret == 1) + { + LOG_I("ld:%s, ln:%s, do:%s, control success", it->ldevice_inst.c_str(), ln_name.c_str(), it->do_name.c_str()); + } + else + { + LOG_E("ld:%s, ln:%s, do:%s, control failed", it->ldevice_inst.c_str(), ln_name.c_str(), it->do_name.c_str()); + } + + break; + } + } + + return ret == 1 ? CONTROL_RESULT_OK : CONTROL_RESULT_FAILED; +} + + +LOCAL CheckHandlerResult check_handler(ControlAction action, void* parameter, MmsValue* ctlVal, bool test, bool interlockCheck) +{ + ClientConnection clientCon = ControlAction_getClientConnection(action); + + if (clientCon) { + LOG_I("Control from client %s\n", ClientConnection_getPeerAddress(clientCon)); + } + else { + LOG_E("clientCon == NULL\n"); + } + + if (ControlAction_isSelect(action)) + LOG_I("check handler called by select command!\n"); + else + LOG_I("check handler called by operate command!\n"); + + if (interlockCheck) + LOG_I(" with interlock check bit set!\n"); + + LOG_I(" ctlNum: %i\n", ControlAction_getCtlNum(action)); + + IedServer server = NULL; + stru_icd *p_icd = NULL; + + if(NULL == (server = mms_s_get_ied_server_ptr())) + { + LOG_E("server is NULL"); + return CONTROL_HARDWARE_FAULT; + } + + if(NULL == (p_icd = mms_s_get_icd_ptr())) + { + LOG_E("p_icd is NULL"); + return CONTROL_HARDWARE_FAULT; + } + + for(std::vector::iterator it = p_icd->ied.vec_control_do.begin(); it != p_icd->ied.vec_control_do.end(); ++it) + { + std::string ln_name = it->ln_prefix + it->ln_class + it->ln_inst; + + if(NULL == it->p_all_do) + { + LOG_E("ld:%s, ln:%s, do:%s, control all_DO is NULL", it->ldevice_inst.c_str(), ln_name.c_str(), it->do_name.c_str()); + continue; + } + + if(NULL == it->p_all_do->DO) + { + LOG_E("ld:%s, ln:%s, do:%s, control DO is NULL", it->ldevice_inst.c_str(), ln_name.c_str(), it->do_name.c_str()); + continue; + } + + if(it->p_all_do->DO == parameter) + { + LOG_I("return CONTROL_ACCEPTED"); + return CONTROL_ACCEPTED; + } + } + + + LOG_E("return CONTROL_OBJECT_UNDEFINED"); + return CONTROL_OBJECT_UNDEFINED; +} + +int mms_s_control_register(stru_mms_s_control *p_control, uint16_t num, mms_s_control_cb cb) +{ + if(NULL == p_control || num == 0) + { + LOG_E("p_control is NULL or num is 0"); + return -1; + } + + vec_control.clear(); + vec_control.reserve(num); + + for(uint16_t i = 0; i < num; ++i) + { + vec_control.push_back(p_control[i]); + } + + if(NULL != cb) + { + cb_control = cb; + } + return 0; +} + +int control_init(IedServer server, stru_icd &icd) +{ + if(NULL == server) + { + LOG_E("server is NULL"); + return -1; + } + + if(vec_control.empty()) + { + LOG_E("vec_control is empty"); + return 0; + } + + for(std::vector::iterator it = icd.ied.vec_control_do.begin(); it != icd.ied.vec_control_do.end(); ++it) + { + std::string ln_name = it->ln_prefix + it->ln_class + it->ln_inst; + + if(NULL == it->p_all_do) + { + LOG_E("ld:%s, ln:%s, do:%s, control all_DO is NULL", it->ldevice_inst.c_str(), ln_name.c_str(), it->do_name.c_str()); + continue; + } + + if(NULL == it->p_all_do->DO) + { + LOG_E("ld:%s, ln:%s, do:%s, control DO is NULL", it->ldevice_inst.c_str(), ln_name.c_str(), it->do_name.c_str()); + continue; + } + + + IedServer_setControlHandler(server, it->p_all_do->DO, (ControlHandler)control_handler, it->p_all_do->DO); + + IedServer_setPerformCheckHandler(server, it->p_all_do->DO, check_handler, it->p_all_do->DO); + + } + + return 0; +} \ No newline at end of file diff --git a/src/protocol/libmms_s/src/mms_s_file.cpp b/src/protocol/libmms_s/src/mms_s_file.cpp new file mode 100644 index 0000000..cf1fe42 --- /dev/null +++ b/src/protocol/libmms_s/src/mms_s_file.cpp @@ -0,0 +1,70 @@ +#include "mms_s_file.h" + +LOCAL std::string g_file_path = ""; + + + +LOCAL void connectionHandler (IedServer self, ClientConnection connection, bool connected, void* parameter) +{ + if (connected) + LOG_I("Connection opened\n"); + else + LOG_I("Connection closed\n"); +} + +LOCAL MmsError fileAccessHandler (void* parameter, MmsServerConnection connection, MmsFileServiceType service, const char* localFilename, const char* otherFilename) +{ + LOG_I("fileAccessHandler: service = %i, local-file: %s other-file: %s\n", service, localFilename, otherFilename); + + /* Don't allow client to rename files */ + if (service == MMS_FILE_ACCESS_TYPE_RENAME) + return MMS_ERROR_FILE_FILE_ACCESS_DENIED; + + /* Don't allow client to delete file "IEDSERVER.BIN" */ + if (service == MMS_FILE_ACCESS_TYPE_DELETE) + { + if (strcmp(localFilename, "IEDSERVER.BIN") == 0) + return MMS_ERROR_FILE_FILE_ACCESS_DENIED; + } + + /* allow all other accesses */ + return MMS_ERROR_NONE; +} + +int mms_s_file_path_set(const char* file_path) +{ + if(nullptr == file_path) + { + LOG_I("file_path is NULL"); + return 0; + } + g_file_path = file_path; + + + LOG_I("file_path = %s", g_file_path.c_str()); + return 0; +} + +int file_init(IedServer server) +{ + if(g_file_path.empty()) + { + LOG_I("file_path is empty"); + return 0; + } + + MmsServer mmsServer = IedServer_getMmsServer(server); + if(nullptr == mmsServer) + { + LOG_E("mmsServer is NULL"); + return -1; + } + + IedServer_setFilestoreBasepath(server, g_file_path.c_str()); + + MmsServer_installFileAccessHandler(mmsServer, fileAccessHandler, NULL); + + IedServer_setConnectionIndicationHandler(server, (IedConnectionIndicationHandler) connectionHandler, NULL); + + return 0; +} \ No newline at end of file diff --git a/src/protocol/libmms_s/src/mms_s_icd.cpp b/src/protocol/libmms_s/src/mms_s_icd.cpp new file mode 100644 index 0000000..498e9c4 --- /dev/null +++ b/src/protocol/libmms_s/src/mms_s_icd.cpp @@ -0,0 +1,1346 @@ +#include "stdio.h" +#include "tinyxml2.h" + +#include "mms_s_icd.h" +#include "mms_s.h" + +// ICD文件中的节点名称 +LOCAL const char *ele_SCL = "SCL"; +LOCAL const char *ele_IED = "IED"; +LOCAL const char *ele_AccessPoint = "AccessPoint"; +LOCAL const char *ele_Server = "Server"; +LOCAL const char *ele_LDevice = "LDevice"; +LOCAL const char *ele_LN0 = "LN0"; +LOCAL const char *ele_LN = "LN"; +LOCAL const char *ele_DataSet = "DataSet"; +LOCAL const char *ele_FCDA = "FCDA"; +LOCAL const char *ele_ReportControl = "ReportControl"; +LOCAL const char *ele_SettingControl = "SettingControl"; +LOCAL const char *ele_TrgOps = "TrgOps"; +LOCAL const char *ele_OptFields = "OptFields"; +LOCAL const char *ele_RptEnabled = "RptEnabled"; +LOCAL const char *ele_LogControl = "LogControl"; +LOCAL const char *ele_Log = "Log"; +LOCAL const char *ele_LogRef = "LogRef"; +LOCAL const char *ele_GSEControl = "GSEControl"; +LOCAL const char *ele_DOI = "DOI"; +LOCAL const char *ele_SDI = "SDI"; +LOCAL const char *ele_DAI = "DAI"; +LOCAL const char *ele_Val = "Val"; + +LOCAL const char *ele_DataTypeTemplates = "DataTypeTemplates"; +LOCAL const char *ele_LNodeType = "LNodeType"; +LOCAL const char *ele_DO = "DO"; +LOCAL const char *ele_DOType = "DOType"; +LOCAL const char *ele_SDO = "SDO"; +LOCAL const char *ele_DA = "DA"; +LOCAL const char *ele_DAType = "DAType"; +LOCAL const char *ele_BDA = "BDA"; +LOCAL const char *ele_EnumType = "EnumType"; +LOCAL const char *ele_EnumVal = "EnumVal"; + +// ICD文件中的属性名称 +LOCAL const char *key_name = "name"; +LOCAL const char *key_desc = "desc"; +LOCAL const char *key_type = "type"; +LOCAL const char *key_inst = "inst"; +LOCAL const char *key_lnClass = "lnClass"; +LOCAL const char *key_lnType = "lnType"; +LOCAL const char *key_ldInst = "ldInst"; +LOCAL const char *key_lnInst = "lnInst"; +LOCAL const char *key_prefix = "prefix"; +LOCAL const char *key_doName = "doName"; +LOCAL const char *key_daName = "daName"; +LOCAL const char *key_fc = "fc"; +LOCAL const char *key_datSet = "datSet"; +LOCAL const char *key_intgPd = "intgPd"; +LOCAL const char *key_rptId = "rptId"; +LOCAL const char *key_confRev = "confRev"; +LOCAL const char *key_buffered = "buffered"; +LOCAL const char *key_bufTime = "bufTime"; +LOCAL const char *key_dchg = "dchg"; +LOCAL const char *key_qchg = "qchg"; +LOCAL const char *key_dupd = "dupd"; +LOCAL const char *key_period = "period"; +LOCAL const char *key_seqNum = "seqNum"; +LOCAL const char *key_dataSet = "dataSet"; +LOCAL const char *key_timeStamp = "timeStamp"; +LOCAL const char *key_reasonCode = "reasonCode"; +LOCAL const char *key_dataRef = "dataRef"; +LOCAL const char *key_entryID = "entryID"; +LOCAL const char *key_configRef = "configRef"; +LOCAL const char *key_max = "max"; +LOCAL const char *key_numOfSGs = "numOfSGs"; +LOCAL const char *key_actSG = "actSG"; +LOCAL const char *key_sAddr = "sAddr"; + +LOCAL const char *key_id = "id"; +LOCAL const char *key_cdc = "cdc"; +LOCAL const char *key_bType = "bType"; +LOCAL const char *key_ord = "ord"; + + + +/************************************************************************************************* */ + +using namespace tinyxml2; + +/* + * parse_DataSet - parse DataSet element + input: ele_ln0 - ln0 element + output: map_dataset - DataSet data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_DataSet(XMLElement *ele_ln0, std::map &map_dataset, std::vector &vec_dataset) +{ + if(nullptr == ele_ln0) + { + LOG_E("ele_ln0 is null"); + return -1; + } + + XMLElement *ele_dataset = nullptr; + for(ele_dataset = ele_ln0->FirstChildElement(ele_DataSet); ele_dataset; ele_dataset = ele_dataset->NextSiblingElement(ele_DataSet)) + { + std::string name = ele_dataset->Attribute(key_name) == nullptr ? "" : ele_dataset->Attribute(key_name); + if(name.empty()) + { + continue; + } + stru_DataSet dataset; + + dataset.dataset = nullptr; + dataset.desc = ele_dataset->Attribute(key_desc) == nullptr ? "" : ele_dataset->Attribute(key_desc); + + XMLElement *ele_fcda = nullptr; + for(ele_fcda = ele_dataset->FirstChildElement(ele_FCDA); ele_fcda; ele_fcda = ele_fcda->NextSiblingElement(ele_FCDA)) + { + stru_FCDA fcda; + + fcda.fcda = nullptr; + fcda.ldInst = ele_fcda->Attribute(key_ldInst) == nullptr ? "" : ele_fcda->Attribute(key_ldInst); + fcda.lnClass = ele_fcda->Attribute(key_lnClass) == nullptr ? "" : ele_fcda->Attribute(key_lnClass); + fcda.lnInst = ele_fcda->Attribute(key_lnInst) == nullptr ? "" : ele_fcda->Attribute(key_lnInst); + fcda.prefix = ele_fcda->Attribute(key_prefix) == nullptr ? "" : ele_fcda->Attribute(key_prefix); + fcda.doName = ele_fcda->Attribute(key_doName) == nullptr ? "" : ele_fcda->Attribute(key_doName); + fcda.daName = ele_fcda->Attribute(key_daName) == nullptr ? "" : ele_fcda->Attribute(key_daName); + fcda.fc = ele_fcda->Attribute(key_fc) == nullptr ? "" : ele_fcda->Attribute(key_fc); + + dataset.vec_fcda.push_back(fcda); + } + + vec_dataset.push_back(name); + map_dataset[name] = dataset; + } + + return 0; +} + +/* + * parse_ReportControl_TrgOps - parse TrgOps element + input: ele_reportControl - reportControl element + output: trgOps - TrgOps data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_ReportControl_TrgOps(XMLElement *ele_reportControl, stru_TrgOps &trgOps) +{ + if(nullptr == ele_reportControl) + { + LOG_E("ele_reportControl is null"); + return -1; + } + + XMLElement *ele_trgOps = ele_reportControl->FirstChildElement(ele_TrgOps); + if(nullptr == ele_trgOps) + { + LOG_E("TrgOps is null"); + return -1; + } + + trgOps.dchg = (ele_trgOps->Attribute(key_dchg) == nullptr ? "false" : ele_trgOps->Attribute(key_dchg)) == "true"; + trgOps.qchg = (ele_trgOps->Attribute(key_qchg) == nullptr ? "false" : ele_trgOps->Attribute(key_qchg)) == "true"; + trgOps.dupd = (ele_trgOps->Attribute(key_dupd) == nullptr ? "false" : ele_trgOps->Attribute(key_dupd)) == "true"; + trgOps.period = (ele_trgOps->Attribute(key_period) == nullptr ? "false" : ele_trgOps->Attribute(key_period)) == "true"; + + return 0; +} + +/* + * parse_ReportControl_OptFields - parse OptFields element + input: ele_reportControl - reportControl element + output: optFields - OptFields data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_ReportControl_OptFields(XMLElement *ele_reportControl, stru_OptFields &optFields) +{ + if(nullptr == ele_reportControl) + { + LOG_E("ele_reportControl is null"); + return -1; + } + + XMLElement *ele_optFields = ele_reportControl->FirstChildElement(ele_OptFields); + if(nullptr == ele_optFields) + { + LOG_E("OptFields is null"); + return -1; + } + + optFields.seqNum = (ele_optFields->Attribute(key_seqNum) == nullptr ? "false" : ele_optFields->Attribute(key_seqNum)) == "true"; + optFields.timeStamp = (ele_optFields->Attribute(key_timeStamp) == nullptr ? "false" : ele_optFields->Attribute(key_timeStamp)) == "true"; + optFields.reasonCode = (ele_optFields->Attribute(key_reasonCode) == nullptr ? "false" : ele_optFields->Attribute(key_reasonCode)) == "true"; + optFields.dataRef = (ele_optFields->Attribute(key_dataRef) == nullptr ? "false" : ele_optFields->Attribute(key_dataRef)) == "true"; + optFields.entryID = (ele_optFields->Attribute(key_entryID) == nullptr ? "false" : ele_optFields->Attribute(key_entryID)) == "true"; + optFields.configRef = (ele_optFields->Attribute(key_configRef) == nullptr ? "false" : ele_optFields->Attribute(key_configRef)) == "true"; + + return 0; +} + +/* + * parse_ReportControl_RptEnable - parse RptEnabled element + input: ele_reportControl - reportControl element + output: RptEnabled_max - maximum number of reports + return: 0 - success, -1 - failure +*/ +LOCAL int parse_ReportControl_RptEnable(XMLElement *ele_reportControl, int &RptEnabled_max) +{ + if(nullptr == ele_reportControl) + { + LOG_E("ele_reportControl is null"); + return -1; + } + + XMLElement *ele_rptEnabled = ele_reportControl->FirstChildElement(ele_RptEnabled); + if(nullptr == ele_rptEnabled) + { + LOG_E("RptEnabled is null"); + return -1; + } + + RptEnabled_max = atoi(ele_rptEnabled->Attribute(key_max) == nullptr ? "0" : ele_rptEnabled->Attribute(key_max)); + + return 0; +} + +/* + * parse_ReportControl - parse ReportControl element + input: ele_ln0 - ln0 element + output: map_reportControl - map to store ReportControl data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_ReportControl(XMLElement *ele_ln0, std::map &map_reportControl, std::vector &vec_reportControl) +{ + if(nullptr == ele_ln0) + { + LOG_E("ele_ln0 is null"); + return -1; + } + + for(XMLElement *ele = ele_ln0->FirstChildElement(ele_ReportControl); ele; ele = ele->NextSiblingElement(ele_ReportControl)) + { + stru_ReportControl reportControl; + const char *temp_str = nullptr; + std::string temp_string = ""; + std::string name = ele->Attribute(key_name) == nullptr ? "" : ele->Attribute(key_name); + if(name.empty()) + { + continue; + } + + reportControl.Rcb = nullptr; + reportControl.datSet = ele->Attribute(key_datSet) == nullptr ? "" : ele->Attribute(key_datSet); + temp_str = ele->Attribute(key_intgPd); + reportControl.intgPd = temp_str == nullptr ? 0 : atoi(temp_str); + reportControl.rptID = ele->Attribute(key_rptId) == nullptr ? "" : ele->Attribute(key_rptId); + temp_str = ele->Attribute(key_confRev); + reportControl.confRev = temp_str == nullptr ? 0 : atoi(temp_str); + temp_string = ele->Attribute(key_buffered) == nullptr ? "false" : ele->Attribute(key_buffered); + reportControl.buffered = (temp_string == "true") ? true : false; + temp_str = ele->Attribute(key_bufTime); + reportControl.bufTime = temp_str == nullptr ? 0 : atoi(temp_str); + + parse_ReportControl_TrgOps(ele, reportControl.trgOps); + parse_ReportControl_OptFields(ele, reportControl.optFields); + parse_ReportControl_RptEnable(ele, reportControl.RptEnabled_max); + + vec_reportControl.push_back(name); + map_reportControl[name] = reportControl; + } + + return 0; +} + +/* + * parse_DAI - parse DAI element + input: ele - dai element + output: map_daI - map to store DA data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_DAI(XMLElement *ele, std::map &map_daI, std::vector &vec_daI) +{ + if(nullptr == ele) + { + LOG_E("ele is null"); + return -1; + } + + for(XMLElement *ele_dai = ele->FirstChildElement(ele_DAI); ele_dai; ele_dai = ele_dai->NextSiblingElement(ele_DAI)) + { + stru_DAI dai; + std::string name = ele_dai->Attribute(key_name) == nullptr ? "" : ele_dai->Attribute(key_name); + if(name.empty()) + { + continue; + } + + dai.sAddr = ele_dai->Attribute(key_sAddr) == nullptr ? "" : ele_dai->Attribute(key_sAddr); + + XMLElement *ele_val = nullptr; + if(nullptr != (ele_val = ele_dai->FirstChildElement(ele_Val))) + { + dai.val = ele_val->GetText() == nullptr ? "" : ele_val->GetText(); + } + + vec_daI.push_back(name); + map_daI[name] = dai; + } + + return 0; +} + +/* + * parse_SDI - parse SDI element + input: ele_doi - doi element + output: map_daI - map to store DA data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_SDI(XMLElement *ele_doi, std::map &map_sdI, std::vector &vec_sdI) +{ + if(nullptr == ele_doi) + { + LOG_E("ele_doi is null"); + return -1; + } + + for(XMLElement *ele_sdi = ele_doi->FirstChildElement(ele_SDI); ele_sdi; ele_sdi = ele_sdi->NextSiblingElement(ele_SDI)) + { + stru_SDI sdi; + std::string name = ele_sdi->Attribute(key_name) == nullptr ? "" : ele_sdi->Attribute(key_name); + if(name.empty()) + { + continue; + } + + parse_SDI(ele_sdi, sdi.map_sdI, sdi.vec_sdI); + parse_DAI(ele_sdi, sdi.map_daI, sdi.vec_daI); + + vec_sdI.push_back(name); + map_sdI[name] = sdi; + } + + return 0; +} + +/* + * parse_DOI - parse DOI element + input: ele_ln - ln element + output: map_doI - map to store DOI data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_DOI(XMLElement *ele_ln, std::map &map_doI, std::vector &vec_doI) +{ + if(nullptr == ele_ln) + { + LOG_E("ele_ln is null"); + return -1; + } + + XMLElement *ele_doi = nullptr; + for(ele_doi = ele_ln->FirstChildElement(ele_DOI); ele_doi; ele_doi = ele_doi->NextSiblingElement(ele_DOI)) + { + stru_DOI doi; + std::string name = ele_doi->Attribute(key_name) == nullptr ? "" : ele_doi->Attribute(key_name); + if(name.empty()) + { + continue; + } + + doi.desc = ele_doi->Attribute(key_desc) == nullptr ? "" : ele_doi->Attribute(key_desc); + + parse_SDI(ele_doi, doi.map_sdI, doi.vec_sdI); + parse_DAI(ele_doi, doi.map_daI, doi.vec_daI); + + vec_doI.push_back(name); + map_doI[name] = doi; + } + + return 0; +} + +/* + * parse_SettingControl - parse SettingControl element + input: ele_ln0 - ln0 element + output: settingControl - settingControl data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_SettingControl(XMLElement *ele_ln0, stru_SettingControl &settingControl) +{ + if(nullptr == ele_ln0) + { + LOG_E("ele_ln0 is null"); + return -1; + } + XMLElement *ele_settingControl = ele_ln0->FirstChildElement(ele_SettingControl); + if(nullptr == ele_settingControl) + { + LOG_E("SettingControl is null"); + return -1; + } + + const char *temp_str = nullptr; + temp_str = ele_settingControl->Attribute(key_actSG) == nullptr ? "" : ele_settingControl->Attribute(key_actSG); + settingControl.actSG = temp_str == nullptr ? 0 : (uint8_t)atoi(temp_str); + temp_str = ele_settingControl->Attribute(key_numOfSGs) == nullptr ? "" : ele_settingControl->Attribute(key_numOfSGs); + settingControl.numOfSGs = temp_str == nullptr ? 0 : (uint8_t)atoi(temp_str); + + return 0; +} + +/* + * parse_LN0 - parse LN0 element + input: ele_ldevice - ldevice element + output: ln0 - ln0 data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_LN0(XMLElement *ele_ldevice, stru_LN0 &ln0) +{ + if(nullptr == ele_ldevice) + { + LOG_E("ldevice is null"); + return -1; + } + + XMLElement *ele_ln0 = ele_ldevice->FirstChildElement(ele_LN0); + if(nullptr == ele_ln0) + { + LOG_E("ln0 is null"); + return -1; + } + + ln0.LLN0 = nullptr; + ln0.lnClass = ele_ln0->Attribute(key_lnClass) == nullptr ? "" : ele_ln0->Attribute(key_lnClass); + ln0.lnType = ele_ln0->Attribute(key_lnType) == nullptr ? "" : ele_ln0->Attribute(key_lnType); + + parse_DataSet(ele_ln0, ln0.map_dataset, ln0.vec_dataset); + parse_ReportControl(ele_ln0, ln0.map_reportControl, ln0.vec_reportControl); + + parse_DOI(ele_ln0, ln0.map_doI, ln0.vec_doI); + + parse_SettingControl(ele_ln0, ln0.settingControl); + return 0; +} + +/* + * parse_LN - parse LN element + input: ele_ldevice - ldevice element + output: vec_ln - vector to store LN data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_LN(XMLElement *ele_ldevice, std::vector &vec_ln) +{ + if(nullptr == ele_ldevice) + { + LOG_E("ldevice is null"); + return -1; + } + + XMLElement *ele_ln = nullptr; + + for(ele_ln = ele_ldevice->FirstChildElement(ele_LN); ele_ln; ele_ln = ele_ln->NextSiblingElement(ele_LN)) + { + stru_LN ln; + ln.LN = nullptr; + ln.lnType = ele_ln->Attribute(key_lnType) == nullptr ? "" : ele_ln->Attribute(key_lnType); + ln.lnClass = ele_ln->Attribute(key_lnClass) == nullptr ? "" : ele_ln->Attribute(key_lnClass); + ln.desc = ele_ln->Attribute(key_desc) == nullptr ? "" : ele_ln->Attribute(key_desc); + ln.inst = ele_ln->Attribute(key_inst) == nullptr ? "" : ele_ln->Attribute(key_inst); + ln.prefix = ele_ln->Attribute(key_prefix) == nullptr ? "" : ele_ln->Attribute(key_prefix); + + if(0 != parse_DOI(ele_ln, ln.map_doI, ln.vec_doI)) + { + LOG_E("parse DOI %s:%s failed", ln.lnClass.c_str(), ln.inst.c_str()); + continue; + } + + vec_ln.push_back(ln); + } + + return 0; +} + +/* + * parse_LDevice - parse LDevice element + input: ele_ldevice - ldevice element + output: ldevice - ldevice data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_LDevice(XMLElement *ele_ldevice, stru_LDevice &ldevice) +{ + if(nullptr == ele_ldevice) + { + LOG_E("ldevice is null"); + return -1; + } + + ldevice.Ldevice = nullptr; + + if(0 != parse_LN0(ele_ldevice, ldevice.ln0)) + { + LOG_E("parse LN0 failed"); + return -1; + } + + if(0 != parse_LN(ele_ldevice, ldevice.vec_ln)) + { + LOG_E("parse LN failed"); + return -1; + } + + return 0; +} + +/* + * parse_ied - parse IED element + input: ele_ied - ied element + output: ied - ied data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_ied(XMLElement *ele_ied, stru_ied &ied) +{ + if(nullptr == ele_ied) + { + LOG_E("ied is null"); + return -1; + } + + ied.model = nullptr; + ied.name = ele_ied->Attribute(key_name) == nullptr ? "" : ele_ied->Attribute(key_name); + ied.desc = ele_ied->Attribute(key_desc) == nullptr ? "" : ele_ied->Attribute(key_desc); + ied.type = ele_ied->Attribute(key_type) == nullptr ? "" : ele_ied->Attribute(key_type); + + XMLElement *ele_accessPoint = ele_ied->FirstChildElement(ele_AccessPoint); + if(nullptr == ele_accessPoint) + { + LOG_E("accessPoint is null"); + return -1; + } + + XMLElement *ele_server = ele_accessPoint->FirstChildElement(ele_Server); + if(nullptr == ele_server) + { + LOG_E("server is null"); + return -1; + } + + XMLElement *ele_ldevice = nullptr; + for(ele_ldevice = ele_server->FirstChildElement(ele_LDevice); ele_ldevice; ele_ldevice = ele_ldevice->NextSiblingElement(ele_LDevice)) + { + std::string inst = ele_ldevice->Attribute(key_inst) == nullptr ? "" : ele_ldevice->Attribute(key_inst); + if(inst.empty()) + { + continue; + } + + stru_LDevice ldevice; + + if(0 != parse_LDevice(ele_ldevice, ldevice)) + { + LOG_E("parse LDevice %s failed", inst.c_str()); + continue; + } + + ied.vec_ldevice.push_back(inst); + ied.map_ldevice[inst] = ldevice; + } + + return 0; +} + +/* + * parse_LNodeType - parse LNodeType element + input: dataTypeTemplates - dataTypeTemplates element + output: map_lnType - map to store LNodeType data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_LNodeType(XMLElement *dataTypeTemplates, std::map &map_lnType, std::vector &vec_lnType) +{ + if(nullptr == dataTypeTemplates) + { + LOG_E("dataTypeTemplates is null"); + return -1; + } + + XMLElement *ele_type = nullptr; + for(ele_type = dataTypeTemplates->FirstChildElement(ele_LNodeType); ele_type; ele_type = ele_type->NextSiblingElement(ele_LNodeType)) + { + stru_LNodeType LNodeType; + std::string id = ele_type->Attribute(key_id) == nullptr ? "" : ele_type->Attribute(key_id); + if(id.empty()) + { + continue; + } + + LNodeType.lnClass = ele_type->Attribute(key_lnClass) == nullptr ? "" : ele_type->Attribute(key_lnClass); + + XMLElement *ele_do = nullptr; + for(ele_do = ele_type->FirstChildElement(ele_DO); ele_do; ele_do = ele_do->NextSiblingElement(ele_DO)) + { + stru_DO DO; + std::string name = ele_do->Attribute(key_name) == nullptr ? "" : ele_do->Attribute(key_name); + if(name.empty()) + { + continue; + } + + DO.type = ele_do->Attribute(key_type) == nullptr ? "" : ele_do->Attribute(key_type); + DO.desc = ele_do->Attribute(key_desc) == nullptr ? "" : ele_do->Attribute(key_desc); + + LNodeType.vec_do.push_back(name); + LNodeType.map_do[name] = DO; + } + + vec_lnType.push_back(id); + map_lnType[id] = LNodeType; + } + + return 0; +} + +/* + * parse_DOType - parse DOType element + input: dataTypeTemplates - dataTypeTemplates element + output: map_doType - map to store DOType data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_DOType(XMLElement *dataTypeTemplates, std::map &map_doType, std::vector &vec_doType) +{ + if(nullptr == dataTypeTemplates) + { + LOG_E("dataTypeTemplates is null"); + return -1; + } + + XMLElement *ele_type = nullptr; + for(ele_type = dataTypeTemplates->FirstChildElement(ele_DOType); ele_type; ele_type = ele_type->NextSiblingElement(ele_DOType)) + { + stru_DOType DOType; + std::string id = ele_type->Attribute(key_id) == nullptr ? "" : ele_type->Attribute(key_id); + DOType.cdc = ele_type->Attribute(key_cdc) == nullptr ? "" : ele_type->Attribute(key_cdc); + + XMLElement *ele_da = nullptr; + for(ele_da = ele_type->FirstChildElement(ele_DA); ele_da; ele_da = ele_da->NextSiblingElement(ele_DA)) + { + stru_DA DA; + std::string name = ele_da->Attribute(key_name) == nullptr ? "" : ele_da->Attribute(key_name); + if(name.empty()) + { + continue; + } + + DA.type = ele_da->Attribute(key_type) == nullptr ? "" : ele_da->Attribute(key_type); + DA.bType = ele_da->Attribute(key_bType) == nullptr ? "" : ele_da->Attribute(key_bType); + DA.dchg = ele_da->Attribute(key_dchg) == nullptr ? "" : ele_da->Attribute(key_dchg); + DA.qchg = ele_da->Attribute(key_qchg) == nullptr ? "" : ele_da->Attribute(key_qchg); + DA.fc = ele_da->Attribute(key_fc) == nullptr ? "" : ele_da->Attribute(key_fc); + + XMLElement *ele_val = nullptr; + if(nullptr != (ele_val = ele_da->FirstChildElement(ele_Val))) + { + DA.text = ele_val->GetText() == nullptr ? "" : ele_val->GetText(); + } + + DOType.vec_da.push_back(name); + DOType.map_da[name] = DA; + } + + XMLElement *ele_sdo = nullptr; + for(ele_sdo = ele_type->FirstChildElement(ele_SDO); ele_sdo; ele_sdo = ele_sdo->NextSiblingElement(ele_SDO)) + { + std::string name = ele_sdo->Attribute(key_name) == nullptr ? "" : ele_sdo->Attribute(key_name); + std::string type = ele_sdo->Attribute(key_type) == nullptr ? "" : ele_sdo->Attribute(key_type); + if(name.empty() || type.empty()) + { + LOG_E("name or type is empty"); + continue; + } + + DOType.vec_sdo.push_back(name); + DOType.map_sdo[name] = type; + } + + vec_doType.push_back(id); + map_doType[id] = DOType; + } + + return 0; +} + +/* + * parse_DAType - parse DAType element + input: dataTypeTemplates - dataTypeTemplates element + output: map_daType - map to store DAType data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_DAType(XMLElement *dataTypeTemplates, std::map &map_daType, std::vector &vec_daType) +{ + if(nullptr == dataTypeTemplates) + { + LOG_E("dataTypeTemplates is null"); + return -1; + } + + XMLElement *ele_type = nullptr; + for(ele_type = dataTypeTemplates->FirstChildElement(ele_DAType); ele_type; ele_type = ele_type->NextSiblingElement(ele_DAType)) + { + stru_DAType DAType; + std::string id = ele_type->Attribute(key_id) == nullptr ? "" : ele_type->Attribute(key_id); + if(id.empty()) + { + continue; + } + + for(XMLElement *ele_bda = ele_type->FirstChildElement(ele_BDA); ele_bda; ele_bda = ele_bda->NextSiblingElement(ele_BDA)) + { + stru_BDA BDA; + std::string name = ele_bda->Attribute(key_name) == nullptr ? "" : ele_bda->Attribute(key_name); + BDA.type = ele_bda->Attribute(key_type) == nullptr ? "" : ele_bda->Attribute(key_type); + BDA.bType = ele_bda->Attribute(key_bType) == nullptr ? "" : ele_bda->Attribute(key_bType); + + DAType.vec_bda.push_back(name); + DAType.map_bda[name] = BDA; + } + + vec_daType.push_back(id); + map_daType[id] = DAType; + } + + return 0; +} + +/* + * parse_EnumType - parse EnumType element + input: dataTypeTemplates - dataTypeTemplates element + output: map_enumType - map to store EnumType data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_EnumType(XMLElement *dataTypeTemplates, std::map &map_enumType, std::vector &vec_enumType) +{ + if(nullptr == dataTypeTemplates) + { + LOG_E("dataTypeTemplates is null"); + return -1; + } + + XMLElement *ele_type = nullptr; + for(ele_type = dataTypeTemplates->FirstChildElement(ele_EnumType); ele_type; ele_type = ele_type->NextSiblingElement(ele_EnumType)) + { + stru_EnumType EnumType; + std::string id = ele_type->Attribute(key_id) == nullptr ? "" : ele_type->Attribute(key_id); + + XMLElement *ele_enumVal = nullptr; + for(ele_enumVal = ele_type->FirstChildElement(ele_EnumVal); ele_enumVal; ele_enumVal = ele_enumVal->NextSiblingElement(ele_EnumVal)) + { + const char *ord = ele_enumVal->Attribute(key_ord) == nullptr ? "" : ele_enumVal->Attribute(key_ord); + const char *value = ele_enumVal->GetText() == nullptr ? "" : ele_enumVal->GetText(); + + EnumType.vec_ord.push_back(atoi(ord)); + EnumType.map_enumVal[atoi(ord)] = value; + } + + vec_enumType.push_back(id); + map_enumType[id] = EnumType; + } + + return 0; +} + +LOCAL void parse_BDA_fc(std::map &map_daType) +{ + for(std::map::iterator it_da = map_daType.begin(); it_da != map_daType.end(); it_da++) + { + for(std::map::iterator it_bda = it_da->second.map_bda.begin(); it_bda != it_da->second.map_bda.end(); it_bda++) + { + if(it_bda->second.fc.empty()) + { + continue; + } + + if(map_daType.find(it_bda->second.type) == map_daType.end()) + { + continue; + } + + stru_DAType &DAType = map_daType[it_bda->second.type]; + + // 遍历DAType中的BDA,将fc字段赋值给BDA + for(std::map::iterator it = DAType.map_bda.begin(); it != DAType.map_bda.end(); it++) + { + it->second.fc = it_bda->second.fc; + it->second.dchg = it_bda->second.dchg; + it->second.qchg = it_bda->second.qchg; + } + } + } +} + +LOCAL void parse_BDA_fc(std::map &map_doType, std::map &map_daType) +{ + for(std::map::iterator it_do = map_doType.begin(); it_do != map_doType.end(); it_do++) + { + for(std::map::iterator it_do_da = it_do->second.map_da.begin(); it_do_da != it_do->second.map_da.end(); it_do_da++) + { + // 到daType中查找type,如果没有找到,直接跳过 + if(map_daType.find(it_do_da->second.type) == map_daType.end()) + { + continue; + } + + // 找到daType,将fc字段赋值给BDA + stru_DAType &DAType = map_daType[it_do_da->second.type]; + + // 遍历DAType中的BDA,将fc字段赋值给BDA + for(std::map::iterator it_bda = DAType.map_bda.begin(); it_bda != DAType.map_bda.end(); it_bda++) + { + it_bda->second.fc = it_do_da->second.fc; + it_bda->second.dchg = it_do_da->second.dchg; + it_bda->second.qchg = it_do_da->second.qchg; + } + } + } +} + +/* + * parse_dataTypeTemplates - parse dataTypeTemplates element + input: dataTypeTemplates - dataTypeTemplates element + output: icd - icd data structure + return: 0 - success, -1 - failure +*/ +LOCAL int parse_dataTypeTemplates(XMLElement *dataTypeTemplates, stru_icd &icd) +{ + if(nullptr == dataTypeTemplates) + { + LOG_E("dataTypeTemplates is null"); + return -1; + } + + if(0 != parse_LNodeType(dataTypeTemplates, icd.map_lnType, icd.vec_lnType)) + { + LOG_E("parse LNodeType failed"); + return -1; + } + + if(0 != parse_DOType(dataTypeTemplates, icd.map_doType, icd.vec_doType)) + { + LOG_E("parse DOType failed"); + return -1; + } + + if(0 != parse_DAType(dataTypeTemplates, icd.map_daType, icd.vec_daType)) + { + LOG_E("parse DAType failed"); + return -1; + } + + if(0 != parse_EnumType(dataTypeTemplates, icd.map_enumType, icd.vec_enumType)) + { + LOG_E("parse EnumType failed"); + return -1; + } + + parse_BDA_fc(icd.map_doType, icd.map_daType); + parse_BDA_fc(icd.map_daType); + + + return 0; +} + +LOCAL int check_da_dataTypeTemplates(stru_icd &icd, std::string da_type, std::vector &vec_sdI, std::map &map_sdI) +{ + if(icd.map_daType.find(da_type) == icd.map_daType.end()) + { + LOG_E("daType %s not found in dataTypeTemplates", da_type.c_str()); + return -1; + } + + stru_DAType *p_DAType = &icd.map_daType[da_type]; + + for(std::vector::iterator it_sdI = vec_sdI.begin(); it_sdI != vec_sdI.end(); it_sdI++) + { + if(map_sdI.find(*it_sdI) == map_sdI.end()) + { + LOG_E("SDI %s not found in DAI", it_sdI->c_str()); + return -1; + } + + stru_SDI *p_sdi = &map_sdI[*it_sdI]; + + if(p_DAType->map_bda.find(*it_sdI) == p_DAType->map_bda.end()) + { + LOG_E("DAI %s not found in DAType %s", it_sdI->c_str(), da_type.c_str()); + return -1; + } + + stru_BDA *p_bda = &p_DAType->map_bda[*it_sdI]; + + if(icd.map_daType.find(p_bda->type) == icd.map_daType.end()) + { + LOG_E("bdaType %s not found in dataTypeTemplates", p_bda->type.c_str()); + return -1; + } + + if(p_bda->type.compare("Struct") == 0) + { + if(0 != check_da_dataTypeTemplates(icd, p_bda->type, p_sdi->vec_sdI, p_sdi->map_sdI)) + { + LOG_E("check struct bda %s failed", it_sdI->c_str()); + return -1; + } + } + } + + return 0; +} + +LOCAL int check_do_dataTypeTemplates(stru_icd &icd, std::string do_type, std::vector &vec_daI, std::map &map_daI) +{ + if(icd.map_doType.find(do_type) == icd.map_doType.end()) + { + LOG_E("doType %s not found in dataTypeTemplates", do_type.c_str()); + return -1; + } + + stru_DOType *p_DOType = &icd.map_doType[do_type]; + + for(std::vector::iterator it_daI = vec_daI.begin(); it_daI != vec_daI.end(); it_daI++) + { + if(map_daI.find(*it_daI) == map_daI.end()) + { + LOG_E("DAI %s not found in DOI", it_daI->c_str()); + return -1; + } + + stru_DAI *p_dai = &map_daI[*it_daI]; + + if(p_DOType->map_da.find(*it_daI) == p_DOType->map_da.end()) + { + LOG_E("DA %s not found in DOType %s", it_daI->c_str(), do_type.c_str()); + return -1; + } + + stru_DA *p_daType = &p_DOType->map_da[*it_daI]; + + if(p_daType->bType.compare("Struct") == 0 && icd.map_daType.find(p_daType->type) == icd.map_daType.end()) + { + LOG_E("DAType %s not found in dataTypeTemplates", p_daType->type.c_str()); + return -1; + } + } + + return 0; +} + + +LOCAL int check_do_dataTypeTemplates(stru_icd &icd, std::string do_type, std::vector &vec_sdI, std::map &map_sdI) +{ + if(icd.map_doType.find(do_type) == icd.map_doType.end()) + { + LOG_E("doType %s not found in dataTypeTemplates", do_type.c_str()); + return -1; + } + + stru_DOType *p_DOType = &icd.map_doType[do_type]; + + for(std::vector::iterator it_sdI = vec_sdI.begin(); it_sdI != vec_sdI.end(); it_sdI++) + { + if(map_sdI.find(*it_sdI) == map_sdI.end()) + { + LOG_E("SDI %s not found in DOI", it_sdI->c_str()); + return -1; + } + + stru_SDI *p_sdi = &map_sdI[*it_sdI]; + + if(p_DOType->map_sdo.find(*it_sdI) == p_DOType->map_sdo.end() && p_DOType->map_da.find(*it_sdI) == p_DOType->map_da.end()) + { + LOG_E("SDI %s not found in DOType %s", it_sdI->c_str(), do_type.c_str()); + return -1; + } + + if(p_DOType->map_sdo.find(*it_sdI) != p_DOType->map_sdo.end()) + { + std::string sdo_type = p_DOType->map_sdo[*it_sdI]; + if(0 != check_do_dataTypeTemplates(icd, sdo_type, p_sdi->vec_sdI, p_sdi->map_sdI)) + { + LOG_E("check sdo %s sdi failed", sdo_type.c_str()); + return -1; + } + + if(0 != check_do_dataTypeTemplates(icd, sdo_type, p_sdi->vec_daI, p_sdi->map_daI)) + { + LOG_E("check sdo %s dai failed", sdo_type.c_str()); + return -1; + } + } + + if(p_DOType->map_da.find(*it_sdI) != p_DOType->map_da.end()) + { + stru_DA *p_daType = &p_DOType->map_da[*it_sdI]; + if(icd.map_daType.find(p_daType->type) == icd.map_daType.end()) + { + LOG_E("DAType %s not found in dataTypeTemplates", p_daType->type.c_str()); + return -1; + } + + if(p_daType->type.compare("Struct") == 0) + { + if(0 != check_da_dataTypeTemplates(icd, p_daType->type, p_sdi->vec_sdI, p_sdi->map_sdI)) + { + LOG_E("check struct dai %s failed", it_sdI->c_str()); + return -1; + } + } + } + } + + return 0; +} + + + +LOCAL int check_ln_dataTypeTemplates(stru_icd &icd, std::string ln_type, std::vector &vec_doI, std::map &map_doI) +{ + if(icd.map_lnType.find(ln_type) == icd.map_lnType.end()) + { + LOG_E("lnType %s not found in dataTypeTemplates", ln_type.c_str()); + return -1; + } + + stru_LNodeType *p_LNodeType = &icd.map_lnType[ln_type]; + + for(std::vector::iterator it_do = vec_doI.begin(); it_do != vec_doI.end(); it_do++) + { + if(map_doI.find(*it_do) == map_doI.end()) + { + LOG_E("DOI %s not found in ln0", it_do->c_str()); + return -1; + } + + stru_DOI *p_doi = &map_doI[*it_do]; + + if(p_LNodeType->map_do.find(*it_do) == p_LNodeType->map_do.end()) + { + LOG_E("DO %s not found in LNodeType %s", it_do->c_str(), ln_type.c_str()); + return -1; + } + + stru_DO *p_do = &p_LNodeType->map_do[*it_do]; + + if(0 != check_do_dataTypeTemplates(icd, p_do->type, p_doi->vec_sdI, p_doi->map_sdI)) + { + LOG_E("check lntype %s do %s sdi failed", ln_type.c_str(), it_do->c_str()); + return -1; + } + + if(0 != check_do_dataTypeTemplates(icd, p_do->type, p_doi->vec_daI, p_doi->map_daI)) + { + LOG_E("check lntype %s do %s dai failed", ln_type.c_str(), it_do->c_str()); + return -1; + } + } + + return 0; +} + + + +LOCAL int check_ied_dataTypeTemplates(stru_icd *p_icd) +{ + if(NULL == p_icd) + { + LOG_E("p_icd is NULL"); + return -1; + } + + for(std::vector::iterator it_ld = p_icd->ied.vec_ldevice.begin(); it_ld != p_icd->ied.vec_ldevice.end(); it_ld++) + { + if(p_icd->ied.map_ldevice.find(*it_ld) == p_icd->ied.map_ldevice.end()) + { + LOG_E("ldevice %s not found in dataTypeTemplates", it_ld->c_str()); + return -1; + } + + stru_LDevice *p_ldevice = &p_icd->ied.map_ldevice[*it_ld]; + + if(0 != check_ln_dataTypeTemplates(*p_icd, p_ldevice->ln0.lnType, p_ldevice->ln0.vec_doI, p_ldevice->ln0.map_doI)) + { + LOG_E("check %s ln0 failed", it_ld->c_str()); + return -1; + } + + for(std::vector::iterator it_ln = p_ldevice->vec_ln.begin(); it_ln != p_ldevice->vec_ln.end(); it_ln++) + { + if(0 != check_ln_dataTypeTemplates(*p_icd, it_ln->lnType, it_ln->vec_doI, it_ln->map_doI)) + { + LOG_E("check %s ln %s failed", it_ld->c_str(), it_ln->lnClass.c_str()); + return -1; + } + } + } + + return 0; +} + +/* + * parse_icd - parse icd file + input: icd_file - icd file path + output: + return: stru_icd* - icd data structure +*/ +stru_icd *icd_parse(const char *icd_file) +{ + if(nullptr == icd_file) + { + LOG_E("icd_file is null"); + return nullptr; + } + + stru_icd *p_icd = new stru_icd; + if(nullptr == p_icd) + { + LOG_E("new stru_icd failed"); + return nullptr; + } + + XMLDocument doc; + XMLElement *scl, *ied, *dataTypeTemplates; + XMLError err = doc.LoadFile(icd_file); + if(err != XML_SUCCESS) + { + LOG_E("load icd file failed, err:%d", err); + goto ERR_EXIT; + } + + scl = doc.FirstChildElement(ele_SCL); + if(nullptr == scl) + { + LOG_E("no SCL element"); + goto ERR_EXIT; + } + + ied = scl->FirstChildElement(ele_IED); + if(NULL == ied) + { + LOG_E("no IED element"); + goto ERR_EXIT; + } + + dataTypeTemplates = scl->FirstChildElement(ele_DataTypeTemplates); + if(nullptr == dataTypeTemplates) + { + LOG_E("no DataTypeTemplates element"); + goto ERR_EXIT; + } + + if(0 != parse_ied(ied, p_icd->ied)) + { + LOG_E("parse ied failed"); + goto ERR_EXIT; + } + + if(0 != parse_dataTypeTemplates(dataTypeTemplates, *p_icd)) + { + LOG_E("parse dataTypeTemplates failed"); + goto ERR_EXIT; + } + + doc.Clear(); + + if(0 != check_ied_dataTypeTemplates(p_icd)) + { + LOG_E("check dataTypeTemplates failed"); + goto ERR_EXIT; + } + + return p_icd; + +ERR_EXIT: + delete p_icd; + + return nullptr; +} + + + + +LOCAL void show_icd_SDI(stru_SDI &sdi) +{ + for(auto it_vec = sdi.vec_sdI.begin(); it_vec != sdi.vec_sdI.end(); it_vec++) + { + stru_SDI *p_sdi = &sdi.map_sdI[*it_vec]; + printf("\t\t\t\tSDI name:%s\n", it_vec->c_str()); + + show_icd_SDI(*p_sdi); + } + + for(auto it_vec = sdi.vec_daI.begin(); it_vec != sdi.vec_daI.end(); it_vec++) + { + stru_DAI *p_dai = &sdi.map_daI[*it_vec]; + printf("\t\t\t\tDAI name:%s, val:%s, sAddr:%s\n", it_vec->c_str(), p_dai->val.c_str(), p_dai->sAddr.c_str()); + } +} + +/* + * show_icd_DOI - show DOI data structure + input: doI - DOI data structure + output: + return: +*/ +LOCAL void show_icd_DOI(stru_DOI &doI) +{ + for(auto it_vec = doI.vec_sdI.begin(); it_vec != doI.vec_sdI.end(); it_vec++) + { + stru_SDI *p_sdi = &doI.map_sdI[*it_vec]; + printf("\t\t\t\tSDI name:%s\n", it_vec->c_str()); + + show_icd_SDI(*p_sdi); + } + + + for(auto it_vec = doI.vec_daI.begin(); it_vec != doI.vec_daI.end(); it_vec++) + { + stru_DAI *p_dai = &doI.map_daI[*it_vec]; + printf("\t\t\t\tDAI name:%s, val:%s, sAddr:%s\n", it_vec->c_str(), p_dai->val.c_str(), p_dai->sAddr.c_str()); + } +} + + +/* + * icd_show - show icd data structure + input: icd - icd data structure + output: + return: +*/ +void icd_show(stru_icd &icd) +{ + + // show ied info + printf("ied name:%s, desc %s, type:%s\n", icd.ied.name.c_str(), icd.ied.desc.c_str(), icd.ied.type.c_str()); + + // for show ldevice info + for(auto it_vec = icd.ied.vec_ldevice.begin(); it_vec != icd.ied.vec_ldevice.end(); it_vec++) + { + stru_LDevice *p_ldevice = &icd.ied.map_ldevice[*it_vec]; + printf("\tldevice inst:%s\n", it_vec->c_str()); + + printf("\t\tln0 lnClass:%s, lnType:%s\n", p_ldevice->ln0.lnClass.c_str(), p_ldevice->ln0.lnType.c_str()); + + // for show ln0 dataset info + for(auto it_dataset_vec = p_ldevice->ln0.vec_dataset.begin(); it_dataset_vec != p_ldevice->ln0.vec_dataset.end(); it_dataset_vec++) + { + stru_DataSet *p_dataset = &p_ldevice->ln0.map_dataset[*it_dataset_vec]; + printf("\t\t\tdataset name:%s, desc:%s\n", it_dataset_vec->c_str(), p_dataset->desc.c_str()); + + // for show ln0 dataset fcda info + for(auto it_fcda = p_dataset->vec_fcda.begin(); it_fcda != p_dataset->vec_fcda.end(); it_fcda++) + { + { + printf("\t\t\t\tldInst %s, prefix %s, lnClass %s, lnInst %s, doName %s, daName %s, fc %s\n", + it_fcda->ldInst.c_str(), it_fcda->prefix.c_str(), it_fcda->lnClass.c_str(), it_fcda->lnInst.c_str(), it_fcda->doName.c_str(), it_fcda->daName.c_str(), it_fcda->fc.c_str()); + } + } + } + + // for show ln0 reportControl info + for(auto it_rpt_vec = p_ldevice->ln0.vec_reportControl.begin(); it_rpt_vec != p_ldevice->ln0.vec_reportControl.end(); it_rpt_vec++) + { + stru_ReportControl *p_rpt = &p_ldevice->ln0.map_reportControl[*it_rpt_vec]; + printf("\t\t\treportControl name:%s, datSet:%s, intgPd:%d, rptID:%s, confRev:%d, buffered:%d, bufTime:%d\n", + it_rpt_vec->c_str(), p_rpt->datSet.c_str(), p_rpt->intgPd, p_rpt->rptID.c_str(), p_rpt->confRev, p_rpt->buffered, p_rpt->bufTime); + } + + // for show ln0 settingControl info + printf("\t\tsettingControl actSG:%d, numOfSGs:%d\n", p_ldevice->ln0.settingControl.actSG, p_ldevice->ln0.settingControl.numOfSGs); + + // for show ln0 doI info + for(auto it_doi_vec = p_ldevice->ln0.vec_doI.begin(); it_doi_vec != p_ldevice->ln0.vec_doI.end(); it_doi_vec++) + { + stru_DOI *p_doi = &p_ldevice->ln0.map_doI[*it_doi_vec]; + printf("\t\t\tdoI name:%s, desc:%s\n", it_doi_vec->c_str(), p_doi->desc.c_str()); + show_icd_DOI(*p_doi); + } + + // for show ln info + for(auto it_ln = p_ldevice->vec_ln.begin(); it_ln != p_ldevice->vec_ln.end(); it_ln++) + { + stru_LN *p_ln = &(*it_ln); + printf("\t\tlnClass:%s, inst:%s, lnType:%s, desc:%s, prefix:%s\n", p_ln->lnClass.c_str(), p_ln->inst.c_str(), p_ln->lnType.c_str(), p_ln->desc.c_str(), p_ln->prefix.c_str()); + + // for show ln doi info + for(auto it_doi_vec = p_ln->vec_doI.begin(); it_doi_vec != p_ln->vec_doI.end(); it_doi_vec++) + { + stru_DOI *p_doi = &p_ln->map_doI[*it_doi_vec]; + printf("\t\t\tdoI name:%s, desc:%s\n", it_doi_vec->c_str(), p_doi->desc.c_str()); + show_icd_DOI(*p_doi); + } + } + } + + // for show lnType info + for(auto it_lnType_vec = icd.vec_lnType.begin(); it_lnType_vec != icd.vec_lnType.end(); it_lnType_vec++) + { + stru_LNodeType *p_lnType = &icd.map_lnType[*it_lnType_vec]; + printf("\tlnType id:%s, lnClass:%s\n", it_lnType_vec->c_str(), p_lnType->lnClass.c_str()); + for(auto it_do_vec = p_lnType->vec_do.begin(); it_do_vec != p_lnType->vec_do.end(); it_do_vec++) + { + stru_DO *p_do = &p_lnType->map_do[*it_do_vec]; + printf("\t\tdo name:%s, desc:%s, type:%s\n", it_do_vec->c_str(), p_do->desc.c_str(), p_do->type.c_str()); + + } + } + + // for show doType info + for(auto it_doType_vec = icd.vec_doType.begin(); it_doType_vec != icd.vec_doType.end(); it_doType_vec++) + { + stru_DOType *p_doType = &icd.map_doType[*it_doType_vec]; + printf("\tdoType id:%s, cdc:%s\n", it_doType_vec->c_str(), p_doType->cdc.c_str()); + for(auto it_da_vec = p_doType->vec_da.begin(); it_da_vec != p_doType->vec_da.end(); it_da_vec++) + { + stru_DA *p_da = &p_doType->map_da[*it_da_vec]; + printf("\t\tda name:%s, type:%s, bType:%s, dchg:%s, qchg:%s, fc:%s, val:%s\n", it_da_vec->c_str(), p_da->type.c_str(), p_da->bType.c_str(), p_da->dchg.c_str(), p_da->qchg.c_str(), p_da->fc.c_str(), p_da->text.c_str()); + } + } + + // for show daType info + for(auto it_daType_vec = icd.vec_daType.begin(); it_daType_vec != icd.vec_daType.end(); it_daType_vec++) + { + stru_DAType *p_daType = &icd.map_daType[*it_daType_vec]; + printf("\tdaType id:%s\n", it_daType_vec->c_str()); + for(auto it_bda_vec = p_daType->vec_bda.begin(); it_bda_vec != p_daType->vec_bda.end(); it_bda_vec++) + { + stru_BDA *p_bda = &p_daType->map_bda[*it_bda_vec]; + printf("\t\tbda name:%s, type:%s, bType:%s, fc:%s\n", it_bda_vec->c_str(), p_bda->type.c_str(), p_bda->bType.c_str(), p_bda->fc.c_str()); + } + } + + // for show enumType info + for(auto it_enumType_vec = icd.vec_enumType.begin(); it_enumType_vec != icd.vec_enumType.end(); it_enumType_vec++) + { + stru_EnumType *p_enumType = &icd.map_enumType[*it_enumType_vec]; + printf("\tenumType id:%s\n", it_enumType_vec->c_str()); + for(auto it_ord_vec = p_enumType->vec_ord.begin(); it_ord_vec != p_enumType->vec_ord.end(); it_ord_vec++) + { + std::string *p_ord = &p_enumType->map_enumVal[*it_ord_vec]; + printf("\t\tenumVal ord:%d, value:%s\n", *it_ord_vec, p_ord->c_str()); + } + } +} \ No newline at end of file diff --git a/src/protocol/libmms_s/src/mms_s_model.cpp b/src/protocol/libmms_s/src/mms_s_model.cpp new file mode 100644 index 0000000..5dc62c0 --- /dev/null +++ b/src/protocol/libmms_s/src/mms_s_model.cpp @@ -0,0 +1,1164 @@ +#include "iec61850_server.h" +#include "string_utilities.h" + +#include "mms_s.h" +#include "mms_s_icd.h" +#include "mms_s_value.h" +#include "mms_s_model.h" + + + +LOCAL std::map g_dataAttributeTypeMap = +{ + {"BOOLEAN", IEC61850_BOOLEAN}, + {"INT8", IEC61850_INT8}, + {"INT16", IEC61850_INT16}, + {"INT32", IEC61850_INT32}, + {"INT64", IEC61850_INT64}, + {"INT128", IEC61850_INT128}, + {"INT8U", IEC61850_INT8U}, + {"INT16U", IEC61850_INT16U}, + {"INT24U", IEC61850_INT24U}, + {"INT32U", IEC61850_INT32U}, + {"FLOAT32", IEC61850_FLOAT32}, + {"FLOAT64", IEC61850_FLOAT64}, + {"Enum", IEC61850_ENUMERATED}, + {"Octet64", IEC61850_OCTET_STRING_64}, + {"Octet6", IEC61850_OCTET_STRING_6}, + {"Octet8", IEC61850_OCTET_STRING_8}, + {"VisString32", IEC61850_VISIBLE_STRING_32}, + {"VisString64", IEC61850_VISIBLE_STRING_64}, + {"VisString65", IEC61850_VISIBLE_STRING_65}, + {"VisString129", IEC61850_VISIBLE_STRING_129}, + {"VisString255", IEC61850_VISIBLE_STRING_255}, + {"Unicode255", IEC61850_UNICODE_STRING_255}, + {"Timestamp", IEC61850_TIMESTAMP}, + {"Quality", IEC61850_QUALITY}, + {"Check", IEC61850_CHECK}, + {"CodedEnum", IEC61850_CODEDENUM}, + {"BitString", IEC61850_GENERIC_BITSTRING}, + {"Struct", IEC61850_CONSTRUCTED}, + {"EntryTime", IEC61850_ENTRY_TIME}, + {"PhyComAddr", IEC61850_PHYCOMADDR}, + {"Currency", IEC61850_CURRENCY}, + {"OptFlds", IEC61850_OPTFLDS}, + {"TrgOps", IEC61850_TRGOPS}, + {"Dbpos", IEC61850_GENERIC_BITSTRING}, +}; + + +LOCAL std::map g_functionalConstraintMap = +{ + {"ST", IEC61850_FC_ST}, + {"MX", IEC61850_FC_MX}, + {"SP", IEC61850_FC_SP}, + {"SV", IEC61850_FC_SV}, + {"CF", IEC61850_FC_CF}, + {"DC", IEC61850_FC_DC}, + {"SG", IEC61850_FC_SG}, + {"SE", IEC61850_FC_SE}, + {"SR", IEC61850_FC_SR}, + {"OR", IEC61850_FC_OR}, + {"BL", IEC61850_FC_BL}, + {"EX", IEC61850_FC_EX}, + {"CO", IEC61850_FC_CO}, + {"US", IEC61850_FC_US}, + {"MS", IEC61850_FC_MS}, + {"RP", IEC61850_FC_RP}, + {"BR", IEC61850_FC_BR}, + {"LG", IEC61850_FC_LG}, + {"GO", IEC61850_FC_GO}, +}; + + +/* + * model_get_triggerOptions - Gets trigger options + input: da - data attribute structure + output: + return: trigger options +*/ +LOCAL int model_get_triggerOptions(stru_DA &da) +{ + int triggerOptions = 0; + + if(da.dchg.compare("true") == 0) + { + triggerOptions |= TRG_OPT_DATA_CHANGED; + } + + if(da.qchg.compare("true") == 0) + { + triggerOptions |= TRG_OPT_QUALITY_CHANGED; + } + + return triggerOptions; +} + +/* + * model_get_rpt_trgOps - Gets report trigger options + input: trgOps - trigger options structure + output: + return: trigger options +*/ +LOCAL int model_get_rpt_trgOps(stru_TrgOps &trgOps) +{ + int ret = 0; + + if(trgOps.dchg) + { + ret |= TRG_OPT_DATA_CHANGED; + } + + if(trgOps.qchg) + { + ret |= TRG_OPT_QUALITY_CHANGED; + } + + if(trgOps.dupd) + { + ret |= TRG_OPT_DATA_UPDATE; + } + + if(trgOps.period) + { + ret |= TRG_OPT_INTEGRITY; + } + + return ret; +} + +/* + * model_get_rpt_options - Gets report options + input: optFields - report options structure + output: + return: report options +*/ +LOCAL int model_get_rpt_options(stru_OptFields &optFields) +{ + int ret = 0; + + if(optFields.seqNum) + { + ret |= RPT_OPT_SEQ_NUM; + } + + if(optFields.timeStamp) + { + ret |= RPT_OPT_TIME_STAMP; + } + + if(optFields.reasonCode) + { + ret |= RPT_OPT_REASON_FOR_INCLUSION; + } + + if(optFields.dataSet) + { + ret |= RPT_OPT_DATA_SET; + } + + if(optFields.dataRef) + { + ret |= RPT_OPT_DATA_REFERENCE; + } + + if(optFields.entryID) + { + ret |= RPT_OPT_ENTRY_ID; + } + + if(optFields.configRef) + { + ret |= RPT_OPT_CONF_REV; + } + + return ret; +} + +/* + * model_BDA_dataobject_create - Creates BDA data object + input: icd - ICD structure + type - BDA data object type + dataAttr - parent data attribute + fc - functional constraint + all_da - BDA data object structure + output: all_da.map_all_da + return: 0 on success, -1 on failure +*/ +LOCAL int model_BDA_dataobject_create(stru_icd &icd, std::string type, int triggerOptions, FunctionalConstraint fc, DataAttribute *dataAttr, stru_all_DA &all_da) +{ + if(icd.map_daType.find(type) == icd.map_daType.end()) + { + LOG_E("DAType %s not found in ICD", type.c_str()); + return -1; + } + + stru_DAType &daType_item = icd.map_daType[type]; + + for(std::vector::iterator it_bda_vec = daType_item.vec_bda.begin(); it_bda_vec!= daType_item.vec_bda.end(); it_bda_vec++) + { + if(daType_item.map_bda.find(*it_bda_vec) == daType_item.map_bda.end()) + { + LOG_E("BDA %s not found in DAType_item", it_bda_vec->c_str()); + continue; + } + + stru_BDA &it_bda = daType_item.map_bda[*it_bda_vec]; + + if(g_dataAttributeTypeMap.find(it_bda.bType) == g_dataAttributeTypeMap.end()) + { + LOG_E("Data attribute type %s not found in g_dataAttributeTypeMap", it_bda.bType.c_str()); + continue; + } + + stru_all_DA *temp_all_da = new stru_all_DA; + + DataAttributeType btype = g_dataAttributeTypeMap[it_bda.bType]; + + temp_all_da->DA = DataAttribute_create(it_bda_vec->c_str(), (ModelNode*) dataAttr, btype, fc, triggerOptions, 0, NULL); + if(NULL == temp_all_da->DA) + { + LOG_E("Failed to create data attribute %s", it_bda_vec->c_str()); + delete temp_all_da; + continue; + } + + temp_all_da->bType = it_bda.bType; + temp_all_da->type = it_bda.type; + temp_all_da->fc = it_bda.fc; + temp_all_da->dchg = it_bda.dchg; + temp_all_da->qchg = it_bda.qchg; + temp_all_da->text = ""; + if(btype == IEC61850_CONSTRUCTED) + { + model_BDA_dataobject_create(icd, it_bda.type, triggerOptions, fc, temp_all_da->DA, *temp_all_da); + } + + if(fc == IEC61850_FC_SE) + { + std::string se_name = *it_bda_vec + "_SE"; + all_da.map_all_da[se_name] = temp_all_da; + } + else + { + all_da.map_all_da[*it_bda_vec] = temp_all_da; + } + } + + return 0; +} + +/* + * model_dataobject_create - Creates data object + input: icd - ICD structure + DOType_item - data object type item + node - parent node + do_name - data object name + all_do - data object structure + output: all_do.map_all_da + return: 0 on success, -1 on failure +*/ +LOCAL int model_dataobject_create(stru_icd &icd, stru_DOType &DOType_item, ModelNode *node, std::string do_name, stru_all_DO &all_do) +{ + if(do_name.empty() || NULL == node) + { + LOG_E("do_name or node is NULL"); + return -1; + } + + all_do.DO = DataObject_create(do_name.c_str(), node, 0); + if(NULL == all_do.DO) + { + LOG_E("Failed to create data object %s", do_name.c_str()); + return -1; + } + + for(std::vector::iterator it_da_vec = DOType_item.vec_da.begin(); it_da_vec!= DOType_item.vec_da.end(); it_da_vec++) + { + if(DOType_item.map_da.find(*it_da_vec) == DOType_item.map_da.end()) + { + LOG_E("DA %s not found in DOType_item", it_da_vec->c_str()); + continue; + } + + stru_DA &da_item = DOType_item.map_da[*it_da_vec]; + if(g_dataAttributeTypeMap.find(da_item.bType) == g_dataAttributeTypeMap.end()) + { + LOG_E("Data attribute type %s not found in g_dataAttributeTypeMap", da_item.bType.c_str()); + continue; + } + + if(g_functionalConstraintMap.find(da_item.fc) == g_functionalConstraintMap.end()) + { + LOG_E("Functional constraint %s not found in g_functionalConstraintMap", da_item.fc.c_str()); + continue; + } + + stru_all_DA *temp_all_da = new stru_all_DA; + + DataAttributeType bType = g_dataAttributeTypeMap[da_item.bType]; + FunctionalConstraint fc = g_functionalConstraintMap[da_item.fc]; + int triggerOptions = model_get_triggerOptions(da_item); + + temp_all_da->DA = DataAttribute_create(it_da_vec->c_str(), (ModelNode*) all_do.DO, bType, fc, triggerOptions, 0, NULL); + if(NULL == temp_all_da->DA) + { + LOG_E("Failed to create data attribute %s", it_da_vec->c_str()); + delete temp_all_da; + continue; + } + + temp_all_da->bType = da_item.bType; + temp_all_da->type = da_item.type; + temp_all_da->fc = da_item.fc; + temp_all_da->dchg = da_item.dchg; + temp_all_da->qchg = da_item.qchg; + temp_all_da->text = da_item.text; + if(bType == IEC61850_CONSTRUCTED) + { + model_BDA_dataobject_create(icd, da_item.type, triggerOptions, fc, temp_all_da->DA, *temp_all_da); + } + + all_do.map_all_da[*it_da_vec] = temp_all_da; + + if(fc == IEC61850_FC_SG) + { + LOG_I("Creating sub-data object for SG DA %s, do %s, ln %s", it_da_vec->c_str(), all_do.DO->name, all_do.DO->parent->name); + + stru_all_DA *p_all_da = new stru_all_DA; + p_all_da->DA = DataAttribute_create(it_da_vec->c_str(), (ModelNode*) all_do.DO, bType, IEC61850_FC_SE, triggerOptions, 0, NULL); + if(NULL == p_all_da->DA) + { + LOG_E("Failed to create data attribute %s", it_da_vec->c_str()); + delete p_all_da; + continue; + } + p_all_da->bType = da_item.bType; + p_all_da->type = da_item.type; + p_all_da->fc = "SE"; + p_all_da->dchg = da_item.dchg; + p_all_da->qchg = da_item.qchg; + p_all_da->text = da_item.text; + + if(bType == IEC61850_CONSTRUCTED) + { + model_BDA_dataobject_create(icd, da_item.type, triggerOptions, IEC61850_FC_SE, p_all_da->DA, *p_all_da); + } + + std::string se_name = *it_da_vec + "_SE"; + all_do.map_all_da[se_name] = p_all_da; + } + } + + return 0; +} + +/* + * model_LNodeType_get - Gets the logical node type + input: lnType - logical node type + icd - ICD structure + output: lnType_item - logical node type item + return: 0 on success, -1 on failure +*/ +LOCAL int model_LNodeType_get(std::string lnType, stru_LNodeType &lnType_item, stru_icd &icd) +{ + if(lnType.empty()) + { + LOG_E("lnType is empty"); + return -1; + } + + if(icd.map_lnType.find(lnType) == icd.map_lnType.end()) + { + LOG_E("lnType %s not found in ICD", lnType.c_str()); + return -1; + } + + lnType_item = icd.map_lnType[lnType]; + + return 0; +} + +/* + * model_DOType_get - Gets the data object type + input: doType - data object type + icd - ICD structure + output: DOType_item - data object type item + return: 0 on success, -1 on failure +*/ +LOCAL int model_DOType_get(std::string doType, stru_DOType &DOType_item, stru_icd &icd) +{ + if(doType.empty()) + { + LOG_E("doType is empty"); + return -1; + } + + if(icd.map_doType.find(doType) == icd.map_doType.end()) + { + LOG_E("doType %s not found in ICD", doType.c_str()); + return -1; + } + + DOType_item = icd.map_doType[doType]; + + return 0; +} + +/* + * model_DAType_get - Gets the data attribute type + input: daType - data attribute type + icd - ICD structure + output: daType_item - data attribute type item + return: 0 on success, -1 on failure +*/ +LOCAL int model_DAType_get(std::string daType, stru_DAType &daType_item, stru_icd &icd) +{ + if(daType.empty()) + { + LOG_E("daType is empty"); + return -1; + } + + if(icd.map_daType.find(daType) == icd.map_daType.end()) + { + LOG_E("daType %s not found in ICD", daType.c_str()); + return -1; + } + + daType_item = icd.map_daType[daType]; + + return 0; +} + +/* + * model_EnumType_get - Gets the enumeration type + input: enumType - enumeration type + icd - ICD structure + output: enumType_item - enumeration type item + return: 0 on success, -1 on failure +*/ +LOCAL int model_EnumType_get(std::string enumType, stru_EnumType &enumType_item, stru_icd &icd) +{ + if(enumType.empty()) + { + LOG_E("enumType is empty"); + return -1; + } + + if(icd.map_enumType.find(enumType) == icd.map_enumType.end()) + { + LOG_E("enumType %s not found in ICD", enumType.c_str()); + return -1; + } + + enumType_item = icd.map_enumType[enumType]; + + return 0; +} + +/* + * model_dataobject_init - Initializes the data objects + input: ln - logical node + icd - ICD structure + lnType - logical node type + output: map_all_do - map of all data objects + return: 0 on success, -1 on failure +*/ +LOCAL int model_dataobject_init(LogicalNode *ln, stru_icd &icd, std::string &lnType, std::map &map_all_do) +{ + if(NULL == ln) + { + LOG_E("ln is NULL"); + return -1; + } + + stru_LNodeType lnType_item; + if(0 != model_LNodeType_get(lnType, lnType_item, icd)) + { + LOG_E("Failed to get lnType %s", lnType.c_str()); + return -1; + } + + for(std::vector::iterator it_do_vec = lnType_item.vec_do.begin(); it_do_vec != lnType_item.vec_do.end(); it_do_vec++) + { + if(lnType_item.map_do.find(*it_do_vec) == lnType_item.map_do.end()) + { + LOG_E("DO %s not found in lnType %s", it_do_vec->c_str(), lnType.c_str()); + continue; + } + + stru_DO &DO_item = lnType_item.map_do[*it_do_vec]; + + stru_DOType DOType_item; + if(0 != model_DOType_get(DO_item.type, DOType_item, icd)) + { + LOG_E("Failed to get DOType %s", DO_item.type.c_str()); + continue; + } + + stru_all_DO *temp_all_do = new stru_all_DO; + + model_dataobject_create(icd, DOType_item, (ModelNode *)ln, *it_do_vec, *temp_all_do); + + for(std::map::iterator it_sdo = DOType_item.map_sdo.begin(); it_sdo != DOType_item.map_sdo.end(); it_sdo++) + { + stru_DOType SDOType_item; + + if(0 != model_DOType_get(it_sdo->second, SDOType_item, icd)) + { + LOG_E("Failed to get SDOType %s", it_sdo->second.c_str()); + continue; + } + + stru_all_DO *temp_all_sdo = new stru_all_DO; + + model_dataobject_create(icd, SDOType_item, (ModelNode *)temp_all_do->DO, it_sdo->first, *temp_all_sdo); + + temp_all_do->map_all_sdo[it_sdo->first] = temp_all_sdo; + } + + map_all_do[*it_do_vec] = temp_all_do; + } + + return 0; +} + +/* + * model_DataSet_init - Initializes the dataset + input: LLN0 - LLN0 node + icd - ICD structure + map_dataset - map of datasets + output: + return: 0 on success, -1 on failure +*/ +LOCAL int model_DataSet_init(LogicalNode *LLN0, stru_icd &icd, std::map &map_dataset, std::vector &vec_dataset) +{ + if(NULL == LLN0) + { + LOG_E("LLN0 is NULL"); + return -1; + } + + std::vector::iterator it_dataset; + for(it_dataset = vec_dataset.begin(); it_dataset != vec_dataset.end(); it_dataset++) + { + // LOG_I(" Initializing dataset %s", it_dataset->c_str()); + + std::map::iterator it_dataset_item = map_dataset.find(*it_dataset); + if(it_dataset_item == map_dataset.end()) + { + LOG_E("Failed to find dataset %s", it_dataset->c_str()); + continue; + } + + stru_DataSet *p_dataset = &it_dataset_item->second; + p_dataset->dataset = DataSet_create(it_dataset->c_str(), LLN0); + if(NULL == p_dataset->dataset) + { + LOG_E("Failed to create dataset %s", it_dataset->c_str()); + continue; + } + // LOG_I(" Created dataset %p", p_dataset->dataset); + std::vector::iterator it_fcda; + for(it_fcda = p_dataset->vec_fcda.begin(); it_fcda != p_dataset->vec_fcda.end(); it_fcda++) + { + std::string variable = it_fcda->prefix + it_fcda->lnClass + it_fcda->lnInst + "$" + \ + it_fcda->fc + "$" + it_fcda->doName + "$" + it_fcda->daName; + + for(int i = 0; i < variable.size(); i++) + { + if(variable[i] == '.') + { + variable[i] = '$'; + } + } + + if(NULL == (it_fcda->fcda = DataSetEntry_create(p_dataset->dataset, variable.c_str(), -1, NULL))) + { + LOG_E(" Failed to create dataset entry %s", variable.c_str()); + } + // LOG_I(" Initializing dataset entry %s, %p", variable.c_str(), it_fcda->fcda); + } + } + + return 0; +} + +/* + * model_ReportControlBlock_init - Initializes the report control block + input: LLN0 - LLN0 node + icd - ICD structure + map_rcb - map of report control blocks + output: + return: 0 on success, -1 on failure +*/ +LOCAL int model_ReportControlBlock_init(LogicalNode *LLN0, stru_icd &icd, std::map &map_rcb, std::vector &vec_rcb) +{ + if(NULL == LLN0) + { + LOG_E("LLN0 is NULL"); + return -1; + } + + for(std::vector::iterator it_rcb = vec_rcb.begin(); it_rcb != vec_rcb.end(); it_rcb++) + { + // LOG_I(" Initializing report control block %s", it_rcb->c_str()); + std::map::iterator it_rcb_item = map_rcb.find(*it_rcb); + if(it_rcb_item == map_rcb.end()) + { + LOG_E("Failed to find report control block %s", it_rcb->c_str()); + continue; + } + stru_ReportControl &rcb = it_rcb_item->second; + + int Options = model_get_rpt_options(rcb.optFields); + int trgOps = model_get_rpt_trgOps(rcb.trgOps); + + ReportControlBlock_create(it_rcb->c_str(), LLN0, rcb.rptID.c_str(), rcb.buffered, rcb.datSet.c_str(), rcb.confRev, trgOps, Options, rcb.bufTime, rcb.intgPd); + } + + return 0; +} + +/* + * model_ln0_init - Initializes the LLN0 + input: ld_model - logical device model + icd - ICD structure + ld - logical device structure + output: + return: 0 on success, -1 on failure +*/ +LOCAL int model_ln0_init(LogicalDevice *ld_model, stru_icd &icd, stru_LDevice &ld) +{ + if(NULL == ld_model) + { + LOG_E("ld_model is NULL"); + return -1; + } + + ld.ln0.LLN0 = LogicalNode_create(ld.ln0.lnClass.c_str(), ld_model); + if(NULL == ld.ln0.LLN0) + { + LOG_E("Failed to create LLN0"); + return -1; + } + + if(0 != model_dataobject_init(ld.ln0.LLN0, icd, ld.ln0.lnType, ld.ln0.map_all_do)) + { + LOG_E("Failed to init data objects for LLN0"); + return -1; + } + + if(0 != model_DataSet_init(ld.ln0.LLN0, icd, ld.ln0.map_dataset, ld.ln0.vec_dataset)) + { + LOG_E("Failed to init datasets for LLN0"); + return -1; + } + + if(0 != model_ReportControlBlock_init(ld.ln0.LLN0, icd, ld.ln0.map_reportControl, ld.ln0.vec_reportControl)) + { + LOG_E("Failed to init RCBs for LLN0"); + return -1; + } + + stru_SettingControl &settingControl = ld.ln0.settingControl; + ld.sgcb = SettingGroupControlBlock_create(ld.ln0.LLN0, settingControl.actSG, settingControl.numOfSGs); + + return 0; +} + +/* + * model_LNodes_init - Initializes the logical nodes + input: icd - ICD structure + ld - logical device structure + ld_model - logical device model + output: + return: 0 on success, -1 on failure +*/ +LOCAL int model_LNodes_init(stru_icd &icd, stru_LDevice &ld, LogicalDevice *ld_model) +{ + if(NULL == ld_model) + { + LOG_E("ld_model is NULL"); + return -1; + } + + std::vector::iterator it_ln; + for(it_ln = ld.vec_ln.begin(); it_ln!= ld.vec_ln.end(); it_ln++) + { + std::string ln_name = it_ln->prefix + it_ln->lnClass + it_ln->inst; + it_ln->LN = LogicalNode_create(ln_name.c_str(), ld_model); + if(NULL == it_ln->LN) + { + LOG_E("Failed to create logical node %s", ln_name.c_str()); + return -1; + } + + if(0 != model_dataobject_init(it_ln->LN, icd, it_ln->lnType, it_ln->map_all_do)) + { + LOG_E("Failed to init data objects for logical node %s", ln_name.c_str()); + return -1; + } + } + + return 0; +} + +/* + * model_ldevice_init - Initializes the logical device + input: model - IED model + icd - ICD structure + output: + return: 0 on success, -1 on failure +*/ +LOCAL int model_ldevice_init(IedModel *model, stru_icd &icd) +{ + if(NULL == model) + { + LOG_E("model is NULL"); + return -1; + } + + stru_ied &ied = icd.ied; + std::vector::iterator it_ld; + for(it_ld = ied.vec_ldevice.begin(); it_ld!= ied.vec_ldevice.end(); it_ld++) + { + // LOG_I("Initializing logical device %s", it_ld->c_str()); + std::map::iterator it_ldevice = icd.ied.map_ldevice.find(*it_ld); + if(it_ldevice == icd.ied.map_ldevice.end()) + { + LOG_E("Failed to find logical device %s", it_ld->c_str()); + continue; + } + + stru_LDevice *p_ldevice = &it_ldevice->second; + p_ldevice->Ldevice = LogicalDevice_create(it_ld->c_str(), model); + if(NULL == p_ldevice->Ldevice) + { + LOG_E("Failed to create logical device %s", it_ld->c_str()); + return -1; + } + + if(0 != model_ln0_init(p_ldevice->Ldevice, icd, *p_ldevice)) + { + LOG_E("Failed to create LLN0 for logical device %s", it_ld->c_str()); + return -1; + } + + model_LNodes_init(icd, *p_ldevice, p_ldevice->Ldevice); + } + + return 0; +} + +void model_sync_da_default_values(stru_icd &icd, stru_SDI &SDI_item, stru_all_DA *p_all_da) +{ + if(NULL == p_all_da) + { + LOG_E("p_all_da is NULL"); + return; + } + + for(std::map::iterator it_sdi = SDI_item.map_sdI.begin(); it_sdi != SDI_item.map_sdI.end(); it_sdi++) + { + if(p_all_da->map_all_da.find(it_sdi->first) != p_all_da->map_all_da.end()) + { + stru_all_DA *p_all_da_temp = p_all_da->map_all_da[it_sdi->first]; + stru_SDI &SDI_item = it_sdi->second; + + if(NULL == p_all_da_temp) + { + LOG_E("p_all_da is NULL"); + continue; + } + + model_sync_da_default_values(icd, SDI_item, p_all_da_temp); + } + } + + + for(std::map::iterator it_daI = SDI_item.map_daI.begin(); it_daI != SDI_item.map_daI.end(); it_daI++) + { + stru_DAI &DAI_item = it_daI->second; + + if(p_all_da->map_all_da.find(it_daI->first) != p_all_da->map_all_da.end()) + { + stru_all_DA *p_all_da_temp = p_all_da->map_all_da[it_daI->first]; + + if(p_all_da_temp) + { + p_all_da_temp->sAddr = DAI_item.sAddr; + p_all_da_temp->val = DAI_item.val; + + if(!p_all_da_temp->sAddr.empty()) + { + std::string saddr = p_all_da_temp->sAddr; + if(p_all_da_temp->DA->fc == IEC61850_FC_SG) + { + saddr = saddr + "_SG"; + } + + p_all_da_temp->DA->sAddr = StringUtils_copyString(saddr.c_str()); + icd.ied.vec_saddr.push_back(saddr); + icd.ied.map_saddr_point[saddr].node = (ModelNode *)p_all_da_temp->DA; + } + } + } + + if(p_all_da->map_all_da.find(it_daI->first + "_SE") != p_all_da->map_all_da.end()) + { + stru_all_DA *p_all_da_se_temp = p_all_da->map_all_da[it_daI->first + "_SE"]; + + if(p_all_da_se_temp) + { + p_all_da_se_temp->sAddr = DAI_item.sAddr; + p_all_da_se_temp->val = DAI_item.val; + + if(!p_all_da_se_temp->sAddr.empty()) + { + std::string saddr = p_all_da_se_temp->sAddr; + if(p_all_da_se_temp->DA->fc == IEC61850_FC_SE) + { + saddr = saddr + "_SE"; + } + + p_all_da_se_temp->DA->sAddr = StringUtils_copyString(saddr.c_str()); + icd.ied.vec_saddr.push_back(saddr); + icd.ied.map_saddr_point[saddr].node = (ModelNode *)p_all_da_se_temp->DA; + } + } + } + } +} + +void model_sync_SDO_default_values(stru_icd &icd, stru_SDI &map_sdi, stru_all_DO *map_all_do) +{ + if(NULL == map_all_do) + { + LOG_E("map_all_do is NULL"); + return; + } + + for(std::map::iterator it_sdi = map_sdi.map_sdI.begin(); it_sdi != map_sdi.map_sdI.end(); it_sdi++) + { + if(map_all_do->map_all_sdo.find(it_sdi->first) != map_all_do->map_all_sdo.end()) + { + stru_all_DO *p_all_sdo = map_all_do->map_all_sdo[it_sdi->first]; + stru_SDI &SDI_item = it_sdi->second; + + if(NULL == p_all_sdo) + { + LOG_E("p_all_sdo is NULL"); + continue; + } + + model_sync_SDO_default_values(icd, SDI_item, p_all_sdo); + } + + if(map_all_do->map_all_da.find(it_sdi->first) != map_all_do->map_all_da.end()) + { + stru_all_DA *p_all_da = map_all_do->map_all_da[it_sdi->first]; + stru_SDI &SDI_item = it_sdi->second; + + if(NULL == p_all_da) + { + LOG_E("p_all_da is NULL"); + continue; + } + model_sync_da_default_values(icd, SDI_item, p_all_da); + } + } +} + + +void model_sync_ln_default_values(stru_icd &icd, std::map &map_doI, std::map &map_all_do) +{ + for(std::map::iterator it_doI = map_doI.begin(); it_doI != map_doI.end(); it_doI++) + { + if(map_all_do.find(it_doI->first) == map_all_do.end()) + { + LOG_E("DO %s not found in map_all_do", it_doI->first.c_str()); + continue; + } + + stru_DOI &DOI_item = it_doI->second; + stru_all_DO *p_all_do = map_all_do[it_doI->first]; + + for(std::map::iterator it_daI = DOI_item.map_daI.begin(); it_daI != DOI_item.map_daI.end(); it_daI++) + { + stru_DAI &DAI_item = it_daI->second; + + if(p_all_do->map_all_da.find(it_daI->first) != p_all_do->map_all_da.end()) + { + stru_all_DA *p_all_da = p_all_do->map_all_da[it_daI->first]; + + if(p_all_da) + { + p_all_da->sAddr = DAI_item.sAddr; + p_all_da->val = DAI_item.val; + + if(!p_all_da->sAddr.empty()) + { + std::string saddr = p_all_da->sAddr; + if(p_all_da->DA->fc == IEC61850_FC_SG) + { + saddr = saddr + "_SG"; + } + + p_all_da->DA->sAddr = StringUtils_copyString(saddr.c_str()); + icd.ied.vec_saddr.push_back(saddr); + icd.ied.map_saddr_point[saddr].node = (ModelNode *)p_all_da->DA; + } + } + } + + if(p_all_do->map_all_da.find(it_daI->first + "_SE") != p_all_do->map_all_da.end()) + { + stru_all_DA *p_all_da_se = p_all_do->map_all_da[it_daI->first + "_SE"]; + if(p_all_da_se) + { + p_all_da_se->sAddr = DAI_item.sAddr; + p_all_da_se->val = DAI_item.val; + + if(!p_all_da_se->sAddr.empty()) + { + std::string saddr = p_all_da_se->sAddr; + if(p_all_da_se->DA->fc == IEC61850_FC_SE) + { + saddr = saddr + "_SE"; + } + + p_all_da_se->DA->sAddr = StringUtils_copyString(saddr.c_str()); + icd.ied.vec_saddr.push_back(saddr); + icd.ied.map_saddr_point[saddr].node = (ModelNode *)p_all_da_se->DA; + } + } + } + } + + for(std::map::iterator it_sdi = DOI_item.map_sdI.begin(); it_sdi != DOI_item.map_sdI.end(); it_sdi++) + { + if(p_all_do->map_all_sdo.find(it_sdi->first) != p_all_do->map_all_sdo.end()) + { + stru_all_DO *p_all_sdo = p_all_do->map_all_sdo[it_sdi->first]; + stru_SDI &SDI_item = it_sdi->second; + + if(NULL == p_all_sdo) + { + LOG_E("p_all_sdo is NULL"); + continue; + } + + model_sync_SDO_default_values(icd, SDI_item, p_all_sdo); + } + + if(p_all_do->map_all_da.find(it_sdi->first) != p_all_do->map_all_da.end()) + { + stru_all_DA *p_all_da = p_all_do->map_all_da[it_sdi->first]; + stru_SDI &SDI_item = it_sdi->second; + + if(NULL == p_all_da) + { + LOG_E("p_all_da is NULL"); + continue; + } + + model_sync_da_default_values(icd, SDI_item, p_all_da); + } + } + } +} + +void model_sync_ied_default_values(stru_icd &icd) +{ + for(std::map::iterator it_ld = icd.ied.map_ldevice.begin(); it_ld!= icd.ied.map_ldevice.end(); it_ld++) + { + model_sync_ln_default_values(icd, it_ld->second.ln0.map_doI, it_ld->second.ln0.map_all_do); + + for(std::vector::iterator it_ln = it_ld->second.vec_ln.begin(); it_ln != it_ld->second.vec_ln.end(); it_ln++) + { + model_sync_ln_default_values(icd, it_ln->map_doI, it_ln->map_all_do); + } + } +} + + +// void model_ied_saddr_point_init(stru_icd &icd) +// { +// for(std::vector::iterator it_saddr = icd.ied.vec_saddr.begin(); it_saddr != icd.ied.vec_saddr.end(); it_saddr++) +// { +// icd.ied.map_saddr_point[*it_saddr].node = IedModel_getModelNodeByShortAddress(icd.ied.model, it_saddr->c_str()); +// if(NULL == icd.ied.map_saddr_point[*it_saddr].node) +// { +// LOG_E("Failed to find node for sAddr %s", it_saddr->c_str()); +// continue; +// } +// } +// } + + +void model_search_ln_control_DataObjects(stru_icd &icd, stru_contorl_DO &in_control_do, stru_all_DO *p_do) +{ + if(NULL == p_do) + { + LOG_E("p_do is NULL"); + return; + } + + stru_contorl_DO control_do = in_control_do; + + for(std::map::iterator it_do = p_do->map_all_sdo.begin(); it_do != p_do->map_all_sdo.end(); it_do++) + { + model_search_ln_control_DataObjects(icd, control_do, it_do->second); + } + + for(std::map::iterator it_da = p_do->map_all_da.begin(); it_da != p_do->map_all_da.end(); it_da++) + { + if(it_da->first.compare("ctlModel") == 0) + { + control_do.p_all_do = p_do; + icd.ied.vec_control_do.push_back(control_do); + } + } +} + + +void model_search_control_DataObjects(stru_icd &icd) +{ + stru_contorl_DO control_do; + + for(std::map::iterator it_ld = icd.ied.map_ldevice.begin(); it_ld!= icd.ied.map_ldevice.end(); it_ld++) + { + control_do.ldevice_inst = it_ld->first; + stru_LDevice &ld = it_ld->second; + + for(std::map::iterator it_do = ld.ln0.map_all_do.begin(); it_do != ld.ln0.map_all_do.end(); it_do++) + { + control_do.ln_class = ld.ln0.lnClass; + control_do.ln_inst = ""; + control_do.ln_type = ld.ln0.lnType; + control_do.ln_prefix = ""; + control_do.do_name = it_do->first; + model_search_ln_control_DataObjects(icd, control_do, it_do->second); + } + + for(std::vector::iterator it_ln = ld.vec_ln.begin(); it_ln != ld.vec_ln.end(); it_ln++) + { + control_do.ln_class = it_ln->lnClass; + control_do.ln_inst = it_ln->inst; + control_do.ln_type = it_ln->lnType; + control_do.ln_prefix = it_ln->prefix; + for(std::map::iterator it_do = it_ln->map_all_do.begin(); it_do != it_ln->map_all_do.end(); it_do++) + { + control_do.do_name = it_do->first; + model_search_ln_control_DataObjects(icd, control_do, it_do->second); + } + } + } +} + +void model_all_da_show(std::map map_all_da) +{ + for(auto it_map_all_da : map_all_da) + { + auto it = it_map_all_da.second; + printf("\t%s, btype %s, fc %s, sAddr %s\n", it_map_all_da.first.c_str(), it->bType.c_str(), it->fc.c_str(), it->sAddr.c_str()); + } +} + +void model_all_do_show(std::map map_all_do) +{ + for(auto it_map_all_do : map_all_do) + { + auto it = it_map_all_do.second; + printf("\t%s\n", it_map_all_do.first.c_str()); + + model_all_do_show(it->map_all_sdo); + model_all_da_show(it->map_all_da); + } +} + +void model_info_show(stru_icd &icd) +{ + for(auto it_vec_ld : icd.ied.vec_ldevice) + { + printf("ldInst %s\n", it_vec_ld.c_str()); + auto it_map_ld = icd.ied.map_ldevice.find(it_vec_ld); + + for(auto itvec_ln : it_map_ld->second.vec_ln) + { + printf("\tlnClass %s, inst %s, lnType %s, prefix %s\n", itvec_ln.lnClass.c_str(), itvec_ln.inst.c_str(), itvec_ln.lnType.c_str(), itvec_ln.prefix.c_str()); + + for(auto it_map_all_do : itvec_ln.map_all_do) + { + model_all_do_show(it_map_all_do.second->map_all_sdo); + model_all_da_show(it_map_all_do.second->map_all_da); + } + } + + } +} + +/* + * model_init - Initializes the IED model + input: icd - ICD structure + output: // icd.ied.model - IED model + return: 0 on success, -1 on failure +*/ +int model_init(stru_icd &icd) +{ + icd.ied.model = IedModel_create(icd.ied.name.c_str()); + if(NULL == icd.ied.model) + { + LOG_E("Failed to create IedModel %s", icd.ied.name.c_str()); + return -1; + } + + if(0 != model_ldevice_init(icd.ied.model, icd)) + { + LOG_E("Failed to init logical device %s", icd.ied.name.c_str()); + IedModel_destroy(icd.ied.model); + return -1; + } + + model_info_show(icd); + + model_sync_ied_default_values(icd); + // model_sync_ied_do_ptrs(icd); + + // model_ied_saddr_point_init(icd); + + for(std::vector::iterator it_saddr = icd.ied.vec_saddr.begin(); it_saddr != icd.ied.vec_saddr.end(); it_saddr++) + { + ModelNode *p_node = icd.ied.map_saddr_point[*it_saddr].node; + if(NULL == p_node) + { + LOG_E("saddr %s node is NULL", it_saddr->c_str()); + continue; + } + + std::string str_temp = p_node->name; + + ModelNode *temp_node = p_node->parent; + + while(temp_node) + { + str_temp = std::string(temp_node->name ? temp_node->name : "?") + "." + str_temp; + + if(temp_node->modelType == LogicalDeviceModelType) + { + break; + } + temp_node = temp_node->parent; + } + + LOG_I("sAddr %s, node type %d, name %s", it_saddr->c_str(), p_node->modelType, str_temp.c_str()); + } + + model_search_control_DataObjects(icd); + + icd.ied.model->initializer = mms_s_values_init; + + return 0; +} \ No newline at end of file diff --git a/src/protocol/libmms_s/src/mms_s_param.cpp b/src/protocol/libmms_s/src/mms_s_param.cpp new file mode 100644 index 0000000..2aa159b --- /dev/null +++ b/src/protocol/libmms_s/src/mms_s_param.cpp @@ -0,0 +1,624 @@ +#include +#include "myMms_s.h" +#include "mms_s_param.h" +// #include "cJSON.h" + +LOCAL std::vector vec_params; + +LOCAL mms_s_param_cb g_param_cb = NULL; + +void param_update_BOOLEAN(IedServer server, DataAttribute* dataAttribute, std::string val) +{ + if(NULL == server || NULL == dataAttribute) + { + LOG_E("server or dataAttribute is NULL"); + return; + } + + IedServer_updateBooleanAttributeValue(server, dataAttribute, val == "1" ? true : false); // call +} + +void param_update_INT(IedServer server, DataAttribute* dataAttribute, std::string val) +{ + if(NULL == server || NULL == dataAttribute) + { + LOG_E("server or dataAttribute is NULL"); + return; + } + + IedServer_updateInt32AttributeValue(server, dataAttribute, atoi(val.c_str())); +} + + +void param_update_UINT(IedServer server, DataAttribute* dataAttribute, std::string val) +{ + if(NULL == server || NULL == dataAttribute) + { + LOG_E("server or dataAttribute is NULL"); + return; + } + + IedServer_updateUnsignedAttributeValue(server, dataAttribute, atoi(val.c_str())); +} + +void param_update_FLOAT(IedServer server, DataAttribute* dataAttribute, std::string val) +{ + if(NULL == server || NULL == dataAttribute) + { + LOG_E("server or dataAttribute is NULL"); + return; + } + + IedServer_updateFloatAttributeValue(server, dataAttribute, atof(val.c_str())); +} + +void param_update_VISIBLE_STRING(IedServer server, DataAttribute* dataAttribute, std::string val) +{ + if(NULL == server || NULL == dataAttribute) + { + LOG_E("server or dataAttribute is NULL"); + return; + } + + IedServer_updateVisibleStringAttributeValue(server, dataAttribute, (char *)val.c_str()); +} + +void param_update_STRING(IedServer server, DataAttribute* dataAttribute, std::string val) +{ + if(NULL == server || NULL == dataAttribute) + { + LOG_E("server or dataAttribute is NULL"); + return; + } + + IedServer_updateAttributeValue(server, dataAttribute, MmsValue_newMmsString((char *)val.c_str())); +} + +LOCAL struct +{ + MmsType type; + void (*update_value)(IedServer server, DataAttribute* dataAttribute, std::string val); +}g_param_update_funcs[] = +{ + {MMS_BOOLEAN, param_update_BOOLEAN}, + {MMS_INTEGER, param_update_INT}, + {MMS_UNSIGNED, param_update_UINT}, + {MMS_FLOAT, param_update_FLOAT}, + {MMS_VISIBLE_STRING, param_update_VISIBLE_STRING}, + {MMS_STRING, param_update_STRING}, +}; + +LOCAL int g_param_update_funcs_count = sizeof(g_param_update_funcs)/sizeof(g_param_update_funcs[0]); + + + + +LOCAL void param_load_active_sg_values(stru_LDevice &ld, int actSG) +{ + stru_icd *p_icd = mms_s_get_icd_ptr(); + if(NULL == p_icd) + { + LOG_E("p_icd is NULL"); + return; + } + + for(std::vector::iterator it_param = vec_params.begin(); it_param != vec_params.end(); it_param++) + { + std::string saddr = std::string(it_param->base.saddr) + "_SG"; + + if(it_param->param_num < actSG) + { + LOG_E("param_num %d is not enough for saddr %s, actSG %d", it_param->param_num, saddr.c_str(), actSG); + continue; + } + std::string val = mms_s_get_string_by_type(it_param->data[actSG-1], it_param->base.type); + + if(p_icd->ied.map_saddr_point.find(saddr) == p_icd->ied.map_saddr_point.end()) + { + LOG_E("sAddr %s not found in ICD", saddr.c_str()); + continue; + } + + ModelNode *node = p_icd->ied.map_saddr_point[saddr].node; + if(node == NULL) + { + LOG_E("ModelNode for sAddr %s is NULL", saddr.c_str()); + continue; + } + + int match = 0; + for(int i = 0; i < g_param_update_funcs_count; i++) + { + if(MmsValue_getType(((DataAttribute *)node)->mmsValue) == g_param_update_funcs[i].type) + { + g_param_update_funcs[i].update_value(mms_s_get_ied_server_ptr(), (DataAttribute *)node, val); + match = 1; + break; + } + } + + if(!match) + { + LOG_E("No update function found for sAddr %s with MMS type %d", saddr.c_str(), MmsValue_getType(((DataAttribute *)node)->mmsValue)); + continue; + } + } + + LOG_I("Load active setting group %d values done", actSG); +} + +LOCAL void param_load_edit_sg_values(stru_LDevice &ld, int editSG) +{ + stru_icd *p_icd = mms_s_get_icd_ptr(); + if(NULL == p_icd) + { + LOG_E("p_icd is NULL"); + return; + } + + + for(std::vector::iterator it_param = vec_params.begin(); it_param != vec_params.end(); it_param++) + { + std::string saddr = std::string(it_param->base.saddr) + "_SE"; + + if(it_param->param_num < editSG) + { + LOG_E("param_num %d is not enough for saddr %s, editSG %d", it_param->param_num, saddr.c_str(), editSG); + continue; + } + std::string val = mms_s_get_string_by_type(it_param->data[editSG-1], it_param->base.type); + + if(p_icd->ied.map_saddr_point.find(saddr) == p_icd->ied.map_saddr_point.end()) + { + LOG_E("sAddr %s not found in ICD", saddr.c_str()); + continue; + } + + ModelNode *node = p_icd->ied.map_saddr_point[saddr].node; + if(node == NULL) + { + LOG_E("ModelNode for sAddr %s is NULL", saddr.c_str()); + continue; + } + + int match = 0; + for(int i = 0; i < g_param_update_funcs_count; i++) + { + if(MmsValue_getType(((DataAttribute *)node)->mmsValue) == g_param_update_funcs[i].type) + { + g_param_update_funcs[i].update_value(mms_s_get_ied_server_ptr(), (DataAttribute *)node, val); + match = 1; + break; + } + } + + if(!match) + { + LOG_E("No update function found for sAddr %s with MMS type %d", saddr.c_str(), MmsValue_getType(((DataAttribute *)node)->mmsValue)); + continue; + } + } +} + +LOCAL bool param_active_sg_changed_handler(void* parameter, SettingGroupControlBlock* sgcb, uint8_t newActSg, ClientConnection connection) +{ + if(NULL == parameter || NULL == sgcb) + { + LOG_E("parameter %p or sgcb %p is NULL", parameter, sgcb); + return false; + } + + stru_LDevice *p_ld = (stru_LDevice*)parameter; + + LOG_I("Switch to setting group %i\n", (int) newActSg); + + param_load_active_sg_values(*p_ld, newActSg); + + return true; +} + +LOCAL bool param_edit_sg_changed_handler(void* parameter, SettingGroupControlBlock* sgcb, uint8_t newEditSg, ClientConnection connection) +{ + if(NULL == parameter || NULL == sgcb) + { + LOG_E("parameter %p or sgcb %p is NULL", parameter, sgcb); + return false; + } + + stru_LDevice *p_ld = (stru_LDevice*)parameter; + + LOG_I("Set edit setting group to %i\n", (int) newEditSg); + + param_load_edit_sg_values(*p_ld, newEditSg); + + return true; +} + +LOCAL void param_min_max_step_get(DataAttribute *node, float &min, float &max, float &step) +{ + if(node == NULL) + { + LOG_E("node is NULL"); + return; + } + + if(node->parent == NULL) + { + LOG_E("DataAttribute has no parent"); + return; + } + + MmsType type = MmsValue_getType(node->mmsValue); + if(type == MMS_STRING || type == MMS_BOOLEAN ) + { + // For string type, min, max and step are not applicable + min = 0; + max = 0; + step = 0; + return; + } + + DataAttribute *da_node = (DataAttribute *)node->parent; + + DataAttribute *da_first = (DataAttribute *)da_node->firstChild; + while(da_first != NULL) + { + if(strcmp(da_first->name, "minVal") == 0) + { + if(type == MMS_FLOAT) + { + min = MmsValue_toFloat(da_first->mmsValue); + } + else + { + min = (float)MmsValue_toInt32(da_first->mmsValue); + } + } + else if(strcmp(da_first->name, "maxVal") == 0) + { + if(type == MMS_FLOAT) + { + max = MmsValue_toFloat(da_first->mmsValue); + } + else + { + max = (float)MmsValue_toInt32(da_first->mmsValue); + } + } + else if(strcmp(da_first->name, "stepSize") == 0) + { + if(type == MMS_FLOAT) + { + step = MmsValue_toFloat(da_first->mmsValue); + } + else + { + step = (float)MmsValue_toInt32(da_first->mmsValue); + } + } + + da_first = (DataAttribute *)da_first->sibling; + } +} + + +LOCAL void param_get_BOOLEAN(DataAttribute *node, std::string &val) +{ + if(node == NULL) + { + LOG_E("node is NULL"); + return; + } + + val = MmsValue_getBoolean(node->mmsValue) ? "1" : "0"; +} + +LOCAL void param_get_INT(DataAttribute *node, std::string &val) +{ + if(node == NULL) + { + LOG_E("node is NULL"); + return; + } + + float min, max, step; + param_min_max_step_get(node, min, max, step); + + if((int)step == 0) + { + return; + } + + int intVal = MmsValue_toInt32(node->mmsValue); + if(intVal < (int)min || intVal > (int)max) + { + LOG_E("Value %d is out of range [%d, %d]", intVal, (int)min, (int)max); + return; + } + + int gap = intVal - (int)min; + if(gap != 0 && gap % (int)step != 0) + { + LOG_E("Value %d does not conform to step size %d", intVal, (int)step); + return; + } + + val = std::to_string(intVal); +} + +LOCAL void param_get_UINT(DataAttribute *node, std::string &val) +{ + if(node == NULL) + { + LOG_E("node is NULL"); + return; + } + + float min, max, step; + param_min_max_step_get(node, min, max, step); + + if((uint32_t)step == 0) + { + return; + } + + int uintVal = MmsValue_toUint32(node->mmsValue); + if(uintVal < (uint32_t)min || uintVal > (uint32_t)max) + { + LOG_E("Value %d is out of range [%d, %d]", uintVal, (uint32_t)min, (uint32_t)max); + return; + } + + int gap = uintVal - (uint32_t)min; + if(gap != 0 && gap % (uint32_t)step != 0) + { + LOG_E("Value %d does not conform to step size %d", uintVal, (uint32_t)step); + return; + } + + val = std::to_string(uintVal); +} + +LOCAL void param_get_FLOAT(DataAttribute *node, std::string &val) +{ + if(node == NULL) + { + LOG_E("node is NULL"); + return; + } + + float min, max, step; + param_min_max_step_get(node, min, max, step); + + const float EPSILON = 1e-6; + + float floatVal = MmsValue_toFloat(node->mmsValue); + if(floatVal < min - EPSILON || floatVal > max + EPSILON) + { + LOG_E("Value %f is out of range [%f, %f]", floatVal, min, max); + return; + } + + if(fabs(step) < EPSILON) + { + val = std::to_string(floatVal); + return; + } + + float gap = floatVal - min; + float gap_mod = fmod(gap, step); + + if(fabs(gap_mod) > EPSILON && fabs(gap_mod - step) > EPSILON) + { + LOG_E("Value %f does not conform to step size %f", floatVal, step); + return; + } + + val = std::to_string(floatVal); +} + +LOCAL void param_get_STRING(DataAttribute *node, std::string &val) +{ + if(node == NULL) + { + LOG_E("node is NULL"); + return; + } + + val = MmsValue_toString(node->mmsValue); +} + + +LOCAL struct +{ + MmsType type; + void (*get_value)(DataAttribute *node, std::string &val); +}g_param_get_funcs[] = +{ + {MMS_BOOLEAN, param_get_BOOLEAN}, + {MMS_INTEGER, param_get_INT}, + {MMS_UNSIGNED, param_get_UINT}, + {MMS_FLOAT, param_get_FLOAT}, + {MMS_VISIBLE_STRING, param_get_STRING}, + {MMS_STRING, param_get_STRING}, +}; + +LOCAL int g_param_get_funcs_count = sizeof(g_param_get_funcs)/sizeof(g_param_get_funcs[0]); + +LOCAL void edit_sg_confirmation_handler(void* parameter, SettingGroupControlBlock* sgcb, uint8_t editSg) +{ + if(NULL == parameter || NULL == sgcb) + { + LOG_E("parameter %p or sgcb %p is NULL", parameter, sgcb); + return; + } + + stru_LDevice *p_ld = (stru_LDevice*)parameter; + + LOG_I("Received edit sg confirm for sg %i\n", editSg); + + IedServer server = mms_s_get_ied_server_ptr(); + if(NULL == server) + { + LOG_E("server is NULL"); + return; + } + + stru_icd *p_icd = mms_s_get_icd_ptr(); + if(NULL == p_icd) + { + LOG_E("p_icd is NULL"); + return; + } + + + for(std::vector::iterator it_param = vec_params.begin(); it_param != vec_params.end(); it_param++) + { + std::string saddr = std::string(it_param->base.saddr) + "_SE"; + if(it_param->param_num < editSg) + { + LOG_E("param_num %d is not enough for saddr %s, editSg %d", it_param->param_num, saddr.c_str(), editSg); + continue; + } + std::string val = mms_s_get_string_by_type(it_param->data[editSg-1], it_param->base.type); + + if(p_icd->ied.map_saddr_point.find(saddr) == p_icd->ied.map_saddr_point.end()) + { + LOG_E("sAddr %s not found in ICD", saddr.c_str()); + continue; + } + + ModelNode *node = p_icd->ied.map_saddr_point[saddr].node; + if(node == NULL) + { + LOG_E("ModelNode for sAddr %s is NULL", saddr.c_str()); + continue; + } + + int match = 0; + for(int i = 0; i < g_param_get_funcs_count; i++) + { + if(MmsValue_getType(((DataAttribute *)node)->mmsValue) == g_param_get_funcs[i].type) + { + g_param_get_funcs[i].get_value((DataAttribute *)node, val); + match = 1; + break; + } + } + + if(!match) + { + LOG_E("No get function found for sAddr %s with MMS type %d", saddr.c_str(), MmsValue_getType(((DataAttribute *)node)->mmsValue)); + continue; + } + } + + if(IedServer_getActiveSettingGroup(server, sgcb) == editSg) + { + param_load_active_sg_values(*p_ld, editSg); + } +} + +LOCAL MmsDataAccessError read_access_handler(LogicalDevice* ld, LogicalNode* ln, DataObject* dataObject, FunctionalConstraint fc, ClientConnection connection, void* parameter) +{ + // if(NULL == ld || NULL == ln || NULL == connection || NULL == parameter) + // { + // LOG_E("parameter %p or ld %p or ln %p or connection %p is NULL", parameter, ld, ln, connection); + // return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + // } + + // stru_LDevice *p_ld = (stru_LDevice*)parameter; + + // void* securityToken = ClientConnection_getSecurityToken(connection); + + // if (dataObject) + // printf("Read access to %s/%s.%s[%s]\n", ld->name, ln->name, dataObject->name, FunctionalConstraint_toString(fc)); + // else + // printf("Read access to %s/%s[%s]\n", ld->name, ln->name, FunctionalConstraint_toString(fc)); + + return DATA_ACCESS_ERROR_SUCCESS; +} + +LOCAL void param_values_show() +{ + if(vec_params.empty()) + { + LOG_E("vec_params is empty"); + return; + } + + for(uint16_t i = 0; i < vec_params.size(); i++) + { + stru_mms_s_param ¶m = vec_params[i]; + + printf("saddr %s, desc %s, type %d\n", param.base.saddr, param.base.desc, param.base.type); + for(uint8_t j = 0; j < param.param_num; j++) + { + std::string val = mms_s_get_string_by_type(param.data[j], param.base.type); + printf("index %d, val %s\n", j, val.c_str()); + } + printf("\n"); + } +} + +int mms_s_param_register(stru_mms_s_param *p_param, uint16_t num, mms_s_param_cb cb) +{ + if(nullptr == p_param || num == 0) + { + LOG_E("p_param is NULL or num is 0"); + return -1; + } + + vec_params.clear(); + vec_params.reserve(num); + + for(uint16_t i = 0; i < num; i++) + { + vec_params.push_back(p_param[i]); + } + + if(NULL != cb) + { + g_param_cb = cb; + } + + return 0; +} + +int param_init(IedServer server, stru_icd &icd) +{ + if(vec_params.empty()) + { + LOG_E("vec_params is empty"); + return 0; + } + + param_values_show(); + + for(std::map::iterator it_ld = icd.ied.map_ldevice.begin(); it_ld!= icd.ied.map_ldevice.end(); it_ld++) + { + stru_LDevice *p_ld = &it_ld->second; + + if(NULL == p_ld->sgcb) + { + LOG_E("sgcb of %s is NULL", it_ld->first.c_str()); + continue; + } + + LogicalNode *ln0 = p_ld->sgcb->parent; + LOG_I("ld %s sgcb ln0 %s, actSG %d, numofSGs %d, editSG %d, cnfEdit %d, timestamp %ld, resvTms %d, sibling %p", + it_ld->first.c_str(), ln0 ? ln0->name : "NULL", p_ld->sgcb->actSG, p_ld->sgcb->numOfSGs, p_ld->sgcb->editSG, + p_ld->sgcb->cnfEdit, p_ld->sgcb->timestamp, p_ld->sgcb->resvTms, p_ld->sgcb->sibling); + + param_load_active_sg_values(*p_ld, p_ld->sgcb->actSG); + + IedServer_setActiveSettingGroupChangedHandler(server, p_ld->sgcb, param_active_sg_changed_handler, p_ld); + IedServer_setEditSettingGroupChangedHandler(server, p_ld->sgcb, param_edit_sg_changed_handler, p_ld); + IedServer_setEditSettingGroupConfirmationHandler(server, p_ld->sgcb, edit_sg_confirmation_handler, p_ld); + + IedServer_setReadAccessHandler(server, read_access_handler, p_ld); + } + + + return 0; +} \ No newline at end of file diff --git a/src/protocol/libmms_s/src/mms_s_setting.cpp b/src/protocol/libmms_s/src/mms_s_setting.cpp new file mode 100644 index 0000000..9dc5f2f --- /dev/null +++ b/src/protocol/libmms_s/src/mms_s_setting.cpp @@ -0,0 +1,523 @@ +#include + +#include "myMms_s.h" +#include "mms_s_setting.h" +// #include "cJSON.h" + + + +LOCAL std::vector vec_settings; +LOCAL mms_s_setting_cb cb_setting = NULL; + + +void setting_update_BOOLEAN(IedServer server, DataAttribute* dataAttribute, std::string val) +{ + if(NULL == server || NULL == dataAttribute) + { + LOG_E("server or dataAttribute is NULL"); + return; + } + + IedServer_updateBooleanAttributeValue(server, dataAttribute, val == "1" ? true : false); // call +} + +void setting_update_INT(IedServer server, DataAttribute* dataAttribute, std::string val) +{ + if(NULL == server || NULL == dataAttribute) + { + LOG_E("server or dataAttribute is NULL"); + return; + } + + IedServer_updateInt32AttributeValue(server, dataAttribute, atoi(val.c_str())); +} + + +void setting_update_UINT(IedServer server, DataAttribute* dataAttribute, std::string val) +{ + if(NULL == server || NULL == dataAttribute) + { + LOG_E("server or dataAttribute is NULL"); + return; + } + + IedServer_updateUnsignedAttributeValue(server, dataAttribute, atoi(val.c_str())); +} + +void setting_update_FLOAT(IedServer server, DataAttribute* dataAttribute, std::string val) +{ + if(NULL == server || NULL == dataAttribute) + { + LOG_E("server or dataAttribute is NULL"); + return; + } + + IedServer_updateFloatAttributeValue(server, dataAttribute, atof(val.c_str())); +} + +void setting_update_VISIBLE_STRING(IedServer server, DataAttribute* dataAttribute, std::string val) +{ + if(NULL == server || NULL == dataAttribute) + { + LOG_E("server or dataAttribute is NULL"); + return; + } + + IedServer_updateVisibleStringAttributeValue(server, dataAttribute, (char *)val.c_str()); +} + +void setting_update_STRING(IedServer server, DataAttribute* dataAttribute, std::string val) +{ + if(NULL == server || NULL == dataAttribute) + { + LOG_E("server or dataAttribute is NULL"); + return; + } + + IedServer_updateAttributeValue(server, dataAttribute, MmsValue_newMmsString((char *)val.c_str())); +} + +LOCAL struct +{ + MmsType type; + void (*update_value)(IedServer server, DataAttribute* dataAttribute, std::string val); +}g_setting_update_funcs[] = +{ + {MMS_BOOLEAN, setting_update_BOOLEAN}, + {MMS_INTEGER, setting_update_INT}, + {MMS_UNSIGNED, setting_update_UINT}, + {MMS_FLOAT, setting_update_FLOAT}, + {MMS_VISIBLE_STRING, setting_update_VISIBLE_STRING}, + {MMS_STRING, setting_update_STRING}, +}; + +LOCAL int g_setting_update_funcs_count = sizeof(g_setting_update_funcs)/sizeof(g_setting_update_funcs[0]); + + + +LOCAL void setting_value_init(IedServer server, stru_icd &icd) +{ + for(std::vector::iterator it = vec_settings.begin(); it != vec_settings.end(); it++) + { + std::string sAddr = it->base.saddr; + std::string str = mms_s_get_string_by_type(it->data, it->base.type); + + if(icd.ied.map_saddr_point.find(sAddr) == icd.ied.map_saddr_point.end()) + { + LOG_E("sAddr %s not found in ICD", sAddr.c_str()); + continue; + } + + ModelNode *node = icd.ied.map_saddr_point[sAddr].node; + if(node == NULL) + { + LOG_E("ModelNode for sAddr %s is NULL", sAddr.c_str()); + continue; + } + + if(((DataAttribute *)node)->fc != IEC61850_FC_SP) + { + LOG_E("sAddr %s is not SP", sAddr.c_str()); + continue; + } + + int match = 0; + for(int i = 0; i < g_setting_update_funcs_count; i++) + { + if(MmsValue_getType(((DataAttribute *)node)->mmsValue) == g_setting_update_funcs[i].type) + { + g_setting_update_funcs[i].update_value(server, (DataAttribute *)node, str); + match = 1; + break; + } + } + + if(!match) + { + LOG_E("No update function found for sAddr %s with MMS type %d", sAddr.c_str(), MmsValue_getType(((DataAttribute *)node)->mmsValue)); + } + } +} + + +LOCAL void setting_min_max_step_get(DataAttribute *node, float &min, float &max, float &step) +{ + if(node == NULL) + { + LOG_E("node is NULL"); + return; + } + + if(node->parent == NULL) + { + LOG_E("DataAttribute has no parent"); + return; + } + + MmsType type = MmsValue_getType(node->mmsValue); + if(type == MMS_STRING || type == MMS_BOOLEAN) + { + // For string type, min, max and step are not applicable + min = 0; + max = 0; + step = 0; + return; + } + + DataAttribute *da_node = (DataAttribute *)node->parent; + + DataAttribute *da_first = (DataAttribute *)da_node->firstChild; + while(da_first != NULL) + { + if(strcmp(da_first->name, "minVal") == 0) + { + if(type == MMS_FLOAT) + { + min = MmsValue_toFloat(da_first->mmsValue); + } + else + { + min = (float)MmsValue_toInt32(da_first->mmsValue); + } + } + else if(strcmp(da_first->name, "maxVal") == 0) + { + if(type == MMS_FLOAT) + { + max = MmsValue_toFloat(da_first->mmsValue); + } + else + { + max = (float)MmsValue_toInt32(da_first->mmsValue); + } + } + else if(strcmp(da_first->name, "stepSize") == 0) + { + if(type == MMS_FLOAT) + { + step = MmsValue_toFloat(da_first->mmsValue); + } + else + { + step = (float)MmsValue_toInt32(da_first->mmsValue); + } + } + + da_first = (DataAttribute *)da_first->sibling; + } +} + +LOCAL int setting_get_BOOLEAN(DataAttribute *node, MmsValue* value, std::string &val_str) +{ + if(node == NULL || value == NULL) + { + LOG_E("node or value is NULL"); + return -1; + } + + bool val = MmsValue_getBoolean(value); + + if(val != true && val != false) + { + LOG_E("Invalid boolean value for node %s", node->name); + return -1; + } + + LOG_I("Boolean value for node %s is %d", node->name, val); + val_str = val ? "true" : "false"; + return 0; +} + +LOCAL int setting_get_INT(DataAttribute *node, MmsValue* value, std::string &val_str) +{ + if(node == NULL || value == NULL) + { + LOG_E("node or value is NULL"); + return -1; + } + + float min, max, step; + setting_min_max_step_get(node, min, max, step); + + if((int)step == 0) + { + return -1; + } + + int intVal = MmsValue_toInt32(value); + if(intVal < (int)min || intVal > (int)max) + { + LOG_E("Value %d is out of range [%d, %d]", intVal, (int)min, (int)max); + return -1; + } + + int gap = intVal - (int)min; + if(gap != 0 && gap % (int)step != 0) + { + LOG_E("Value %d does not conform to step size %d", intVal, (int)step); + return -1; + } + + LOG_I("Integer value for node %s is %d", node->name, intVal); + val_str = std::to_string(intVal); + return 0; +} + +LOCAL int setting_get_UINT(DataAttribute *node, MmsValue* value, std::string &val_str) +{ + if(node == NULL || value == NULL) + { + LOG_E("node or value is NULL"); + return -1; + } + + float min, max, step; + setting_min_max_step_get(node, min, max, step); + + if((uint32_t)step == 0) + { + return -1; + } + + int uintVal = MmsValue_toUint32(value); + if(uintVal < (uint32_t)min || uintVal > (uint32_t)max) + { + LOG_E("Value %d is out of range [%d, %d]", uintVal, (uint32_t)min, (uint32_t)max); + return -1; + } + + int gap = uintVal - (uint32_t)min; + if(gap != 0 && gap % (uint32_t)step != 0) + { + LOG_E("Value %d does not conform to step size %d", uintVal, (uint32_t)step); + return -1; + } + + LOG_I("Unsigned integer value for node %s is %d", node->name, uintVal); + val_str = std::to_string(uintVal); + return 0; +} + +LOCAL int setting_get_FLOAT(DataAttribute *node, MmsValue* value, std::string &val_str) +{ + if(node == NULL || value == NULL) + { + LOG_E("node or value is NULL"); + return -1; + } + + float min, max, step; + setting_min_max_step_get(node, min, max, step); + + const float EPSILON = 1e-6; + + float floatVal = MmsValue_toFloat(value); + if(floatVal < min - EPSILON || floatVal > max + EPSILON) + { + LOG_E("Value %f is out of range [%f, %f]", floatVal, min, max); + return -1; + } + + if(fabs(step) < EPSILON) + { + return 0; + } + + float gap = floatVal - min; + float gap_mod = fmod(gap, step); + + if(fabs(gap_mod) > EPSILON && fabs(gap_mod - step) > EPSILON) + { + LOG_E("Value %f does not conform to step size %f", floatVal, step); + return -1; + } + + LOG_I("Float value for node %s is %f", node->name, floatVal); + val_str = std::to_string(floatVal); + return 0; +} + +LOCAL int setting_get_STRING(DataAttribute *node, MmsValue* value, std::string &val_str) +{ + if(node == NULL || value == NULL) + { + LOG_E("node or value is NULL"); + return -1; + } + + LOG_I("String value for node %s is %s", node->name, MmsValue_toString(value)); + val_str = MmsValue_toString(value); + return 0; +} + + +LOCAL struct +{ + MmsType type; + int (*get_value)(DataAttribute *node, MmsValue* value, std::string &val_str); +}g_setting_get_funcs[] = +{ + {MMS_BOOLEAN, setting_get_BOOLEAN}, + {MMS_INTEGER, setting_get_INT}, + {MMS_UNSIGNED, setting_get_UINT}, + {MMS_FLOAT, setting_get_FLOAT}, + {MMS_VISIBLE_STRING, setting_get_STRING}, + {MMS_STRING, setting_get_STRING}, +}; + +LOCAL int g_setting_get_funcs_count = sizeof(g_setting_get_funcs)/sizeof(g_setting_get_funcs[0]); + +LOCAL MmsDataAccessError writeAccessHandler (DataAttribute* dataAttribute, MmsValue* value, ClientConnection connection, void* parameter) +{ + stru_icd *p_icd = mms_s_get_icd_ptr(); + if(NULL == p_icd) + { + LOG_E("p_icd is NULL"); + return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; + } + + LOG_I("da %p, value %p, connection %p, parameter %p", dataAttribute, value, connection, parameter); + if(dataAttribute) + { + LOG_I("da name: %s, sAddr: %s, fc %d", dataAttribute->name, dataAttribute->sAddr, dataAttribute->fc); + } + + // for(int i = 0; i < vec_settings.size(); i++) + for(std::vector::iterator it = vec_settings.begin(); it != vec_settings.end(); it++) + { + std::string sAddr = it->base.saddr; + + if(p_icd->ied.map_saddr_point.find(sAddr) == p_icd->ied.map_saddr_point.end()) + { + LOG_E("sAddr %s not found in ICD", sAddr.c_str()); + continue; + } + + ModelNode *node = p_icd->ied.map_saddr_point[sAddr].node; + if(node == NULL) + { + LOG_E("ModelNode for sAddr %s is NULL", sAddr.c_str()); + continue; + } + + if(node != (ModelNode *)dataAttribute) + { + continue; + } + + for(int i = 0; i < g_setting_get_funcs_count; i++) + { + if(MmsValue_getType(dataAttribute->mmsValue) == g_setting_get_funcs[i].type) + { + std::string val_str = ""; + int ret = g_setting_get_funcs[i].get_value(dataAttribute, value, val_str); + if(ret == 0) + { + if(cb_setting != NULL) + { + LOG_I("cb_setting %p, sAddr %s, val %s", cb_setting, sAddr.c_str(), val_str.c_str()); + cb_setting(&*it, val_str.c_str()); + } + return DATA_ACCESS_ERROR_SUCCESS; + } + break; + } + } + } + + LOG_E("No update function found for sAddr %s with MMS type %d", dataAttribute->sAddr, MmsValue_getType(dataAttribute->mmsValue)); + return DATA_ACCESS_ERROR_OBJECT_ACCESS_DENIED; +} + + +LOCAL void setting_handle_init(IedServer server, stru_icd &icd) +{ + for(int i = 0; i < vec_settings.size(); i++) + { + std::string sAddr = vec_settings[i].base.saddr; + + if(icd.ied.map_saddr_point.find(sAddr) == icd.ied.map_saddr_point.end()) + { + LOG_E("sAddr %s not found in ICD", sAddr.c_str()); + continue; + } + + ModelNode *node = icd.ied.map_saddr_point[sAddr].node; + if(node == NULL) + { + LOG_E("ModelNode for sAddr %s is NULL", sAddr.c_str()); + continue; + } + + if(node->modelType != DataAttributeModelType) + { + LOG_E("ModelNode for sAddr %s is not DataAttributeModelType", sAddr.c_str()); + continue; + } + + if(((DataAttribute *)node)->fc != IEC61850_FC_SP) + { + LOG_E("sAddr %s is not SP", sAddr.c_str()); + continue; + } + + IedServer_handleWriteAccess(server, (DataAttribute *)node, writeAccessHandler, NULL); + + DataAttribute *da = (DataAttribute *)node; + LOG_I("Write access handler set for sAddr %s, data attribute name: %s, da %p", sAddr.c_str(), da->name, da); + } +} + +LOCAL void setting_values_show() +{ + for(int i = 0; i < vec_settings.size(); i++) + { + stru_mms_s_setting &setting = vec_settings[i]; + LOG_I("saddr %s, desc %s, type %d", + setting.base.saddr, setting.base.desc, setting.base.type); + } +} + +int mms_s_setting_register(stru_mms_s_setting *p_setting, uint16_t num, mms_s_setting_cb cb) +{ + if(p_setting == NULL || num == 0) + { + LOG_E("p_setting or num is NULL or 0"); + return -1; + } + + vec_settings.clear(); + vec_settings.reserve(num); + + for(int i = 0; i < num; i++) + { + vec_settings.push_back(p_setting[i]); + } + + if(cb != NULL) + { + cb_setting = cb; + } + + return 0; +} + +int setting_init(IedServer server, stru_icd &icd) +{ + if(vec_settings.empty()) + { + LOG_E("vec_settings is empty"); + return 0; + } + + setting_values_show(); + + setting_value_init(server, icd); + + /* Don't allow access to SP variables by default */ + IedServer_setWriteAccessPolicy(server, IEC61850_FC_SP, ACCESS_POLICY_DENY); + + setting_handle_init(server, icd); + + return 0; +} \ No newline at end of file diff --git a/src/protocol/libmms_s/src/mms_s_value.cpp b/src/protocol/libmms_s/src/mms_s_value.cpp new file mode 100644 index 0000000..410c599 --- /dev/null +++ b/src/protocol/libmms_s/src/mms_s_value.cpp @@ -0,0 +1,767 @@ +#include "mms_s_value.h" + + +LOCAL void model_da_value_update_Boolean(IedServer server, DataAttribute *da, void *value); +LOCAL void model_da_value_update_INT32(IedServer server, DataAttribute *da, void *value); +LOCAL void model_da_value_update_INT32U(IedServer server, DataAttribute *da, void *value); +LOCAL void model_da_value_update_FLOAT32(IedServer server, DataAttribute *da, void *value); +LOCAL void model_da_value_update_Enum(IedServer server, DataAttribute *da, void *value); +LOCAL void model_da_value_update_Visible_String(IedServer server, DataAttribute *da, void *value); +LOCAL void model_da_value_update_Unicode_String(IedServer server, DataAttribute *da, void *value); +LOCAL void model_da_value_update_timesramp(IedServer server, DataAttribute *da, void *value); + +LOCAL struct +{ + const char *btype; + void (*value_update_cb)(IedServer server, DataAttribute *da, void *value); +}g_iec61850s_value_update_cb[] = +{ + {"BOOLEAN", model_da_value_update_Boolean}, + {"INT8", NULL}, + {"INT16", NULL}, + {"INT32", model_da_value_update_INT32}, + {"INT64", NULL}, + {"INT128", NULL}, + {"INT8U", NULL}, + {"INT16U", NULL}, + {"INT32U", model_da_value_update_INT32U}, + {"FLOAT32", model_da_value_update_FLOAT32}, + {"FLOAT64", NULL}, + {"Enum", model_da_value_update_Enum}, + {"Octet64", NULL}, + {"Octet6", NULL}, + {"Octet8", NULL}, + {"VisString32", model_da_value_update_Visible_String}, + {"VisString64", model_da_value_update_Visible_String}, + {"VisString65", model_da_value_update_Visible_String}, + {"VisString129", model_da_value_update_Visible_String}, + {"VisString255", model_da_value_update_Visible_String}, + {"Unicode255", model_da_value_update_Unicode_String}, + {"Timestamp", model_da_value_update_timesramp}, + {"Quality", NULL}, + {"Check", NULL}, + {"CodedEnum", NULL}, + {"BitString", NULL}, + {"Struct", NULL}, + {"EntryTime", NULL}, + {"PhyComAddr", NULL}, + {"Currency", NULL}, + {"OptFlds", NULL}, + {"TrgOps", NULL}, + {"Dbpos", NULL}, +}; +LOCAL int g_iec61850s_value_update_cb_count = sizeof(g_iec61850s_value_update_cb) / sizeof(g_iec61850s_value_update_cb[0]); + + +LOCAL void model_da_value_update_Boolean(IedServer server, DataAttribute *da, void *value) +{ + if(NULL == server || NULL == da || NULL == value || strlen((char*)value) == 0) + { + // LOG_E("server, da or value is NULL"); + return; + } + + int int_value = atoi((char*)value); + if(int_value == 0) + { + IedServer_updateBooleanAttributeValue(server, da, false); + } + else if(int_value == 1) + { + IedServer_updateBooleanAttributeValue(server, da, true); + } + else + { + LOG_E("Invalid boolean value %s", (char *)value); + } +} + +LOCAL void model_da_value_update_INT32(IedServer server, DataAttribute *da, void *value) +{ + if(NULL == server || NULL == da || NULL == value || strlen((char*)value) == 0) + { + // LOG_E("server, da or value is NULL"); + return; + } + + IedServer_updateInt32AttributeValue(server, da, atoi((char*)value)); +} + +LOCAL void model_da_value_update_INT32U(IedServer server, DataAttribute *da, void *value) +{ + if(NULL == server || NULL == da || NULL == value || strlen((char*)value) == 0) + { + // LOG_E("server, da or value is NULL"); + return; + } + + IedServer_updateUnsignedAttributeValue(server, da, atoi((char*)value)); +} + +LOCAL void model_da_value_update_FLOAT32(IedServer server, DataAttribute *da, void *value) +{ + if(NULL == server || NULL == da || NULL == value || strlen((char*)value) == 0) + { + // LOG_E("server, da or value is NULL"); + return; + } + + IedServer_updateFloatAttributeValue(server, da, atof((char*)value)); +} + +LOCAL void model_da_value_update_Enum(IedServer server, DataAttribute *da, void *value) +{ + if(NULL == server || NULL == da || NULL == value) + { + // LOG_E("server, da or value is NULL"); + return; + } + + LOG_I("da %p, name %s, value %d", da, da->name, *(int *)value); + // IedServer_updateInt32AttributeValue(server, da, *(int *)value); + da->mmsValue = MmsValue_newIntegerFromInt32(*(int *)value); +} + +LOCAL void model_da_value_update_Visible_String(IedServer server, DataAttribute *da, void *value) +{ + if(NULL == server || NULL == da || NULL == value || strlen((char*)value) == 0) + { + // LOG_E("server, da or value is NULL"); + return; + } + + IedServer_updateVisibleStringAttributeValue(server, da, (char*)value); +} + +LOCAL void model_da_value_update_Unicode_String(IedServer server, DataAttribute *da, void *value) +{ + if(NULL == server || NULL == da || NULL == value || strlen((char*)value) == 0) + { + // LOG_E("server, da or value is NULL"); + return; + } + + // LOG_I("da %p, value %s", da, (char*)value); + IedServer_updateAttributeValue(server, da, MmsValue_newMmsString((char*)value)); +} + +LOCAL void model_da_value_update_timesramp(IedServer server, DataAttribute *da, void *value) +{ + if(NULL == server || NULL == da) + { + LOG_E("server or da is NULL"); + return; + } + + IedServer_updateUTCTimeAttributeValue(server, da, Hal_getTimeInMs()); +} + +// void model_dataAttribute_value_init(IedServer server, stru_icd &icd, std::string da_name, stru_DAI &DAI, stru_BDA &BDA_item) +// { +// if(NULL == server) +// { +// LOG_E("server is NULL"); +// return; +// } + +// DataAttribute *da = DAI.DA; +// if(NULL == da) +// { +// LOG_E("DA is NULL"); +// return; +// } + +// // LOG_I("daname %s, btype %s, value %s, da %p", da_name.c_str(), BDA_item.bType.c_str(), DAI.val.c_str(), da); + +// if(BDA_item.bType.compare("Struct") == 0) +// { +// if(icd.map_daType.find(BDA_item.type) == icd.map_daType.end()) +// { +// LOG_E("DAType %s not found in ICD", BDA_item.type.c_str()); +// return; +// } + +// std::map::iterator it_dai; +// for(it_dai = DAI.map_daI.begin(); it_dai != DAI.map_daI.end(); it_dai++) +// { +// model_dataAttribute_value_init(server, icd, it_dai->first, it_dai->second, icd.map_daType[BDA_item.type].map_bda[it_dai->first]); +// } + +// } +// else if(BDA_item.bType.compare("Enum") == 0) +// { +// if(icd.map_enumType.find(BDA_item.type) == icd.map_enumType.end()) +// { +// LOG_E("EnumType %s not found in ICD", BDA_item.type.c_str()); +// return; +// } + +// if(DAI.val.empty()) +// { +// int temp = 0; +// model_da_value_update_Enum(server, da, (void*)&temp); +// // LOG_I("Enum value is empty, set to 0"); +// return; +// } +// else +// { +// // LOG_I("Enum value %s", DAI.val.c_str()); +// } + +// std::map::iterator it_enum; +// for(it_enum = icd.map_enumType[BDA_item.type].map_enumVal.begin(); it_enum != icd.map_enumType[BDA_item.type].map_enumVal.end(); it_enum++) +// { +// if(it_enum->second.compare(DAI.val) == 0) +// { +// model_da_value_update_Enum(server, da, (void*)&it_enum->first); +// } +// else if(it_enum->first == atoi(DAI.val.c_str())) +// { +// model_da_value_update_Enum(server, da, (void*)&it_enum->first); +// } +// } +// } +// else +// { +// for(int i = 0; i < g_iec61850s_value_update_cb_count; i++) +// { +// if(BDA_item.bType.compare(g_iec61850s_value_update_cb[i].btype) == 0) +// { +// if(g_iec61850s_value_update_cb[i].value_update_cb != NULL) +// { +// g_iec61850s_value_update_cb[i].value_update_cb(server, da, (void*)DAI.val.c_str()); +// } +// else +// { +// LOG_E("No value update callback for bType %s", BDA_item.bType.c_str()); +// } +// break; +// } +// } +// } +// } + +// void model_dataAttribute_value_init(IedServer server, stru_icd &icd, std::string da_name, stru_DAI &DAI, stru_DA &DA_item) +// { +// if(NULL == server) +// { +// LOG_E("server is NULL"); +// return; +// } + +// DataAttribute *da = DAI.DA; +// if(NULL == da) +// { +// LOG_E("DA is NULL"); +// return; +// } + +// // LOG_I("daname %s, btype %s, value %s, da %p", da_name.c_str(), DA_item.bType.c_str(), DAI.val.c_str(), da); + +// if(DA_item.bType.compare("Struct") == 0) +// { +// if(icd.map_daType.find(DA_item.type) == icd.map_daType.end()) +// { +// LOG_E("DAType %s not found in ICD", DA_item.type.c_str()); +// return; +// } + +// std::map::iterator it_dai; +// for(it_dai = DAI.map_daI.begin(); it_dai != DAI.map_daI.end(); it_dai++) +// { +// model_dataAttribute_value_init(server, icd, it_dai->first, it_dai->second, icd.map_daType[DA_item.type].map_bda[it_dai->first]); +// } + +// } +// else if(DA_item.bType.compare("Enum") == 0) +// { +// if(icd.map_enumType.find(DA_item.type) == icd.map_enumType.end()) +// { +// LOG_E("EnumType %s not found in ICD", DA_item.type.c_str()); +// return; +// } + +// if(DAI.val.empty()) +// { +// int temp = 0; +// model_da_value_update_Enum(server, da, (void*)&temp); +// LOG_I("Enum value is empty, set to 0"); +// return; +// } +// else +// { +// // LOG_I("Enum value %s", DAI.val.c_str()); +// } + +// std::map::iterator it_enum; +// for(it_enum = icd.map_enumType[DA_item.type].map_enumVal.begin(); it_enum != icd.map_enumType[DA_item.type].map_enumVal.end(); it_enum++) +// { +// if(it_enum->second.compare(DAI.val) == 0) +// { +// model_da_value_update_Enum(server, da, (void*)&it_enum->first); +// } +// else if(it_enum->first == atoi(DAI.val.c_str())) +// { +// model_da_value_update_Enum(server, da, (void*)&it_enum->first); +// } +// } +// } +// else +// { +// for(int i = 0; i < g_iec61850s_value_update_cb_count; i++) +// { +// if(DA_item.bType.compare(g_iec61850s_value_update_cb[i].btype) == 0) +// { +// if(g_iec61850s_value_update_cb[i].value_update_cb != NULL) +// { +// g_iec61850s_value_update_cb[i].value_update_cb(server, da, (void*)DAI.val.c_str()); +// } +// else +// { +// LOG_E("No value update callback for bType %s", DA_item.bType.c_str()); +// } +// break; +// } +// } +// } + +// } + + +// /* +// * model_dataObject_value_init - initialize the values of the data objects in the IED model +// input: server - the IedServer object +// icd - the ICD object, contains all the information of the model and values +// lnType_item - the LNodeType object, contains all the information of the logical node type +// map_all_do - the map of all data objects in the IED model +// map_doI - the map of data object instances in the IED model +// output: +// return: 0 - success, other - failure +// */ +// int model_dataObject_value_init(IedServer server, stru_icd &icd, stru_LNodeType &lnType_item, std::map &map_all_do, std::map &map_doI) +// { +// for(std::map::iterator it_doI = map_doI.begin(); it_doI != map_doI.end(); it_doI++) +// { +// // LOG_I("doiname %s", it_doI->first.c_str()); +// if(map_all_do.find(it_doI->first) == map_all_do.end()) +// { +// LOG_E("Data object %s not found in map_all_do", it_doI->first.c_str()); +// continue; +// } +// stru_all_DO &all_DO_item = *map_all_do[it_doI->first]; + +// it_doI->second.DO = all_DO_item.DO; + +// if(lnType_item.map_do.find(it_doI->first) == lnType_item.map_do.end()) +// { +// LOG_E("Data object %s not found in lnType_item.map_do", it_doI->first.c_str()); +// continue; +// } +// stru_DO &DO_item = lnType_item.map_do[it_doI->first]; + +// if(icd.map_doType.find(DO_item.type) == icd.map_doType.end()) +// { +// LOG_E("DOType %s not found in ICD", DO_item.type.c_str()); +// continue; +// } +// stru_DOType &DOType_item = icd.map_doType[DO_item.type]; + +// for(std::map::iterator it_dai = it_doI->second.map_daI.begin(); it_dai != it_doI->second.map_daI.end(); it_dai++) +// { +// if(all_DO_item.map_all_sdo.find(it_dai->first) != all_DO_item.map_all_sdo.end()) +// { +// if(DOType_item.map_sdo.find(it_dai->first) == DOType_item.map_sdo.end()) +// { +// LOG_E("SDO %s not found in DOType %s", it_dai->first.c_str(), DO_item.type.c_str()); +// continue; +// } + + +// } +// else if(all_DO_item.map_all_da.find(it_dai->first) != all_DO_item.map_all_da.end()) +// { +// if(DOType_item.map_da.find(it_dai->first) == DOType_item.map_da.end()) +// { +// LOG_E("DA %s not found in DOType %s", it_dai->first.c_str(), DO_item.type.c_str()); +// continue; +// } +// model_dataAttribute_value_init(server, icd, it_dai->first, it_dai->second, DOType_item.map_da[it_dai->first]); +// } +// } + +// } + + + + +// return 0; +// } + + + +// /* +// * iec61850s_value_update - update the values of the data attributes in the IED model +// input: server - the IedServer object +// icd - the ICD object, contains all the information of the model and values +// output: +// return: +// */ +// void iec61850s_value_update(IedServer server, stru_icd &icd) +// { +// if(NULL == server) +// { +// LOG_E("server is NULL"); +// return; +// } + +// // for each logical device in the IED model +// for(std::map::iterator it_ld = icd.ied.map_ldevice.begin(); it_ld!= icd.ied.map_ldevice.end(); it_ld++) +// { +// // LOG_I("ldname %s", it_ld->first.c_str()); +// // LLN0 +// if(icd.map_lnType.find(it_ld->second.ln0.lnType) != icd.map_lnType.end()) +// { +// // LOG_I("ln0 lnType %s", it_ld->second.ln0.lnType.c_str()); +// model_dataObject_value_init(server, icd, icd.map_lnType[it_ld->second.ln0.lnType], it_ld->second.ln0.map_all_do, it_ld->second.ln0.map_doI); +// } +// else +// { +// LOG_E("lnType %s not found in ICD", it_ld->second.ln0.lnType.c_str()); +// } + +// // for each logical node in the logical device +// for(std::vector::iterator it_ln = it_ld->second.vec_ln.begin(); it_ln != it_ld->second.vec_ln.end(); it_ln++) +// { +// if(icd.map_lnType.find(it_ln->lnType) != icd.map_lnType.end()) +// { +// // LOG_I("ln lnType %s", it_ln->lnType.c_str()); +// model_dataObject_value_init(server, icd, icd.map_lnType[it_ln->lnType], it_ln->map_all_do, it_ln->map_doI); +// } +// else +// { +// LOG_E("lnType %s not found in ICD", it_ln->lnType.c_str()); +// } +// } +// } +// } + + + +LOCAL void mms_s_da_value_init_BOOLEAN(DataAttribute *da, void *value); +LOCAL void mms_s_da_value_init_INT32(DataAttribute *da, void *value); +LOCAL void mms_s_da_value_init_INT32U(DataAttribute *da, void *value); +LOCAL void mms_s_da_value_init_FLOAT32(DataAttribute *da, void *value); +LOCAL void mms_s_da_value_init_Visible_String(DataAttribute *da, void *value); +LOCAL void mms_s_da_value_init_Unicode_String(DataAttribute *da, void *value); +LOCAL void mms_s_da_value_init_Timestamp(DataAttribute *da, void *value); +LOCAL void mms_s_da_value_init_Dbpos(DataAttribute *da, void *value); + +LOCAL struct +{ + const char *bType; + void (*value_init)(DataAttribute *da, void *value); +}g_iec61850s_value_init_cb[] = +{ + {"BOOLEAN", mms_s_da_value_init_BOOLEAN}, + {"INT8", NULL}, + {"INT16", NULL}, + {"INT32", mms_s_da_value_init_INT32}, + {"INT64", NULL}, + {"INT128", NULL}, + {"INT8U", mms_s_da_value_init_INT32U}, + {"INT16U", NULL}, + {"INT32U", mms_s_da_value_init_INT32U}, + {"FLOAT32", mms_s_da_value_init_FLOAT32}, + {"FLOAT64", NULL}, + {"Enum", NULL}, + {"Octet64", NULL}, + {"Octet6", NULL}, + {"Octet8", NULL}, + {"VisString32", mms_s_da_value_init_Visible_String}, + {"VisString64", mms_s_da_value_init_Visible_String}, + {"VisString65", mms_s_da_value_init_Visible_String}, + {"VisString129", mms_s_da_value_init_Visible_String}, + {"VisString255", mms_s_da_value_init_Visible_String}, + {"Unicode255", mms_s_da_value_init_Unicode_String}, + {"Timestamp", mms_s_da_value_init_Timestamp}, + {"Quality", NULL}, + {"Check", NULL}, + {"CodedEnum", NULL}, + {"BitString", NULL}, + {"Struct", NULL}, + {"EntryTime", NULL}, + {"PhyComAddr", NULL}, + {"Currency", NULL}, + {"OptFlds", NULL}, + {"TrgOps", NULL}, + {"Dbpos", mms_s_da_value_init_Dbpos}, +}; + +LOCAL int g_iec61850s_value_init_cb_count = sizeof(g_iec61850s_value_init_cb) / sizeof(g_iec61850s_value_init_cb[0]); + +LOCAL void mms_s_da_value_init_BOOLEAN(DataAttribute *da, void *value) +{ + if(NULL == da) + { + LOG_E("da is NULL"); + return; + } + + if(value == NULL || strlen((char*)value) == 0 || strcmp((char*)value, "false") == 0 || strcmp((char*)value, "0") == 0) + { + da->mmsValue = MmsValue_newBoolean(false); + } + + if(value != NULL && (strcmp((char*)value, "true") == 0 || strcmp((char*)value, "1") == 0)) + { + da->mmsValue = MmsValue_newBoolean(true); + } +} + +LOCAL void mms_s_da_value_init_INT32(DataAttribute *da, void *value) +{ + if(NULL == da) + { + LOG_E("da is NULL"); + return; + } + + if(value == NULL || strlen((char*)value) == 0) + { + da->mmsValue = MmsValue_newIntegerFromInt32(0); + } + else + { + da->mmsValue = MmsValue_newIntegerFromInt32(atoi((char*)value)); + } +} + +LOCAL void mms_s_da_value_init_INT32U(DataAttribute *da, void *value) +{ + if(NULL == da) + { + LOG_E("da is NULL"); + return; + } + + if(value == NULL || strlen((char*)value) == 0) + { + da->mmsValue = MmsValue_newUnsignedFromUint32(0); + } + else + { + da->mmsValue = MmsValue_newUnsignedFromUint32(atoi((char*)value)); + } +} + +LOCAL void mms_s_da_value_init_FLOAT32(DataAttribute *da, void *value) +{ + if(NULL == da) + { + LOG_E("da is NULL"); + return; + } + + if(value == NULL || strlen((char*)value) == 0) + { + da->mmsValue = MmsValue_newFloat(0.0); + } + else + { + da->mmsValue = MmsValue_newFloat(atof((char*)value)); + } +} + +LOCAL void mms_s_da_value_init_Visible_String(DataAttribute *da, void *value) +{ + if(NULL == da) + { + LOG_E("da is NULL"); + return; + } + + if(value == NULL || strlen((char*)value) == 0) + { + da->mmsValue = MmsValue_newVisibleString(""); + } + else + { + da->mmsValue = MmsValue_newVisibleString((char*)value); + } +} + +LOCAL void mms_s_da_value_init_Unicode_String(DataAttribute *da, void *value) +{ + if(NULL == da) + { + LOG_E("da is NULL"); + return; + } + + if(value == NULL || strlen((char*)value) == 0) + { + da->mmsValue = MmsValue_newMmsString(""); + } + else + { + da->mmsValue = MmsValue_newMmsString((char*)value); + } +} + +LOCAL void mms_s_da_value_init_Timestamp(DataAttribute *da, void *value) +{ + if(NULL == da) + { + LOG_E("da is NULL"); + return; + } + + da->mmsValue = MmsValue_newUtcTimeByMsTime(Hal_getTimeInMs()); +} + +LOCAL void mms_s_da_value_init_Dbpos(DataAttribute *da, void *value) +{ + if(NULL == da) + { + LOG_E("da is NULL"); + return; + } + + Dbpos pos = DBPOS_INTERMEDIATE_STATE; + + if(value == NULL || strlen((char*)value) == 0) + { + pos = DBPOS_INTERMEDIATE_STATE; + } + else + { + int i = atoi((char*)value); + if(i == 0) + { + pos = DBPOS_INTERMEDIATE_STATE; + } + else if(i == 1) + { + pos = DBPOS_OFF; + } + else if(i == 2) + { + pos = DBPOS_ON; + } + else if(i == 3) + { + pos = DBPOS_BAD_STATE; + } + else + { + pos = DBPOS_BAD_STATE; + } + } + + Dbpos_toMmsValue(da->mmsValue, pos); + + LOG_I("da %s-%s, value %s, pos %d", da->parent->name, da->name, (char *)value, pos); +} + +LOCAL void mms_s_da_values_init(stru_icd &icd, std::string da_name, stru_all_DA *p_all_da) +{ + if(NULL == p_all_da) + { + LOG_E("da_name %s p_all_da is NULL", da_name.c_str()); + return; + } + + for(std::map::iterator it_da = p_all_da->map_all_da.begin(); it_da != p_all_da->map_all_da.end(); it_da++) + { + mms_s_da_values_init(icd, it_da->first, it_da->second); + } + + if(p_all_da->bType.compare("Struct") == 0) + { + + } + else if(p_all_da->bType.compare("Enum") == 0) + { + if(icd.map_enumType.find(p_all_da->type) == icd.map_enumType.end()) + { + LOG_E("EnumType %s not found in ICD", p_all_da->type.c_str()); + return; + } + + std::map::iterator it_enum; + for(it_enum = icd.map_enumType[p_all_da->type].map_enumVal.begin(); it_enum != icd.map_enumType[p_all_da->type].map_enumVal.end(); it_enum++) + { + if(it_enum->second.compare(p_all_da->val) == 0) + { + p_all_da->DA->mmsValue = MmsValue_newIntegerFromInt32(it_enum->first); + return; + } + } + + if(icd.map_enumType[p_all_da->type].map_enumVal.find(atoi(p_all_da->val.c_str())) != icd.map_enumType[p_all_da->type].map_enumVal.end()) + { + p_all_da->DA->mmsValue = MmsValue_newIntegerFromInt32(atoi(p_all_da->val.c_str())); + return; + } + + p_all_da->DA->mmsValue = MmsValue_newIntegerFromInt32(0); + // LOG_I("Enum value %s not found in EnumType %s, set to 0", p_all_da->val.c_str(), p_all_da->type.c_str()); + } + else + { + for(int i = 0; i < g_iec61850s_value_init_cb_count; i++) + { + if(p_all_da->bType.compare(g_iec61850s_value_init_cb[i].bType) == 0) + { + if(NULL != g_iec61850s_value_init_cb[i].value_init) + { + // LOG_I("BDAType %s, value %s", p_all_da->bType.c_str(), p_all_da->val.c_str()); + g_iec61850s_value_init_cb[i].value_init(p_all_da->DA, (void *)p_all_da->val.c_str()); + } + else + { + // LOG_E("btype %s, value_init is NULL", p_all_da->bType.c_str()); + } + return; + } + } + + LOG_E("BDAType %s not found in ICD", p_all_da->bType.c_str()); + } +} + +LOCAL void mms_s_do_values_init(stru_icd &icd, std::map &map_all_do) +{ + for(std::map::iterator it_do = map_all_do.begin(); it_do != map_all_do.end(); it_do++) + { + for(std::map::iterator it_sdo = it_do->second->map_all_sdo.begin(); it_sdo != it_do->second->map_all_sdo.end(); it_sdo++) + { + mms_s_do_values_init(icd, it_sdo->second->map_all_sdo); + } + + for(std::map::iterator it_da = it_do->second->map_all_da.begin(); it_da != it_do->second->map_all_da.end(); it_da++) + { + mms_s_da_values_init(icd, it_da->first, it_da->second); + } + } +} + +void mms_s_values_init() +{ + stru_icd *p_icd = mms_s_get_icd_ptr(); + if(NULL == p_icd) + { + LOG_E("p_icd is NULL"); + return; + } + + for(std::map::iterator it_ld = p_icd->ied.map_ldevice.begin(); it_ld!= p_icd->ied.map_ldevice.end(); it_ld++) + { + mms_s_do_values_init(*p_icd, it_ld->second.ln0.map_all_do); + + for(std::vector::iterator it_ln = it_ld->second.vec_ln.begin(); it_ln != it_ld->second.vec_ln.end(); it_ln++) + { + mms_s_do_values_init(*p_icd, it_ln->map_all_do); + } + } +} \ No newline at end of file diff --git a/src/system/RTU/src/app_sys.cpp b/src/system/RTU/src/app_sys.cpp index 6238fdf..1866da4 100644 --- a/src/system/RTU/src/app_sys.cpp +++ b/src/system/RTU/src/app_sys.cpp @@ -29,7 +29,8 @@ LOCAL std::vector g_vec_app = {"app_self_ptl", 0, app_self_ptl_init1, app_self_ptl_init2, (app_func_cb)app_self_ptl, NULL, 0, NULL}, {"app_web_server", 0, app_web_server_init1, app_web_server_init2, (app_func_cb)app_web_server, NULL, 0, NULL}, {"app_iec61850m", 0, app_iec61850m_init1, app_iec61850m_init2, (app_func_cb)app_iec61850m, NULL, 0, NULL}, - + {"app_iec61850s", 0, app_iec61850s_init1, app_iec61850s_init2, (app_func_cb)app_iec61850s, NULL, 0, NULL}, + }; diff --git a/src/system/libdatacenter/src/dc_siganl.cpp b/src/system/libdatacenter/src/dc_siganl.cpp index 78d69f7..343b3b3 100644 --- a/src/system/libdatacenter/src/dc_siganl.cpp +++ b/src/system/libdatacenter/src/dc_siganl.cpp @@ -145,7 +145,7 @@ int dc_get_in_signal_info(const std::string &saddr, std::string &desc, uint8_t & return -1; } -int dc_get_ao_siganl_info(const std::string &saddr, std::string &desc, uint8_t &data_type, stru_signal_param ¶m, uint8_t &ctrl_type, std::vector &vec_p_data, std::vector &vec_p_default_data) +int dc_get_ao_signal_info(const std::string &saddr, std::string &desc, uint8_t &data_type, stru_signal_param ¶m, uint8_t &ctrl_type, std::vector &vec_p_data, std::vector &vec_p_default_data) { stru_signal *p_signal = dc_find_signal(XXH3_128bits(saddr.c_str(), saddr.length()), g_datacenter.signal_ao); if(p_signal == nullptr) @@ -1054,7 +1054,7 @@ int dc_signal_out_with_callback(const std::string &saddr, const std::string &des return dc_signal_add_to_map(signal, g_datacenter.signal_out); } -int dc_signal_in(const std::string &saddr, const std::string &desc, const std::string &link_saddr, uint8_t data_type, void **p_data) +int dc_signal_in(const std::string &saddr, const std::string &desc, const std::string &link_saddr, void **p_data) { if(p_data == nullptr) { @@ -1074,7 +1074,6 @@ int dc_signal_in(const std::string &saddr, const std::string &desc, const std::s signal.hash = XXH3_128bits(saddr.c_str(), saddr.length()); signal.saddr.assign(saddr); signal.desc.assign(desc); - signal.data_type = data_type; if(link_saddr.empty()) { @@ -1090,6 +1089,7 @@ int dc_signal_in(const std::string &saddr, const std::string &desc, const std::s } (*p_data) = p_signal_out->vec_p_data[0]; + signal.data_type = p_signal_out->data_type; signal.vec_p_data.push_back((*p_data)); bool found = false; @@ -1114,7 +1114,7 @@ int dc_signal_in(const std::string &saddr, const std::string &desc, const std::s return dc_signal_add_to_map(signal, g_datacenter.signal_in); } -int dc_signal_in_with_callback(const std::string &saddr, const std::string &desc, const std::string &link_saddr, uint8_t data_type, void **p_data, out_signal_change_cb cb) +int dc_signal_in_with_callback(const std::string &saddr, const std::string &desc, const std::string &link_saddr, void **p_data, out_signal_change_cb cb) { if(p_data == nullptr) { @@ -1133,7 +1133,6 @@ int dc_signal_in_with_callback(const std::string &saddr, const std::string &desc signal.hash = XXH3_128bits(saddr.c_str(), saddr.length()); signal.saddr.assign(saddr); signal.desc.assign(desc); - signal.data_type = data_type; if(link_saddr.empty()) { @@ -1149,6 +1148,7 @@ int dc_signal_in_with_callback(const std::string &saddr, const std::string &desc } (*p_data) = p_signal_out->vec_p_data[0]; + signal.data_type = p_signal_out->data_type; signal.vec_p_data.push_back((*p_data)); if(nullptr != cb) @@ -1222,7 +1222,7 @@ int dc_signal_ao(const std::string &saddr, const std::string &desc, uint8_t data return -1; } -int dc_signal_ao_link_with_callback(const std::string &saddr, uint8_t data_type, void **p_data, signal_change_cb cb) +int dc_signal_ao_link_with_callback(const std::string &saddr, void **p_data, signal_change_cb cb) { if(p_data == nullptr) { @@ -1425,18 +1425,18 @@ int dc_signal_param(const std::string &saddr, const std::string &desc, uint8_t d return -1; } -int dc_signal_param_link_with_callback(const std::string &saddr, uint8_t data_type, std::vector &vec_p_data, signal_change_cb cb) +int dc_signal_param_link_with_callback(const std::string &saddr, std::vector &vec_p_data, signal_change_cb cb) { XXH128_hash_t hash = XXH3_128bits(saddr.c_str(), saddr.length()); stru_signal *p_signal = dc_find_signal(hash, g_datacenter.signal_param); if(p_signal != nullptr) { - if(p_signal->data_type != data_type) - { - LOG_E("saddr %s data type %s(%d) not match %s(%d)", - saddr.c_str(), dc_get_data_type_str_by_id(p_signal->data_type), p_signal->data_type, dc_get_data_type_str_by_id(data_type), data_type); - return -1; - } + // if(p_signal->data_type != data_type) + // { + // LOG_E("saddr %s data type %s(%d) not match %s(%d)", + // saddr.c_str(), dc_get_data_type_str_by_id(p_signal->data_type), p_signal->data_type, dc_get_data_type_str_by_id(data_type), data_type); + // return -1; + // } if(cb) { @@ -1581,7 +1581,7 @@ int dc_signal_yk(const std::string &saddr, const std::string &desc, uint8_t data return -1; } -int dc_signal_yk_link_with_callback(const std::string &saddr, uint8_t data_type, void **p_data, signal_change_cb cb) +int dc_signal_yk_link_with_callback(const std::string &saddr, void **p_data, signal_change_cb cb) { if(p_data == nullptr) { diff --git a/src/system/libiec/src/iec.cpp b/src/system/libiec/src/iec.cpp index bddd620..e842ba4 100644 --- a/src/system/libiec/src/iec.cpp +++ b/src/system/libiec/src/iec.cpp @@ -434,7 +434,7 @@ int app_iec_init2(void *arg) for(uint32_t j = 0; j < p_vec->size(); j++) { void *p_data = nullptr; - ret = dc_signal_in_with_callback(p_vec->at(j).saddr, p_vec->at(j).desc, p_vec->at(j).link, p_vec->at(j).type, &p_data, iec_signal_link_change); + ret = dc_signal_in_with_callback(p_vec->at(j).saddr, p_vec->at(j).desc, p_vec->at(j).link, &p_data, iec_signal_link_change); if(ret != 0) { LOG_E("dc_signal_in failed, saddr %s, desc %s, link %s, type %s", @@ -452,7 +452,7 @@ int app_iec_init2(void *arg) for(uint32_t j = 0; j < p_vec->size(); j++) { void *p_data = nullptr; - ret = dc_signal_yk_link_with_callback(p_vec->at(j).saddr, p_vec->at(j).type, &p_data, iec_signal_ctrl_change); + ret = dc_signal_yk_link_with_callback(p_vec->at(j).saddr, &p_data, iec_signal_ctrl_change); if(ret != 0) { LOG_E("dc_signal_yk_link failed, saddr %s, type %s", diff --git a/src/system/libiec61850m/src/iec61850m.cpp b/src/system/libiec61850m/src/iec61850m.cpp index ac08a1c..e274b1f 100644 --- a/src/system/libiec61850m/src/iec61850m.cpp +++ b/src/system/libiec61850m/src/iec61850m.cpp @@ -199,7 +199,7 @@ void iec61850m_init() } -LOCAL int iec61850m_signal_change_decode(std::string saddr, SIGNAL_CTRL_STEP step, uint8_t data_type, void *p_data, uint8_t &ctrl_type, uint8_t &mms_type) +LOCAL int iec61850m_signal_change_decode(std::string saddr, SIGNAL_CTRL_STEP step, uint8_t data_type, void *p_data, uint8_t &ctrl_type, uint8_t &mms_type, std::string signal_type) { std::string value = ""; if(p_data) @@ -234,7 +234,10 @@ LOCAL int iec61850m_signal_change_decode(std::string saddr, SIGNAL_CTRL_STEP ste break; case SIGNAL_CTRL_STEP::DIRECT: step_str = "DIRECT"; - ctrl_type = _MMS_M_EVENT_AO_WRITE; + if(signal_type == "co") + ctrl_type = _MMS_M_EVENT_CO_DIRECT; + else + ctrl_type = _MMS_M_EVENT_AO_WRITE; break; case SIGNAL_CTRL_STEP::CANCEL: step_str = "CANCEL"; @@ -255,7 +258,7 @@ LOCAL void iec61850m_signal_co_change_callback(std::string saddr, SIGNAL_CTRL_ST uint8_t mms_type = 0; uint8_t ctrl_type = 0; - if(0 != iec61850m_signal_change_decode(saddr, step, data_type, p_data, ctrl_type, mms_type)) + if(0 != iec61850m_signal_change_decode(saddr, step, data_type, p_data, ctrl_type, mms_type, "co")) { return; } @@ -282,7 +285,7 @@ LOCAL void iec61850m_signal_ao_change_callback(std::string saddr, SIGNAL_CTRL_ST uint8_t mms_type = 0; uint8_t ctrl_type = 0; - if(0 != iec61850m_signal_change_decode(saddr, step, data_type, p_data, ctrl_type, mms_type)) + if(0 != iec61850m_signal_change_decode(saddr, step, data_type, p_data, ctrl_type, mms_type, "ao")) { return; } @@ -314,7 +317,7 @@ LOCAL void iec61850m_signal_param_change_callback(std::string saddr, SIGNAL_CTRL uint8_t mms_type = 0; uint8_t ctrl_type = 0; - if(0 != iec61850m_signal_change_decode(saddr, step, data_type, p_data, ctrl_type, mms_type)) + if(0 != iec61850m_signal_change_decode(saddr, step, data_type, p_data, ctrl_type, mms_type, "param")) { return; } @@ -490,7 +493,7 @@ int app_iec61850m_init1(void *arg) int app_iec61850m_init2(void *arg) { - dc_signal_in("iec61850m.iec_run_cnt_in", "iec61850m.iec_run_cnt_in", "iec.run_cnt", DATA_TYPE_U32, (void **)&p_iec_run_cnt); + dc_signal_in("iec61850m.iec_run_cnt_in", "iec61850m.iec_run_cnt_in", "iec.run_cnt", (void **)&p_iec_run_cnt); MY_LOG_I("p_iec_run_cnt %p", p_iec_run_cnt); return 0; @@ -500,7 +503,7 @@ void *app_iec61850m(void *arg) { if(NULL == arg) { - LOG_E("app_com_scan arg null"); + LOG_E("app_iec61850m arg null"); return NULL; } diff --git a/src/system/libiec61850s/inc/iec61850s.h b/src/system/libiec61850s/inc/iec61850s.h new file mode 100644 index 0000000..5ad23e6 --- /dev/null +++ b/src/system/libiec61850s/inc/iec61850s.h @@ -0,0 +1,5 @@ +#pragma once + +#include "myBase.h" +#include "mySystem.h" +#include "myMms_s.h" \ No newline at end of file diff --git a/src/system/libiec61850s/src/iec61850s.cpp b/src/system/libiec61850s/src/iec61850s.cpp new file mode 100644 index 0000000..f7ab2b0 --- /dev/null +++ b/src/system/libiec61850s/src/iec61850s.cpp @@ -0,0 +1,298 @@ +#include "iec61850_common.h" +#include "iec61850s.h" +#include "myLog.h" +#include "myCmd.h" + + +LOCAL std::vector vec_control = +{ + {"iec61850m.prj.co.0", "遥控01", 4}, + {"iec61850m.prj.co.1", "遥控02", 4}, + {"iec61850m.prj.co.2", "遥控03", 4}, + {"iec61850m.prj.co.3", "遥控04", 4}, +}; + +LOCAL std::vector vec_setting = +{ + { + .base = {.saddr = "iec61850m.prj.ao.0", .desc = "参数01", .type = DATA_TYPE_S32}, + .data = NULL, + }, + { + .base = {.saddr = "iec61850m.prj.ao.1", .desc = "参数02", .type = DATA_TYPE_STR}, + .data = NULL, + } +}; + +LOCAL std::vector vec_param = +{ + { + .base = {.saddr = "iec61850m.prj.param.0", .desc = "定值01", .type = DATA_TYPE_F32}, + .data = NULL, + }, +}; + +void iec61850s_control_callback(stru_mms_s_control *p_control, uint8_t state) +{ + if(NULL == p_control) + { + LOG_E("p_control is NULL"); + return; + } + + LOG_I("control callback called saddr: %s, state: %i", p_control->saddr, state); + + uint8_t temp_st = 0; + stru_signal_ctrl ctrl = { + .step = SIGNAL_CTRL_STEP::READY, + .type = SIGNAL_CTRL_TYPE::NONE, + .data_type = DATA_TYPE_U8, + .p_data = &temp_st, + }; + + if(p_control->ctrl_model == CONTROL_MODEL_DIRECT_NORMAL || p_control->ctrl_model == CONTROL_MODEL_DIRECT_ENHANCED) + { + ctrl.type = SIGNAL_CTRL_TYPE::DIRECT_NORMAL; + if(0 != dc_signal_yk_set_status(p_control->saddr, SIGNAL_CTRL_STEP::DIRECT, ctrl, &state)) + { + MY_LOG_E("dc_signal_yk_set_status failed"); + return; + } + } + else if(p_control->ctrl_model == CONTROL_MODEL_SBO_NORMAL || p_control->ctrl_model == CONTROL_MODEL_SBO_ENHANCED) + { + ctrl.type = SIGNAL_CTRL_TYPE::SBO_NORMAL; + if(0 != dc_signal_yk_set_status(p_control->saddr, SIGNAL_CTRL_STEP::SELECT, ctrl, &state)) + { + MY_LOG_E("dc_signal_yk_set_status failed"); + return; + } + + if(0 != dc_signal_yk_set_status(p_control->saddr, SIGNAL_CTRL_STEP::DIRECT, ctrl, &state)) + { + MY_LOG_E("dc_signal_yk_set_status failed"); + return; + } + } + else if(p_control->ctrl_model == CONTROL_MODEL_STATUS_ONLY) + { + MY_LOG_I("CONTROL_MODEL_STATUS_ONLY"); + return; + } +} + +void iec61850s_setting_callback(stru_mms_s_setting *p_setting, const char *p_data) +{ + if(NULL == p_setting || NULL == p_data) + { + LOG_E("p_setting or p_data is NULL"); + return; + } + + LOG_I("setting callback called saddr: %s, data: %s", p_setting->base.saddr, p_data); + + uint8_t temp_val[128] = {0}; + uint8_t temp_ctrl_val[128] = {0}; + dc_set_signal_val_from_str(temp_val, p_setting->base.type, p_data); + + stru_signal_ctrl ctrl = { + .step = SIGNAL_CTRL_STEP::READY, + .type = SIGNAL_CTRL_TYPE::NONE, + .data_type = p_setting->base.type, + .p_data = temp_ctrl_val, + }; + + if(p_setting->base.ctrl_model == SIGNAL_CTRL_TYPE::DIRECT_NORMAL) + { + ctrl.type = SIGNAL_CTRL_TYPE::DIRECT_NORMAL; + if(0 != dc_signal_ao_set_val(p_setting->base.saddr, SIGNAL_CTRL_STEP::DIRECT, ctrl, temp_val)) + { + MY_LOG_E("dc_signal_ao_set_val failed"); + return; + } + } + else if(p_setting->base.ctrl_model == SIGNAL_CTRL_TYPE::SBO_NORMAL) + { + ctrl.type = SIGNAL_CTRL_TYPE::SBO_NORMAL; + if(0 != dc_signal_ao_set_val(p_setting->base.saddr, SIGNAL_CTRL_STEP::SELECT, ctrl, temp_val)) + { + MY_LOG_E("dc_signal_ao_set_val select failed"); + return; + } + + if(0 != dc_signal_ao_set_val(p_setting->base.saddr, SIGNAL_CTRL_STEP::DIRECT, ctrl, temp_val)) + { + MY_LOG_E("dc_signal_ao_set_val direct failed"); + return; + } + } +} + +void iec61850s_param_callback(stru_mms_s_param *p_param, const char *p_data, int setting_zone) +{ + if(NULL == p_param || NULL == p_data) + { + LOG_E("p_param or p_data is NULL"); + return; + } + + LOG_I("param callback called saddr: %s, data: %s, setting_zone: %i", p_param->base.saddr, p_data, setting_zone); + + uint8_t temp_val[128] = {0}; + uint8_t temp_ctrl_val[128] = {0}; + dc_set_signal_val_from_str(temp_val, p_param->base.type, p_data); + + stru_signal_ctrl ctrl = { + .step = SIGNAL_CTRL_STEP::READY, + .type = SIGNAL_CTRL_TYPE::NONE, + .data_type = p_param->base.type, + .p_data = temp_ctrl_val, + }; + + if(p_param->base.ctrl_model == SIGNAL_CTRL_TYPE::DIRECT_NORMAL) + { + ctrl.type = SIGNAL_CTRL_TYPE::DIRECT_NORMAL; + if(0 != dc_signal_param_set_val(p_param->base.saddr, SIGNAL_CTRL_STEP::DIRECT, ctrl, setting_zone, temp_val)) + { + MY_LOG_E("dc_signal_param_set_val failed"); + return; + } + } + else if(p_param->base.ctrl_model == SIGNAL_CTRL_TYPE::SBO_NORMAL) + { + ctrl.type = SIGNAL_CTRL_TYPE::SBO_NORMAL; + if(0 != dc_signal_param_set_val(p_param->base.saddr, SIGNAL_CTRL_STEP::SELECT, ctrl, setting_zone, temp_val)) + { + MY_LOG_E("dc_signal_param_set_val select failed"); + return; + } + + if(0 != dc_signal_param_set_val(p_param->base.saddr, SIGNAL_CTRL_STEP::DIRECT, ctrl, setting_zone, temp_val)) + { + MY_LOG_E("dc_signal_param_set_val direct failed"); + return; + } + } +} + +int app_iec61850s_init1(void *arg) +{ + mms_s_dbg_switch(true); + mms_s_control_register(vec_control.data(), vec_control.size(), iec61850s_control_callback); + + + return 0; +} + +int app_iec61850s_init2(void *arg) +{ + for(std::vector::iterator it = vec_setting.begin(); it != vec_setting.end(); ++it) + { + if(0 != dc_signal_ao_link_with_callback(it->base.saddr, (void **)&it->data, NULL)) + { + MY_LOG_E("dc_signal_ao_link_with_callback failed"); + return -1; + } + + std::string desc = ""; + uint8_t data_type = 0; + stru_signal_param param = {}; + uint8_t ctrl_type = 0; + std::vector vec_p_data = {}; + std::vector vec_p_default_data = {}; + + dc_get_ao_signal_info(it->base.saddr, desc, data_type, param, ctrl_type, vec_p_data, vec_p_default_data); + + strcpy(it->base.desc, desc.c_str()); + it->base.type = data_type; + it->base.ctrl_model = ctrl_type; + } + + for(std::vector::iterator it = vec_param.begin(); it != vec_param.end(); ++it) + { + // std::vector vec_p_data = {}; + // if(0 != dc_signal_param_link_with_callback(it->base.saddr, vec_p_data, NULL)) + // { + // MY_LOG_E("dc_signal_param_link_with_callback failed"); + // return -1; + // } + + std::string desc = ""; + uint8_t data_type = 0; + stru_signal_param param = {}; + uint8_t ctrl_type = 0; + std::vector vec_p_data = {}; + std::vector vec_p_default_data = {}; + + if(0 != dc_get_param_signal_info(it->base.saddr, desc, data_type, param, ctrl_type, vec_p_data, vec_p_default_data)) + { + MY_LOG_E("dc_get_param_signal_info failed"); + return -1; + } + + strcpy(it->base.desc, desc.c_str()); + it->base.type = data_type; + it->base.ctrl_model = ctrl_type; + + it->param_num = vec_p_data.size(); + for(uint8_t j = 0; j < it->param_num; j++) + { + it->data[j] = (uint8_t *)vec_p_data[j]; + } + } + + mms_s_setting_register(vec_setting.data(), vec_setting.size(), iec61850s_setting_callback); + mms_s_param_register(vec_param.data(), vec_param.size(), iec61850s_param_callback); + + if(0 != mms_s_init("/mnt/RTU/test/file/MMS/PCS.icd", 102)) + { + MY_LOG_E("mms_s_init failed"); + return -1; + } + + return 0; +} + + +void *app_iec61850s(void *arg) +{ + if(NULL == arg) + { + LOG_E("app_iec61850s arg null"); + return NULL; + } + + stru_app *p_app = (stru_app *)arg; + + uint32_t event; + stru_app_msg_queue *p_mq = NULL; + stru_msg_head *p_head = NULL; + stru_rtx_data *p_rtx = &p_app->rtx; + + + + while (1) + { + task_event_recv(p_app->p_event, + EV_TIMER1 | EV_TIMER2 | EV_TIMER3 , + TASK_EVENT_FLAG_OR | TASK_EVENT_FLAG_CLEAR, + TASK_EVENT_WAIT_FOREVER, + &event); + + + if(event & EV_TIMER1) + { + ; + } + + if(event & EV_TIMER2) + { + ; + } + + if(event & EV_TIMER3) + { + p_app->run_cnt++; + } + } +} diff --git a/src/system/libself_ptl/src/self_ptl.cpp b/src/system/libself_ptl/src/self_ptl.cpp index 6556859..1817fd9 100644 --- a/src/system/libself_ptl/src/self_ptl.cpp +++ b/src/system/libself_ptl/src/self_ptl.cpp @@ -917,8 +917,6 @@ int self_ptl_do_signal_out(stru_app *p_app) param.step = safeStringToFloat(p_param->p_param->step); param.unit = p_param->p_param->unit; - - // ret(saddr, p(saddr, p->name, p->type, p->p_data); ret |= dc_signal_param(p_param->p_param->base.saddr, p_param->p_param->base.desc, p_param->p_param->type, param, SIGNAL_CTRL_TYPE::SBO_NORMAL, p_param->vec_p_data, p_param->vec_p_default_data, self_ptl_signal_change_callback); } } @@ -960,7 +958,7 @@ LOCAL uint32_t *p_iec_run_cnt_in = NULL; int app_self_ptl_init2(void *arg) { - dc_signal_in("self_ptl.iec_run_cnt_in", "self_ptl.iec_run_cnt_in", "iec.run_cnt", DATA_TYPE_U32, (void **)&p_iec_run_cnt_in); + dc_signal_in("self_ptl.iec_run_cnt_in", "self_ptl.iec_run_cnt_in", "iec.run_cnt", (void **)&p_iec_run_cnt_in); MY_LOG_I("p_iec_run_cnt_in %p", p_iec_run_cnt_in); return 0; diff --git a/src/system/libweb_server/src/ws_method.cpp b/src/system/libweb_server/src/ws_method.cpp index 2fedb34..0560f3f 100644 --- a/src/system/libweb_server/src/ws_method.cpp +++ b/src/system/libweb_server/src/ws_method.cpp @@ -144,9 +144,9 @@ void add_signal(const std::string& saddr, const std::string& signal_type) p_signals->back().p_param = new stru_signal_param; p = &p_signals->back(); - if(0 != dc_get_ao_siganl_info(saddr, p->desc, p->data_type, *p->p_param, p->ctrl_type, p->vec_p_data, p->vec_p_default_data)) + if(0 != dc_get_ao_signal_info(saddr, p->desc, p->data_type, *p->p_param, p->ctrl_type, p->vec_p_data, p->vec_p_default_data)) { - LOG_E("add_signals: dc_get_ao_siganl_info failed, saddr = %s", saddr.c_str()); + LOG_E("add_signals: dc_get_ao_signal_info failed, saddr = %s", saddr.c_str()); delete p->p_ctrl; delete p->p_param; @@ -286,6 +286,16 @@ void set_signal_data(const std::string& saddr, const std::string& signal_type, c return; } + uint8_t data[128] = {0}; + memset(data, 0, sizeof(data)); + uint8_t data_type = dc_get_data_type_id_by_str(signal_type); + if(data_type == 0) + { + LOG_E("set_signal_data: invalid signal_type = %s", signal_type.c_str()); + return; + } + dc_set_signal_val_from_str(data, data_type, signal_data); + if(signal_type == "out") { p_signals = &g_ws_out_signals; @@ -294,7 +304,7 @@ void set_signal_data(const std::string& saddr, const std::string& signal_type, c stru_ws_signal *p_signal = &p_signals->at(i); if(p_signal->saddr == saddr) { - if(0 != dc_set_out_signal_val(saddr, (void *)signal_data.c_str())) + if(0 != dc_set_out_signal_val(saddr, (void *)data)) { LOG_E("set_signal_data: dc_set_signal_val failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str()); return; @@ -311,8 +321,6 @@ void set_signal_data(const std::string& saddr, const std::string& signal_type, c { p_signals = &g_ws_yk_signals; - uint8_t ctrl_status = atoi(signal_data.c_str()); - for(uint32_t i = 0; i < p_signals->size(); i++) { stru_ws_signal *p_signal = &p_signals->at(i); @@ -320,33 +328,33 @@ void set_signal_data(const std::string& saddr, const std::string& signal_type, c { if(p_signal->ctrl_type == SIGNAL_CTRL_TYPE::DIRECT_NORMAL) { - if(0 != dc_signal_yk_set_status(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, (void *)&ctrl_status)) + if(0 != dc_signal_yk_set_status(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, (void *)data)) { LOG_E("set_signal_data: dc_signal_yk_set_status direct failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str()); return; } - LOG_I("saddr %s, direct, value %d success !!!", saddr.c_str(), ctrl_status); + LOG_I("saddr %s, direct, value %d success !!!", saddr.c_str(), signal_data.c_str()); return; } else if(p_signal->ctrl_type == SIGNAL_CTRL_TYPE::SBO_NORMAL) { - if(0 != dc_signal_yk_set_status(saddr, SIGNAL_CTRL_STEP::SELECT, *p_signal->p_ctrl, (void *)&ctrl_status)) + if(0 != dc_signal_yk_set_status(saddr, SIGNAL_CTRL_STEP::SELECT, *p_signal->p_ctrl, (void *)data)) { LOG_E("set_signal_data: dc_signal_yk_set_status select failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str()); return; } task_sleep_ms(1000); - MY_LOG_I("saddr %s, select value %d success !!!", saddr.c_str(), ctrl_status); + MY_LOG_I("saddr %s, select value %s success !!!", saddr.c_str(), signal_data.c_str()); - if(0 != dc_signal_yk_set_status(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, (void *)&ctrl_status)) + if(0 != dc_signal_yk_set_status(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, (void *)data)) { LOG_E("set_signal_data: dc_signal_yk_set_status direct failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str()); return; } - MY_LOG_I("saddr %s, direct value %d success", saddr.c_str(), ctrl_status); + MY_LOG_I("saddr %s, direct value %s success !!!", saddr.c_str(), signal_data.c_str()); return; } else @@ -361,8 +369,6 @@ void set_signal_data(const std::string& saddr, const std::string& signal_type, c { p_signals = &g_ws_ao_signals; - char temp_data[128] = {0}; - for(uint32_t i = 0; i < p_signals->size(); i++) { stru_ws_signal *p_signal = &p_signals->at(i); @@ -370,10 +376,7 @@ void set_signal_data(const std::string& saddr, const std::string& signal_type, c { if(p_signal->ctrl_type == SIGNAL_CTRL_TYPE::DIRECT_NORMAL) { - memset(temp_data, 0, sizeof(temp_data)); - dc_set_signal_val_from_str(temp_data, p_signal->data_type, signal_data); - - if(0 != dc_signal_ao_set_val(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, (void *)temp_data)) + if(0 != dc_signal_ao_set_val(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, (void *)data)) { LOG_E("set_signal_data: dc_signal_ao_set_val direct failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str()); return; @@ -384,10 +387,8 @@ void set_signal_data(const std::string& saddr, const std::string& signal_type, c } else if(p_signal->ctrl_type == SIGNAL_CTRL_TYPE::SBO_NORMAL) { - memset(temp_data, 0, sizeof(temp_data)); - dc_set_signal_val_from_str(temp_data, p_signal->data_type, signal_data); - if(0 != dc_signal_ao_set_val(saddr, SIGNAL_CTRL_STEP::SELECT, *p_signal->p_ctrl, (void *)temp_data)) + if(0 != dc_signal_ao_set_val(saddr, SIGNAL_CTRL_STEP::SELECT, *p_signal->p_ctrl, (void *)data)) { LOG_E("set_signal_data: dc_signal_ao_set_val select failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str()); return; @@ -395,7 +396,7 @@ void set_signal_data(const std::string& saddr, const std::string& signal_type, c LOG_I("saddr %s, select, value %s success !!!", saddr.c_str(), signal_data.c_str()); - if(0 != dc_signal_ao_set_val(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, (void *)temp_data)) + if(0 != dc_signal_ao_set_val(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, (void *)data)) { LOG_E("set_signal_data: dc_signal_ao_set_val direct failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str()); return; @@ -423,7 +424,7 @@ void set_signal_data(const std::string& saddr, const std::string& signal_type, c { if(p_signal->ctrl_type == SIGNAL_CTRL_TYPE::DIRECT_NORMAL) { - if(0 != dc_signal_param_set_val(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, setting_zone, (void *)signal_data.c_str())) + if(0 != dc_signal_param_set_val(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, setting_zone, (void *)data)) { LOG_E("set_signal_data: dc_signal_param_set_val direct failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str()); return; @@ -434,7 +435,7 @@ void set_signal_data(const std::string& saddr, const std::string& signal_type, c } else if(p_signal->ctrl_type == SIGNAL_CTRL_TYPE::SBO_NORMAL) { - if(0 != dc_signal_param_set_val(saddr, SIGNAL_CTRL_STEP::SELECT, *p_signal->p_ctrl, setting_zone, (void *)signal_data.c_str())) + if(0 != dc_signal_param_set_val(saddr, SIGNAL_CTRL_STEP::SELECT, *p_signal->p_ctrl, setting_zone, (void *)data)) { LOG_E("set_signal_data: dc_signal_param_set_val select failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str()); return; @@ -442,7 +443,7 @@ void set_signal_data(const std::string& saddr, const std::string& signal_type, c LOG_I("saddr %s, select, value %s success !!!", saddr.c_str(), signal_data.c_str()); - if(0 != dc_signal_param_set_val(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, setting_zone, (void *)signal_data.c_str())) + if(0 != dc_signal_param_set_val(saddr, SIGNAL_CTRL_STEP::DIRECT, *p_signal->p_ctrl, setting_zone, (void *)data)) { LOG_E("set_signal_data: dc_signal_param_set_val direct failed, saddr = %s, signal_data = %s", saddr.c_str(), signal_data.c_str()); return; @@ -661,8 +662,6 @@ void ws_task() cJSON_AddItemToObject(item, "saddr", cJSON_CreateString(p_signal->saddr.c_str())); cJSON_AddItemToObject(item, "desc", cJSON_CreateString(p_signal->desc.c_str())); cJSON_AddItemToObject(item, "type", cJSON_CreateString(dc_get_data_type_str_by_id(p_signal->data_type).c_str())); - // std::string val = dc_get_signal_val(p_signal->vec_p_data[0], p_signal->data_type); - // cJSON_AddItemToObject(item, "val", cJSON_CreateString(val.c_str())); cJSON_AddItemToObject(item, "ctrl_type", cJSON_CreateNumber(p_signal->ctrl_type)); if(p_signal->p_param) { @@ -670,7 +669,6 @@ void ws_task() cJSON_AddItemToObject(item, "max", cJSON_CreateString(std::to_string(p_signal->p_param->max).c_str())); cJSON_AddItemToObject(item, "step", cJSON_CreateString(std::to_string(p_signal->p_param->step).c_str())); cJSON_AddItemToObject(item, "unit", cJSON_CreateString(p_signal->p_param->unit.c_str())); - // cJSON_AddItemToObject(item, "default", cJSON_CreateString(p_signal->p_param->default_value.c_str())); } std::string val = dc_get_signal_val(p_signal->vec_p_data[0], p_signal->data_type); @@ -699,8 +697,6 @@ void ws_task() cJSON_AddItemToObject(item, "saddr", cJSON_CreateString(p_signal->saddr.c_str())); cJSON_AddItemToObject(item, "desc", cJSON_CreateString(p_signal->desc.c_str())); cJSON_AddItemToObject(item, "type", cJSON_CreateString(dc_get_data_type_str_by_id(p_signal->data_type).c_str())); - // std::string val = dc_get_signal_val(p_signal->vec_p_data[0], p_signal->data_type); - // cJSON_AddItemToObject(item, "val", cJSON_CreateString(val.c_str())); cJSON_AddItemToObject(item, "ctrl_type", cJSON_CreateNumber(p_signal->ctrl_type)); if(p_signal->p_param) { @@ -708,7 +704,6 @@ void ws_task() cJSON_AddItemToObject(item, "max", cJSON_CreateString(std::to_string(p_signal->p_param->max).c_str())); cJSON_AddItemToObject(item, "step", cJSON_CreateString(std::to_string(p_signal->p_param->step).c_str())); cJSON_AddItemToObject(item, "unit", cJSON_CreateString(p_signal->p_param->unit.c_str())); - // cJSON_AddItemToObject(item, "default", cJSON_CreateString(p_signal->p_param->default_value.c_str())); } for(uint32_t j = 0; j < p_signal->vec_p_data.size(); j++) diff --git a/test/file/MMS/prj.xml b/test/file/MMS/prj.xml index 47eff9b..b00f296 100644 --- a/test/file/MMS/prj.xml +++ b/test/file/MMS/prj.xml @@ -29,7 +29,7 @@ - +