控制客户端)
前言上一讲主要讲了控制服务端的实现这一讲我们来讲如何实现控制的客户端首先要启动客户端并实现与服务端的连接前面章节介绍了如何启动客户端这里采用另外一种方法来连接服务端代码位置https://gitee.com/yunxingtianxia/yx-toolsyx-pis-dll\example\09 controlClient直接使用服务端的模型文件本地配置文件这种方法可以直接加载服务端的cid模型文件但是需要在本地增加配置本例是在工程目录下增加了一个config目录并在下面放入了client.ini文件文件内容如下[IED] nameClientIED AP_Count1 [AP_0] nameap01 ipAddress192.168.8.1 subnet255.255.255.0 gateway192.168.8.2 macAddress00-50-56-C0-00-08这里面配置了IED名称然后1个接入点并配置了网络信息如果没有goose、svmacAddress无需配置本例这样配置是为了展示全部的配置信息。建模工具建模工具直接访问云端版http://scl.yunxing.tech:8888也可在该地址下载桌面版。CID文件本例是对上一节控制服务端的模型进行控制所以直接将上一节的CID文件拿过来即可由于本章节的控制请求包含了DAID和短地址的使用所以模型拿过来后需要对要控制的模型做一下daid和短地址的映射设置。为SPC01设置短地址为SPC01设置DAID上述步骤分别对SPC01和SPC02设置了短地址和DAIDSPC03和SPC04本课采用引用方式无需设置。启动代码IEC61850_ErrorCodeStartIEC61850(){IEC61850_ErrorCode errorS_OK;IEC61850_Parameters param{0};// 参数结构体param.clientServerFlagIEC61850_CLIENT;// 设置为服务端param.Ed1_Ed2_FlagIEC61850_Edition2;// 设置为IEC61850第二版param.fnCmdTermCallback(IEC61850_ControlCommandTerminationCallback)CommandTerminationCallback;// 指定命令终止的回调函数#ifdefMMSparam.fnErrorCallback(IEC61850_ErrorCallback)ErrorCallbackHandler;// 指定错误的回调函数#endifparam.dataMapModeIEC61850_MAP_MODE_REFERENCE;param.configPath../../../config/client.ini;// 创建IEC61850对象g_iec61850IEC61850_Create(param,error);if(g_iec61850){StringList*sclListStringListMalloc();printf(Client success to create: %s (%u)\n,IEC61850_ErrorString(error),error);//加载CID模型StringListAdd(sclList,../../../cidFiles/controlServer.cid);errorIEC61850_LoadServerSCLList(g_iec61850,sclList);if(errorS_OK){printf(Server success to load cid file\n);// 设置控制请求的发起者类别errorIEC61850_SetOriginator(g_iec61850,NULL,ORCAT_BAY_CONTROL,NULL,0);}FreeStringList(sclList);}//启动服务if(errorS_OK){errorIEC61850_Start(g_iec61850);if(error!S_OK){printf( Cant 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 resultS_OK;char*sAddrSPC01;IEC61850_DataAttributeData daData{0};IEC61850_ControlParameters CtrlControlParams{0};daData.bitLengthsizeof(Boolean)*8;daData.typeIEC61850_DATATYPE_BOOLEAN;daData.pvDatainCtrlValue;resultIEC61850_ControlOperateWithShortAddr(g_iec61850,sAddr,daData,CtrlControlParams);if(resultS_OK){SetCtlVal(inCtrlValue,1);}else{printf(Operate failed:(%i)\n,result);}returnresult;}常规安全的操作前选择控制对应模型 ControlOperIEDLD0/GGIO0.SPCSO2前面我们在CID中设置了DAID可以使用DAID进行控制IEC61850_ErrorCodeOperateSPC02(Boolean inCtrlValue){IEC61850_ErrorCode resultS_OK;IEC61850_DataAttributeID daid{1,0,0,0,0};IEC61850_ControlParameters CtrlControlParams{0};resultIEC61850_ControlSelect(g_iec61850,daid,NULL,CtrlControlParams);if(resultS_OK){IEC61850_DataAttributeData daData{0};daData.bitLengthsizeof(Boolean)*8;daData.typeIEC61850_DATATYPE_BOOLEAN;daData.pvDatainCtrlValue;resultIEC61850_ControlOperate(g_iec61850,daid,daData,CtrlControlParams);if(resultS_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 resultS_OK;char*referenceControlOperIEDLD0/GGIO0.SPCSO3;IEC61850_DataAttributeData daData{0};IEC61850_ControlParameters CtrlControlParams{0};daData.bitLengthsizeof(Boolean)*8;daData.typeIEC61850_DATATYPE_BOOLEAN;daData.pvDatainCtrlValue;resultIEC61850_ControlOperateWithRef(g_iec61850,0,reference,daData,CtrlControlParams);if(resultS_OK){SetCtlVal(inCtrlValue,1);}else{printf(Operate failed:(%i)\n,result);}returnresult;}增强安全的操作前选择控制对应模型 ControlOperIEDLD0/GGIO0.SPCSO4前面我们未做任何设置只能使用引用进行控制IEC61850_ErrorCodeOperateSPC04(Boolean inCtrlValue){IEC61850_ErrorCode resultS_OK;char*referenceControlOperIEDLD0/GGIO0.SPCSO4;IEC61850_ControlParameters CtrlControlParams{0};IEC61850_DataAttributeData daData{0};daData.bitLengthsizeof(Boolean)*8;daData.typeIEC61850_DATATYPE_BOOLEAN;daData.pvDatainCtrlValue;resultIEC61850_ControlSelectWithRef(g_iec61850,0,reference,daData,CtrlControlParams);if(resultS_OK){resultIEC61850_ControlOperateWithRef(g_iec61850,0,reference,daData,CtrlControlParams);if(resultS_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 eErrorIEC61850_COMMAND_ERROR_ADD_CAUSE_NONE;if(controlResult){if(controlResult-eCtlAddCauseIEC61850_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 eErrorIEC61850_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中控制模型的正常的控制方法。当然还有取消的动作这里并没有介绍可以自行查看对应函数的说明。本文就介绍到这里谢谢大家。