Skip to content

Resolve index-based symbol mappings easily

The information in this post are usable with:

Array-based access to TwinCAT HMI symbols can be tricky, but in the latest version (>= 1.12.718.0) some convience functionalities has been added to the Server API. Let’s have a look.

The TwinCAT HMI Server API is provided in “C:\TwinCAT\Functions\TE2000-HMI-Engineering\Infrastructure\TcHmiServer\Latest”. Right now we are interested in “TcHmiSrvExtNet.Core.dll”. With JetBrains dotPeek we can discover the internals of the DLL.

Check the namespace “TcHmiSrv.Core.Extensions”, four extension methods are provided:

  1. public static Value ResolveBy(this Value value, Queue elements)
  2. public static Value ResolveBy(this Value value, string path)
  3. public static bool TryResolveBy(this Value value, Queue elements, out Value result)
  4. public static bool TryResolveBy(this Value value, string path, out Value result)

These are very handy methods to resolve index-based access for array. Let us check a very small example. The latest version is always available on GitHub (Go to repository…)

We have a basic HMI-project and a small Server Extension, as you can see the extension is added as project reference to the HMI-project and is loaded/running proved by the green arrow of the extension domain node:

As followed in the code snipped, the extension config (GitHub: link to source) provides the symbol “VideoFiles” of the datatype “tchmi:framework#/definitions/VideoSourceList” (Beckhoff InfoSys: link) which is predefined by the TwinCAT HMI Framework.

{
  "$schema": "ExtensionSettings.Schema.json",
  "guid": "6d5021d1-962a-4975-9f8c-0aaf1df26dc4",
  "version": "1.0.0.0",
  "configVersion": "1.0.0.1",
  "symbols": {
    "VideoFiles": {
      "readValue": {
        "$ref": "tchmi:framework#/definitions/VideoSourceList"
      },
      "hidden": false
    }
  }
}

As a result, the configured symbol will be shown in TwinCAT HMI Configuration Tool Window which is automatically provided as mapped symbol (i.e. it can be used ad-hoc and without further configuration):

First Approach (easy to apply, bad architecture)

Several ways exist to access specific items of the array, for example the function “TcHmi.Functions.Beckhoff.GetElementByIndex” (Beckhoff InfoSys: link) of the TwinCAT HMI Framework can be applied. Just copy the following code to the Desktop.view and check the result with the TwinCAT HMI Live-View:

<div id="TcHmi_Controls_Beckhoff_TcHmiTextbox" 
     data-tchmi-type="TcHmi.Controls.Beckhoff.TcHmiTextbox" 
     data-tchmi-height="26" data-tchmi-height-unit="px" 
     data-tchmi-left="10" data-tchmi-left-unit="px" 
     data-tchmi-top="10" data-tchmi-top-unit="px" 
     data-tchmi-width="354" data-tchmi-width-unit="px" 
     data-tchmi-text="%f%TcHmi.Functions.Beckhoff.GetElementByIndex(
        %s%ServerExtensionVideos.VideoFiles%/s%, 0).source
     %/f%" 
     data-tchmi-text-horizontal-alignment="Center">

</div>

In this case the Framework queries the whole list of the array and access the array on its own. This approach can be very expensive in case of large arrays. It is not only a problem of waste of time, also the memory footprint can be very large and probably can hit the maximum allowed allocation of memory. Crashes or unpredicable behaviours are mostly the case. For small array it can be a very easy approach and the result will look like this:

Second Approach (faster execution, no memory waste)

Probably you like to access the first item of the array, always. In this case the easiest would be a new mapping to link to the first index. Within the configuration window, select the symbol and call “Map Symbol”:

Select the index your are interested in and click “OK”:

As a result a new mapping “VideoFiles.0” is added which links to “VideoFiles[0]”:

The mapping can be used by “%s%VideoFiles.0::source%/s%”. As a result the TwinCAT HMI Framework still tries to resolve the symbol “VideoFiles”, but in this case an additional path is added, i.e. “0::source” (the server gets “[0]::source”. Check the debugger information:

ResolveBy*

That is the part where the functionalities ResolveBy* are come into the game. It is not required anymore that you have to parse all that information. The extension functionalities resolve the path of provided mapping and path and will deliver valid symbol results.

This saves network traffic and a lot of memory waste.

By enabling “Show live values ..” you can have a look to the result without any instatiation of any control:

Be First to Comment

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.