ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

零基础实现IEC61850(五)报告客户端

零基础实现IEC61850(五)报告客户端

前言

报告客户端也就是接收端,在前面的报告服务端部分已经介绍了,但是是采用的模拟工具作为客户端,本文就是介绍如何自己开发报告客户端。

报告使能

前文我们已经启动了客户端并且完成了与服务端的连接,但是并没有使能报告控制块的动作,使用YX-PIS可以实现自动使能,也就是通过CID文件的修改实现使能

建模

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

自动使能

打开上一节的CID,如下图操作

添加后会自动展示填写框,工具支持自动填写,默认即可

保存再启动昨天的程序抓包看看
MMS:

CMS

和昨天的内容相比,我们只是修改了CID内容就可以实现自动发起使能功能

手动使能

手动使能是用户通过代码调用API接口实现,文章初期以简单为主暂不介绍了

如何处理接收到的报告

当接收到报告YX-PIS协议栈会以回调的方式将解析好的数据传递给回调函数

回调函数的原型

typedef void (IEC61850_UpdateCallback)(void * userData, const voiddataMap, const IEC61850_DataAttributeData * newValue);

在API手册以及头文件中都有详细的说明

创建回调函数

依据这个原型我们创建一个回调函数,先在原有工程中添加Callback.c和Callback.h,专门用于存放回调函数。
在头文件和源文件中分别放入回调函数的声明和定义,下面是定义部分,先做个空函数。

voidUpdateCallbackHandler(void*userData,constvoid*dataMap,constIEC61850_DataAttributeData*newValue){printf("update callback\n");}

设置好回调函数及回调模式

在iec61850client.c的main函数中调用IEC61850_Create之前,设置启动参数位置增加如下两行

param.fnUpdateCallback=UpdateCallbackHandler;// 指定update回调param.dataMapMode=IEC61850_MAP_MODE_REFERENCE;// 回调函数的数据映射模式

这里制定好回调函数,并且设置回调模式为引用方式,关于回调模式后文会介绍。这里先编译运行服务端和客户端

去除周期性触发

为了避免周期性触发发送过多报告,testIED.cid中报告控制块可以先关闭周期性触发,将period由true改为false,如下:

<ReportControlbuffered="false"confRev="1"datSet="testDataSet"desc="测试用的报告控制块"indexed="true"intgPd="9000"name="testReportCB"><TrgOpsdchg="true"dupd="true"gi="true"period="false"qchg="true"/><OptFields/><RptEnabledmax="3"/></ReportControl>

效果演示

在服务端输入一个整数,回车

在客户端会看到界面打印

说明报告的发送已经通过协议栈转移到回调函数,这里打印了九次,是因为数据集关联的数据A是结构体,包含了9个基本类型的成员,如图:

回调函数说明

函数中包含三个参数,其中userData较少使用暂时不做介绍,
dataMap,指的是数据映射,根据参数设置的映射模式,当映射模式为引用,那么该值就是引用字符串
newValue,代表传入的数据值
接下来修改代码来打印引用

voidUpdateCallbackHandler(void*userData,constvoid*dataMap,constIEC61850_DataAttributeData*newValue){printf("reference:%s\n",(char*)dataMap);}

当发送报告

可见我们可以通过dataMap获取到引用,这样我们就可以通过引用的判断而直知道收到的数据是什么了,从而针对其类型进行数值的解析,重新组织代码如下:

voidUpdateCallbackHandler(void*userData,constvoid*dataMap,constIEC61850_DataAttributeData*newValue){if(dataMap&&newValue&&newValue->pvData){if(strcmp((char*)dataMap,"TEMPLATELDevice1/MMXU0.A.phsA.cVal.mag.i")==0){S32 val=*((S32*)newValue->pvData);printf("reference:%s value:%d\n",(char*)dataMap,val);}}}

上述代码只判断了一个引用的数值用作参考,下面服务端也更新这个数据(更新方法参考前面文章),效果如下:

短地址回调

首先需要设置好回调模式,如下:

param.dataMapMode=IEC61850_MAP_MODE_SADDR;// 回调函数的数据映射模式

UpdateCallbackHandler回调函数的参数dataMap则为短地址,该短地址需要在testClientIED.cid中设置

注意:这个短地址是客户端自身的数据映射,无需与服务端保持一致
短地址是字符串类型,同样通过字符串比较来判断即可。

DAID回调

首先需要设置好回调模式,或者删除回调模式的设置(DAID是默认的回调模式),如下:

param.dataMapMode=IEC61850_MAP_MODE_DAID;// 回调函数的数据映射模式

UpdateCallbackHandler回调函数的参数dataMap则为DAID,该DAID需要在testClientIED.cid中设置

注意:这个DAID是客户端自身的数据映射,无需与服务端保持一致

回调函数对DAID的判断

constIEC61850_DataAttributeID*daid=(constIEC61850_DataAttributeID*)dataMap;if((daid->field1==1)&&(daid->field2==2)&&(daid->field3==3)&&(daid->field4==4)&&(daid->field5==5)){S32 val=*((S32*)newValue->pvData);printf("DAID :%d,%d,%d,%d,%d value:%d\n",daid->field1,daid->field2,daid->field3,daid->field4,daid->field5,val);}

这里就不做演示截图了

好了,关于报告客户端的使用就简单介绍到这里,感谢阅读。

返回列表