<修改> 1、调整上送mms服务端数据;2、新增客户端文件等功能

This commit is contained in:
ypc 2026-06-09 14:13:04 +08:00
parent cd61e8e27b
commit 1a16180a9c
16 changed files with 621 additions and 94 deletions

View File

@ -171,6 +171,17 @@ int mms_m_set_data_value(void *srt, void *dst, uint8_t type);
int mms_m_get_data_value_str(void *data, uint8_t type, char *str);
int mms_m_set_data_by_str(void *data, uint8_t type, const char *str);
typedef void (*mms_m_file_read_cb)(int fd, const char *fn, const uint8_t *d, int len, bool mf, int e);
typedef void (*mms_m_file_op_cb)(int fd, const char *fn, int e);
typedef void (*mms_m_server_cb)(int fd, const char *vendor, const char *model, const char *rev, int log_st, int phy_st, int e);
typedef void (*mms_m_sg_cb)(int fd, const char *ld, int act_sg, int num_sg, int e);
int mms_m_read_file(int fd, const char *rf, mms_m_file_read_cb cb);
int mms_m_delete_file(int fd, const char *rf, mms_m_file_op_cb cb);
int mms_m_query_server(int fd, mms_m_server_cb cb);
int mms_m_read_sg_info(int fd, const char *ld, mms_m_sg_cb cb);
#ifdef __cplusplus
}
#endif

View File

@ -187,3 +187,5 @@ typedef struct
void *mms_m_get_obj(int app_fd);

View File

@ -0,0 +1,67 @@
/**
* @file mms_m_ext.h
* @brief MMS
*
* @details
* myMms_m.h
*/
#pragma once
#include "myMms_m.h"
#include "mms_m.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* IED
*
* MMS (ObtainFile)
*
*
* @param app_fd
* @param rf
* @param cb
* @return 0 -1
*/
int mms_m_read_file(int app_fd, const char *rf, mms_m_file_read_cb cb);
/**
* IED
*
* @param app_fd
* @param rf
* @param cb
* @return 0 -1
*/
int mms_m_delete_file(int app_fd, const char *rf, mms_m_file_op_cb cb);
/**
* IED
*
* MMS identify //
* VMD
*
* @param app_fd
* @param cb
* @return 0 -1
*/
int mms_m_query_server(int app_fd, mms_m_server_cb cb);
/**
* IED
*
* SGCB
*
* @param app_fd
* @param ld "PROT"
* @param cb
* @return 0 -1
*/
int mms_m_read_sg_info(int app_fd, const char *ld, mms_m_sg_cb cb);
#ifdef __cplusplus
}
#endif

View File

@ -336,6 +336,19 @@ static int mms_m_send_ao_write(stru_mms_m_obj &obj, stru_mms_m_event &event)
return 0;
}
static void demo_sg_cb(int fd, const char *ld_name,
int act_sg, int num_sg, int err)
{
if (IED_ERROR_OK != err)
{
LOG_E("read SG info failed: %s, err=%d", ld_name, err);
/** 定值组信息读取回调 */
return;
}
LOG_I("%s: active SG=%d, total SG=%d", ld_name, act_sg, num_sg);
}
static int mms_m_send_param_write(stru_mms_m_obj &obj, stru_mms_m_event &event)
{
stru_point_item *p_item = NULL;
@ -356,6 +369,8 @@ static int mms_m_send_param_write(stru_mms_m_obj &obj, stru_mms_m_event &event)
return -1;
}
mms_m_read_sg_info(obj.obj_fd, p_item->ldev, demo_sg_cb);
std::string ref = p_item->reference;
size_t pos = ref.find("/");
if(pos == std::string::npos)
@ -955,18 +970,8 @@ static int mms_m_get_MmsValue(stru_point_value &point_value, stru_mms_m_out_valu
tm_flag = 1;
break;
case MMS_BIT_STRING:
point_value.quality = 0;
for (int i = 0; i < MmsValue_getBitStringSize(p_mms_values); i++)
{
if (MmsValue_getBitStringBit(p_mms_values, i))
{
point_value.quality |= (1 << i);
}
else
{
point_value.quality &= ~(1 << i);
}
}
out_val.type = MMS_BIT_STRING;
*(uint32_t *)p_val = MmsValue_getBitStringAsIntegerBigEndian(p_mms_values);
break;
default:
break;
@ -1477,7 +1482,8 @@ static void mms_m_do_comm(stru_mms_m_obj &obj)
if(IED_STATE_CONNECTED != run.con_state && IED_STATE_CONNECTED == run.old_con_state)
{
LOG_I("mms_m %s connected %s:%d offline", obj.ied_name.c_str(), obj.run.ip.c_str(), obj.run.port);
LOG_I("mms_m %s connected %s:%d offline, reset RCB subscription", obj.ied_name.c_str(), obj.run.ip.c_str(), obj.run.port);
obj.run.running_init = false;
if(run.out_status_cb)
{
@ -1803,6 +1809,11 @@ static int mms_m_ied_init(stru_mms_m_obj &obj)
void *mms_m_get_obj(int app_fd){
auto it = g_mms_m_obj_map.find(app_fd);
return (it != g_mms_m_obj_map.end()) ? (void*)it->second : NULL;
}
int mms_m_out_init(stru_cfg *p_cfg, int debug_print_flag, uint32_t connectionTimeout)
{
if(NULL == p_cfg)

View File

@ -0,0 +1,127 @@
/**
* @file mms_m_file.cpp
* @brief MMS
*
* @details libiec61850 MmsConnection
* - (ObtainFile)
* -
*
*
* 1. MmsConnection_fileOpen()
* 2. MmsConnection_fileRead()
* 3. MmsConnection_fileClose()
* 4.
*
*
*/
#include "myMms_m.h"
#include <string.h>
#include <stdlib.h>
#include "mms_m.h"
#include "mms_m_ext.h"
#include "iec61850_client.h"
/**
* IED
*
*
*
* @param app_fd
* @param rf
* @param cb
* @return 0 -1
*/
int mms_m_read_file(int app_fd, const char *rf, mms_m_file_read_cb cb)
{
if (NULL == rf || NULL == cb)
{
LOG_E("Invalid parameter, rf %p, cb %p", rf, cb);
return -1;
}
stru_mms_m_obj *p_obj = (stru_mms_m_obj *)mms_m_get_obj(app_fd);
if (NULL == p_obj)
{
LOG_E("app_fd %d not found", app_fd);
return -1;
}
/* 获取底层 MmsConnection 以使用文件服务 API */
MmsConnection mc = IedConnection_getMmsConnection(p_obj->run.con);
if (NULL == mc)
{
LOG_E("%s: getMmsConnection failed", p_obj->cfg_path.c_str());
return -1;
}
MmsError me;
uint32_t file_size = 0;
uint64_t last_modified = 0;
/* 打开远端文件,获取大小和修改时间 */
int32_t frsm_id = MmsConnection_fileOpen(mc, &me, rf, 0,
&file_size, &last_modified);
if (MMS_ERROR_NONE != me)
{
LOG_E("%s: fileOpen(%s) failed: %d",
p_obj->cfg_path.c_str(), rf, me);
cb(app_fd, rf, NULL, 0, false, IED_ERROR_UNKNOWN);
return -1;
}
LOG_I("%s: file %s opened, size=%u, lastModified=%lu",
p_obj->cfg_path.c_str(), rf, file_size, last_modified);
/*
* TODO:
*
*
* 1. (malloc file_size)
* 2. MmsConnection_fileReadAsync()
* 3. read_cb
* 4. moreFollows=false
* 5. MmsConnection_fileClose()
*/
MmsConnection_fileClose(mc, &me, frsm_id);
cb(app_fd, rf, NULL, 0, false, IED_ERROR_SERVICE_NOT_IMPLEMENTED);
return -1;
}
/**
* IED
*
* @param app_fd
* @param rf
* @param cb err==0
* @return 0 -1
*/
int mms_m_delete_file(int app_fd, const char *rf, mms_m_file_op_cb cb)
{
if (NULL == rf || NULL == cb)
{
LOG_E("Invalid parameter, rf %p, cb %p", rf, cb);
return -1;
}
stru_mms_m_obj *p_obj = (stru_mms_m_obj *)mms_m_get_obj(app_fd);
if (NULL == p_obj)
{
LOG_E("app_fd %d not found", app_fd);
return -1;
}
MmsConnection mc = IedConnection_getMmsConnection(p_obj->run.con);
MmsError me;
MmsConnection_fileDelete(mc, &me, rf);
IedClientError ie = (MMS_ERROR_NONE == me) ? IED_ERROR_OK
: IED_ERROR_UNKNOWN;
cb(app_fd, rf, ie);
return (MMS_ERROR_NONE == me) ? 0 : -1;
}

View File

@ -0,0 +1,71 @@
/**
* @file mms_m_server.cpp
* @brief IED
*
* @details MMS identify getServerStatus
* - (vendorName)
* - (modelName)
* - (revision)
* - VMD (0=, 1=, 2=, 3=)
* - VMD (0=, 1=, 2=, 3=)
*/
#include "myMms_m.h"
#include <string.h>
#include "mms_m.h"
#include "mms_m_ext.h"
#include "iec61850_client.h"
/**
* IED
*
* MMS identify getServerStatus
*
*
* @param app_fd
* @param cb
* @return 0 -1
*/
int mms_m_query_server(int app_fd, mms_m_server_cb cb)
{
if (NULL == cb)
{
LOG_E("cb is NULL");
return -1;
}
stru_mms_m_obj *p_obj = (stru_mms_m_obj *)mms_m_get_obj(app_fd);
if (NULL == p_obj)
{
LOG_E("app_fd %d not found", app_fd);
return -1;
}
MmsConnection mc = IedConnection_getMmsConnection(p_obj->run.con);
MmsError me;
/* MMS identify 服务:获取厂商/型号/版本 */
MmsServerIdentity *p_id = MmsConnection_identify(mc, &me);
/* MMS getServerStatus 服务:获取 VMD 运行状态 */
int log_st = 0;
int phy_st = 0;
MmsConnection_getServerStatus(mc, &me, &log_st, &phy_st, false);
const char *vendor = p_id ? p_id->vendorName : "";
const char *model = p_id ? p_id->modelName : "";
const char *rev = p_id ? p_id->revision : "";
IedClientError err = (MMS_ERROR_NONE != me) ? IED_ERROR_UNKNOWN
: IED_ERROR_OK;
cb(app_fd, vendor, model, rev, log_st, phy_st, err);
if (p_id)
{
MmsServerIdentity_destroy(p_id);
}
return 0;
}

View File

@ -0,0 +1,83 @@
/**
* @file mms_m_sg.cpp
* @brief IED (Setting Group)
*
* @details IED 线
* LLN0.SGCB
*
* SGCB (Setting Group Control Block)
* - ActSG :
* - NumOfSG:
* - EditSG :
*
*
* - (Write ActSG)
* - (Write CnfEdit)
*/
#include "myMms_m.h"
#include <string.h>
#include "mms_m.h"
#include "mms_m_ext.h"
#include "iec61850_client.h"
/**
* IED
*
* LLN0.SGCB
* act_sg=1, num_sg=1
*
* @param app_fd
* @param ld "PROT""CTRL"
* @param cb
* @return 0 -1
*/
int mms_m_read_sg_info(int app_fd, const char *ld, mms_m_sg_cb cb)
{
if (NULL == ld || NULL == cb)
{
LOG_E("Invalid parameter, ld %p, cb %p", ld, cb);
return -1;
}
stru_mms_m_obj *p_obj = (stru_mms_m_obj *)mms_m_get_obj(app_fd);
if (NULL == p_obj)
{
LOG_E("app_fd %d not found", app_fd);
return -1;
}
int act_sg = 1;
int num_sg = 1;
IedClientError err = IED_ERROR_OK;
/* 拼接 SGCB 对象引用:{LD}/LLN0.SGCB */
char sgcbref[256];
snprintf(sgcbref, sizeof(sgcbref), "%s/LLN0.SGCB", ld);
/* 读取 SGCB 的 FC=ST 属性(包含 ActSG, NumOfSG, EditSG */
MmsValue *p_val = IedConnection_readObject(p_obj->run.con, &err,
sgcbref, IEC61850_FC_ST);
if (p_val && IED_ERROR_OK == err)
{
MmsValue *p_act = MmsValue_getElement(p_val, 0);
MmsValue *p_num = MmsValue_getElement(p_val, 1);
if (p_act)
{
act_sg = MmsValue_toInt32(p_act);
}
if (p_num)
{
num_sg = MmsValue_toInt32(p_num);
}
MmsValue_delete(p_val);
}
cb(app_fd, ld, act_sg, num_sg, err);
return (IED_ERROR_OK == err) ? 0 : -1;
}

View File

@ -21,4 +21,17 @@
* @param icd ICD
* @return 0 -1
*/
/**
*
* @param saddr
* @param state
* @return true false
*/
typedef bool (*mms_s_interlock_cb)(const char *saddr, int state);
/**
*
*/
void mms_s_set_interlock_cb(mms_s_interlock_cb cb);
int control_init(IedServer server, stru_icd &icd);

View File

@ -462,6 +462,8 @@ typedef struct
typedef struct
{
ModelNode *node;
DataAttribute *da_t;
DataAttribute *da_q;
}stru_saddr_point;
/**

View File

@ -43,34 +43,46 @@ LOCAL IedServer gp_iedServer = NULL;
/* 调试输出开关 */
LOCAL bool g_dbg_switch = false;
/** SIGINT 信号处理:通知后台线程退出 */
/* RCB event handler for monitoring client report subscriptions */
LOCAL void rcbEventHandler(void* parameter, ReportControlBlock* rcb, ClientConnection connection, IedServer_RCBEventType event, const char* parameterName, MmsDataAccessError serviceError)
{
const char* name = ReportControlBlock_getName(rcb);
char* rptId = ReportControlBlock_getRptID(rcb);
char* dataSet = ReportControlBlock_getDataSet(rcb);
switch (event)
{
case RCB_EVENT_ENABLE: LOG_I("RCB %s ENABLED rptId=%s datSet=%s trigOps=0x%x", name, rptId, dataSet, rcb->trgOps); break;
case RCB_EVENT_DISABLE: LOG_I("RCB %s DISABLED", name); break;
case RCB_EVENT_RESERVED: LOG_I("RCB %s RESERVED", name); break;
case RCB_EVENT_UNRESERVED:LOG_I("RCB %s UNRESERVED", name); break;
case RCB_EVENT_GI: LOG_I("RCB %s GI triggered", name); break;
case RCB_EVENT_SET_PARAMETER:
LOG_I("RCB %s SET param=%s err=%d trigOps=0x%x (before)", name, parameterName ? parameterName : "?", serviceError, rcb->trgOps);
if (parameterName && strcmp(parameterName, "TrgOps") == 0) {
rcb->trgOps |= 0x01;
LOG_I("RCB %s forced dchg, trigOps=0x%x", name, rcb->trgOps);
}
break;
case RCB_EVENT_GET_PARAMETER: LOG_I("RCB %s GET param=%s err=%d", name, parameterName ? parameterName : "?", serviceError); break;
default: LOG_I("RCB %s event=%d", name, event); break;
}
free(rptId);
free(dataSet);
{
if(mms_s_dbg_get())
{
const char* name = ReportControlBlock_getName(rcb);
char* rptId = ReportControlBlock_getRptID(rcb);
char* dataSet = ReportControlBlock_getDataSet(rcb);
switch (event)
{
case RCB_EVENT_ENABLE: LOG_I("RCB %s ENABLED rptId=%s datSet=%s trigOps=0x%x", name, rptId, dataSet, rcb->trgOps); break;
case RCB_EVENT_DISABLE: LOG_I("RCB %s DISABLED", name); break;
case RCB_EVENT_RESERVED: LOG_I("RCB %s RESERVED", name); break;
case RCB_EVENT_UNRESERVED:LOG_I("RCB %s UNRESERVED", name); break;
case RCB_EVENT_GI: LOG_I("RCB %s GI triggered", name); break;
case RCB_EVENT_SET_PARAMETER:
if (serviceError != DATA_ACCESS_ERROR_SUCCESS)
{
LOG_E("RCB %s SET param=%s FAILED err=%d", name, parameterName ? parameterName : "?", serviceError);
}
else
{
LOG_I("RCB %s SET param=%s OK trigOps=0x%x", name, parameterName ? parameterName : "?", rcb->trgOps);
if (parameterName && strcmp(parameterName, "TrgOps") == 0)
{
rcb->trgOps |= 0x01;
LOG_I("RCB %s forced dchg, trigOps=0x%x", name, rcb->trgOps);
}
}
break;
case RCB_EVENT_GET_PARAMETER: LOG_I("RCB %s GET param=%s err=%d", name, parameterName ? parameterName : "?", serviceError); break;
default: LOG_I("RCB %s event=%d", name, event); break;
}
free(rptId);
free(dataSet);
}
}
/** SIGINT 信号处理:通知后台线程退出 */
LOCAL void sigint_handler(int signum)
{
g_running = 0;

View File

@ -32,6 +32,14 @@
LOCAL std::vector<stru_mms_s_control> g_vec_control;
/** 控制操作回调函数 */
LOCAL mms_s_control_cb cb_control = NULL;
/** 联锁检查回调 */
LOCAL mms_s_interlock_cb cb_interlock = NULL;
void mms_s_set_interlock_cb(mms_s_interlock_cb cb)
{
cb_interlock = cb;
}
/**
* Operate
@ -287,7 +295,7 @@ int control_init(IedServer server, stru_icd &icd)
if(g_vec_control.empty())
{
LOG_E("g_vec_control is empty");
LOG_I("g_vec_control is empty, no controls registered");
return 0;
}

View File

@ -812,6 +812,24 @@ LOCAL int model_ldevice_init(IedModel *model, stru_icd &icd)
return 0;
}
LOCAL void find_tq_for_da(DataAttribute *da, DataAttribute* *t, DataAttribute* *q)
{
*t = NULL;
*q = NULL;
if (!da) return;
ModelNode *parent = da->parent;
while (parent && parent->modelType != DataObjectModelType)
parent = parent->parent;
if (parent && parent->modelType == DataObjectModelType) {
DataAttribute *child = (DataAttribute *)parent->firstChild;
while (child) {
if (strcmp(child->name, "t") == 0) *t = child;
else if (strcmp(child->name, "q") == 0) *q = child;
child = (DataAttribute *)child->sibling;
}
}
}
/**
* SDI DAI sAddr / val all_DA
*
@ -906,7 +924,8 @@ void model_sync_da_default_values(stru_icd &icd, stru_SDI &SDI_item, stru_all_DA
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;
icd.ied.map_saddr_point[saddr].node = (ModelNode *)p_all_da_se_temp->DA;
find_tq_for_da(p_all_da_se_temp->DA, &icd.ied.map_saddr_point[saddr].da_t, &icd.ied.map_saddr_point[saddr].da_q);
}
}
}
@ -1021,7 +1040,8 @@ void model_sync_ln_default_values(stru_icd &icd, std::map<std::string, stru_DOI>
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; // 建立映射
icd.ied.map_saddr_point[saddr].node = (ModelNode *)p_all_da->DA;
find_tq_for_da(p_all_da->DA, &icd.ied.map_saddr_point[saddr].da_t, &icd.ied.map_saddr_point[saddr].da_q); // 建立映射
}
}
}

View File

@ -313,6 +313,8 @@ LOCAL bool param_edit_sg_changed_handler(void* parameter, SettingGroupControlBlo
* @param max
* @param step
*/
/* TODO: 与 mms_s_setting.cpp 中的校验函数重复,建议抽取到公共模块 */
LOCAL void param_min_max_step_get(DataAttribute *node, float &min, float &max, float &step)
{
if(node == NULL)
@ -465,12 +467,12 @@ LOCAL void param_get_INT(DataAttribute *node_SE, DataAttribute *node_SG, std::st
float min, max, step;
param_min_max_step_get(node_SG, min, max, step);
int intVal = MmsValue_toInt32(node_SE->mmsValue);
if((int)step == 0)
{
val = std::to_string(intVal);
return;
}
int intVal = MmsValue_toInt32(node_SE->mmsValue);
if(intVal < (int)min || intVal > (int)max)
{
LOG_E("Value %d is out of range [%d, %d]", intVal, (int)min, (int)max);
@ -499,12 +501,12 @@ LOCAL void param_get_UINT(DataAttribute *node_SE, DataAttribute *node_SG, std::s
float min, max, step;
param_min_max_step_get(node_SG, min, max, step);
int uintVal = MmsValue_toUint32(node_SE->mmsValue);
if((uint32_t)step == 0)
{
val = std::to_string(uintVal);
return;
}
int uintVal = MmsValue_toUint32(node_SE->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);
@ -542,19 +544,16 @@ LOCAL void param_get_FLOAT(DataAttribute *node_SE, DataAttribute *node_SG, std::
return;
}
if(fabs(step) < EPSILON)
{
val = std::to_string(floatVal);
return;
}
float gap = floatVal - min;
if(fabs(step) > EPSILON)
{
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;
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);
@ -704,7 +703,7 @@ LOCAL void param_values_show()
{
if(g_vec_params.empty())
{
LOG_E("g_vec_params is empty");
LOG_I("g_vec_params is empty, no params registered");
return;
}
@ -766,7 +765,7 @@ int param_init(IedServer server, stru_icd &icd)
{
if(g_vec_params.empty())
{
LOG_E("g_vec_params is empty");
LOG_I("g_vec_params is empty, no params registered");
return 0;
}

View File

@ -286,11 +286,6 @@ LOCAL int setting_get_INT(DataAttribute *node, MmsValue* value, std::string &val
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)
{
@ -322,11 +317,6 @@ LOCAL int setting_get_UINT(DataAttribute *node, MmsValue* value, std::string &va
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)
{
@ -367,18 +357,16 @@ LOCAL int setting_get_FLOAT(DataAttribute *node, MmsValue* value, std::string &v
return -1;
}
if(fabs(step) < EPSILON)
{
return 0;
}
float gap = floatVal - min;
if(fabs(step) > EPSILON)
{
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;
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);
@ -597,7 +585,7 @@ int setting_init(IedServer server, stru_icd &icd)
{
if(g_vec_settings.empty())
{
LOG_E("g_vec_settings is empty");
LOG_I("g_vec_settings is empty, no settings registered");
return 0;
}

View File

@ -353,13 +353,34 @@ LOCAL void mms_s_da_value_init_Unicode_String(DataAttribute *da, std::string val
/** 初始化 Timestamp设为当前毫秒时间 */
LOCAL void mms_s_da_value_init_Timestamp(DataAttribute *da, std::string val)
{
if(NULL == da || val.empty())
if(NULL == da) return;
da->mmsValue = MmsValue_newUtcTimeByMsTime(Hal_getTimeInMs());
}
LOCAL std::string get_DA_path(ModelNode *node)
{
std::string str_temp = "";
if(NULL == node)
{
LOG_E("da or val is empty, da %p, val %s", da, val.c_str());
return;
return str_temp;
}
da->mmsValue = MmsValue_newUtcTimeByMsTime(Hal_getTimeInMs());
str_temp = node->name ? node->name : "?";
ModelNode *temp_node = node->parent; // 向上遍历父节点
while(temp_node) // 逐级拼装完整路径
{
str_temp = std::string(temp_node->name ? temp_node->name : "?") + "." + str_temp; // parent.name + "." + 当前路径
if(temp_node->modelType == LogicalDeviceModelType) // 到达逻辑设备层则停止
{
break;
}
temp_node = temp_node->parent; // 继续向上一级
}
return str_temp;
}
/**
@ -368,19 +389,12 @@ LOCAL void mms_s_da_value_init_Timestamp(DataAttribute *da, std::string val)
*/
LOCAL void mms_s_da_value_init_Dbpos(DataAttribute *da, std::string val)
{
if(NULL == da || val.empty())
{
LOG_E("da or val is empty, da %p, val %s", da, val.c_str());
return;
}
if(NULL == da) return;
Dbpos pos = DBPOS_INTERMEDIATE_STATE;
if(val == "")
{
pos = DBPOS_INTERMEDIATE_STATE;
}
else
if(!val.empty())
{
int i = atoi(val.c_str());
if(i == 0)
@ -405,11 +419,20 @@ LOCAL void mms_s_da_value_init_Dbpos(DataAttribute *da, std::string val)
}
}
Dbpos_toMmsValue(da->mmsValue, pos);
IedServer server = mms_s_get_ied_server_ptr();
if (server)
{
IedServer_updateDbposValue(server, da, pos);
}
else
{
da->mmsValue = Dbpos_toMmsValue(NULL, pos);
}
if(mms_s_dbg_get())
// if(mms_s_dbg_get())
{
LOG_I("da %s-%s, value %s, pos %d", da->parent->name, da->name, val.c_str(), pos);
MmsType val_type = MmsValue_getType(da->mmsValue);
LOG_I("da %s-%s, value %s, pos %d, type %d, path %s", da->parent->name, da->name, val.c_str(), pos, val_type, get_DA_path((ModelNode *)da).c_str());
}
}
@ -477,7 +500,7 @@ LOCAL void mms_s_da_values_init(stru_icd &icd, std::string da_name, stru_all_DA
return;
}
if(NULL != g_iec61850s_value_init_cb_map[p_all_da->bType] && !p_all_da->val.empty())
if(NULL != g_iec61850s_value_init_cb_map[p_all_da->bType] && (!p_all_da->val.empty() || p_all_da->bType == "Timestamp" || p_all_da->bType == "Quality" || p_all_da->bType == "Dbpos"))
{
g_iec61850s_value_init_cb_map[p_all_da->bType](p_all_da->DA, p_all_da->val);
}

View File

@ -7,6 +7,7 @@
#include "parse_xml.h"
LOCAL void mms_event_back(void *arg, int ret);
LOCAL std::string get_base_path()
@ -177,6 +178,8 @@ LOCAL void mms_data_back(stru_mms_m_out_value *p)
}
}
LOCAL int iec61850m_ext_demo(int fd);
LOCAL void iec61850m_connect_status(int fd, int status)
{
std::string prj_name = "";
@ -196,6 +199,11 @@ LOCAL void iec61850m_connect_status(int fd, int status)
}
LOG_I("iec61850m_connect_status, fd %d, prj_name %s, status %s", fd, prj_name.c_str(), status == MMS_M_ON_LINE? "ON_LINE" : "OFF_LINE");
if (MMS_M_ON_LINE == status)
{
iec61850m_ext_demo(fd);
}
}
@ -588,6 +596,88 @@ int app_iec61850m_init1(void *arg)
return 0;
}
/*****************************************************************************
*
*****************************************************************************/
/***************************************************************************** * 新增功能演示回调 * 连接上线后由 iec61850m_ext_demo() 调用,演示文件服务、服务器查询、定值组操作 *****************************************************************************/
LOCAL void demo_file_read_cb(int fd, const char *filename,
const uint8_t *p_data, int data_len, bool more_follows,
int err)
/** 文件读取回调 */
{
if (IED_ERROR_OK != err)
{
LOG_E("file read failed: %s, err=%d", filename, err);
return;
}
LOG_I("file %s read %d bytes", filename, data_len);
/* TODO: 将文件数据写入本地磁盘 */
}
LOCAL void demo_file_delete_cb(int fd, const char *filename, int err)
{
if (IED_ERROR_OK == err)
{
/** 文件删除回调 */
LOG_I("file %s deleted successfully", filename);
}
else
{
LOG_E("file %s delete failed: %d", filename, err);
}
}
LOCAL void demo_server_query_cb(int fd, const char *vendor,
const char *model, const char *revision,
int logical_status, int physical_status, int err)
{
if (IED_ERROR_OK != err)
/** 服务器身份和状态查询回调 */
{
LOG_E("server query failed: %d", err);
return;
}
LOG_I("server: vendor=%s, model=%s, rev=%s, log_st=%d, phy_st=%d",
vendor, model, revision, logical_status, physical_status);
}
LOCAL void demo_sg_cb(int fd, const char *ld_name,
int act_sg, int num_sg, int err)
{
if (IED_ERROR_OK != err)
{
LOG_E("read SG info failed: %s, err=%d", ld_name, err);
/** 定值组信息读取回调 */
return;
}
LOG_I("%s: active SG=%d, total SG=%d", ld_name, act_sg, num_sg);
}
LOCAL int iec61850m_ext_demo(int fd)
{
/* 查询服务器信息 */
mms_m_query_server(fd, demo_server_query_cb);
/* 读取定值组信息 */
mms_m_read_sg_info(fd, "PROT", demo_sg_cb);
/** * 新功能演示入口 * 查询服务器信息、读取定值组状态 */
/* 删除文件示例 */
// mms_m_delete_file(fd, "IEDSERVER.BIN", demo_file_delete_cb);
/* 读取文件示例 */
// mms_m_read_file(fd, "COMTRADE/FAULT01.CFG", demo_file_read_cb);
return 0;
}
int app_iec61850m_init2(void *arg)
{
static uint32_t *p_iec_run_cnt = NULL;