前言
报告客户端也就是接收端,在前面的报告服务端部分已经介绍了,但是是采用的模拟工具作为客户端,本文就是介绍如何自己开发报告客户端。
报告使能
前文我们已经启动了客户端并且完成了与服务端的连接,但是并没有使能报告控制块的动作,使用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);}这里就不做演示截图了
好了,关于报告客户端的使用就简单介绍到这里,感谢阅读。