[ref]同步711

This commit is contained in:
shi_jq 2025-03-13 15:53:44 +08:00
parent 4d85df836b
commit 622341b73e
20 changed files with 436 additions and 120 deletions

View File

@ -26,6 +26,7 @@ LIBS += -llibcositcps \
-llibslog \
-lkbd61850dbinterface
LIBS += -lboost_system
win32{
LIBS += -lws2_32
@ -40,7 +41,7 @@ include(../iec860.pri)
INCLUDEPATH += modules/Scout
INCLUDEPATH += ../../include/
SOURCES += \

View File

@ -428,6 +428,29 @@ int GetYkDaInfobyChanNoAndPointID(int nChanNo, int pointid, tagYkTypeInfo &resul
return EN_RET_FAILURE;
}
//通过测点ID和通道号获取模拟量控制/混合量控制的其他信息
int GetCtrlInfobyChanNoAndPointID(int nChanNo,eSignalInstType pntType,int pointid, tagYkTypeInfo &result)
{
//通过通道号找到装置的tagName
//通过装置的TagName和pointid找到遥控的属性
if(g_mapChanNoToIedInfo.find(nChanNo) != g_mapChanNoToIedInfo.end())
{
const CIedInfo &ied = g_mapChanNoToIedInfo[nChanNo];
QString key = IEC850C::getCfgSignalInstKey(ied.m_strIedName, pntType,pointid);
if(g_mapCfgSignalInst.contains(key))
{
const CCfgSignalInst *pSignal = g_mapCfgSignalInst[key];
result.m_nTypeid = pSignal->m_nTypeid;
result.m_strRef = pSignal->m_strIedName + pSignal->m_strPointRef;
return EN_RET_SUCCESS;
}
else
return EN_RET_ERROR_POINTNO_ERROR;
}
return EN_RET_FAILURE;
}
void GetDeviceParaRefbyDzCode(int nChanNo,int nDZCode, QString &strDeviceReference)
{
//定值和装置参数如何区分?,DZCode是唯一的

View File

@ -571,6 +571,66 @@ static ST_VOID _addVariablesWithFc(const char *pszFC, char *pszLnName, char *psz
}
}
static ST_VOID _AO_tagControlParaToTagVariable(const tagControlPara *pSBOw, tagVariable *ptVarSBOw)
{
assert(pSBOw != NULL);
assert(ptVarSBOw != NULL);
tagPrimitiveValue tPrim;
ptVarSBOw->reference = pSBOw->ControlObjectReference;
ptVarSBOw->mapRefToPrim.clear();
tPrim = pSBOw->ctlVal;
ptVarSBOw->mapRefToPrim["$setMag$f"] = tPrim;
if(pSBOw->operTm.secs != 0)
{
tPrim.basicType = EN_BasicType_UTC_TIME_STAMP;
memcpy(&tPrim.value.utc_time_value, &pSBOw->operTm, sizeof(tagUtcTimeStamp));
ptVarSBOw->mapRefToPrim["$operTm"] = tPrim;
}
tPrim.basicType = EN_BasicType_INT8;
tPrim.value.int8_value = pSBOw->origin.orCat;
ptVarSBOw->mapRefToPrim["$origin$orCat"] = tPrim;
tPrim.basicType = EN_BasicType_OCTET_STRING;
tPrim.value.octet_string_value = pSBOw->origin.orIdent;
ptVarSBOw->mapRefToPrim["$origin$orIdent"] = tPrim;
tPrim.basicType = EN_BasicType_INT8U;
tPrim.value.int8u_value = pSBOw->ctlNum;
ptVarSBOw->mapRefToPrim["$ctlNum"] = tPrim;
tPrim.basicType = EN_BasicType_UTC_TIME_STAMP;
//tPrim.value.utc_time_value = pSBOw->T;
//2022-07-14 thxiao 遥控时间取当前的UTC时间,按照R80 61850的格式填写,不需要加时区
M_UTC_TIME_STAMP localTime;
localTime.secs = (ST_UINT32)time(NULL);
localTime.fraction = 99;
localTime.qflags = 0xff;
tPrim.value.utc_time_value = localTime;
ptVarSBOw->mapRefToPrim["$T"] = tPrim;
if(!ptVarSBOw->mapRefToPrim.contains("$operTm"))
{
ptVarSBOw->mapRefToPrim["$operTm"] = tPrim;
}
tPrim.basicType = EN_BasicType_Boolean;
tPrim.value.boolean_value = pSBOw->Test;
ptVarSBOw->mapRefToPrim["$Test"] = tPrim;
tPrim.basicType = EN_BaiscType_PACKED_LIST;
tPrim.value.packed_list_value = pSBOw->Check;
ptVarSBOw->mapRefToPrim["$Check"] = tPrim;
ptVarSBOw->respTag = 0; //ASSUME FAILURE
ptVarSBOw->dataAccessError = 0;
}
static ST_VOID _tagControlParaToTagVariable(const tagControlPara *pSBOw, tagVariable *ptVarSBOw)
{
assert(pSBOw != NULL);
@ -614,6 +674,11 @@ static ST_VOID _tagControlParaToTagVariable(const tagControlPara *pSBOw, tagVari
ptVarSBOw->mapRefToPrim["$T"] = tPrim;
if(!ptVarSBOw->mapRefToPrim.contains("$operTm"))
{
ptVarSBOw->mapRefToPrim["$operTm"] = tPrim;
}
tPrim.basicType = EN_BasicType_Boolean;
tPrim.value.boolean_value = pSBOw->Test;
ptVarSBOw->mapRefToPrim["$Test"] = tPrim;
@ -1934,6 +1999,42 @@ M_RET Operate(mvl_net_info *con, const tagControlPara *pOperate, M_ENUMERATED *p
return nRetCode;
}
M_RET YtWithOperObject(mvl_net_info *con, const tagControlPara *pOperate, M_ENUMERATED *pAddCause, const int timeOut)
{
M_RET nRetCode = EN_RET_FAILURE;
ST_INT8 nAddCause = -1;
tagVariable tVarOperate;
QVector<tagVariable> vecVarOperate;
tagControlPara tSBOwControl = *pOperate;
tSBOwControl.ControlObjectReference += "$Oper";
_AO_tagControlParaToTagVariable(&tSBOwControl, &tVarOperate);
u_start_tracking_last_appl_error(tSBOwControl.ControlObjectReference.toLocal8Bit().data());
vecVarOperate.push_back(tVarOperate);
nRetCode = SetDataValues(con, vecVarOperate, timeOut);
if (EN_RET_SUCCESS == nRetCode)
{
if (vecVarOperate[0].respTag != 1)
{
//Write Failure
nAddCause = u_get_add_cause();
nRetCode = EN_RET_FAILURE;
}
}
if (pAddCause)
{
*pAddCause = nAddCause;
}
return nRetCode;
}
/*==============================================================================
* :
* : con

View File

@ -526,6 +526,9 @@ M_RET Select(mvl_net_info *con, const QString &strControlObjectReference, cons
M_RET SelectWithValue(mvl_net_info *con, const tagControlPara *ptSBOw, M_ENUMERATED *pAddCause, const int timeOut); // 带值选择
M_RET Cancel(mvl_net_info *con, const tagControlPara *ptCancel, M_ENUMERATED *pAddCause, const int timeOut); // 取消
M_RET Operate(mvl_net_info *con, const tagControlPara *ptOperate, M_ENUMERATED *pAddCause, const int timeOut); // 执行
//用于实现模拟量和混合量的对象控制类型部分设备的模拟量使用了增强型的控制对象类型类似遥控的Oper对象
M_RET YtWithOperObject(mvl_net_info *con, const tagControlPara *ptOperate, M_ENUMERATED *pAddCause, const int timeOut); // 执行
M_RET TimeActivationOperate(mvl_net_info *con, const tagControlPara *ptOperate, M_ENUMERATED *pAddCause, const int timeOut); // 时间激活操作
// 文件传输模型

View File

@ -100,13 +100,15 @@ int getFesDataType(int signalInstType)
switch(signalInstType)
{
case eSignalInstType_Accuml:
return 3;
return ePointType_ACC;
case eSignalInstType_Analog:
return 1;
return ePointType_AI;
case eSignalInstType_Digital:
return 2;
return ePointType_DI;
case eSignalInstType_Const:
return 4;
return ePointType_DZ;
case eSignalInstType_Mix:
return ePointType_Mi;
default:
return -1;
}
@ -117,14 +119,16 @@ eSignalInstType getSignalInstType(int fesType)
{
switch(fesType)
{
case 3:
case ePointType_ACC:
return eSignalInstType_Accuml;
case 1:
case ePointType_AI:
return eSignalInstType_Analog;
case 2:
case ePointType_DI:
return eSignalInstType_Digital;
case 4:
case ePointType_DZ:
return eSignalInstType_Const;
case ePointType_Mi:
return eSignalInstType_Mix;
default:
return eSignalInstType_Invalid;
}

View File

@ -34,7 +34,8 @@ IEC850C::ComtradeThread g_ComtradeThread;
IEC850C::LogThread g_LogThread;
IEC850C::doCommServiceThread g_doCommServiceThread;
#endif
int _writeSEValue(const int ChanNo, const int Timeout,const int GroupNo, const std::vector<SIEC61850SGValue>& SetValue, std::vector<SIEC61850SGResp>& RespValue, eSignalInstType eSignalType);
//retCtrlSelect是否执行了定值区激活命令
int _writeSEValue(const int ChanNo, const int Timeout,const int GroupNo, const std::vector<SIEC61850SGValue>& SetValue, std::vector<SIEC61850SGResp>& RespValue, eSignalInstType eSignalType, bool &bCtrlSelect);
#ifdef DEBUG_SISCO
@ -619,13 +620,14 @@ int FES_ReportEnable(const int EnableFlag)
return 0;
}
bool GetTagControlPara(tagControlPara &tControlPara,const SIEC61850CtrlReq *pCmd,const tagYkTypeInfo &YkInfo)
bool GetTagControlPara(tagControlPara &tControlPara,const SIEC61850CtrlReq *pCmd,const tagYkTypeInfo &YkInfo,const QString &leaf)
{
bool ret = true;
tControlPara.ControlObjectReference = YkInfo.m_strRef;//"PRS7367DPROT/LLN0$CO$FuncEna1";
int nTypeId = YkInfo.m_nTypeid;
EnBasicType basicType = GetBasicType(nTypeId, "$ctlVal");
//EnBasicType basicType = GetBasicType(nTypeId, "$ctlVal");
EnBasicType basicType = GetBasicType(nTypeId, leaf);
//判断是否为不支持的基本类型,不支持则直接返回
switch(basicType)
@ -720,8 +722,9 @@ bool GetTagControlPara(tagControlPara &tControlPara,const SIEC61850CtrlReq *pCm
int do_writeAOValue(const int ChanNo, const int Timeout, const std::vector<SIEC61850SGValue>& SetValue, std::vector<SIEC61850SGResp>& RespValue)
{
int ret = _writeSEValue(ChanNo, Timeout, 0, SetValue, RespValue, eSignalInstType_AnalogCtrl);
if(0 == ret)
bool bCtrlSelect = false;
int ret = _writeSEValue(ChanNo, Timeout, 0, SetValue, RespValue, eSignalInstType_AnalogCtrl,bCtrlSelect);
if(0 == ret && bCtrlSelect)
{
// 下发定值确认修改命令
ret = FES_ConfirmEditSGValue(ChanNo, Timeout, 0);
@ -730,7 +733,21 @@ int do_writeAOValue(const int ChanNo, const int Timeout, const std::vector<SIEC
return ret;
}
eCtlModel GetCtlModel(mvl_net_info *conn, QString &ControlObjectReference, const int timeOut)
int do_writeMOValue(const int ChanNo, const int Timeout, const std::vector<SIEC61850SGValue>& SetValue, std::vector<SIEC61850SGResp>& RespValue)
{
bool bCtrlSelect = false;
int ret = _writeSEValue(ChanNo, Timeout, 0, SetValue, RespValue, eSignalInstType_MixCtrl,bCtrlSelect);
if(0 == ret && bCtrlSelect)
{
// 下发定值确认修改命令
ret = FES_ConfirmEditSGValue(ChanNo, Timeout, 0);
}
return ret;
}
eCtlModel GetCtlModel(mvl_net_info *conn, QString &ControlObjectReference,
const QStringList &ykFC,const QString &confFC, const int timeOut)
{
eCtlModel nCtlModel = eCtlModel_NULL;
// 首先从资源区获取遥控测点的ctlModel值
@ -740,7 +757,12 @@ eCtlModel GetCtlModel(mvl_net_info *conn, QString &ControlObjectReference, const
// 资源区获取失败, 则在线读取
tagVariable tVariable;
tVariable.reference = ControlObjectReference + QString("$ctlModel");
tVariable.reference.replace("$CO$","$CF$"); //将遥控FC替换为配置FC
//tVariable.reference.replace("$CO$","$CF$"); //将遥控FC替换为配置FC
for(int nFCIdx = 0; nFCIdx < ykFC.size();nFCIdx++)
{
tVariable.reference.replace(ykFC.at(nFCIdx),confFC); //将遥控FC替换为配置FC
}
QVector<tagVariable> vecVariables;
vecVariables.push_back(tVariable);
M_RET ret = GetDataValues(conn, vecVariables, timeOut);
@ -769,6 +791,64 @@ eCtlModel GetCtlModel(mvl_net_info *conn, QString &ControlObjectReference, const
return nCtlModel;
}
//Mo以对象形式控制类似do控制需要写整个控制对象
int yt_OperObjControl(mvl_net_info *conn, const SIEC61850CtrlReq *pCmd,const tagYkTypeInfo &YkInfo, const int timeout)
{
int ret = EN_RET_SUCCESS;
eCtlModel nCtlModel = eCtlModel_NULL;
M_ENUMERATED addCause = -1;
//获取下发的遥控数据
tagControlPara tControlPara;
if(!GetTagControlPara(tControlPara, pCmd, YkInfo,"$setMag$f"))
{
USER_LOG_ERR0("获取控制命令参数失败\n");
return EN_RET_FAILURE;
}
//获取遥控测点对象的ctlModel
const QStringList FClist = {"$SP$","$CO$"};
nCtlModel = GetCtlModel(conn, tControlPara.ControlObjectReference,FClist,"$CF$", timeout);
if(nCtlModel == eCtlModel_NULL)
{
USER_LOG_ERR1("Get ctlModel for '%s' failed!", tControlPara.ControlObjectReference.toLocal8Bit().data());
return EN_RET_FAILURE;
}
// 根据约定的遥控类型, 结合ctlMode, 分别处理遥控命令
switch(pCmd->CtrlActType)
{
case eCtrlType_excute: //执行类型
{
switch (nCtlModel)
{
case eCtlModel_STATUS_ONLY:
USER_LOG_ERR1("对象 '%s' 为只读(ctlModel = 0), 不可遥控!", tControlPara.ControlObjectReference.toLocal8Bit().data());
ret = EN_RET_FAILURE;
break;
case eCtlModel_DIRECT_WITH_NORMAL_SECURITY:
case eCtlModel_DIRECT_WITH_ENHANCED_SECURITY:
case eCtlModel_SBO_WITH_NORMAL_SECURITY:
case eCtlModel_SBO_WITH_ENHANCED_SECURITY:
ret = YtWithOperObject(conn, &tControlPara, &addCause, timeout); // 执行
break;
default:
USER_LOG_ERR1("遥控类型[%d]错误\n", nCtlModel);
ret = EN_RET_FAILURE;
break;
}
break;
}
default:
USER_LOG_ERR1("遥控类型[%d]错误\n",pCmd->CtrlActType);
ret = EN_RET_FAILURE;
break;
}
return ret;
}
/*==============================================================================
* :
* : conn
@ -786,14 +866,15 @@ int do_control(mvl_net_info *conn, const SIEC61850CtrlReq *pCmd,const tagYkType
//获取下发的遥控数据
tagControlPara tControlPara;
if(!GetTagControlPara(tControlPara, pCmd, YkInfo))
if(!GetTagControlPara(tControlPara, pCmd, YkInfo,"$ctlVal"))
{
USER_LOG_ERR0("获取控制命令参数失败\n");
return EN_RET_FAILURE;
}
//获取遥控测点对象的ctlModel
nCtlModel = GetCtlModel(conn, tControlPara.ControlObjectReference, timeout);
const QStringList FClist = {"$CO$"};
nCtlModel = GetCtlModel(conn, tControlPara.ControlObjectReference,FClist,"$CF$", timeout);
if(nCtlModel == eCtlModel_NULL)
{
USER_LOG_ERR1("Get ctlModel for '%s' failed!", tControlPara.ControlObjectReference.toLocal8Bit().data());
@ -894,6 +975,64 @@ void get_ctrl_return(const SIEC61850CtrlReq *pCmd, SIEC61850CtrlResp &ControlRe
ControlResult.retStatus = ret;
}
//模拟量和混合量类型遥控的Oper对象控制类型
int _ytWithOperObject(const int ChanNo, const int Timeout,mvl_net_info *conn,
const SIEC61850CtrlReq *pControl,SIEC61850CtrlResp &ControlResult)
{
tagYkTypeInfo resultInfo;
eSignalInstType instType = (pControl->PointType == ePointType_Ao) ? eSignalInstType_AnalogCtrl : eSignalInstType_MixCtrl;
int ret = GetCtrlInfobyChanNoAndPointID(ChanNo,instType,pControl->PointId,resultInfo);
if(ret == EN_RET_SUCCESS)
ret = yt_OperObjControl(conn,pControl, resultInfo, Timeout);
get_ctrl_return(pControl, ControlResult, ret);
return ret;
}
//模拟量和混合量,值控制类型
int _ytWithSingleValue(const int ChanNo, const int Timeout,
std::vector<SIEC61850SGValue> SetValue,std::vector<SIEC61850SGResp> &RespValue,
const SIEC61850CtrlReq *pControl,
SIEC61850CtrlResp &ControlResult)
{
int ret = 0;
SetValue.clear();
RespValue.clear();
SIEC61850SGValue AOValue;
AOValue.DZCode = pControl->PointId;
AOValue.ValueType = pControl->ValueType;
memcpy(&(AOValue.Value) ,&(pControl->Value),sizeof(pControl->Value));
SetValue.push_back(AOValue);
if(pControl->PointType == ePointType_Ao)
{
ret = do_writeAOValue(ChanNo, Timeout, SetValue, RespValue);
}
else
{
ret = do_writeMOValue(ChanNo, Timeout, SetValue, RespValue);
}
// 拼接返回参数
ControlResult.PointType = pControl->PointType;
ControlResult.PointId = pControl->PointId;
ControlResult.CtrlActType = pControl->CtrlActType;
//不为0可能没有下发成功返回返回的ret值
if(ret != 0)
{
USER_LOG_ERR2("PointID[%d] AO control failed. ret = '%d'",pControl->PointId, ret);
ControlResult.retStatus = ret; //返回状态 成功则返回sucess0否则返回错误码errcode
}
else //为0可能服务返回错误码
{
if(!RespValue.empty())
ControlResult.retStatus = RespValue.front().retStatus;; //返回状态 成功则返回sucess0否则返回错误码errcode
}
return ret;
}
int FES_Control(const int ChanNo, const int Timeout,const std::vector<SIEC61850CtrlReq>& CtrlReq,std::vector<SIEC61850CtrlResp>& CtrlResp)
{
int iotSuccess = EN_ARE_SUCCESS;
@ -926,30 +1065,14 @@ int FES_Control(const int ChanNo, const int Timeout,const std::vector<SIEC61850C
get_ctrl_return(pControl, ControlResult, ret);
break;
case ePointType_Ao:
SetValue.clear();
RespValue.clear();
SIEC61850SGValue AOValue;
AOValue.DZCode = pControl->PointId;
AOValue.ValueType = pControl->ValueType;
memcpy(&(AOValue.Value) ,&(pControl->Value),sizeof(pControl->Value));
SetValue.push_back(AOValue);
ret = do_writeAOValue(ChanNo, Timeout, SetValue, RespValue);
// 拼接返回参数
ControlResult.PointType = pControl->PointType;
ControlResult.PointId = pControl->PointId;
ControlResult.CtrlActType = pControl->CtrlActType;
//不为0可能没有下发成功返回返回的ret值
if(ret != 0)
case ePointType_Mo:
if(pControl->CtrlObjType == eCtrlObjType_SingleValue)
{
USER_LOG_ERR2("PointID[%d] AO control failed. ret = '%d'",pControl->PointId, ret);
ControlResult.retStatus = ret; //返回状态 成功则返回sucess0否则返回错误码errcode
ret = _ytWithSingleValue(ChanNo,Timeout,SetValue,RespValue,pControl,ControlResult);
}
else //为0可能服务返回错误码
else
{
if(!RespValue.empty())
ControlResult.retStatus = RespValue.front().retStatus;; //返回状态 成功则返回sucess0否则返回错误码errcode
ret = _ytWithOperObject(ChanNo,Timeout,conn,pControl,ControlResult);
}
break;
}
@ -1456,7 +1579,7 @@ int _ConvertFESSGValuetoVecTagVariable(int ChanNo, const std::vector<SIEC61850SG
* @param eSignalType:
* @return: SUCCESS/FAILURE
*/
int _writeSEValue(const int ChanNo, const int Timeout,const int GroupNo, const std::vector<SIEC61850SGValue>& SetValue, std::vector<SIEC61850SGResp>& RespValue, eSignalInstType eSignalType)
int _writeSEValue(const int ChanNo, const int Timeout,const int GroupNo, const std::vector<SIEC61850SGValue>& SetValue, std::vector<SIEC61850SGResp>& RespValue, eSignalInstType eSignalType, bool &bCtrlSelect)
{
int nRet = EN_RET_SUCCESS;
mvl_net_info *conn = GetMvlNetInfobyChanNo(ChanNo); // 获取通道号的连接参数
@ -1514,6 +1637,7 @@ int _writeSEValue(const int ChanNo, const int Timeout,const int GroupNo, const
USER_LOG_ERR3("strSGCBReference=%s,nEditGroup=%d 激活定值区失败,错误码%d",strSGCBReference.toLocal8Bit().data(),nEditGroup,nRet);
break;
}
bCtrlSelect = true;
//写定值
nRet = SetSGValues(conn, vecSettings, Timeout);
@ -1550,7 +1674,6 @@ int _writeSEValue(const int ChanNo, const int Timeout,const int GroupNo, const
return nRet;
}
/**
* @brief FES_WriteSEValue FES接口
* @param ChanNo
@ -1561,7 +1684,8 @@ int _writeSEValue(const int ChanNo, const int Timeout,const int GroupNo, const
*/
int FES_WriteSEValue(const int ChanNo, const int Timeout,const int GroupNo, const std::vector<SIEC61850SGValue>& SetValue, std::vector<SIEC61850SGResp>& RespValue)
{
return _writeSEValue(ChanNo, Timeout, GroupNo, SetValue, RespValue, eSignalInstType_Const);
bool bCtrlSelect = false;
return _writeSEValue(ChanNo, Timeout, GroupNo, SetValue, RespValue, eSignalInstType_Const, bCtrlSelect);
}
/**
@ -2167,4 +2291,9 @@ int save_osi_cfg(int maxCalling, const QString &CfgPath)
}
void setPingMng(const iot_fes::CPingInterfacePtr ptrPingMng)
{
g_MonitorThread.setPingMngPtr(ptrPingMng);
}
}

View File

@ -51,7 +51,8 @@ bool releaseData();
int FES_Connect(const int ChanNo, const int NetAB, const int EnableReport);
// 连接结果
void FES_ConnentStatus_Callback(const int ChanNo, const int retStatus);
// 设置Ping功能对象用于提高MonitorThread线程中重连速度
void setPingMng(const iot_fes::CPingInterfacePtr ptrPingMng);
// 报告使能结果
void FES_RptStatus_Callback(const int ChanNo, const char *RptName, const int retStatus);

View File

@ -209,7 +209,7 @@ void Monitor_ReEnable_and_CycleGI(int nChanno, CIedInfo &ied)
}
// 通道重连
void Monitor_Channel_Reconnect(int nChanno, CIedInfo &ied)
void Monitor_Channel_Reconnect(int nChanno, bool bPingOk, CIedInfo &ied)
{
if(ied.m_nConnStauts != eConnStatus_OPEN_FAILURE)
{
@ -249,7 +249,7 @@ void Monitor_Channel_Reconnect(int nChanno, CIedInfo &ied)
S_W_LOCK_RESOURCE(ied, 3);
// 发起通道连接
if(0 == Connect(m_strDeviceTagName, nChanno, ied.m_nEnableReport, mmsconfig_ini.m_nChannelReConnectTimeout))
if(bPingOk && 0 == Connect(m_strDeviceTagName, nChanno, ied.m_nEnableReport, mmsconfig_ini.m_nChannelReConnectTimeout))
{
ied.m_nReConnectCount = 0; // 重连失败计数器清零
}
@ -354,11 +354,13 @@ void MonitorThread::onRun()
// 通道状态监视
Monitor_ChannelConnStatus(nChanno, ied);
// 通道重连
Monitor_Channel_Reconnect(nChanno, ied);
// 通道重连,先看一下是否ping通ping的通才会调用connect函数
bool bPingOk = pingOk(nChanno);
Monitor_Channel_Reconnect(nChanno,bPingOk,ied);
// 按通道sleep, 释放资源, 避免过度占用
std::chrono::milliseconds t1(100);
//std::chrono::milliseconds t1(10);
std::this_thread::sleep_for(t1);
}
@ -371,6 +373,23 @@ void MonitorThread::onRun()
return;
}
//设置ping管理类指针
void MonitorThread::setPingMngPtr(const iot_fes::CPingInterfacePtr ptrPingMng)
{
m_ptrPingMng = ptrPingMng;
}
//查询指定通道是否能够ping通
bool MonitorThread::pingOk(const int nChannelNo)
{
if(m_ptrPingMng != NULL)
{
return m_ptrPingMng->getPingResult(nChannelNo);
}
return true;
}
MonitorThread::~MonitorThread()
{
USER_LOG_ERR0("MonitorThread.~MonitorThread 1\n");
@ -378,6 +397,7 @@ MonitorThread::~MonitorThread()
if (pthread)
delete pthread;
pthread = nullptr;
m_ptrPingMng.reset();
USER_LOG_ERR0("MonitorThread.~MonitorThread 2\n");
}
@ -418,6 +438,8 @@ void MonitorThread::close()
}
// _sem.wait();
}
m_ptrPingMng.reset();
USER_LOG_ERR0("MonitorThread.close 2\n");
}

View File

@ -6,6 +6,7 @@
#include <future>
#include "CELLTimeStamp.hpp"
#include "CELLSemaphore.hpp"
#include "fes_ping_api/PingInterface.h"
namespace IEC850C {
@ -27,6 +28,8 @@ private:
std::atomic_bool _bIsExit;
CELLSemaphore _sem;
CELLTimestamp m_Timer;
iot_fes::CPingInterfacePtr m_ptrPingMng; //Ping管理类指针
public:
std::thread *pthread = nullptr;
public:
@ -37,7 +40,12 @@ public:
void start();
void close();
void onRun();
//设置ping管理指针用于优化MonitorThread线程中重连效率未ping通不执行connect
void setPingMngPtr(const iot_fes::CPingInterfacePtr ptrPingMng);
private:
//查询指定通道号是否能够ping通
bool pingOk(const int nChannelNo);
};
}

View File

@ -742,6 +742,14 @@ void OperTacking_Control(QString strCmdText, const int ChanNo, const int Timeout
strPointRef = pSigalInst->m_strSignalRef;
}
}
else if(ePointType_Mo == req.PointType)
{
CCfgSignalInst *pSigalInst = GetSettingSignalbyDZNo(ChanNo,req.PointId,eSignalInstType_MixCtrl);
if(pSigalInst != NULL)
{
strPointRef = pSigalInst->m_strSignalRef;
}
}
OperTacking.m_strDetail << "遥控通道: " << i << std::endl;
OperTacking.m_strDetail << strSpace(4) << "61850路径: " << strPointRef.toStdString() << std::endl;
@ -805,6 +813,14 @@ void OperTacking_Control(QString strCmdText, const int ChanNo, const int Timeout
strPointRef = pSigalInst->m_strSignalRef;
}
}
else if(ePointType_Mo == req.PointType)
{
CCfgSignalInst *pSigalInst = GetSettingSignalbyDZNo(ChanNo,req.PointId,eSignalInstType_MixCtrl);
if(pSigalInst != NULL)
{
strPointRef = pSigalInst->m_strSignalRef;
}
}
OperTacking.m_strDetail << "遥控通道: " << i << std::endl;
OperTacking.m_strDetail << strSpace(4) << "61850路径: " << strPointRef.toStdString() << std::endl;

View File

@ -799,7 +799,7 @@ void writeIndData(const tagRptParse *ptRptParse)
// 将数据值保存起来
//2022-11-23 thxiao 7SJ686 故障启动信号包含general\dirGeneral\q\t, mapReferenceToDataValue数组大小最后会变为2
//在后面取值时取了dirGeneral的值作为点值导致DI点值常为0。此处增加判断dirGeneral的值不保存在mapReferenceToDataValue
if (!strReference.contains("$dirGeneral"))
if (!strReference.contains("$dirGeneral") && !strReference.contains("$stSeld"))
mapReferenceToDataValue[strReference] = sIECValue;
}
@ -901,7 +901,12 @@ void writeIndData(const tagRptParse *ptRptParse)
SIEC61850DataInfo dataInfo;
strIEDName = cfgSignalInst->m_strIedName; // 获取对象的IEDName, 后续会使用
int FesType = getFesDataType(cfgSignalInst->m_nPointType);
if(FesType == -1) USER_LOG_ERR1("cfgSignalInst::strSignalRef= '%s' signalType is Wrong!", cfgSignalInst->m_strSignalRef.toLocal8Bit().data());
if(FesType == -1)
{
USER_LOG_ERR1("cfgSignalInst::strSignalRef= '%s' signalType is Wrong!", cfgSignalInst->m_strSignalRef.toLocal8Bit().data());
continue;
}
dataInfo.strPntRef = cfgSignalInst->m_strPointRef.toStdString();
dataInfo.PointType = FesType;
dataInfo.PointId = cfgSignalInst->m_nPointid;
dataInfo.ValueType = iter.value().ValueType;
@ -930,7 +935,7 @@ void writeIndData(const tagRptParse *ptRptParse)
getChanNoByIedName(strIEDName, cChanNo);
if(cChanNo == -1)
{
//USER_LOG_ERR1("getChanNoByIedName '%s' return failed!", strIEDName.toLocal8Bit().data());
USER_LOG_ERR1("getChanNoByIedName '%s' return failed!", strIEDName.toLocal8Bit().data());
return;
}
@ -1281,7 +1286,13 @@ int rptIndHandleEx (MVL_COMM_EVENT *event)
info_va[va_num++] = rcb_info->rcb_var.Inclusion;
assert (va_num < va_total);
assert (va_num <= va_total);
if (va_num > va_total)
{
USER_LOG_ERR3 ("RptID '%s' result size error.va_total:%d va_num:%d", saveRptID,va_total,va_num);
retcode = SD_FAILURE;
goto CLEANUP;
}
/* Perform 2nd decode (up through "Inclusion"). */
mvl_info_data_to_local (event, va_num, info_va);

View File

@ -71,6 +71,11 @@ int CIEC61850dll::FES_Connect(const int ChanNo, const int NetAB, const int Enabl
return IEC850C::FES_Connect(ChanNo, NetAB, EnableReport);
}
void CIEC61850dll::setPingMngPtr(const iot_fes::CPingInterfacePtr ptrPingMng)
{
IEC850C::setPingMng(ptrPingMng);
}
int CIEC61850dll::FES_Disconnect(const int ChanNo)
{
IEC850C::OperTacking_ChanStatus("发起通道释放", ChanNo);

View File

@ -1,5 +1,6 @@
#pragma once
#include <vector>
#include <string>
#include "DataType.h"
const int CN_IEC61850cMaxRefSize = 128;
@ -7,11 +8,15 @@ const int CN_IEC61850cMaxRefSize = 128;
//typedef unsigned __int64 uint64;
typedef void *HANDLE;
#define IEC61850_K_MAX_REFERENCE_SIZE 128
//todo:此文件为什么要拷贝一份放在这iec61850client2和fes/ice61850/include下各有一份了暂时没敢合并所以修改时记得2个文件同步
typedef struct {
int PointType;//5:DO 6:AO
int PointId; //Param1
int ValueType;//1:int 2:float 3:int64
int ValueType;//1:int 2:float 3:int64 对应Param2
int CtrlObjType; //对应IEC850C_Resource.h中的eCtrlObjType控制对象类型用来标识当前控制点是值控制还是类似遥控的对象控制方式
//有的设备将模拟量控制设置为一个与遥控一样的对象,$Oper$setMag$f
//用Param3标识暂时只对混合量和模拟量生效0代表值控制1代表对象控制
int orCat; //for DO
union
{
@ -48,6 +53,7 @@ typedef struct {
}SIEC61850SGResp;
typedef struct {
std::string strPntRef; //不带IEDName
int PointType;//1:AI 2:DI 3:ACC 4:DZ
int PointId; //Param1
int ValueType;//1:int 2:float 3:int64

View File

@ -1,8 +1,9 @@
#pragma once
#include <vector>
#include "IEC61850c_pub.h"
#include "common/Export.h"
#include "fes_ping_api/PingInterface.h"
#ifdef PROTOCOLBASE_API_EXPORT
#define PROTOCOLBASE_API G_DECL_EXPORT
#else
@ -75,6 +76,7 @@ public:
static bool release();
void OperTacking();
int FES_Connect(const int ChanNo, const int NetAB, const int EnableReport);
void setPingMngPtr(const iot_fes::CPingInterfacePtr ptrPingMng);
// 关闭指定通道
int FES_Disconnect(const int ChanNo);

View File

@ -487,8 +487,25 @@ enum eCtrlType
//DO/DA
enum ePointType
{
//todo:此定义不能修改原来只定义了DO和AO其余没有定义不确定哪些地方使用了魔数所以不要动原定义只能增加
ePointType_AI=1,
ePointType_DI=2,
ePointType_ACC=3,
ePointType_DZ=4,
ePointType_Do=5, //Do,DataObject
ePointType_Ao=6, //DA,DataAttribute
ePointType_Mo=7,
ePointType_Mi=8
};
//控制对象类型,用来标识当前控制点是值控制还是类似遥控的对象控制方式,
//有的设备将模拟量控制设置为一个与遥控一样的对象,$Oper$setMag$f
//用Param3标识暂时只对混合量和模拟量生效0代表值控制1代表对象控制
//关联SIEC61850CtrlReq
enum eCtrlObjType
{
eCtrlObjType_SingleValue = 0,
eCtrlObjType_OperObj
};
enum eSignalModelType
@ -795,6 +812,10 @@ void *getGlobalRptTypeids();
int GetYkDoInfobyChanNoAndPointID(int nChanNo, int pointid, tagYkTypeInfo &result);
//通过测点ID和通道号获取模拟量的其他信息
int GetYkDaInfobyChanNoAndPointID(int nChanNo,int pointid, tagYkTypeInfo &result);
//通过测点ID和通道号获取模拟量控制/混合量控制的其他信息
int GetCtrlInfobyChanNoAndPointID(int nChanNo,eSignalInstType pntType,int pointid, tagYkTypeInfo &result);
//通过GroupNo获取SGCB的Ref
void GetSGCBRefbyGroupNo(int nChanNo, int GroupNo, QString &strSGCBReference);
//通过DZCode获取定值Ref

View File

@ -5,22 +5,6 @@ CONFIG -= qt
TARGET = libasn1
QMAKE_CFLAGS_DEBUG += \
-DMMS_LITE \
-DDEBUG_SISCO
QMAKE_CFLAGS_RELEASE += \
-DMMS_LITE \
-DDEBUG_SISCO
QMAKE_CXXFLAGS_DEBUG += \
-DMMS_LITE \
-DDEBUG_SISCO
QMAKE_CXXFLAGS_RELEASE += \
-DMMS_LITE \
-DDEBUG_SISCO
include(../iec860.pri)
@ -53,5 +37,20 @@ SOURCES += \
$$IEC61850PATH/sisco/src/asn1r_maxlen.c
QMAKE_CFLAGS_DEBUG += \
-DMMS_LITE \
-DDEBUG_SISCO
QMAKE_CFLAGS_RELEASE += \
-DMMS_LITE \
-DDEBUG_SISCO
QMAKE_CXXFLAGS_DEBUG += \
-DMMS_LITE \
-DDEBUG_SISCO
QMAKE_CXXFLAGS_RELEASE += \
-DMMS_LITE \
-DDEBUG_SISCO

View File

@ -28,6 +28,8 @@ LIBS += \
-llibslog \
-lkbd61850dbinterface
LIBS += -lboost_system
win32{
LIBS += -lws2_32 \
# -lxerces-c_3
@ -38,6 +40,7 @@ linux-g++*{
}
include(../iec860.pri)
INCLUDEPATH += ../../include/
SOURCES += \

View File

@ -30,6 +30,8 @@ LIBS += -llibcositcps \
-llibslog \
-lkbd61850dbinterface
LIBS += -lboost_system -lfes_ping_api
win32{
LIBS += -lws2_32
}
@ -77,6 +79,7 @@ HEADERS += \
$$IEC61850_INCLUDE/IEC850C_DataInit.h\
$$IEC61850_INCLUDE/IEC850C_Osicfg.h
INCLUDEPATH += ../../include/
include($$IEC61850_EASY_TCP_CLIENT/EasyTcpClient.pri)
win32{

View File

@ -44,7 +44,7 @@ win32{
SOURCES += \
$$IEC61850PATH/sisco/src/glbsem_w32.c
}
linux-g++* {
linux-*g++* {
SOURCES += \
$$IEC61850PATH/sisco/src/glbsem_unix.c
}

View File

@ -708,9 +708,9 @@ ST_RET rcb_enable (MVL_NET_INFO *netInfo, ST_CHAR *domName,
sprintf(varName, "%s$EntryID", rcbName);
ret = named_var_read(netInfo, varName, DOM_SPEC, domName, rpt_typeids->ostring8, EntryIDStr, timeOut);
if (ret == SD_SUCCESS)
USER_LOG_ERR2("%s %s named_var_read() OK", varName, domName);
USER_LOG_ERR2("%s %s named_var_write() OK", varName, domName);
else
USER_LOG_ERR2("%s %s named_var_read() ERROR", varName, domName);
USER_LOG_ERR2("%s %s named_var_write() ERROR", varName, domName);
}
if (ret == SD_SUCCESS)
@ -722,48 +722,6 @@ ST_RET rcb_enable (MVL_NET_INFO *netInfo, ST_CHAR *domName,
else
USER_LOG_ERR2("%s %s named_var_write() ERROR", varName, domName);
}
//2023-05-08 thxiao 重复三次,保证写成功
//if (ret == SD_SUCCESS)
{
sprintf(varName, "%s$EntryID", rcbName);
ret = named_var_read(netInfo, varName, DOM_SPEC, domName, rpt_typeids->ostring8, EntryIDStr, timeOut);
if (ret == SD_SUCCESS)
USER_LOG_ERR2("%s %s named_var_read() OK", varName, domName);
else
USER_LOG_ERR2("%s %s named_var_read() ERROR", varName, domName);
}
if (ret == SD_SUCCESS)
{
sprintf(varName, "%s$EntryID", rcbName);
ret = named_var_write(netInfo, varName, DOM_SPEC, domName, rpt_typeids->ostring8, EntryIDStr, timeOut);
if (ret == SD_SUCCESS)
USER_LOG_ERR2("%s %s named_var_write() OK", varName, domName);
else
USER_LOG_ERR2("%s %s named_var_write() ERROR", varName, domName);
}
//if (ret == SD_SUCCESS)
{
sprintf(varName, "%s$EntryID", rcbName);
ret = named_var_read(netInfo, varName, DOM_SPEC, domName, rpt_typeids->ostring8, EntryIDStr, timeOut);
if (ret == SD_SUCCESS)
USER_LOG_ERR2("%s %s named_var_read() OK", varName, domName);
else
USER_LOG_ERR2("%s %s named_var_read() ERROR", varName, domName);
}
if (ret == SD_SUCCESS)
{
sprintf(varName, "%s$EntryID", rcbName);
ret = named_var_write(netInfo, varName, DOM_SPEC, domName, rpt_typeids->ostring8, EntryIDStr, timeOut);
if (ret == SD_SUCCESS)
USER_LOG_ERR2("%s %s named_var_write() OK", varName, domName);
else
USER_LOG_ERR2("%s %s named_var_write() ERROR", varName, domName);
}
//2022-04-06 写EntryID的代码段"ret == SD_SUCCESS"改为“ret = SD_SUCCESS”否则会导致不支持EntryID读写的保护初始化不成功。
ret = SD_SUCCESS;//如果设备相应失败,说明可能是不支持该方式,所以可以忽略。
}