Sharing variables among programs in the same component

Hello, We are analyzing the possibility on sharing variables and/or ports among 2 or more programs in a component. In the code generated with eclipse when a PLCNext project is created in the component.hpp file the next comment is included in the port section od the declaration: //#port

//#name(NameOfPort)
boolean portField; The name comment defines the name of the port and is optional. Default is the name of the field.
Attributes which are defined for a component port are IGNORED. If component ports with attributes
are necessary, define a single structure port where attributes can be defined foreach field of the
structure. It states that attributes for a component are ignored and that if attributes are needed a single structure defining attibutes for each field is the correct way. This question is important for us because we need some ports and/or field to be retained. I have tried the next code //#port
//#name(OutPort2EnComponente)
struct TipoPort
{
//#port
//#attributes(Output|Retain|Ehmi)
int16 Integer16=0;
//#port
//#attributes(Output|Retain|Ehmi)
int32 Integer32=0; } EstructuraPuerto1; But fields are not retained and have a different behavior concerning the retain attribute than program ports; Along with this, component ports seem not to be initialized when a cold start is done. Could you kindly explain, in case it is possible, how to declare the port structure and its fields to use the retain attribute? Component ports are not available in the port list of the PLCNext environ, I suppose this is the correct behaviour but just to be sure. Please confirm. Thanks in advance. Javier Garcia.

Hello Javier, Sorry for the delay … Please look at this example on Github: https://github.com/PLCnext/CppExamples/tree/master/Examples/ProgramComponentInteraction This example shows how two Programs belonging to the same Component can reference variables in that Component. In this way, you can easily share data among two or more programs. (the diagram does not render properly on Github, so I’ve copied it below). Does this help? 01 04 2019 13 48 45

Hello Martin, Thank you for the info. We had checked the github example prior to ask about this question and our question has relation but is different. It is possible to define variables and variables asociated to ports in the component, we have define a port in the component and the variable of the porta can be accesed from the 2 programs of the component, till this point all is ok, we can share variables of the component among programs in the component. The question is to know if the port defined in the component can have attribute retain, ehmi, etc. In the code generated with eclipse when a PLCNext project is created in the component.hpp file the next comment is included in the port section od the declaration: //#port

//#name(NameOfPort)
boolean portField; The name comment defines the name of the port and is optional. Default is the name of the field.
Attributes which are defined for a component port are IGNORED. If component ports with attributes
are necessary, define a single structure port where attributes can be defined foreach field of the
structure. This automatic comment states that attributes for a component are ignored and that if attributes are needed a single structure defining attibutes for each field is the correct way. This question is important for us because we need some components ports and/or field to be retained . Can you explain how to declare a port in the component to have the Retain attribute? Thanks in advance.

Hi Javier, My apologies, I misunderstood your original question. I will try to get an answer for you as soon as possible. - Martin.

Hey Javier,

“But fields are not retained and have a different behavior concerning the retain attribute than program ports; Along with this, component ports seem not to be initialized when a cold start is done.Could you kindly explain, in case it is possible, how to declare the port structure and its fields to use the retain attribute?Component ports are not available in the port list of the PLCNext environ, I suppose this is the correct behaviour but just to be sure. Please confirm.”

Component Port support was added in PLCnext Engineer 2019.3 FW 2019.3 which was released recently.
Component Ports are not reinitialised with a cold start because a coldstart does not affect the Component but only the Program.
You will need to implement the start/stop methods inherited from the IComponentInterface to implement a initialisation at any Cold, Hot or Warmstart.
You can also do the initialise in the constructor of a Program. (component.variable = 0;) to Initialise only at Cold/Warmstarts (The Program constructor will be called when doing a Coldstart/Warmstarts.)

you can use either of these implementations in a component.hpp:

struct TipoPort1 {
    int16 Integer16_start = 0;
    int32 Integer32_constructor = 0;
    int32 Integer32_retain = 0;
};
//#port
//#name(TipoPort1)
//#attributes(Retain|Opc)
TipoPort1 EstructuraPuerto1;

//#port
//#name(TipoPort2)
struct TipoPort2 {
    //#attributes(Retain|Opc)
    int16 Integer16_start = 0;
    //#attributes(Retain)
    int32 Integer32_constructor = 0;
    //#attributes(Retain)
    int32 Integer32_retain = 0;
} EstructuraPuerto2;

Please note that the ehmi attribute currently can not be used in a Component.
This feature will be added later.
Also there is no Inport and Outport declaration for component ports.
When adding a variable it will automatically be both In and Outport
Components are not sceduled by the ESM and are not using GDS buffers, so handle them with care when exchanging realtime relevant data.

Example:

Program::Execute
{
    ProjectComponent.EstructuraPuerto1.Integer16_start++;
\tProjectComponent.EstructuraPuerto1.Integer32_constructor++;
\tProjectComponent.EstructuraPuerto1.Integer32_retain++;
}

ProgramConstructor
{
    ProjectComponent.EstructuraPuerto1.Integer32_constructor = 0;
}

void ProjectComponent::Start()
{
    EstructuraPuerto1.Integer16_start = 0;
}

----------------------------
Values:
Integer16_start = 100
Integer32_constructor = 100
Integer32_retain = 100 → Execute Coldstart

Integer16_start = 0
Integer32_constructor = 0
Integer32_retain = 100

- → wait some time

Integer16_start = 50
Integer32_constructor = 50
Integer32_retain = 100 - → Execute HotStart

Integer16_start = 0
Integer32_constructor = 50
Integer32_retain = 100

Hello Oliver, Thank you for the complete explanation. I will test it and come back with result and/or doubts.

Hello Oliver, I have checked your proposal. I add the next declaration in the component: //#port //#name(OutPort2EnComponente) struct TipoPort { //#attributes(Retain) int16 Integer16_Start=0; //#attributes(Retain) int16 Integer16_Constructor=0; //#attributes(Retain) int16 Integer16_Retain=0; } EstructuraPuerto1; I increment the values of the ports in the execute method of the program and I check is working properly. I initialized to 0 the value of the field constructor in the program constructor and I check that in warm and cold starts is initialized, this is correct. First question. When I switch off/on power supply of de device all values are initialized to 0, therefore something is not working properly or something is not well declared and values are not retained.. Second question. I implement a method called Start in the component to initialize the Star field to 0 but it seems it is never invoked. If I declare the method as override the compiler say the method is not overrridable and without override it seems it is not invoked. I suppose I am not doing correctly. The declaration is public: // IComponent operationspublic: // IComponent operations void Initialize() override; void LoadConfig() override; void SetupConfig() override; void ResetConfig() override; void Start(); and the implementation: void MyComponent::Start()void MyComponent::Start() {

this->EstructuraPuerto1.Integer16_Start=0;

} I wait for your answers. Thanks in advandce.

Hello Javier, To answer your second question - to use the Start and Stop methods, your component must implement the IControllerComponent interface, which is not the default behaviour. To do this, in your Component.hpp file:

                                               1. #include "Arp/System/Acf/IControllerComponent.hpp"
                                               2. In your component class definition, add "public IControllerComponent" to the inheritence list.
                                               3. Override the Start and Stop methods (as you tried already).

I will let Oliver answer your first question. Another point worth mentioning - Oliver has confirmed to me that the following auto-generated comment is not correct:

“Attributes which are defined for a component port are IGNORED.
If component ports with attributesare necessary, define a single structure port where attributes can be defined foreach field of thestructure.”

Attributes on component ports are not ignored. Component ports can be created from elementary data types in the same way as Program ports (with the caveats that Oliver describes above). It is not necessary to define a structure port in order to create component ports, although component ports can be defined using structures as Oliver has described. - Martin.

Hello Martin, Thank you for your explanation. I will check carefully. I wait for Oliver answer about the first question: Retained ports are initialized when power is cycled. Javier.

Hello Martin, I have checked and the Start/Stop methods works as you explain, I wait for Oliver answer about the first question: Retained ports are initialized when power is cycled to be able to retain data on components ports. Javier