---
title: "MQTT TagProvider Integration"
tags: [mqtt, tagprovider, uns, iiot, asset-navigation, dynamic-tags]
description: "Connect to an MQTT broker via TagProvider, explore its namespace, link selected nodes into the UNS AssetTree, and build an asset-navigation UI with DataGrid, TrendChart, and AlarmViewer — all driven by dynamic Asset() bindings."
version: "0.1-draft"
author: "Tatsoft"
---


Connect FrameworX to an external MQTT broker using TagProvider (zero-local-tags), auto-discover topic trees, link them into the UNS AssetTree, and build a dynamic asset-navigation UI with DataGrid, TrendChart, and AlarmViewer — all driven by Asset() bindings and Client.Context properties.


This skill has open items that require resolution before publishing. See the Open Items section at the bottom of this page.



What This Skill Does

This skill connects FrameworX to an external MQTT broker using a TagProvider — the dynamic, zero-local-tags approach. Instead of creating individual UnsTags and mapping them with Device Points, the TagProvider auto-discovers the broker's topic tree and extends the UNS namespace directly. The skill then builds a complete asset-navigation UI: a Layout with an AssetTree on the left, a header with commands, and a content area that reacts to the user's tree selection using Asset() bindings and Client.Context properties.

MQTT Broker ??? TagProvider ??? UNS Namespace (dynamic)
                                    ?
                              AssetTree Folder
                                    ?
                    ?????????????????????????????????
                  Header        AssetTree         MainPage
                 (Canvas)    (Navigation)     (DataGrid + Trend)
                                    ?
                          Client.Context.AssetPath
                          drives all content dynamically



On this page:


When to Use This Skill

Use this skill when:

Do NOT use this skill when:

Decision guide:

Scenario

Approach

Dynamic data, auto-discovery wanted

This skill (TagProvider)

Specific tags, strict validation (FDA)

Device Module

Large topic tree, monitoring/IoT

This skill (TagProvider)

Small fixed set of MQTT topics

Device Module may be simpler

Prerequisites

MCP Tools and Tables Involved

Category

Items

Tools

designer_action, get_designer_state, get_table_schema, write_objects, list_protocols, list_elements, get_screenshot

Tables

UnsTagProviders, UnsAssetTree, DisplaysList, DisplaysLayouts

Designer Actions

navigate (to DataExplorer.MQTTTools), connect_mqtt_explorer (new), start_mqtt_broker, start_mqtt_simulator

Key Namespaces

Client.Context.AssetPath, Client.Context.AssetName, Client.Context.AssetNodeName, Client.Context.SelectedTag

Implementation Steps

Step 0: Discover the MQTT Broker Data (Interactive)

Before creating any configuration, you need to see what data the broker has. This step is interactive — it involves the user.

If using the built-in broker for testing:

designer_action('start_mqtt_broker')
designer_action('start_mqtt_simulator')

This starts a local MQTT broker and a SparkplugB simulator that publishes sample data (solar panels, cities, sensors).

Navigate to MQTT Tools:

designer_action('navigate', 'DataExplorer.MQTTTools')

Connect to the broker:

designer_action('connect_mqtt_explorer', '<PrimaryStation string>')

The PrimaryStation format for MQTT is a semicolon-delimited string with 14 fields:

{Host};{Port};{ClientID};{Username};{Password};{CertFile};{KeyFile};{TLS};{CleanSession};{WillTopic};{QoS};{KeepAlive};{RetainPublish};{UseWebSocket};

Common examples:

Scenario

PrimaryStation

Local built-in broker

localhost;1883;FrameworX-Explorer;;;;;None;False;;AtLeastOnce;10;False;False;

Remote broker

mqtt.factory.local;1883;FrameworX-001;;;;;None;False;;AtLeastOnce;10;False;False;

With authentication

broker.cloud.io;8883;MyClient;admin;password123;;;TLS 1.2;False;;AtLeastOnce;30;False;False;

Ask the user to explore and select:

The MQTT browser is now connected. Please navigate the tree to explore the available data. When you've identified the nodes you want to integrate into the Unified Namespace, select them and let me know — or I can read your current selection.

Read the user's selection:

get_designer_state()

This returns the current MQTT Tools state including which nodes the user has selected (or browsed to). Use this information to determine the initial tree nodes for the TagProvider link.

AI-driven alternative: If the user says "just connect everything" or "pick reasonable defaults," the AI can read the top-level structure from get_designer_state() and propose a reasonable default selection, then create the configuration. Verify with the user afterward — it's easier to modify an existing object than to wait for the user to manually select before creating anything.

Step 1: Create the TagProvider Connection

Fetch the schema and protocol details:

get_table_schema('UnsTagProviders')
list_protocols('mqtt')

Write the TagProvider object:

{
  "table_type": "UnsTagProviders",
  "data": [
    {
      "Name": "MQTT",
      "Protocol": "MQTT",
      "PrimaryStation": "localhost;1883;FrameworX-001;;;;;None;False;;AtLeastOnce;10;False;False;",
      "Separators": "BranchSeparator=/;AttributeSeparator=/;",
      "Description": "Production MQTT Broker"
    }
  ]
}

Key decisions:

After creation, the TagProvider immediately starts discovering topics when runtime starts. Topics appear as dynamic tags under Tag.<ProviderName>.<topic.path>.

Step 2: Create the Linked Folder in AssetTree

The AssetTree folder is what makes the TagProvider data visible and navigable in the UI. A Linked Folder connects an AssetTree node to a TagProvider and specifies which initial nodes from the provider's namespace to display.

UnsAssetTree currently reports readOnly: true in the schema. The exact field names for TagProviderLink and InitialPath require confirmation from Tatsoft. See Open Items at the bottom of this page.


{
  "table_type": "UnsAssetTree",
  "data": [
    {
      "Name": "Production",
      "TagProviderLink": "MQTT",
      "InitialPath": "spBv1.0/GroupID",
      "Description": "MQTT production data from SparkplugB broker"
    }
  ]
}

Key decisions:

From this point down, the AssetTree is dynamic — the platform auto-expands the tree based on whatever the MQTT broker publishes. No further tag creation needed.

Step 3: Build the Layout (Header + AssetTree + Content)

The standard pattern for asset-navigation applications is a Layout with three regions:

get_table_schema('DisplaysLayouts')
list_elements('Layout')


{
  "table_type": "DisplaysLayouts",
  "data": [
    {
      "Name": "Startup",
      "Header": "Header",
      "Menu": "AssetTreeMenu",
      "Content": "MainPage",
      "Description": "Asset navigation layout — tree on left, dynamic content on right"
    }
  ]
}

The Layout Startup (ID 0) is the predefined startup layout — modifying it changes what loads on application launch.

Regions:

Step 4: Create the Header Display

A simple Canvas display with the application title:

get_table_schema('DisplaysList')
list_elements('TextBlock,Button')


{
  "table_type": "DisplaysList",
  "data": [
    {
      "Name": "Header",
      "PanelType": "Canvas",
      "Width": 1200,
      "Height": 60,
      "Description": "Application header bar",
      "Objects": [
        {
          "Type": "TextBlock",
          "Name": "Title",
          "Left": 20,
          "Top": 15,
          "Text": "MQTT Production Monitor",
          "FontSize": 18,
          "FontWeight": "Bold"
        }
      ]
    }
  ]
}

Step 5: Create the AssetTree Menu Display

A Canvas display containing the AssetTree control that drives navigation:

list_elements('AssetsTree')


{
  "table_type": "DisplaysList",
  "data": [
    {
      "Name": "AssetTreeMenu",
      "PanelType": "Canvas",
      "Width": 300,
      "Height": 700,
      "Description": "Asset tree navigation panel",
      "Objects": [
        {
          "Type": "AssetsTree",
          "Name": "NavTree",
          "Left": 0,
          "Top": 0,
          "Width": 300,
          "Height": 700
        }
      ]
    }
  ]
}

When the user clicks a node in the AssetsTree, the platform automatically updates:

Property

Example Value

Client.Context.AssetPath

MQTT/spBv1.0/GroupID/Barcelona/Panel1

Client.Context.AssetName

Panel1

Client.Context.AssetNodeName

leaf node name

Client.Context.SelectedTag

full tag path of the selected tag

These properties drive the content display reactively.

Step 6: Create the MainPage (Dynamic Content)

The MainPage uses Asset() bindings to react to the user's tree selection. All content is driven by Client.Context.AssetPath.

list_elements('DataGrid,TrendChart,TextBlock,AlarmViewer')


{
  "table_type": "DisplaysList",
  "data": [
    {
      "Name": "MainPage",
      "PanelType": "Dashboard",
      "Columns": 2,
      "Rows": 3,
      "Description": "Dynamic content — reacts to AssetTree selection",
      "Objects": [
        {
          "Type": "TextBlock",
          "Name": "AssetTitle",
          "Row": 0,
          "Column": 0,
          "ColSpan": 2,
          "Text": "",
          "LinkedValue": "@Client.Context.AssetName",
          "FontSize": 20,
          "FontWeight": "Bold"
        },
        {
          "Type": "DataGrid",
          "Name": "AssetData",
          "Row": 1,
          "Column": 0,
          "ColSpan": 2,
          "LinkedValue": "@Tag",
          "LinkedContext": "@Client.Context.AssetPath",
          "Width": 800,
          "Height": 300
        },
        {
          "Type": "TrendChart",
          "Name": "AssetTrend",
          "Row": 2,
          "Column": 0,
          "Width": 500,
          "Height": 250,
          "Duration": "00:05:00"
        },
        {
          "Type": "AlarmViewer",
          "Name": "AssetAlarms",
          "Row": 2,
          "Column": 1,
          "Width": 400,
          "Height": 250
        }
      ]
    }
  ]
}

Key pattern — the DataGrid LinkedValue:

When you set the DataGrid's LinkedValue to @Tag and provide a LinkedContext pointing to @Client.Context.AssetPath, the DataGrid automatically shows all children (sub-tags and attributes) of whatever the user selected in the AssetTree. This is the heart of the dynamic pattern — one display serves the entire asset hierarchy.

The Asset() syntax for code and expressions:

// In scripts or CodeBehind:
double value = Asset(@Client.Context.AssetPath + "/Temperature");

// In display element LinkedValue fields:
// Static: @Tag.MQTT.plant.line1.temperature
// Dynamic: Asset(Client.Context.AssetPath + "/Temperature")

Step 7: Start Runtime and Verify

designer_action('start_runtime')

After starting:

  1. The TagProvider connects to the MQTT broker and discovers topics
  2. The AssetTree populates with the linked folder structure
  3. Clicking any node in the tree updates Client.Context properties
  4. The DataGrid, TrendChart, and other elements on MainPage react to the selection

Take a single screenshot to verify:

get_screenshot('runtime')

Code Examples

Asset() in CodeBehind (Display Events)

void Opening()
{
    // Optionally set a default branch to expand
    @Client.Context.TreeInitialBranch = "MQTT/spBv1.0/GroupID";
}

Asset() in Scripts

public static double GetTemperature(string assetPath)
{
    return TK.ToDouble(Asset(assetPath + "/Temperature"));
}

Data Type Handling for HTML5/Portable Clients

// WPF (.NET Framework 4.8) — automatic type resolution
var value = Asset("/MQTT/plant/line1/temperature");

// HTML5/Portable (NetStandard 2.0) — explicit conversion required
int intValue = TK.ToInt(Asset("/MQTT/plant/line1/count"));
double dblValue = TK.ToDouble(Asset("/MQTT/plant/line1/temperature"));
string strValue = TK.ToString(Asset("/MQTT/plant/line1/status"));
bool boolValue = TK.ToDigital(Asset("/MQTT/plant/line1/running"));

Verification

  1. get_objects('UnsTagProviders') — verify the TagProvider was created with correct PrimaryStation
  2. designer_action('navigate', 'Uns.AssetTree')get_designer_state() — confirm the linked folder appears with the TagProvider reference
  3. designer_action('start_runtime')get_runtime_state() — confirm the TagProvider connection is active
  4. get_screenshot('runtime') — verify the AssetTree populates and the Layout renders correctly
  5. Ask the user to click different nodes in the AssetTree and confirm the DataGrid updates dynamically

Common Pitfalls

Mistake

Why It Happens

How to Avoid

Creating local UnsTags for MQTT data

Habit from Device Module workflow

TagProviders don't need local tags — that's the whole point. Only create UnsTags if you need alarms or historian on specific points.

Wrong PrimaryStation format

Forgetting semicolon delimiters or field order

Always call list_protocols('mqtt') first. The format is 14 semicolon-separated fields.

DataGrid shows nothing

LinkedValue not correctly bound to context

Use @Tag with LinkedContext set to @Client.Context.AssetPath. The DataGrid needs both.

Topics with special chars not accessible

MQTT topics like spBv1.0/Group contain dots

Use quoted syntax: Tag.ProviderName.("spBv1.0/Group/Node")

AssetTree empty after runtime start

TagProvider not connected or linked folder not configured

Verify TagProvider connection in ServicesMonitor, then check that UnsAssetTree folder has correct TagProviderLink

Trying to set alarms on dynamic tags

Dynamic tags don't exist as local UnsTags

Create a local tag and use a Script expression to copy the Asset() value into it. Or switch those specific points to Device Module.

Layout regions not rendering

Wrong display names in Layout configuration

Display names in Header, Menu, Content fields must match exactly (case-insensitive)

Variations

Variation A: Mixed Approach (TagProvider + Device Module)

Variation B: SparkplugB-Specific

Variation C: Multiple Brokers

Variation D: Add Historian to Dynamic Tags

Related Skills

Documentation References

Open Items (Draft Notes)

#

Item

Status

1

connect_mqtt_explorer designer_action: New action needed — navigates to DataExplorer.MQTTTools and initiates connection with a PrimaryStation string. Not yet implemented.

2

get_designer_state() for MQTT Tools: Must return the user's selected nodes in the MQTT browser tree. This is how the AI reads which nodes the user wants to integrate.

3

UnsAssetTree write support: Currently readOnly: true. Need writable schema with fields: Name, TagProviderLink, InitialPath, Description. Exact field names TBD.

4

DataGrid LinkedContext property: Verify exact property name and behavior — does DataGrid have LinkedContext as a separate field, or is asset-driven behavior configured differently?

5

TrendChart Asset() binding: How does a TrendChart dynamically bind its pens to the currently selected asset's children?

6

Layout field names: Verify exact field names for DisplaysLayouts — is it Header, Menu, Content or different property names?

7

Template integration: If solution templates with built-in Header+AssetTree+Content exist, reference them as a shortcut.


In this section...