TwinCAT HMI JavaScript VS Server Extension

TwinCAT HMI can receive data from the PLC by using the JavaScript framework. In this article, we shall receive the same data from PLC by using an extension framework developed in C#.  The C# extension module uses a wrapper DLL (PLC driver which wraps TwinCAT ADS library) from the PLC. The extension module is needed for various purposes (see https://www.hemelix.com/scada-hmi/twincat-hmi/twincat-hmi-server-extension/ )

In the following image,  four variables are read from the PLC (running in local mode). Those variables are shown side by side.

In the following code, a simple PLC program is used for reading data to HMI.  The data is subscribed so if it changes in the PLC or UI that is updated.We run a timer to simulate it as live data.

//Declaration
PROGRAM MAIN
VAR
testBool : BOOL := FALSE;
testInt : INT := 0;
testReal : REAL := 3.14;
testString : STRING := 'MyString';
myTimer : TON;
END_VAR
//Body
myTimer(IN:= TRUE, PT:=T#500MS);
IF myTimer.Q = TRUE THEN
myTimer(IN:= FALSE);
testInt := testInt +1;
IF testInt > 30999 THEN
testInt:= 0;
END_IF
END_IF

The red boxes modules are written by us in C#.  Extension module is developed by using the wizards provided by Beckhoff. PLC data driver is a windows DLL that wraps ADS library provided by Beckhoff. PLC Data driver helps to keep track of different types of variables. If a variable is changed then that is propagated to the HMI. Upper path of the image is the JavaScript and ADS (bundled in the framework)

Some code is shown from the extension module (mostly omitted)

                commands.Result = ExtensionErrorValue.HMI_EXT_SUCCESS;
                string mapping = "";
                foreach (Command command in commands)
                {
                    mapping = command.Mapping;
                    try
                    {
                        // Use the mapping to check which command is requested
                        switch (mapping)
                        {
                            case "plcMakeConnection":
                                if (command.WriteValue.IsSet && command.WriteValue.Type == TcHmiSrv.ValueType.ValueType_String)
                                {
                                    string data = command.WriteValue;
                                    if (plcDriverObject == null && data.Contains("connectplc") == true)
                                    {
                                        plcDriverObject = new PlcDataDriverClass();
                                        plcDriverObject.ChangedNotification += AdsDriverClass_ChangedNotification; ;
                                        plcDriverObject.ConnectionEstablished += AdsDriverClass_ConnectionStatusChanged;
                                        plcDriverObject.InitializeConnectionToPLC("MAIN", "local", 851);
                                    }
                                }
                                command.ExtensionResult = ExtensionErrorValue.HMI_EXT_SUCCESS;
                                ret = ErrorValue.HMI_SUCCESS;
                                break;
                            case "plcMakeDisconnection":
                                if (command.WriteValue.IsSet && command.WriteValue.Type == TcHmiSrv.ValueType.ValueType_String)
                                {
                                    string data = command.WriteValue;
                                    if (plcDriverObject != null && plcDriverObject.IsPLCConnected == true && data.Contains("disconnectplc") == true)
                                    {
                                        plcDriverObject.ChangedNotification -= AdsDriverClass_ChangedNotification;
                                        plcDriverObject.ConnectionEstablished -= AdsDriverClass_ConnectionStatusChanged;
                                        plcDriverObject.CloseAdsConnection();
                                        plcDriverObject = null;
                                        _data.PLCConnectionStatus = "PLC Not Connected";
                                    }
                                }
                                command.ExtensionResult = ExtensionErrorValue.HMI_EXT_SUCCESS;
                                ret = ErrorValue.HMI_SUCCESS;
                                break;
                            case "plcWriteBool":
                                if (command.WriteValue.IsSet && command.WriteValue.Type == TcHmiSrv.ValueType.ValueType_String)
                                {
                                    string data = command.WriteValue;
                                    if (plcDriverObject != null && plcDriverObject.IsPLCConnected == true)
                                    {
                                        if (data.Contains("true") == true)
                                        {
                                            bool b = true;
                                            object oBool = b;
                                            plcDriverObject.WriteValue("MAIN.testBool", oBool);
                                        }
                                        else
                                        {
                                            bool b = false;
                                            object oBool = b;
                                            plcDriverObject.WriteValue("MAIN.testBool", oBool);
                                        }
                                    }
                                }
                                command.ExtensionResult = ExtensionErrorValue.HMI_EXT_SUCCESS;
                                ret = ErrorValue.HMI_SUCCESS;
                                break;                         

The project has been compiled with VS 2017, if you use an earlier version, you may have a problem loading the solution, you know!

The actual complete project can be downloaded from this link. Unfortunately, we can’t comment here but I am planning to upload this stuff to the YouTube channel soon. If you have any questions related to this, you could use the Hemelix channel. Thank you for reading so far.

Download  Windows Form application sample to read a variable from PLC ADS_Windows_Example_Hemelix.zip.

Download the sample from the link given above.

Next, let’s try to understand how to publish at https://www.hemelix.com/scada-hmi/twincat-hmi/beckhoff-pc-plc-communication-module-development/

Ask questions related to Hemelix sample code and design at Google group https://groups.google.com/g/hemelix