Multiple GOOSE publishers/subscribers on one network adapter (without client-server communication)

This sample shows the implementation of multiple GOOSE publishers and subscribers in a TwinCAT project. Several publishers and subscribers are combined into IED groups and configured in such a way that they only require one TwinCAT real-time Ethernet adapter for the exchange of GOOSE messages.

Download TwinCAT XAE Project (*.zip): Sample29.zip

General information about this sample project

Sometimes there are several identical IED devices (Intelligent Electronic Devices) in a GOOSE network. These identical devices then logically have the same IEC 61850 data model (logical nodes, data objects, data attributes, etc.). If the TwinCAT application is to exchange GOOSE messages with several identical devices, then it is advantageous to create and use an array of IED instances for this purpose in the TwinCAT project. An IED array element then corresponds to a GOOSE publisher or subscriber device instance in the field. The array elements should preferably be either all of type: GOOSE publisher or all of type: GOOSE subscriber. This simplifies the implementation of the individual GOOSE functions in the PLC application. The PLC application can then, for example, enable or disable all publishers in a FOR loop. Other configurations (some IED array elements are subscribers and other publishers) are also possible, but are not presented in this sample to keep the sample simple. The devices in the field logically have different IED and logical device names. However, all IED array elements initially have the same IED and logical device names. However, this is not a problem for the PLC application. The individual IED array elements can be reconfigured accordingly at PLC program start. Each IED array element is given a new, unique IED and LD name. Because of this renaming, some attribute values, such as "GoID" or "DatSet" must also be adjusted.

The IEC 61850 data model for these identical IED devices is then only present once in the TwinCAT project and does not have to be duplicated and renamed for each individual IED device instance. This saves resources and increases the performance of the application.

For projects with only one subscriber or publisher, the link from the "TwinCAT real-time Ethernet adapter" (RT Ethernet adapter) to the PLC is established via the instances of the "FB_[IEDName]Gse" function block. The IED data model of a subscriber or publisher to be communicated is communicated to the function block via the "ipIED" property. For more information see: RT Ethernet adapter configuration and in the samples: Client - GOOSE subscriber and Server - GOOSE publisher.
It is theoretically possible to link up to 20 instances of the "FB_[IEDName]Gse" function block with a "TwinCAT RT Ethernet adapter" in this way. This allows up to 20 publishers or subscribers to be implemented in one project. However, it is more resource-efficient to use, for example, only one instance of the adapter function block for a group of publishers and another instance for the group of subscribers.

If all devices are in a common GOOSE network, then all publishers/subscribers in the TwinCAT application can use the same "Real-Time Ethernet adapter (Multiple Protocol Handler)". How has it been realized in the sample? First, several publishers were assigned to an IED group. All subscribers were assigned to a second IED group. Each IED group was given a unique group name. The IED groups are instances of the function block: "FB_GROUP_[GroupName]". The IED group to be communicated is communicated to the "FB_[GroupName]Gse" adapter function block via the "ipGroup" property. The two instances of the adapter function block "FB_[GroupName]Gse" (one belongs to the publisher group and the other to the subscriber group) are then linked to the "TwinCAT real-time Ethernet adapter" as described in the RT Ethernet adapter configuration.

Generation of the IED data model

The IEC 61850 data model of the IEDs in this sample was first generated with the TwinCAT Telecontrol Configurator from the SCL file: Sample29.icd. The file is also located in the TwinCAT project zip archive. This ICD file describes the data model of 6 different IED devices. The image below shows the IEDs in the TwinCAT Telecontrol Configurator:

Multiple GOOSE publishers/subscribers on one network adapter (without client-server communication) 1:

Each IED has a DataSet and a GOOSE control block. After automatic PLC code generation (e.g. as a client project), the PLC project was modified manually and the unneeded function blocks for client/server communication were removed.

Definition of the IED groups

From the 6 automatically generated IED data models, a total of 3 publishers and 11 subscribers are to be implemented in this sample project. All publishers were assigned to an IED group named "PubGroupName" and subscribers were assigned to an IED group named "SubGroupName".

Global variable list TcTelecontrol

In this GVL, a publisher group "fbPubGroupName" and a subscriber group "fbSubGroupName" are instantiated respectively. There is also an instance of the publisher adapter function block "fbPubGroupNameGse" and an instance of the subscriber adapter function block "fbSubGroupNameGse".

The "ipGroup" property is used to assign the publisher IED group to the "fbPubGroupNameGse" and the subscriber IED group to the "fbSubGroupNameGse".

VAR_GLOBAL
    ipCreator: I_AcsiCodeCreatorClass := GVL_AcsiVars.Creator.SetCodeRev(codeRev:=3).SetGuiVer(major:=3, minor:=1, build:=96, revision:=3);

    fbSubGroupName: FB_GROUP_SubGroupName:=(bLinkResult:=fbSubGroupName.Init());
    fbPubGroupName: FB_GROUP_PubGroupName:=(bLinkResult:=fbPubGroupName.Init());

    fbSubGroupNameGse: FB_SubGroupNameGse := (fbAdapter:=(ipGroup:=fbSubGroupName, settings:=(sMulticastAddr:='01-0C-CD-01-00-01', eDispatchMode:=E_GseDispatchMode.NonPromiscuous)));
    fbPubGroupNameGse: FB_PubGroupNameGse := (fbAdapter:=(ipGroup:=fbPubGroupName, settings:=(sMulticastAddr:='01-0C-CD-01-00-00', eDispatchMode:=E_GseDispatchMode.NonPromiscuous)));
END_VAR

Subscriber group

The subscriber group "FB_GROUP_SubGroupName" configures 11 subscribers. "IED5Name" is instantiated as an array[1..8] in the subscriber group. Each array element shall be a subscriber that receives GOOSE messages from another identical device in the field. The subscriber group can only receive GOOSE messages from a publisher if the publisher sends the GOOSE message to the address: '01-0C-CD-01-00-01' or broadcast address or to the MAC address of the TwinCAT RT network adapter. The subscriber source address is configured for all subscribers in a subscriber group at the instance of the "FB_[GroupName]Gse". The table below lists the main parameters of the subscribers in this IED group.

IED

IED name/LD name

SrcAddress

APPID

GoID

DatSet

IED1Name

IED1Name/IED1NameLD1

01-0C-CD-01-00-01

16#0010

'IED1NameLD1/LLN0.gocb01'

'IED1NameLD1/LLN0.ds01'

IED2Name

IED2Name/IED2NameLD1

01-0C-CD-01-00-01

16#0020

'IED2NameLD1/LLN0.gocb01'

'IED2NameLD1/LLN0.ds01'

IED3Name

IED3Name/IED3NameLD1

01-0C-CD-01-00-01

16#0030

'IED3NameLD1/LLN0.gocb01'

'IED3NameLD1/LLN0.ds01'

IED5Name[1]

CH1/CH1LD1

01-0C-CD-01-00-01

16#0051

'CH1LD1/LLN0.GoID.gocb01'

'CH1LD1/LLN0.ds01'

IED5Name[2]

CH2/CH2LD1

01-0C-CD-01-00-01

16#0052

'CH2LD1/LLN0.GoID.gocb01'

'CH2LD1/LLN0.ds01'

IED5Name[3]

CH3/CH3LD1

01-0C-CD-01-00-01

16#0053

'CH3LD1/LLN0.GoID.gocb01'

'CH3LD1/LLN0.ds01'

IED5Name[4]

CH4/CH4LD1

01-0C-CD-01-00-01

16#0054

'CH4LD1/LLN0.GoID.gocb01'

'CH4LD1/LLN0.ds01'

IED5Name[5]

CH5/CH5LD1

01-0C-CD-01-00-01

16#0055

'CH5LD1/LLN0.GoID.gocb01'

'CH5LD1/LLN0.ds01'

IED5Name[6]

CH6/CH6LD1

01-0C-CD-01-00-01

16#0056

'CH6LD1/LLN0.GoID.gocb01'

'CH6LD1/LLN0.ds01'

IED5Name[7]

CH7/CH7LD1

01-0C-CD-01-00-01

16#0057

'CH7LD1/LLN0.GoID.gocb01'

'CH7LD1/LLN0.ds01'

IED5Name[8]

CH8/CH8LD1

01-0C-CD-01-00-01

16#0058

'CH8LD1/LLN0.GoID.gocb01'

'CH8LD1/LLN0.ds01'

The "FB_GROUP_SubGroupName" group function block is derived from the "FB_AcsiCommonIEDGroupClass" function block and serves as a container for several IEDs. The "AddIEDToContainer" method adds the individual IEDs to the subscriber group. For IED array elements, each individual array element must be added to the subscriber group in this way.

The "Tag" property can be used to provide the individual array elements of "IED5Name" with additional information. In the sample, the array element numbers are set there. This number can be queried in the "Init" method or later at runtime in the methods of the IED. Each array element can also be configured a little differently depending on the number.

FUNCTION_BLOCK FB_GROUP_SubGroupName EXTENDS FB_AcsiCommonIEDGroupClass
VAR CONSTANT
    Max_GROUP_IED5Name: DINT:=8; (* Max. number of IED5Name instances *)
END_VAR
VAR_INPUT
    IED1Name: FB_IED_IED1Name:=(bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED1Name));
    IED2Name: FB_IED_IED2Name:=(bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED2Name));
    IED3Name: FB_IED_IED3Name:=(bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED3Name));
    IED5Name: ARRAY[1..Max_GROUP_IED5Name] OF FB_IED_IED5Name:=
    [
        (Tag:=1, sObjectName:='CH1', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[1])),
        (Tag:=2, sObjectName:='CH2', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[2])),
        (Tag:=3, sObjectName:='CH3', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[3])),
        (Tag:=4, sObjectName:='CH4', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[4])),
        (Tag:=5, sObjectName:='CH5', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[5])),
        (Tag:=6, sObjectName:='CH6', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[6])),
        (Tag:=7, sObjectName:='CH7', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[7])),
        (Tag:=8, sObjectName:='CH8', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED5Name[8]))
    ];
END_VAR
VAR
    fbError     : FB_ServiceErrorClass;
    ipLastError : I_ServiceErrorClass;
    i           : DINT; (* Temp array index variable *)
END_VAR

Subscriber group methods

The function block "FB_GROUP_SubGroupName" implements several methods. "Enable" enables all subscribers. "Disable" disables all subscribers. "Execute" must be called cyclically. "Init" initializes all IEDs, LDs, LNs, etc. in the group. The method "Init" is executed once by the initialization code (already before the first PLC cycle).

Adjustment of IED name and LD name for IED5Name array

The setter of the "sObjectName" property of the "FB_IED_IED5Name" function block was overwritten. When setting a new IED name, the new setter implementation is called and the new IED name is applied. The logical device name of the function block "FB_LD_IED5NameLD1" is also corrected because it also contains the IED name.

PROPERTY FINAL sObjectName : T_AcsiObjectName
VAR
END_VAR
(* Adopt the modified IED name *)
SUPER^.sObjectName:= sObjectName;

(* Adjust the logical-device names too *)
IED6NameLD1.sObjectName:= CONCAT(sObjectName, 'LD1');

Adjustment of APPID, GoID and DatSet for IED5Name array

The adjustment is made in the "Init" method of the logical node "LLN0".

METHOD FINAL Init : BOOL
VAR_INPUT
    IED: REFERENCE TO FB_IED_IED5Name;
    LogicalDevice: REFERENCE TO FB_LD_IED5NameLD1;
END_VAR
VAR
END_VAR
IF NOT __ISVALIDREF(IED) THEN RETURN; END_IF
IF NOT __ISVALIDREF(LogicalDevice) THEN RETURN; END_IF

(* Example: Adjust subscribers GoID string *)
gocb01.GoID.sValue:= CONCAT(CONCAT(LogicalDevice.sObjectName, '/'), CONCAT(CONCAT(THIS^.sObjectName, '.'), gocb01.sObjectName));

(* Example: Adjust subscribers data-set reference string *)
gocb01.DatSet.sValue:= CONCAT(CONCAT(LogicalDevice.sObjectName, '/'), CONCAT(CONCAT(THIS^.sObjectName, '.'), ds01.sObjectName));

(* Example: Adjust subscribers APPID by use of IED's Tag property value *)
gocb01.DstAddress.APPID.nValue:= WORD#16#0050 + TO_WORD(IED.Tag);

(* Forward IED reference to all data-sets *)
Init:= TRUE;
Init:= Init AND ds01.Init(IED:=IED);

Publisher group

The publisher group "FB_GROUP_PubGroupName" configures 3 publishers. "IED6Name" is instantiated as array[1..2] in the publisher group. Each array element shall be a publisher that sends the GOOSE messages to a different target address and with a special APPID. The table below lists the main parameters of the publishers in this group.

IED

IED name/LD name

DstAddress

APPID

GoID

DatSet

IED4Name

IED4Name/IED4NameLD1

01-0C-CD-01-00-00

16#0040

'IED4NameLD1/LLN0.gocb01'

'IED4NameLD1/LLN0.ds01'

IED6Name[1]

CNT1/CNT1LD1

01-0C-CD-01-00-01

16#0061

'CNT1LD1/LLN0.gocb01'

'CNT1LD1/LLN0.ds01'

IED6Name[2]

CNT2/CNT2LD1

01-0C-CD-01-00-02

16#0062

'CNT2LD1/LLN0.gocb01'

'CNT2LD1/LLN0.ds01'

The "FB_GROUP_PubGroupName" group function block is derived from the "FB_AcsiCommonIEDGroupClass" function block and serves as a container for several IEDs. The "AddIEDToContainer" method adds the individual IEDs to the publisher group. For IED array elements, each individual array element must be added to the publisher group in this way.

The "Tag" property can be used to provide the individual array elements of "IED6Name" with additional information. In the sample, the array element numbers are set there. This number can be queried in the "Init" method or later at runtime in the methods of the IED. Each array element can also be configured a little differently, depending on the number.

FUNCTION_BLOCK FB_GROUP_PubGroupName EXTENDS FB_AcsiCommonIEDGroupClass
VAR CONSTANT
    Max_GROUP_IED6Name: DINT:=2; (* Max. number of IED6Name instances *)
END_VAR
VAR_INPUT
    IED4Name: FB_IED_IED4Name:=(bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED4Name));
    IED6Name: ARRAY[1..Max_GROUP_IED6Name] OF FB_IED_IED6Name:=
    [
        (Tag:=1, sObjectName:='CNT1', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED6Name[1])),
        (Tag:=2, sObjectName:='CNT2', bLinkResult:=THIS^.AddIEDToContainer(ipIED:=IED6Name[2]))
    ];
END_VAR
VAR
    bUpdate_GROUP_IED4Name_IED4NameLD1_LLN0_gocb01: BOOL; (* If TRUE => Update 'IED4Name.IED4NameLD1.LLN0.gocb01' publisher *)
    aUpdate_GROUP_IED6Name_IED6NameLD1_LLN0_gocb01: ARRAY[1..Max_GROUP_IED6Name] OF BOOL; (* If array element n is TRUE => Update 'IED6Name[n].IED6NameLD1.LLN0.gocb01' publisher *)

    fbError          : FB_ServiceErrorClass;
    ipLastError      : I_ServiceErrorClass;
    i                : DINT; (* Temp array index variable *)
    iUpdateElement   : DINT; (* Array index of first array element that needs to be updated *)

    bSimulation      : BOOL := TRUE; (* Enables/disables simulation of cyclic GOOSE data update *)
    tSimulation      : TIME := T#5S; (* Cycle time of simulated GOOSE data update *)
    fbUpdateTimer    : TON;
    iLiveCounter     : LINT; (*Live counter (example) *)
    tT               : T_UtcTime; (* Temp time-stamp value *)
END_VAR

Publisher group methods

The function block "FB_GROUP_PubGroupName" implements several methods. "Start" starts all publishers. "Stop" stops all publishers. "Execute" must be called cyclically. "Update" performs an update of the publisher data. "Init" initializes all IEDs, LDs, LNs, etc. in the group. The method "Init" is executed once by the initialization code (already before the first PLC cycle). In the method "MapSimuPubData" publisher data are simulated/modified.

Adjustment of IED name and LD name for IED6Name array

The setter of the "sObjectName" property of the "FB_IED_IED6Name" function block was overwritten. When setting a new IED name, the new setter implementation is called and the new IED name is applied. The logical device name of the function block "FB_LD_IED6NameLD1" is also corrected because it also contains the IED name.

PROPERTY FINAL sObjectName : T_AcsiObjectName
VAR
END_VAR
(* Adopt the modified IED name *)
SUPER^.sObjectName:= sObjectName;

(* Adjust the logical-device names too *)
IED6NameLD1.sObjectName:= CONCAT(sObjectName, 'LD1');

Adjustment of APPID, GoID and DatSet for IED6Name array

The adjustment takes place in the "Init" method of the logical node "LLN0".

METHOD FINAL Init : BOOL
VAR_INPUT
    IED: REFERENCE TO FB_IED_IED6Name;
    LogicalDevice: REFERENCE TO FB_LD_IED6NameLD1;
END_VAR
VAR
    mac: ETHERNET_ADDRESS;
END_VAR
IF NOT __ISVALIDREF(IED) THEN RETURN; END_IF
IF NOT __ISVALIDREF(LogicalDevice) THEN RETURN; END_IF

(* Example: Adjust publishers GoID string *)
gocb01.GoID.sValue:= CONCAT(CONCAT(LogicalDevice.sObjectName, '/'), CONCAT(CONCAT(THIS^.sObjectName, '.'), gocb01.sObjectName));

(* Example: Adjust publishers data-set reference string *)
gocb01.DatSet.sValue:= CONCAT(CONCAT(LogicalDevice.sObjectName, '/'), CONCAT(CONCAT(THIS^.sObjectName, '.'), ds01.sObjectName));

(* Example: Adjust publishers multicast address by use of IED's Tag property value *)
mac:= THIS^.gocb01.DstAddress.macAddr;// Get current address
mac.b[5]:= TO_BYTE(IED.Tag);// Modifiy last digit
THIS^.gocb01.DstAddress.macAddr:= mac;// Set new address

(* Example: Adjust publishers APPID by use of IED's Tag property value *)
gocb01.DstAddress.APPID.nValue:= WORD#16#0060 + TO_WORD(IED.Tag);

(* Forward IED reference to all data-sets *)
Init:= TRUE;
Init:= Init AND ds01.Init(IED:=IED);

In the sample code above, the last digit of the MAC address of "DstAddress" is set equal to the value of the "Tag" property. If a completely different MAC address is to be configured for the two publishers then the "Tag" property can also be used in the following way:

IF IED.Tag = 1 THEN
    THIS^.gocb01.DstAddress.sAddr:='01-0C-CD-01-02-56';
ELSIF IED.Tag = 2 THEN
    THIS^.gocb01.DstAddress.sAddr:='01-0C-CD-01-01-78';
END_IF

Network adapter function block FB_SubGroupNameGse

A rising edge at the Boolean variable "bSubscribe" (initial value is already "TRUE") enables all subscribers in the subscriber group when the PLC is started. A rising edge at the Boolean variable "bUnsubscribe" disables all subscribers in the group. The rest of the time, the "Execute" method of the subscriber group and the network adapter must be called cyclically. This is necessary so that the GOOSE messages are received and passed on to the subscriber instances.

FUNCTION_BLOCK FB_SubGroupNameGse IMPLEMENTS I_GseLinkStatusEventSink
VAR_INPUT
    fbAdapter   : FB_GseAdapterClass := (ipLinkStatus:=THIS^);
END_VAR
VAR
    eLinkStatus : E_GseLinkStatus;
    bSuccess    : BOOL;
    ipError     : I_ServiceErrorClass;
    bSubscribe  : BOOL := TRUE; (* Rising edge enables subscriber GoCB's *)
    bUnsubscribe: BOOL; (* Rising edge disables subscriber GoCB's *)
END_VAR
bSuccess:= fbAdapter.Execute(ipError=>ipError); (* Execute network adapter *)

IF bSubscribe THEN (* Enable subscriber GoCB's *)
    bSubscribe:= FALSE;
    bSuccess:= fbSubGroupName.Enable(ipAdapter:=fbAdapter, ipError=>ipError);
ELSIF bUnsubscribe THEN (* Disable subscriber GoCB's *)
    bUnsubscribe:= FALSE;
    bSuccess:= fbSubGroupName.Disable(ipError=>ipError);
ELSE (* Execute subscriber GoCB's *)
    bSuccess:= fbSubGroupName.Execute(ipError=>ipError);
END_IF

Network adapter function block FB_PubGroupNameGse

A rising edge at the Boolean variable "bStart" (initial value is already "TRUE") enables all publishers in the publisher group when the PLC is started. A rising edge at the Boolean variable "bStop" disables all publishers in the group. On a rising edge at the Boolean variable "bUpdate", the "Update" method of the publisher group is called. But the "bUpdate" variable becomes "TRUE" only if the "MapSimuPubData" method also returns "TRUE" because the data was changed or updated by at least one publisher. The rest of the time, the "Execute" method of the publisher group and the network adapter must be called cyclically. This is necessary so that the publisher instances can send their GOOSE messages.

FUNCTION_BLOCK FB_PubGroupNameGse IMPLEMENTS I_GseSystemClockEventSink, I_GseLinkStatusEventSink
VAR_INPUT
    fbAdapter   : FB_GseAdapterClass := (ipSystemClock:=THIS^, ipLinkStatus:=THIS^);
END_VAR
VAR
    eLinkStatus : E_GseLinkStatus;
    bSuccess    : BOOL;
    ipError     : I_ServiceErrorClass;
    bStart      : BOOL := TRUE; (* Rising edge starts publishing of GOOSE data *)
    bStop       : BOOL; (* Rising edge stops publishing of GOOSE data *)
    bUpdate     : BOOL; (* Rising edge updates published GOOSE data *)
    bSync       : BOOL := TRUE; (* Rising edge synchronizes the GSE system clock to external time *)
    tSync       : T_UtcTime := String_TO_UtcTime(in:='UT#2019-07-12-12:00:00.000000000|000|3'); (* External (test) time *)
    fbClock     : FB_GseSystemClock;
END_VAR
IF bSync THEN (* Synchronize clock time to external time source *)
    bSync:= FALSE;
    bSuccess:= fbClock.SetToUtcTime(in:=tSync);
ELSE (* Execute clock instance *)
    fbClock.Execute();
END_IF

(* Map/simulate GOCB's data-set member values: 'IED4Name.IED4NameLD1.LLN0.ds01' and/or 'ARRAY OF IED6Name[1..Max_GROUP_IED6Name].IED6NameLD1.LLN0.ds01' *)
bUpdate:= fbPubGroupName.MapSimuPubData(ipClock:=fbClock);

bSuccess:= fbAdapter.Execute(ipError=>ipError); (* Execute network adapter *)

IF bStart THEN (* Start publishing of GOOSE data *)
    bStart:= FALSE;
    bSuccess:= fbPubGroupName.Start(ipAdapter:=fbAdapter, ipError=>ipError);
ELSIF bStop THEN (* Stop publishing of GOOSE data *)
    bStop:= FALSE;
    bSuccess:= fbPubGroupName.Stop(ipError=>ipError);
ELSIF bUpdate THEN (* Update published GOOSE data *)
    bUpdate:= FALSE;
    bSuccess:= fbPubGroupName.Update(ipError=>ipError);
ELSE (* Execute publisher GoCB's *)
    bSuccess:= fbPubGroupName.Execute(ipError=>ipError);
END_IF

Simulation of publisher data in the sample project

If the Boolean variable "bSimulation" has the value "TRUE", then some changing publisher data will be simulated in the method "MapSimuPubData". E.g. a counter value "iLiveCounter" or some quality flags.

In addition, a very simple data concentrator was implemented there for testing purposes. Some subscriber data of the subscriber group IEDs are copied over to the publisher data when the value changes. In case of a value change, a Boolean variable such as "bUpdate_GROUP_IED4Name_IED4NameLD1_LLN0_gocb01" is also set to "TRUE". The "Update" method can detect via this variable that an update of the publisher data of the control block "gocb01" is to be performed.

Test of the subscriber group

There are other ICD files in the zip archive that can be used for testing or simulation purposes of the subscriber group:

Publisher_IED1Name.icd
Publisher_IED2Name.icd
Publisher_IED3Name.icd
Publisher_CH1_To_CH8.icd

You can use these files in a third party tool to simulate the "IED1Name", "IED2Name", "IED3Name" and "CH1".."CH8" publishers. Furthermore, you can also create a TwinCAT publisher project from these files. The subscribers in this sample project can receive the data from these publishers.

Publisher group test

There are two more ICD files in the zip archive that can be used when testing the publisher group in this sample project:

Subscriber_CNT1_To_CNT2.icd
Subscriber_IED4Name.icd

You can use these files in a third party tool to simulate the "CNT1".. "CNT8" and "IED4Name" subscribers. The sent data of the publisher group in this sample project can be received by these subscribers.