概述
定值组也是非常常用的功能,在IEC61850的定值组模型中,允许数据定值数据属性有多个值,并且能够进行切换使用,本文就为大家介绍一下定值组服务端是如何实现的。
代码位置
https://gitee.com/yunxingtianxia/yx-tools
yx-pis-dll\example\10 settingGroupServer
定值组的介绍
定值组主要支持下列服务:
- 选择激活定值组服务(SelectActiveSG),由客户端向服务端发起,服务端收到该请求后将激活定值组切换到指定的组。
- 选择编辑定值组服务(SelectEditSG),由客户端向服务端发起,服务端收到该请求后将编辑定值组切换到指定的组,并将改组值复制到编辑缓冲区。
- 设置编辑定值组值服务(SetEditSGValue),由客户端向服务端发起,对编辑缓冲区的数值进行设置值操作,前提是当前编辑定值组号非0,也就是刚刚做了SelectEditSG操作,并且没有超时及尚未确认编辑定值组。
- 确认编辑定值组值服务(ConfirmEditSGValues),由客户端向服务端发起,确认SetEditSGValue操作,将编辑缓冲区的值写入SelectEditSG时选择的组号对应的组中。
- 读编辑定值组值服务(GetEditSGValue),由客户端向服务端发起,读取当前激活或当前编辑的组的数据值。(字面上看是读编辑定值的组,实际上可以读激活组的值)
- 读定值组控制块值服务(GetSGCBValues),由客户端向服务端发起,读取定值组控制块信息。
本文主要针对上述服务进行介绍。
- 关于定值组激活和编辑处理机制可参考下图:
定值组有以下知识点需要了解
- 一个逻辑设备最多只有一个定值组控制块;
- 定值组控制块在LLN0中;
- 定值组控制块管理其所在逻辑设备的所有功能约束为SG/SE的数据;
建模工具
建模工具直接访问云端版:
http://scl.yunxing.tech:8888
也可在该地址下载桌面版。
CID建模
一、服务端建模
使用建模工具新建一个模型文件,添加逻辑节点
将数据设置为定制数据
同样放放将RcdMod和MemFull也设置为定制数据。
添加定值组控制块
1、Services设置
实际效果如下:
<ServicesnameLength="64"><SettingGroups><ConfSG/><SGEdit/></SettingGroups></Services>2.定值组控制块:
<LN0desc="Logical node zero"inst=""lnClass="LLN0"lnType="LLN0_0"><SettingControlactSG="1"desc="setting group"numOfSGs="5"resvTms="50"/></LN0>3.定值数据(功能约束为SG的数据属性)
同样方法添加其他值
最终效果如下:
<LNdesc="Archiving"inst="0"lnClass="IARC"lnType="IARC_0"prefix=""><DOIdesc="Integer status setting"name="MaxNumRcd"><DAIname="setVal"><ValsGroup="1">11</Val><ValsGroup="2">12</Val><ValsGroup="3">13</Val><ValsGroup="4">14</Val><ValsGroup="5">15</Val></DAI></DOI><DOIdesc="Recorder operation mode (saturation, overwrite)"name="RcdMod"><DAIname="setVal"><ValsGroup="1">Overwrite existing values</Val><ValsGroup="2">Stop when full or saturated</Val><ValsGroup="3">Overwrite existing values</Val><ValsGroup="4">Stop when full or saturated</Val><ValsGroup="5">Stop when full or saturated</Val></DAI></DOI><DOIdesc="Integer status setting"name="MemFull"><DAIname="setVal"><ValsGroup="1">31</Val><ValsGroup="2">32</Val><ValsGroup="3">33</Val><ValsGroup="4">34</Val><ValsGroup="5">35</Val></DAI></DOI></LN>启动服务端
服务端只要加载这个模型即可,无需任何编码就可以实现定值组的基本功能
虽然服务端已经具备了定值组的功能,但是用户层想获得定值组相关的操作并做对应的处理就需要处理定值组相关的回调了。
代码
指定回调
param.fnSettingGroupCallback=(IEC61850_SettingGroupCallback)SettingGroupCallbackHandler;// 指定定值操作的回调函数param.fnWriteCallback=(IEC61850_WriteCallback)WriteCallbackHandler;// 指定写回调,选择激活定值组会更新定值,定值更新会触发本回调本例采用引用回调,无需为数据设置DAID,短地址
回调函数如下
eServiceErrorSettingGroupCallbackHandler(void*userData,IEC61850_SettingGroup_Operation sgOper,void*SGParam){eServiceError serveiceError=SERVICE_ERROR_NO_ERROR;if(SGParam){switch(sgOper){caseSG_SELECT_ACTIVE:printf("select active callback:\n");caseSG_SELECT_EDIT:if(sgOper==SG_SELECT_EDIT){printf("select edit callback:\n");}{SGCallback_Select*select=SGParam;printf("\treference = %s\n",select->reference);printf("\tgroup number = %u\n",select->sgNumber);}break;caseSG_CONFIRM_EDIT:printf("confirm edit callback:\n");printf("\treference = %s\n",(char*)SGParam);break;caseSG_GET_VALUE:printf("get edit value callback:\n");caseSG_SET_VALUE:if(SG_SET_VALUE==sgOper){printf("set edit value callback:\n");}{SGCallback_Data*dataParam=SGParam;printf("\treference = %s\n",dataParam->reference);printf("\tfc = %s\n",dataParam->fc);printf("\ttype = %d\n",dataParam->type);printf("\tsize = %u\n",dataParam->size);// 下方关于值的打印是根据模型简化了,正常需要依据type决定如何获取if(32==dataParam->size){printf("\tvalue = %u\n",*((S32*)dataParam->data));}elseif(8==dataParam->size){printf("\tvalue = %u\n",*((U8*)dataParam->data));}}break;caseSG_GET_SGCB:printf("set SGCB values callback:\n");printf("\treference = %s\n",(char*)SGParam);break;}}returnserveiceError;}IEC61850_CallbackReturnServiceErrorCodeWriteCallbackHandler(void*userData,char*reference,constIEC61850_DataAttributeData*data){IEC61850_CallbackReturnServiceErrorCode ErrorCode=IEC61850_CB_ERROR_NONE;if(reference&&data&&data->pvData){if(strcmp(reference,"SettingGroupServerLD0/IARC0.MaxNumRcd.setVal")==0){S32 newVal=*((S32*)data->pvData);printf("MaxNumRcd = %d\n",newVal);}elseif(strcmp(reference,"SettingGroupServerLD0/IARC0.RcdMod.setVal")==0){U8 newVal=*((U8*)data->pvData);printf("RcdMod = %u\n",newVal);}elseif(strcmp(reference,"SettingGroupServerLD0/IARC0.MemFull.setVal")==0){S32 newVal=*((S32*)data->pvData);printf("MemFull = %d\n",newVal);}}returnErrorCode;}运行
结合下一章的客户端部分,向本服务端发起定值相关请求,会配合打印相关回调内容
1) GetEditSGValue
2) SelectActiveSG
先显示选择激活的回调,显示了引用和新新组号,接下来是切换后定值发生变化,触发了写回调,分别打印了定值的新值,如下图:
3) SelectEditSG
4) SetEditSGValue
5) ConfirmEditSGValues
6) GetSGCBValues
补充
本例推荐使用下一篇的客户端配合操作,也可以使用sim860工具,MMS版本也可以使用iedscout等工具配合,MMS版本和CMS版本可自由切换,无需改动代码。