Extending the HMI parallel class (FB)

In many use cases, the number of displayed values on the surface is to be extended. For this purpose, the HMI parallel class can be extended so that the new values are accessible in the HMI environment at a suitable location.

For the complete implementation the extension of the base class (FB) is necessary.
1. Perform steps 1 to 5 of Base class extension (FB) for the base class.
2. Create a new class (FB) and remove VAR_INPUT and VAR_OUTPUT.
FUNCTION_BLOCK FB_CustomAxisHmi 
VAR
END_VAR
3. Add the class to be inherited to the class definition using the EXTENDS keyword.
FUNCTION_BLOCK FB_CustomAxisHmi EXTENDS FB_AxisHmi 
VAR
END_VAR
4. So that you can also address the class and the added elements via an interface, create an interface with the same name.
INTERFACE I_CustomAxisHmi
5. Let the interface inherit from the interface of the inherited class.
INTERFACE I_CustomAxisHmi EXTENDS I_AxisHmi
6. Implement the interface in the previously created class (FB).
FUNCTION_BLOCK FB_CustomAxisHmi EXTENDS FB_AxisHmi IMPLEMENTS I_CustomAxisHmi
VAR
END_VAR
7. Instantiate the interface in the base class (FB).
FUNCTION_BLOCK FB_CustomAxis EXTENDS FB_Axis IMPLEMENTS I_CustomAxis
VAR
    iCustomAxisHmi:        I_CustomAxisHmi;    
END_VAR
8. Overwrite the SetHMI() method of the base class.
// Setter method for HMI-Class
METHOD SetHMI : HRESULT
VAR_INPUT
    ipBaseHmi:        I_BaseHmi;        // interface on hmi object
END_VAR



IF NOT __QUERYINTERFACE(ipBaseHmi, iCustomAxisHmi) THEN
    SetHMI := F_HresultFailure(E_AdsErr.DEVICE_INVALIDINTERFACE);
    RETURN;
END_IF

SetHmi := S_OK;
9. Extend the Init() method and add a __QUERYINTERFACE() operation for the new interface.
METHOD Init : HRESULT



IF NOT __QUERYINTERFACE(iCustomAxisHmi, iAxisHmi) THEN
    RETURN;                
ELSIF NOT F_SucceededHr(SUPER^.Init(), Init) THEN
    RETURN;
END_IF

Add a new setting or command value for the HMI

10. Add a new property to the HMI class.
PROPERTY NewHmiProperty : LREAL
11. Add the Monitoring attribute to the declaration to make the property visible to the HMI.
This makes the property visible even when the PLC is logged in.
{attribute “monitoring” := “call”}
PROPERTY NewHmiProperty : LREAL
12. Copy the property to the interface with the same name.
Extending the HMI parallel class (FB) 1:
13. Create a similarly named variable in the HMI class where the value can be cached.
FUNCTION_BLOCK FB_CustomAxisHmi EXTENDS FB_AxisHmi IMPLEMENTS I_CustomAxisHmi
VAR
    fNewHmiProperty:            LREAL;
END_VAR
14. Add the 'TcHmiSymbol.Hide' attribute to the declaration so that the variable is not seen by the HMI.
This ensures that the variable is not mistakenly used by the HMI instead of the property. If you set the ADS mapping in the HMI to Use whitelisting, you can basically hide all variables. To continue showing the HMI classes, you must add the {attribute 'TcHmiSymbol.ShowRecursively'} to the declaration.
FUNCTION_BLOCK FB_CustomAxisHmi EXTENDS FB_AxisHmi IMPLEMENTS I_CustomAxisHmi
VAR
    {attribute 'TcHmiSymbol.Hide'}
    fNewHmiProperty:            LREAL;
END_VAR
15. Implement the property write and read operation in the Get and Set method.
You have successfully added a property.

Making an existing property of the base class accessible to the HMI

1. Instantiate an interface of the base class type in the HMI parallel class.
FUNCTION_BLOCK FB_CustomAxisHmi EXTENDS FB_AxisHmi IMPLEMENTS I_CustomAxisHmi
VAR
    {attribute “TcHmiSymbol.Hide”}
    iCustomAxis:                I_CustomAxis;
    {attribute “TcHmiSymbol.Hide”}
    fNewHmiProperty:            LREAL;
END_VAR
2. Add the Init() method to the HMI class.
// Init method for linking to a control class (FB)
METHOD Init : HRESULT
VAR_INPUT
    ipBase:    I_Base;    // Base interface on linked control class (FB)
END_VAR
3. In the Init() method, perform a __QUERYINTERFACE() operation from the base interface passed to the last interface instantiated.
Init := F_HresultFailure(E_AdsErr.DEVICE_NOTINIT);

RETURN(NOT __QUERYINTERFACE(ipBase, iCustomAxis));
RETURN(NOT F_SucceededHr(SUPER^.Init(ipBase), Init));

Init :=  F_HresultSuccess(NOERR);
4. [If inheriting from FB_BaseHmi] Implement the call to the HMI-Init() in the Init() method of the base class.
Init:=F_HresultFailure(E_AdsErr.DEVICE_NOTINIT);

IF iCustomAxisHmi = 0 THEN
    RETURN;                
ELSIF NOT F_SucceededHr(iCustomAxisHmi.Init(THIS^), Init) THEN
    RETURN;    
ELSIF NOT F_SucceededHr(SUPER^.Init(), Init) THEN
    RETURN;
END_IF
5. Add a new property to the HMI class.
PROPERTY SecondNewHmiProperty : LREAL
6. Add the Monitoring attribute to the declaration to make the property visible to the HMI.
This makes the property visible even when the PLC is logged in.
{attribute “monitoring” := “call”}
PROPERTY NewHmiProperty : LREAL
7. Copy the property to the interface with the same name.
Extending the HMI parallel class (FB) 2:
8. Program the access to the property of the interface in the Get (and if necessary Set) method of the property.
IF iCustomAxis <> 0 THEN
    SecondNewHmiProperty := iCustomAxis.ExistingValue;
END_IF
9. For further properties with reference access, steps 1 to 4 are omitted accordingly.
You have successfully added a property with reference access to the main class.