IEC61499/ OPCUA 融合(1)功能块通信的PUB/SUB协议

        OpenDACS  是基于OPCUA 信息模型的IEC61499 分布式自动控制系统。用于研究OPCUA 与IEC61499 相互融合。本文介绍它如何采用Opcua Pub/Sub 实现分布式系统中IEC61499功能块之间的通信。在IEC61499 中并没有明确地确定采取哪一种协议,在具体实现中可能采取TCP/IP,UDP ,MQTT ,WebSocket 等多种协议。数据负载的格式也没有具体规定,在4diac Forte 中使用ISO 的ASN.1 格式。其它机构采取哪一种协议不得而知。这严重影响了IEC61499 系统的互联互通。

OPCUA pub/sub 机制

        OPCUA 主要的通信协议是Cliet/Server 方式。它基于TCP/IP 协议,是一种点对点通信方式。OPC UA 在2018年2月份发布了发布/订阅(pub/sub )模式。pub/sub 适合点对多点方式,一个节点发布的消息,可以被多个设备订阅。pub/sub 通信分为代理模式和非代理模式。典型的代理模式是MQTT 协议。发布者发布的消息通过一个代理服务器(Broker)转发给多个订阅者。

IEC61499/ OPCUA 融合(1)功能块通信的PUB/SUB协议_第1张图片

     代理服务器方式的PUB/SUB 使用存储转发的方式交换消息,显然不符合实时通信的要求。集中交换方式也不利于带宽均衡利于和可靠性。

     非代理方式Pub/Sub利用IP 网络的组播方式实现点对多点通信。通信协议为UDP 协议(在OPCUA中称为UADP)。适合实时通信的要求。目前在tsn网络上实现的OPC UA pub/sub 是非代理方式的 协议。

IEC61499/ OPCUA 融合(1)功能块通信的PUB/SUB协议_第2张图片

OPCUA Pub/Sub 机制 

IEC61499/ OPCUA 融合(1)功能块通信的PUB/SUB协议_第3张图片

 OPC UA Pub/Sub 与MQTT 的区别

        OPCUA Pub /Sub 机制主要是为分享数据而设计的。它的机制与MQTT 协议有区别。在MQTT中,应用程序需要发布消息时就发布一个消息。而OPCUA 的Pub/Sub机制则不同,它是由应用程序预先指定哪些变量需要发布,然后由pub/sub 机制自动地周期性发布数据。而且与视频通信类似,它分为关键帧和数据变化帧两种,关键帧是每一个变量都发布,而非数据变化帧只发送数据变化的变量。这种方式对应数据流传输无疑提高了可靠性。但是变量的重复发送,可能会使订阅的数据是重复的。这对于状态和事件变量可能会引发多次触发。在IEC61499 功能块网络的通信中,我们将事件变量和数据变量同时发送,由SUBSCRIBE 功能块判断事件是否发生变化。避免功能块重复执行。

4diac 构建IEC61499 系统和应用

系统结构

       试验系统共有三台设备,为了实验方便,我们让它们在一台Linux PC 上运行,它们具有不同的端口,使用OPCUA Pub/sub 的UDAP协议,这是一种组播通信方式。使用4diac 定义系统。

IEC61499/ OPCUA 融合(1)功能块通信的PUB/SUB协议_第4张图片

 应用

OpenDACS中,我们实现了几种OpcUa 的IEC61499功能块:

  • WriteOPCUA
  • ReadOPCUA
  • PUBLISH_1
  • SUBSCRIBE_1

应用包含了总体的控制逻辑,分别映射到三台设备中。

IEC61499/ OPCUA 融合(1)功能块通信的PUB/SUB协议_第5张图片

映射

        在总体应用中并没有包含Publish和Subscribe 功能块。要在device 资源中手动添加PUBLISH和SUBSCRIBE 功能块,为了测试更全面,我们在Forte_PC 设备中,添加了两个PUBLISH 功能块,分别向其它两台设备发布数据。

FortePC 

这是一个发布消息的节点,它向其它两台设备发布数据。

IEC61499/ OPCUA 融合(1)功能块通信的PUB/SUB协议_第6张图片

Forte_PC_1

添加一个SUBSCRIBE。

IEC61499/ OPCUA 融合(1)功能块通信的PUB/SUB协议_第7张图片

 Forte_PC_2

添加一个SUBSCRIBE。

IEC61499/ OPCUA 融合(1)功能块通信的PUB/SUB协议_第8张图片

         注意:在上面的架构中,两个PUBLISH 发送的是同一个数据源,所有也可以简化系统的结构,采取Forte_PC 添加一个发布(PUBLISH ),其它两个设备订阅(SUBSCRIBE )。

pub/sub 中的ID 结构

OPC UA pub/sub 的架构如下:

IEC61499/ OPCUA 融合(1)功能块通信的PUB/SUB协议_第9张图片

 Publisher 和Subscriber 的ID

  OPCUA Pub/Sub 可以发送多个数据源,它们是通过一组标识符(ID)来标注数据的。

发布一个消息 涉及下面几个组件:

  • connection
  • WriteGroup
  • DataSetWriter
  • DataSet

每个组件都有一个ID,订阅者要使用发布者的三个ID 来确定接收哪一种数据源,它们是:

  • PublisherID
  • WriteGroupID
  • DataSetWriterID

 所有PUBLISH 功能块ID定义:

ID=PublisherID.WriteGroupID.DataSetWriterID

SUBSCRIBE 功能块的ID定义为:

ID=PublisherID.WriteGroupID.DataSetWriterID

        订阅数据组读入器(DatReader)的PublisherID,WriteGroupID,DataSetWriterID要与发布者一致。

        一个Server 中可以定义多个WriterGroup,一个WriterGroup 中可以有多个DataSetWriter,

由于Pub/Sub 是基于UDP 组播方式的。所以SUBSCRIBER 可以接收:

  • 不同PublisherID 的消息
  • 相同PublisherID ,不同WriterGroupID 的消息
  • 相同WriterGroupID ,不同DataSetWriterID的消息

    如果考虑一个设备可以发送多个组播,情况更加复杂。目前我们没有考虑多个组播IP的情形。

在系统设计时,要规划ID方案。

设计流程

Step1 使用4diac IDE 设计上面的系统,保存了Blinky.sys 文件。将自定义的功能块放在功能块库的user 子目录中。

Step2 使用Converter2023 工具转换成为OPCUA 的Design Model XML 文档,它们按Device 分解为:

  • Forte_PC.xml
  • Forte_PC_1.xml
  • Forte_PC_2.xml

Step3 使用UpcUaModelCompiler 工具将上面三个文件转换成为NodeSet2.xml 文档,装入三个目录(Publisher,Subscribe1,Subscribe2)

Step4 运行,它们的顺序为

  • Subscribe1 的ForteA
  • Subscribe2的ForteA
  • Publish 的ForteA

  Step5 使用uaExpert监控

    由于在同一台电脑中运行,所以IP 地址是一致的,因此在Subscribe2 运行后 启动uaExpert 可以看见Subscribe 的OpcUa Server 中的模型,最后运行Publisher 的ForteA。 

关于pub/sub 的publish周期

OPCUA 的Pub/Sub 是一种周期发送的方法,它会在数据的生命周期中重复发送,这里有两个参数:

publishingInterval;
keepAliveTime;

        网络上多数人讲Interval 时间最小是1 ms ,其实不然,它是一个Double ,可以设为小数,我修改到0.25 发送的时间快了。

UA_NodeId
addWriterGroup(UA_Server *server,UA_NodeId connectionId,UA_UInt16 Id) {
	/* Now we create a new WriterGroupConfig and add the group to the existing
	* PubSubConnection. */
	UA_WriterGroupConfig writerGroupConfig;
	memset(&writerGroupConfig, 0, sizeof(UA_WriterGroupConfig));
	writerGroupConfig.name = UA_STRING((char*)"WriterGroup1");
	writerGroupConfig.publishingInterval =0.25;
	writerGroupConfig.keepAliveTime=4;
	writerGroupConfig.enabled = UA_TRUE;
	writerGroupConfig.writerGroupId = Id;
	writerGroupConfig.encodingMimeType = UA_PUBSUB_ENCODING_UADP;
	writerGroupConfig.messageSettings.encoding = UA_EXTENSIONOBJECT_DECODED;
	writerGroupConfig.messageSettings.content.decoded.type = &UA_TYPES[UA_TYPES_UADPWRITERGROUPMESSAGEDATATYPE];
		UA_UadpWriterGroupMessageDataType *writerGroupMessage = UA_UadpWriterGroupMessageDataType_new();
	writerGroupMessage->networkMessageContentMask = (UA_UadpNetworkMessageContentMask)(UA_UADPNETWORKMESSAGECONTENTMASK_PUBLISHERID |
		(UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_GROUPHEADER |
		(UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_WRITERGROUPID |
		(UA_UadpNetworkMessageContentMask)UA_UADPNETWORKMESSAGECONTENTMASK_PAYLOADHEADER);
	writerGroupConfig.messageSettings.content.decoded.data = writerGroupMessage;
	UA_NodeId writerGroupId;
	UA_Server_addWriterGroup(server, connectionId, &writerGroupConfig, &writerGroupId);
	UA_Server_setWriterGroupOperational(server, writerGroupId);
	UA_UadpWriterGroupMessageDataType_delete(writerGroupMessage);
return writerGroupId;
}

pub/sub 的这种机制会重复收到数据。在有些场合是不允许的。比如事件触发,不允许多次。可以通过功能块检测数据是否改变。

结论

人世间的任何事物一旦深入细节,就会发现一堆问题。但是不深入细节,什么都不是。

你可能感兴趣的:(OPCUA,IEC61499)