...
| Warning | ||
|---|---|---|
| ||
This skill has open items that require resolution before publishing. See the Open Items section at the bottom of this page. |
...
| Section | |||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
Use this skill when:
...
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 |
open_solution or create_solution completed)Category | Items |
|---|---|
Tools |
|
Tables |
|
Designer Actions |
|
Key Namespaces |
|
Before creating any configuration, you need to see what data the broker has. This step is interactive — it involves the user.
...
| Tip |
|---|
AI-driven alternative: If the user says "just connect everything" or "pick reasonable defaults," the AI can read the top-level structure from |
Fetch the schema and protocol details:
...
After creation, the TagProvider immediately starts discovering topics when runtime starts. Topics appear as dynamic tags under Tag.<ProviderName>.<topic.path>.
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.
...
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.
The standard pattern for asset-navigation applications is a Layout with three regions:
...
A simple Canvas display with the application title:
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
{
"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"
}
]
}
]
}
|
A Canvas display containing the AssetTree control that drives navigation:
...
These properties drive the content display reactively.
The MainPage uses Asset() bindings to react to the user's tree selection. All content is driven by Client.Context.AssetPath.
...
| Code Block | ||||
|---|---|---|---|---|
| ||||
// 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") |
| Code Block | ||
|---|---|---|
| ||
designer_action('start_runtime')
|
...
| Code Block | ||
|---|---|---|
| ||
get_screenshot('runtime')
|
| Code Block | ||||
|---|---|---|---|---|
| ||||
void Opening()
{
// Optionally set a default branch to expand
@Client.Context.TreeInitialBranch = "MQTT/spBv1.0/GroupID";
}
|
| Code Block | ||||
|---|---|---|---|---|
| ||||
public static double GetTemperature(string assetPath)
{
return TK.ToDouble(Asset(assetPath + "/Temperature"));
}
|
| Code Block | ||||
|---|---|---|---|---|
| ||||
// 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"));
|
get_objects('UnsTagProviders') — verify the TagProvider was created with correct PrimaryStationdesigner_action('navigate', 'Uns.AssetTree') → get_designer_state() — confirm the linked folder appears with the TagProvider referencedesigner_action('start_runtime') → get_runtime_state() — confirm the TagProvider connection is activeget_screenshot('runtime') — verify the AssetTree populates and the Layout renders correctlyMistake | 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 |
DataGrid shows nothing | LinkedValue not correctly bound to context | Use |
Topics with special chars not accessible | MQTT topics like | Use quoted syntax: |
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) |
Variation A: Mixed Approach (TagProvider + Device Module)
...
Asset() syntax to automatically query historical data from historian TagProvidersskill-device-mqtt — Explicit MQTT integration using Device Module (Channel → Node → Points)skill-asset-navigation — Generic asset-navigation UI patterns (not MQTT-specific)skill-sparkplugb-collector — SparkplugB Collector setup with Device Module| Status | ||||
|---|---|---|---|---|
|
# | Item | Status | ||||||
|---|---|---|---|---|---|---|---|---|
1 |
|
| ||||||
2 |
|
| ||||||
3 |
|
| ||||||
4 | DataGrid |
| ||||||
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 |
| ||||||
7 | Template integration: If solution templates with built-in Header+AssetTree+Content exist, reference them as a shortcut. |
|
...
| Page Tree | ||
|---|---|---|
|
...