零基础实现IEC61850(九)控制客户端

发布时间:2026/11/5 7:41:04
零基础实现IEC61850(九)控制客户端

前言

上一讲主要讲了控制服务端的实现,这一讲我们来讲如何实现控制的客户端,首先要启动客户端并实现与服务端的连接,前面章节介绍了如何启动客户端,这里采用另外一种方法来连接服务端
代码位置:
https://gitee.com/yunxingtianxia/yx-tools
yx-pis-dll\example\09 controlClient

直接使用服务端的模型文件

本地配置文件

这种方法可以直接加载服务端的cid模型文件,但是需要在本地增加配置,本例是在工程目录下增加了一个config目录,并在下面放入了client.ini文件,文件内容如下:

[IED] name=ClientIED AP_Count=1 [AP_0] name=ap01 ipAddress=192.168.8.1 subnet=255.255.255.0 gateway=192.168.8.2 macAddress=00-50-56-C0-00-08

这里面配置了IED名称,然后1个接入点,并配置了网络信息,如果没有goose、sv,macAddress无需配置,本例这样配置是为了展示全部的配置信息。

建模工具

建模工具直接访问云端版:
http://scl.yunxing.tech:8888
也可在该地址下载桌面版。

CID文件

本例是对上一节控制服务端的模型进行控制,所以直接将上一节的CID文件拿过来即可,由于本章节的控制请求包含了DAID和短地址的使用,所以模型拿过来后需要对要控制的模型做一下daid和短地址的映射设置。

为SPC01设置短地址


为SPC01设置DAID



上述步骤分别对SPC01和SPC02设置了短地址和DAID,SPC03和SPC04本课采用引用方式,无需设置。

启动代码

IEC61850_ErrorCodeStartIEC61850(){IEC61850_ErrorCode error=S_OK;IEC61850_Parameters param={0};// 参数结构体param.clientServerFlag=IEC61850_CLIENT;// 设置为服务端param.Ed1_Ed2_Flag=IEC61850_Edition2;// 设置为IEC61850第二版param.fnCmdTermCallback=(IEC61850_ControlCommandTerminationCallback)CommandTerminationCallback;// 指定命令终止的回调函数#ifdefMMSparam.fnErrorCallback=(IEC61850_ErrorCallback)ErrorCallbackHandler;// 指定错误的回调函数#endifparam.dataMapMode=IEC61850_MAP_MODE_REFERENCE;param.configPath="../../../config/client.ini";// 创建IEC61850对象g_iec61850=IEC61850_Create(&param,&error);if(g_iec61850){StringList*sclList=StringListMalloc();printf("Client success to create: %s (%u)\n",IEC61850_ErrorString(error),error);//加载CID模型StringListAdd(sclList,"../../../cidFiles/controlServer.cid");error=IEC61850_LoadServerSCLList(g_iec61850,sclList);if(error==S_OK){printf("Server success to load cid file\n");// 设置控制请求的发起者类别error=IEC61850_SetOriginator(g_iec61850,NULL,ORCAT_BAY_CONTROL,NULL,0);}FreeStringList(sclList);}//启动服务if(error==S_OK){error=IEC61850_Start(g_iec61850);if(error!=S_OK){printf(" Can't start server: %s (%i)\n",IEC61850_ErrorString(error),error);}else{printf("Server success to start\n");}}returnerror;}

代码解读

1、param.configPath = “…/…/…/config/client.ini”; 是指配置文件带路径的文件名,这里采用了进程所在目录的相对路径;
2、IEC61850_LoadServerSCLList 接口直接加载服务端的cid模型文件,可以支持多文件;
3、IEC61850_SetOriginator 接口设置了发起者类型,这里为ORCAT_BAY_CONTROL,设置信息回保存下来,后续调用控制接口会携带设置信息。

常规安全的直接控制

对应模型 ControlOperIEDLD0/GGIO0.SPCSO1
前面我们在CID中设置了短地址,可以使用短地址进行控制

IEC61850_ErrorCodeOperateSPC01(Boolean inCtrlValue){IEC61850_ErrorCode result=S_OK;char*sAddr="SPC01";IEC61850_DataAttributeData daData={0};IEC61850_ControlParameters CtrlControlParams={0};daData.bitLength=sizeof(Boolean)*8;daData.type=IEC61850_DATATYPE_BOOLEAN;daData.pvData=&inCtrlValue;result=IEC61850_ControlOperateWithShortAddr(g_iec61850,sAddr,&daData,&CtrlControlParams);if(result==S_OK){SetCtlVal(inCtrlValue,1);}else{printf("Operate failed:(%i)\n",result);}returnresult;}

常规安全的操作前选择控制

对应模型 ControlOperIEDLD0/GGIO0.SPCSO2
前面我们在CID中设置了DAID,可以使用DAID进行控制

IEC61850_ErrorCodeOperateSPC02(Boolean inCtrlValue){IEC61850_ErrorCode result=S_OK;IEC61850_DataAttributeID daid={1,0,0,0,0};IEC61850_ControlParameters CtrlControlParams={0};result=IEC61850_ControlSelect(g_iec61850,&daid,NULL,&CtrlControlParams);if(result==S_OK){IEC61850_DataAttributeData daData={0};daData.bitLength=sizeof(Boolean)*8;daData.type=IEC61850_DATATYPE_BOOLEAN;daData.pvData=&inCtrlValue;result=IEC61850_ControlOperate(g_iec61850,&daid,&daData,&CtrlControlParams);if(result==S_OK){SetCtlVal(inCtrlValue,2);}else{printf("Operate failed:(%i)\n",result);}}else{printf("Select failed:(%i)\n",result);}returnresult;}

增强安全的直接控制

对应模型 ControlOperIEDLD0/GGIO0.SPCSO3
前面我们未做任何设置,只能使用引用进行控制

IEC61850_ErrorCodeOperateSPC03(Boolean inCtrlValue){IEC61850_ErrorCode result=S_OK;char*reference="ControlOperIEDLD0/GGIO0.SPCSO3";IEC61850_DataAttributeData daData={0};IEC61850_ControlParameters CtrlControlParams={0};daData.bitLength=sizeof(Boolean)*8;daData.type=IEC61850_DATATYPE_BOOLEAN;daData.pvData=&inCtrlValue;result=IEC61850_ControlOperateWithRef(g_iec61850,0,reference,&daData,&CtrlControlParams);if(result==S_OK){SetCtlVal(inCtrlValue,1);}else{printf("Operate failed:(%i)\n",result);}returnresult;}

增强安全的操作前选择控制

对应模型 ControlOperIEDLD0/GGIO0.SPCSO4
前面我们未做任何设置,只能使用引用进行控制

IEC61850_ErrorCodeOperateSPC04(Boolean inCtrlValue){IEC61850_ErrorCode result=S_OK;char*reference="ControlOperIEDLD0/GGIO0.SPCSO4";IEC61850_ControlParameters CtrlControlParams={0};IEC61850_DataAttributeData daData={0};daData.bitLength=sizeof(Boolean)*8;daData.type=IEC61850_DATATYPE_BOOLEAN;daData.pvData=&inCtrlValue;result=IEC61850_ControlSelectWithRef(g_iec61850,0,reference,&daData,&CtrlControlParams);if(result==S_OK){result=IEC61850_ControlOperateWithRef(g_iec61850,0,reference,&daData,&CtrlControlParams);if(result==S_OK){SetCtlVal(inCtrlValue,2);}else{printf("Operate failed:(%i)\n",result);}}else{printf("Select failed:(%i)\n",result);}returnresult;}

命令终止回调

对于增强安全的控制,服务端会返回命令终止,客户端收到后会通过命令终止回调传控制的结果参数;
前面启动参数的设置中已经指定了命令终止回调

param.fnCmdTermCallback=(IEC61850_ControlCommandTerminationCallback)CommandTerminationCallback;

函数定义如下:(这里仅做最基本的结果打印)

eCommandAddCauseCommandTerminationCallback(void*userData,constvoid*dataMap,constControlResult*controlResult){printf("\n========= Command Termination Callback =======\n");eCommandAddCause eError=IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE;if(controlResult){if(controlResult->eCtlAddCause==IEC61850_COMMAND_ERROR_ADD_CAUSE_NONE){printf("Control result is success, addcase = % d\n",controlResult->eCtlAddCause);}else{printf("Control result is failure, addcase = % d\n",controlResult->eCtlAddCause);}}returneError;}

MMS版本特有的错误回调

根据IEC61850规范,控制的错误有附加原因码AddCause,由于控制在MMS协议中是基本读写操作,其应答码无法提现AddCause,所以在MMS协议中需要将控制的附加原因码AddCause以infomationReport单独发送,而想拿到AddCause就必须通过错误回调获取,前面启动参数的设置中已经指定了错误回调

#ifdefMMSparam.fnErrorCallback=(IEC61850_ErrorCallback)ErrorCallbackHandler;// 指定错误的回调函数#endif

回调定义

eCommandAddCauseErrorCallbackHandler(void*userData,constvoid*dataMap,constIEC61850_ErrorParameters*errorParameters){eCommandAddCause eError=IEC61850_COMMAND_ERROR_NONE;printf("\n========= Error Callback =======\n");printf("\t The cause is %s and type %s \n",errorParameters->errorCause,errorParameters->errorType);printf("\n");returneError;};

CMS版本如何获取AddCause

所有CMS的控制接口传送的控制参数结构体,比MMS版本多了一个addCause成员变量;控制请求会直接返回addCause,无需在回调中获取。

如何构造失败的控制

1、请求的控制值与服务端当前值一致,例如服务端状态值是布尔True,请求的控制值也是布尔True,那么必然控制失败;
2、重复的选择,先选择成功后,再发起选择操作就会失败;
3、选择和操作不是同一个客户端发起的,客户端A发起了选择,客户端B发起操作;
4、对于操作前选择的模型,直接发起操作请求;
5、增强安全的操作前选择控制过程中,选择传递的参数和操作传递的参数不一致,或者取消的传递的参数和选择的不一致;
6、服务端在控制回调中直接返回错误;
7、服务端收到控制请求后,对应的状态值在超时时间内没有变化;
8、为执行IEC61850_SetOriginator ,也未在请求参数中设置响应信息等。

控制演示

启动本例程序,服务端启动上一讲的控制服务端
客户端如下:

可以根据界面菜单进行操作,对应动作及报文等,可以参考上一节的介绍。

总结

相对于服务端,客户端的控制逻辑还是简单了很多,本文顺便介绍了协议栈的第二种连接服务端的方法,然后介绍了4中控制模型的正常的控制方法。当然还有取消的动作,这里并没有介绍,可以自行查看对应函数的说明。本文就介绍到这里,谢谢大家。