Skip to content
  • There are no suggestions because the search field is empty.

Getting Started: Namespaces and Smart Query

 

What Does This Article Cover?

  • What is a Namespace.
  • How to setup a Namespace.
  • What is Smart Query.
  • How to use Smart Query stage in a Pipeline.
  • Other Related Material

What is a Namespace

A namespace organizes sources of data into a logical hierarchy. A common use of namespaces is to organize an ISA-95 hierarchy of sites, areas, and lines and then populate this with modeled data like motors, machines, and other assets.   Traditionally when publishing data to MQTT or other destinations, a hierarchy of names are used define the relationship of entities.   This hierarchy of names is organized using a number of methods including creating static instance, using system variables and hardcoding the values in connectors / pipelines.    With version 4.0, the Namespace can be imported and manage within the Intelligence Hub UI.    This simplifies the management of the hierarch and creates a standard methodology for defining and using the hierarchy.

How to setup a Namespace

With Namespaces, the names and relationships are designed within Intelligence Hub.   Each name is known as a node.   A node can just be a name, or the node could also reference information from input or instances.   When building the hierarchy from an input or instance, the nodes can be added using drag and drop.   Once a node is built, the hierarchy as well as the reference data is read when the "Read Node" button is pressed from the Test Read section.

NSCreate

Smart Query 

Once the Namespace is setup, a Smart Query stage is within a pipeline is used to read from the Namespace.   Smart Query uses a lightweight query and transformation language named JSONata to read and filter data from the Namespace.  The results from query match the same structure used in the Read Node function on the Namespace Test Read.

Smart Query can also read from the HighByte configuration using "HighByte" as the name of the top level. 

How to use Smart Query stage in a Pipeline

A common use case for Smart Query is to query the Namespaces at particular location and use the result to send data to a destination.  A popular destination for building a UNS is MQTT.    In this example, we will be sending the results from Smart Query to the Intelligence Hub internal MQTT broker.

Below is the code for a sample project.   This project is all that is needed to read data from OPC UA and write the data to MQTT.   The project uses a pipeline that runs on a regular basis that will query the Namespace using Smart Query.  The results from the Smart Query are transformed and published to MQTT to a topic that is based on the hierarchy of the Namespace. 

{
    "productInfo": {
        "company": "HighByte",
        "product": "IntelligenceHub",
        "version": "4.0.0",
        "build": "2024.10.4.590",
        "stage": "Alpha"
    },
    "project": {
        "version": 9,
        "connections": [
            {
                "name": "Tutorial_MQTT",
                "uri": "mqtt://0.0.0.0:1885",
                "tags": [
                    "Tutorial"
                ],
                "writes": {
                    "flattenModeledValues": false
                },
                "subscriptions": {},
                "storeForward": {
                    "enabled": false,
                    "maxEntries": 100,
                    "waitOnFailureInterval": {
                        "duration": 1,
                        "units": "Seconds"
                    }
                },
                "settings": {
                    "connectionTimeoutSeconds": 10,
                    "keepAliveSeconds": 60,
                    "requestTimeoutMS": 5000,
                    "cleanSession": true,
                    "ssl": false,
                    "redundantBrokers": [],
                    "inputDiscovery": ""
                }
            },
            {
                "name": "Tutorial_OPC_UA",
                "uri": "opc.tcp://52.10.6.4:49320",
                "tags": [
                    "Tutorial"
                ],
                "writes": {
                    "flattenModeledValues": false
                },
                "subscriptions": {
                    "subscriptionRate": {
                        "duration": 1,
                        "units": "Seconds"
                    }
                },
                "storeForward": {
                    "enabled": false,
                    "maxEntries": 100,
                    "waitOnFailureInterval": {
                        "duration": 1,
                        "units": "Seconds"
                    }
                },
                "settings": {
                    "security": "None",
                    "authentication": {
                        "type": "Anonymous"
                    },
                    "connectTimeoutSeconds": 5,
                    "requestTimeoutMS": 5000,
                    "maxItemsPerRead": 512,
                    "maxItemsPerWrite": 256,
                    "certificateKeyPair": "app-certificate-private-key",
                    "sessionName": ""
                }
            }
        ],
        "inputs": [
            {
                "name": "INJECT1_InjectionMolding1",
                "connection": "Tutorial_OPC_UA",
                "type": "opc.tcp",
                "qualifier": {
                    "namespaceIndex": 2,
                    "identifierType": "String",
                    "identifier": "INJECT1.InjectionMolding1",
                    "dataType": "Auto",
                    "type": "Branch",
                    "maxDepth": 1
                },
                "cacheLifetime": {
                    "enabled": false
                },
                "template": {
                    "type": "Off"
                }
            }
        ],
        "outputs": [],
        "modeling": {
            "models": [
                {
                    "name": "Injection",
                    "tags": [],
                    "attributes": [
                        {
                            "attributeType": "Internal",
                            "name": "Pressure",
                            "nullable": false,
                            "required": false,
                            "array": false,
                            "internalType": "Any"
                        },
                        {
                            "attributeType": "Internal",
                            "name": "Temperature",
                            "nullable": false,
                            "required": false,
                            "array": false,
                            "internalType": "Any"
                        },
                        {
                            "attributeType": "Internal",
                            "name": "Cycles",
                            "nullable": false,
                            "required": false,
                            "array": false,
                            "internalType": "Any"
                        }
                    ]
                }
            ],
            "instances": [
                {
                    "name": "Injection1",
                    "tags": [],
                    "model": "Injection",
                    "rootValueAs": "Object",
                    "template": {
                        "type": "Off"
                    },
                    "executeMode": "V4",
                    "initExpression": "",
                    "attributes": [
                        {
                            "name": "Pressure",
                            "expression": {
                                "type": "Reference",
                                "reference": "{{Connection.Tutorial_OPC_UA.INJECT1_InjectionMolding1.MainCylinderPressure}}"
                            }
                        },
                        {
                            "name": "Temperature",
                            "expression": {
                                "type": "Reference",
                                "reference": "{{Connection.Tutorial_OPC_UA.INJECT1_InjectionMolding1.injectmold1temp}}"
                            }
                        },
                        {
                            "name": "Cycles",
                            "expression": {
                                "type": "Reference",
                                "reference": "{{Connection.Tutorial_OPC_UA.INJECT1_InjectionMolding1.CycleTime}}"
                            }
                        }
                    ]
                }
            ]
        },
        "conditions": [],
        "functions": [],
        "tags": [],
        "pipelines": [
            {
                "name": "NamespaceNodeReadsToUNS",
                "uri": "pipeline",
                "tags": [],
                "settings": {
                    "inputStages": [
                        "SmartQuery"
                    ],
                    "trackActivity": true,
                    "triggers": [
                        {
                            "name": "PolledTrigger",
                            "config": {
                                "type": ".TriggerPolled",
                                "interval": {
                                    "duration": 10,
                                    "units": "Seconds"
                                },
                                "enabled": true
                            },
                            "display": {
                                "position": {
                                    "x": -450,
                                    "y": 0
                                }
                            }
                        }
                    ],
                    "stages": [
                        {
                            "name": "SmartQuery",
                            "outputs": [
                                "Flatten"
                            ],
                            "config": {
                                "type": ".SmartQueryConfig",
                                "query": {
                                    "from": [
                                        "Site1.**"
                                    ],
                                    "select": {
                                        "what": [
                                            "value"
                                        ],
                                        "as": "Hierarchy",
                                        "delim": "/"
                                    }
                                },
                                "breakup": true,
                                "metadataKey": "query"
                            },
                            "display": {
                                "position": {
                                    "x": 240,
                                    "y": 0
                                }
                            }
                        },
                        {
                            "name": "Breakup",
                            "outputs": [
                                "ToUNS"
                            ],
                            "config": {
                                "type": ".BreakupConfig",
                                "breakupType": "object"
                            },
                            "display": {
                                "position": {
                                    "x": 1140,
                                    "y": 0
                                }
                            }
                        },
                        {
                            "name": "ToUNS",
                            "outputs": [],
                            "config": {
                                "type": ".DynamicWriteConfig",
                                "failureOutputs": [],
                              "connectionReference": "{{Connection.Tutorial_MQTT}}",
                                "ignoreResult": false,
                                "qualifier": {
                                    "topic": "UNS/ ",
                                    "qos": 0,
                                    "namedRoot": false,
                                    "retained": true,
                                    "breakupArrays": false,
                                    "filterList": [
                                        "_timestamp"
                                    ]
                                },
                                "connectionType": "mqtt"
                            },
                            "display": {
                                "position": {
                                    "x": 1590,
                                    "y": 0
                                }
                            }
                        },
                        {
                            "name": "Flatten",
                            "outputs": [
                                "Breakup"
                            ],
                            "config": {
                                "type": ".FlattenConfig",
                                "delimiter": "/"
                            },
                            "display": {
                                "position": {
                                    "x": 690,
                                    "y": 0
                                }
                            }
                        }
                    ]
                }
            }
        ],
        "namespace": [
            {
                "id": "b38ac8c1-2a5d-44d9-9e04-ea0a6b0d224a",
                "name": "Site1"
            },
            {
                "id": "ceab426c-e05d-4e47-9127-5b4042c2d1e6",
                "name": "Area1",
                "parentNamespaceId": "b38ac8c1-2a5d-44d9-9e04-ea0a6b0d224a"
            },
            {
                "id": "e41f3ed8-b771-4f71-a3cf-687f827f25eb",
                "name": "Line1",
                "parentNamespaceId": "ceab426c-e05d-4e47-9127-5b4042c2d1e6"
            },
            {
                "id": "8b621ef5-df9e-406f-847b-a2d0e95a2c2e",
                "name": "Injection1",
                "parentNamespaceId": "e41f3ed8-b771-4f71-a3cf-687f827f25eb",
                "reference": {
                    "type": "Instance",
                    "name": "Injection1"
                }
            }
        ]
    },
    "network": {
        "groups": [],
        "hubs": []
    }
}

Here are the steps to use the sample project.

  1.  Import Project
    1. Import project to your Intelligence Hub Instance by clicking 'Project' on the left-hand navigation panel.
    2. Select Import Type as "JSON", paste the code above and click 'Import'.
  2. Enable the MQTT Broker
    1. In the left-hand navigation panel, navigate to Manage, and click Settings
    2. Under the MQTT Broker section, select Enabled to turn on the Intelligence Hub internal broker then press Save which is located in the upper righthand corner of the page.
      1. By default, ports 1885 and 1886 are defined on the Intelligence Hub broker.  If you choose to change these ports, you must also update the ports on the Tutorial_MQTT connection.
  3. Read Namespace
    1. In the left-hand navigation panel, navigate to Manage, and click Namespaces
    2. Click on "Site1" text under Namespaces.   This should expand the hierarchy to show "Area1".
    3. Click on "Area1" to expand to show "Line1"
    4. Click on "Line1" to expand to show "Injection1"
    5. Press Read Node under Test Read to read the Namespace.   You should get a similar result.
    6. {
          "Site1": {
              "Area1": {
                  "Line1": {
                      "Injection1": {
                          "Pressure": 12.25,
                          "Temperature": 70.1,
                          "Cycles": 17.7
                      }
                  }
              }
          }
      }

       

  4. Open Pipeline
      1. In the left-hand navigation panel, navigate to Manage, and click Pipelines
      2. Click on the "NamespaceNodeReadsToUNS" pipeline.  This will open the pipeline.
          1. Click on the PolledTrigger stage.  This opens the properties on this stage and show that the state is run every 10 seconds. 
          2. Click on the Start stage (stage with a Play icon).  This opens the properties on this stage and show statistics on the pipeline.
          3. Click on the SmartQuery stage.  This opens the properties on this stage and the properties used in defining the Smart Query.
            1. From - This property contains the path filter.
            2. Where - This property filters the list of nodes.
            3. Select - This is the list of values that will be outputted in the query.
            4. Path Delimiter- This is the delimiter between each node in the path.
            5. As - Specifies whether result is a list or a hierarchy.
          4. Click on the Flatten stage.  This opens the properties on this stage.   The delimiter property defines the character used to flatten the hierarchy.
          5. Click on the Breakup stage.  This opens the properties on this stage.  The Breakup Type defines how the breakup will be done. 
          6. Click on the ToUNS.  This opens the properties on this WriteNew stage.  The Topic is set to the breakUpName that is defined in the metadata.
        1. View UNSClient
          1. In the left-hand navigation panel, navigate to Tool, and click UNSClient
          2. Make sure the Connection is set as "Tutorial_MQTT" and press Connect.
          3. See the Namespace strucuture under the UNS topic.   Select the topics under Inspection1 to see the current values being populated by the pipeline from OPC UA.
            UNSTopicFromNS

           

           

          Other Related Material: