<修改> 1、添加变化上送时的品质与时间;2、调整解析icd文件肿获取报告下的配置数据;3、调试事件报告控制块,实现客户端使能后上送变化数据
This commit is contained in:
parent
7c18f5ee9d
commit
cd61e8e27b
|
|
@ -44,6 +44,33 @@ LOCAL IedServer gp_iedServer = NULL;
|
||||||
LOCAL bool g_dbg_switch = false;
|
LOCAL bool g_dbg_switch = false;
|
||||||
|
|
||||||
/** SIGINT 信号处理:通知后台线程退出 */
|
/** 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);
|
||||||
|
}
|
||||||
|
|
||||||
LOCAL void sigint_handler(int signum)
|
LOCAL void sigint_handler(int signum)
|
||||||
{
|
{
|
||||||
g_running = 0;
|
g_running = 0;
|
||||||
|
|
@ -268,6 +295,7 @@ int mms_s_init(const char *icd_path, int port)
|
||||||
param_init(gp_iedServer, *gp_icd);
|
param_init(gp_iedServer, *gp_icd);
|
||||||
|
|
||||||
file_init(gp_iedServer);
|
file_init(gp_iedServer);
|
||||||
|
IedServer_setRCBEventHandler(gp_iedServer, rcbEventHandler, NULL);
|
||||||
|
|
||||||
IedServer_start(gp_iedServer, port);
|
IedServer_start(gp_iedServer, port);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -182,10 +182,10 @@ LOCAL int parse_ReportControl_TrgOps(XMLElement *ele_reportControl, stru_TrgOps
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
trgOps.dchg = (ele_trgOps->Attribute(key_dchg) == nullptr ? "false" : ele_trgOps->Attribute(key_dchg)) == "true";
|
trgOps.dchg = (ele_trgOps->Attribute(key_dchg) == nullptr ? false : strcmp(ele_trgOps->Attribute(key_dchg), "true") == 0);
|
||||||
trgOps.qchg = (ele_trgOps->Attribute(key_qchg) == nullptr ? "false" : ele_trgOps->Attribute(key_qchg)) == "true";
|
trgOps.qchg = (ele_trgOps->Attribute(key_qchg) == nullptr ? false : strcmp(ele_trgOps->Attribute(key_qchg), "true") == 0);
|
||||||
trgOps.dupd = (ele_trgOps->Attribute(key_dupd) == nullptr ? "false" : ele_trgOps->Attribute(key_dupd)) == "true";
|
trgOps.dupd = (ele_trgOps->Attribute(key_dupd) == nullptr ? false : strcmp(ele_trgOps->Attribute(key_dupd), "true") == 0);
|
||||||
trgOps.period = (ele_trgOps->Attribute(key_period) == nullptr ? "false" : ele_trgOps->Attribute(key_period)) == "true";
|
trgOps.period = (ele_trgOps->Attribute(key_period) == nullptr ? false : strcmp(ele_trgOps->Attribute(key_period), "true") == 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -211,12 +211,12 @@ LOCAL int parse_ReportControl_OptFields(XMLElement *ele_reportControl, stru_OptF
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
optFields.seqNum = (ele_optFields->Attribute(key_seqNum) == nullptr ? "false" : ele_optFields->Attribute(key_seqNum)) == "true";
|
optFields.seqNum = (ele_optFields->Attribute(key_seqNum) == nullptr ? false : strcmp(ele_optFields->Attribute(key_seqNum), "true") == 0);
|
||||||
optFields.timeStamp = (ele_optFields->Attribute(key_timeStamp) == nullptr ? "false" : ele_optFields->Attribute(key_timeStamp)) == "true";
|
optFields.timeStamp = (ele_optFields->Attribute(key_timeStamp) == nullptr ? false : strcmp(ele_optFields->Attribute(key_timeStamp), "true") == 0);
|
||||||
optFields.reasonCode = (ele_optFields->Attribute(key_reasonCode) == nullptr ? "false" : ele_optFields->Attribute(key_reasonCode)) == "true";
|
optFields.reasonCode = (ele_optFields->Attribute(key_reasonCode) == nullptr ? false : strcmp(ele_optFields->Attribute(key_reasonCode), "true") == 0);
|
||||||
optFields.dataRef = (ele_optFields->Attribute(key_dataRef) == nullptr ? "false" : ele_optFields->Attribute(key_dataRef)) == "true";
|
optFields.dataRef = (ele_optFields->Attribute(key_dataRef) == nullptr ? false : strcmp(ele_optFields->Attribute(key_dataRef), "true") == 0);
|
||||||
optFields.entryID = (ele_optFields->Attribute(key_entryID) == nullptr ? "false" : ele_optFields->Attribute(key_entryID)) == "true";
|
optFields.entryID = (ele_optFields->Attribute(key_entryID) == nullptr ? false : strcmp(ele_optFields->Attribute(key_entryID), "true") == 0);
|
||||||
optFields.configRef = (ele_optFields->Attribute(key_configRef) == nullptr ? "false" : ele_optFields->Attribute(key_configRef)) == "true";
|
optFields.configRef = (ele_optFields->Attribute(key_configRef) == nullptr ? false : strcmp(ele_optFields->Attribute(key_configRef), "true") == 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -611,7 +611,7 @@ LOCAL int model_DataSet_init(LogicalNode *LLN0, stru_icd &icd, std::map<std::str
|
||||||
for(it_fcda = p_dataset->vec_fcda.begin(); it_fcda != p_dataset->vec_fcda.end(); 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 + "$" + \
|
std::string variable = it_fcda->prefix + it_fcda->lnClass + it_fcda->lnInst + "$" + \
|
||||||
it_fcda->fc + "$" + it_fcda->doName + "$" + it_fcda->daName; // 拼装 FCDA 变量名
|
it_fcda->fc + "$" + it_fcda->doName + (it_fcda->daName.empty() ? "" : "$" + it_fcda->daName); // 拼装 FCDA 变量名
|
||||||
|
|
||||||
for(int i = 0; i < variable.size(); i++) // 将变量名中所有 '.' 替换为 '$'
|
for(int i = 0; i < variable.size(); i++) // 将变量名中所有 '.' 替换为 '$'
|
||||||
{
|
{
|
||||||
|
|
@ -663,7 +663,9 @@ LOCAL int model_ReportControlBlock_init(LogicalNode *LLN0, stru_icd &icd, std::m
|
||||||
int Options = model_get_rpt_options(rcb.optFields); // 将 OptFields 结构转为位掩码
|
int Options = model_get_rpt_options(rcb.optFields); // 将 OptFields 结构转为位掩码
|
||||||
int trgOps = model_get_rpt_trgOps(rcb.trgOps); // 将 TrgOps 结构转为位掩码
|
int trgOps = model_get_rpt_trgOps(rcb.trgOps); // 将 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); // 创建 RCB
|
LOG_I("RCB CREATE: name=%s dchg=%d qchg=%d dupd=%d period=%d -> trgOps=0x%x",
|
||||||
|
it_rcb->c_str(), rcb.trgOps.dchg, rcb.trgOps.qchg, rcb.trgOps.dupd, rcb.trgOps.period, trgOps);
|
||||||
|
rcb.Rcb = 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;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -580,6 +580,9 @@ LOCAL void mms_s_value_update(const char *str_saddr, const char *str_val)
|
||||||
|
|
||||||
DataAttribute *p_da = (DataAttribute *)p_node;
|
DataAttribute *p_da = (DataAttribute *)p_node;
|
||||||
|
|
||||||
|
LOG_I("mms_s_value_update: saddr=%s val=%s da_type=%d da_name=%s",
|
||||||
|
saddr.c_str(), val.c_str(), p_da->type, p_da->name);
|
||||||
|
|
||||||
if(g_iec61850s_value_update_cb_map.find(p_da->type) == g_iec61850s_value_update_cb_map.end())
|
if(g_iec61850s_value_update_cb_map.find(p_da->type) == g_iec61850s_value_update_cb_map.end())
|
||||||
{
|
{
|
||||||
LOG_E("EnumType %d not found in ICD", p_da->type);
|
LOG_E("EnumType %d not found in ICD", p_da->type);
|
||||||
|
|
@ -590,7 +593,34 @@ LOCAL void mms_s_value_update(const char *str_saddr, const char *str_val)
|
||||||
|
|
||||||
if(NULL != g_iec61850s_value_update_cb_map[p_da->type] && p_ied_server != NULL)
|
if(NULL != g_iec61850s_value_update_cb_map[p_da->type] && p_ied_server != NULL)
|
||||||
{
|
{
|
||||||
|
IedServer_lockDataModel(p_ied_server);
|
||||||
|
|
||||||
g_iec61850s_value_update_cb_map[p_da->type](p_ied_server, p_da, val);
|
g_iec61850s_value_update_cb_map[p_da->type](p_ied_server, p_da, val);
|
||||||
|
|
||||||
|
/* 向上查找父级 DO,同步更新时间戳(t)和品质(q) */
|
||||||
|
ModelNode *parent = p_node->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)
|
||||||
|
{
|
||||||
|
IedServer_updateUTCTimeAttributeValue(p_ied_server, child, Hal_getTimeInMs());
|
||||||
|
}
|
||||||
|
else if (strcmp(child->name, "q") == 0)
|
||||||
|
{
|
||||||
|
IedServer_updateQuality(p_ied_server, child, QUALITY_VALIDITY_GOOD);
|
||||||
|
}
|
||||||
|
child = (DataAttribute *)child->sibling;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IedServer_unlockDataModel(p_ied_server);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ LOCAL void iec61850s_st_mx_change_callback(std::string saddr, uint8_t data_type,
|
||||||
std::string val = dc_get_signal_val(p_data, data_type);
|
std::string val = dc_get_signal_val(p_data, data_type);
|
||||||
if(val.empty())
|
if(val.empty())
|
||||||
{
|
{
|
||||||
LOG_E("val is empty");
|
LOG_E("val is empty for saddr: %s", saddr.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue