Tutorial: Models and Instances

What Does This Tutorial Cover?

This tutorial will walk you through the basics of working with Models & Instances. Modeling is fundamental to HighByte Intelligence Hub. Modeling allows for pulling data from many discrete data sources (e.g., OPC UA, SQL, REST) and combining that data into useful information in a common format. Upstream data consumers can then rely on standardized information regardless of the underlying data sources, which can differ greatly per location. The Intelligence Hub breaks modeling into Models and Instances.

When building a new Model, it’s important to consider the use case problem statement and data requirements to ensure that the consumer(s) are successful. This tutorial use case is to develop a standardized format for all makes and models of our CNC devices. We also want to incorporate data from our CMMS system to the consuming endpoints as it will critical to display within our visualization system.

  • Tutorial Prerequisites
  • Tutorial Preparation
  • Tutorial Instructions
  • Tutorial Summary

Tutorial Prerequisites

  1. You have completed the initial Installation of the Intelligence Hub
  2. You have applied your Intelligence Hub license to your environment
  3. It is recommended to read the Getting Started Series before completing this tutorial exercise
  4. It is recommended to complete “Tutorial: Connections”

Tutorial Preparation

  1. Enable Intelligence Hub MQTT broker

    • In the left-hand navigation panel, navigate to Manage, and click Settings
    • Under the MQTT Broker section enable the broker, if ports 1885 and 1886 are being utilized on your Intelligence Hub server, update to ports of your choosing, otherwise accept the defaults and click save
  2. Import the required Components

    • In the left-hand navigation panel, navigate to Manage, and click Project
    • Within the Import screen, ensure Full Project is off (otherwise your existing project will be overwritten
    • Change the Import Type to JSON and paste in the following with the Project box and click the import button
{
	"productInfo": {
		"company": "HighByte",
		"product": "IntelligenceHub",
		"version": "3.2.0",
		"build": "2023.8.24.982",
		"stage": "Alpha"
	},
	"project": {
		"version": 5,
		"connections": [
			{
				"name": "Tutorial_CMMS_servicelogs",
				"uri": "jdbc.sqlserver://52.10.6.4:1433",
				"tags": [
					"Share"
				],
				"writes": {
					"flattenModeledValues": false
				},
				"storeForward": {
					"enabled": false,
					"maxEntries": 100,
					"waitOnFailureInterval": {
						"duration": 1,
						"units": "Seconds"
					}
				},
				"settings": {
					"database": "serviceinfo",
					"username": "highbyte"
				}
			},
			{
				"name": "Tutorial_MQTT",
				"uri": "mqtt://0.0.0.0:1885",
				"tags": [
					"Share"
				],
				"writes": {
					"flattenModeledValues": false
				},
				"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": [
					"Share"
				],
				"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": "Tutorial_All_Assets",
				"connection": "Tutorial_CMMS_servicelogs",
				"type": "jdbc.sqlserver",
				"qualifier": {
					"query": "select * from [dbo].[cmms_servicelogs]"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_All_Assets_CNC",
				"connection": "Tutorial_CMMS_servicelogs",
				"type": "jdbc.sqlserver",
				"qualifier": {
					"query": "select * from [dbo].[cmms_servicelogs] where [dbo].[cmms_servicelogs].[asset_type] = 'CNC'"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_AirPressure",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.AirPressure",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_AssetID",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.AssetID",
					"type": "Tag",
					"dataType": "String"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_AxisPositionX",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.AxisPositionX",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_AxisPositionY",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.AxisPositionY",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_AxisPositionZ",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.AxisPositionZ",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_CoolantpH",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.CoolantpH",
					"type": "Tag",
					"dataType": "Int16"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_CuttingSpeed",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.CuttingSpeed",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_FaultCode",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.FaultCode",
					"type": "Tag",
					"dataType": "Int16"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_FeedRate",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.FeedRate",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_MachineState",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.MachineState",
					"type": "Tag",
					"dataType": "Int16"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_MachineTemperature",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.MachineTemperature",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_PartProgramID",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.PartProgramID",
					"type": "Tag",
					"dataType": "String"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_PowerCurrent",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.PowerCurrent",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_PowerCurrentXAxis",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.PowerCurrentXAxis",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_PowerCurrentYAxis",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.PowerCurrentYAxis",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_PowerCurrentZAxis",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.PowerCurrentZAxis",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_ProductionCount",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.ProductionCount",
					"type": "Tag",
					"dataType": "Int16"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_RejectCount",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.RejectCount",
					"type": "Tag",
					"dataType": "Int16"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_SpindleLoad",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.SpindleLoad",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_SpindleSpeed",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.SpindleSpeed",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_SpindleTemperature",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.SpindleTemperature",
					"type": "Tag",
					"dataType": "Real32"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_StateDescription",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.StateDescription",
					"type": "Tag",
					"dataType": "String"
				},
				"cacheLifetime": {
					"enabled": false
				}
			},
			{
				"name": "Tutorial_CNC_Fanuc_1001_ToolID",
				"connection": "Tutorial_OPC_UA",
				"type": "opc.tcp",
				"qualifier": {
					"namespaceIndex": 2,
					"identifierType": "String",
					"identifier": "Tutorial.CNC_Fanuc_1001.ToolID",
					"type": "Tag",
					"dataType": "String"
				},
				"cacheLifetime": {
					"enabled": false
				}
			}
		],
		"outputs": [
			{
				"name": "Tutorial_Model_Complex",
				"connection": "Tutorial_MQTT",
				"type": "mqtt",
				"qualifier": {
					"qos": 0,
					"namedRoot": false,
					"breakupArrays": false,
					"topic": "Tutorial/Model/Complex",
					"retained": false
				}
			},
			{
				"name": "Tutorial_Model_Simple",
				"connection": "Tutorial_MQTT",
				"type": "mqtt",
				"qualifier": {
					"qos": 0,
					"namedRoot": false,
					"breakupArrays": false,
					"topic": "Tutorial/Model/Simple",
					"retained": false
				}
			}
		],
		"modeling": {
			"models": [
				{
					"name": "CNC_Asset_Info",
					"tags": [
						"Share"
					],
					"attributes": [
						{
							"name": "AssetID",
							"type": "String",
							"array": false,
							"required": true
						},
						{
							"name": "Temperature",
							"type": "Any",
							"array": false,
							"required": true
						},
						{
							"name": "CuttingSpeed",
							"type": "Any",
							"array": false,
							"required": true
						},
						{
							"name": "PowerCurrent",
							"type": "Any",
							"array": false,
							"required": true
						},
						{
							"name": "FeedRate",
							"type": "Any",
							"array": false,
							"required": true
						}
					]
				}
			],
			"instances": []
		},
		"flows": [],
		"conditions": [],
		"functions": [],
		"tags": [],
		"pipelines": []
	},
	"network": {
		"groups": [],
		"hubs": []
	}
}
  1. Update the imported Connections as required

    • Navigate to Configure and click Connections, Click Tutorial_MQTT and Update the MQTT settings as required based on the prior preparation step #1
    • Navigate to Configure and click Connections, Click “Tutorial_CMMS_servicelogs” and type the following within the password field and click “Save”
                          password
  1. Setup UNS Client

    • In the left-hand navigation panel, navigate to Tools and right click UNS client and open Link in New Tab
    • Enter login information
    • For Connection select Tutorial_MQTT
    • For Subscribed Topics remove the default wildcard entry # and Subscribe to Topic “Tutorial/#”
    • Click Add
    • Click Connect and confirm UNS client says “Connected to Tutorial_MQTT”
    • Return to the previous tab

Tutorial Instructions

Consider the Use Case and design your Model with re-usability in mind, we know we have 2 different sources of data: Real time data and transactional data. We also know we will have different needs of the data. We’ll account for these considerations in the following Instructions

  1. Login to your Intelligence Hub environment

  2. Review source data

    • Navigate to Connections
    • Select Tutorial_OPC_UA
    • Navigate to Inputs and review the imported Tutorial_CNC_Fanuc_#### tags
    • Navigate to Connections
    • Select Tutorial_CMMS_servicelogs
    • Navigate to Inputs
    • Select Tutorial_All_Assets_CNC
    • Click Test Input and review the source data
  3. Review Imported Model

    • Navigate to Models

    • Select CNC_Asset_Info

    • Review the existing Attributes, we can see the AssetID is being set as a “String” type and all 5 attributes are required

      • NOTE: Required attributes will ensure these attributes always have values when outputted
  4. Create an Instance from the CNC_Asset_Info Model

    • From the CNC_Asset_Info, click Actions, Create Instance

    • From the New Instance Details screen, accept the defaults and click next

    • From the Model screen, accept the default Model and click next

    • Within the Attributes screen, set your References Panel type to Input

    • Within the References Panel, set Connections to Tutorial_OPC_UA

    • From the References Panel, map the following attributes to the Model Attribute Expression box:

      AssetID – Tutorial_CNC_Fanuc_1001_AssetID
      Temperature - Tutorial_CNC_Fanuc_1001_MachineTemperature
      CuttingSpeed - Tutorial_CNC_Fanuc_1001_CuttingSpeed
      PowerCurrent - Tutorial_CNC_Fanuc_1001_PowerCurrent
      FeedRate - Tutorial_CNC_Fanuc_1001_FeedRate
    • Click submit

    • Click Test Instance to review the results

  1. Add new values to the existing Model

    • Navigate to CNC_Asset_Info model by clicking the hyperlink within your Instance
    • Click New Attribute three times
    • Enter “Temperature_UOM” for the name of the first new attribute
    • Enter “LastServiceDate” for the name of the second new attribute
    • Enter “LastServiceNotes” for the name of the third new attribute
    • Leave the attribute type and required as is
    • Map the new Temperature_UOM attribute to Attribute order 3 (below the Temperature attribute) so it’s inline with the Temperature reading
    • Click save

  1. Add new attribute values to the existing Instance

    • From the CNC_Asset_Info, click Usage and click CNC_Asset_Info_Instance

    • For the Temperature_UOM attribute, Let’s assume we do not have a source input to provide a UOM, using the Default field enter “F”

    • Within the Attributes screen, set your References Panel type to Input

    • Within the References Panel, set Connections to Tutorial_CMMS_servicelogs

    • Expand Tutorial_All_Assets_CNC, also expand object 0

    • From the References Panel, map the following attributes to the Model Attribute

      LastServiceDate – {{Connection.Tutorial_CMMS_servicelogs.Reference_CNC_Assets}}[0].date
      LastServiceNotes – {{Connection.Tutorial_CMMS_servicelogs.Reference_CNC_Assets}}[0].notes
    • Click save

    • Click Test Instance to review the results

  1. Create a Flow from the Instance to UNS

    • From the CNC_Asset_Info_Instance, click actions and create Flow
    • From the New Flow Details screen, accept the defaults and click next
    • From the New Flow Sources & Targets screen, set your Reference Type to Output, set Connections to Tutorial_MQTT and map Tutorial_Model_Simple to the Targets panel
    • Click next
    • From the New Flow Settings screen, change the interval to 10 seconds
    • Click enabled and Submit
    • Navigate to your UNS Client to review the results, you should notice our metrics from Tutorial_OPC_UA, as well as the _timestamp are updated every 10 seconds
  2. Create a new complex Model

    • Navigate to Models

    • Click New Model

    • From the New Model Details screen, enter “Enterprise_CNC_Model” as the name and click next

    • From the New Model Attributes screen, click New Attribute and add the following:

      • Enterprise
      • Site
      • Area
      • Line
      • Values
      • ProgramInfo
    • For the Values attribute type, select CNC_Asset_Info model from the drop down menu, this will nest the existing Model from the previous steps as a child model

    • For the ProgramInfo attribute type, select New Model, enter ProgramInfo_Model as the name and add the following attributes:

      • ProgramID
      • ToolID
      • MachineState
      • RejectCount
    • Click Submit and take note this process just created two new Models

  1. Create an Instance of Enterprise_CNC_Model

    • From the Enterprise_CNC_Model, click actions, Create Instance

    • From the New Instance Details screen, accept the defaults and click Next

    • From the New Instance Model screen, accept the defaults and click Next

    • From the New Instance Attribute screen, add the following for default values for your Enterprise values:

      Enterprise: Tutorial
      Site: Site1
      Area: Area1
      Line: Line1
    • For the Values attribute, click the select drop-down and select CNC_Asset_Info_Instance, this reuses our existing Instance from the previous steps

    • For the ProgramInfo attribute, click the select drop-down and select Create ProgramInfo_Model

    • From the References Panel, set your type to Input, Connection to Tutorial_OPC_UA and map the following attributes to the ProgramInfo attribute expressions

      ProgramID - Tutorial_CNC_Fanuc_1001_PartProgramID
      ToolID - Tutorial_CNC_Fanuc_1001_ToolID
      MachineState - Tutorial_CNC_Fanuc_1001_MachineState
      RejectCount - Tutorial_CNC_Fanuc_1001_RejectionCount
    • Click save

      • Take note this created a new child Instance
    • Click Test Instance to review the results

  1. Use a JavaScript expression to manipulate an attribute

    • Let’s assume that we have an Enterprise initiative to standardize our temperature UOM to Celsius, we can utilize Intelligence Hub’s expressions to handle this UOM change. Instance Expressions support the JavaScript language, let’s incorporate a basic example of this to our use case

    • From the Enterprise_CNC_Model_Instance, expand the Value attribute’s nested CNC_Asset_Info_Instance

    • Update the Temperature attribute to the following

      • Add () around the whole expression

      • After MachineTemperature}}. add “-32”

      • After the closing ), add “*.5556”

        Before: {{Connection.Tutorial_OPC_UA.Tutorial_CNC_Fanuc_1001_MachineTemperature}} 
        
        After: ({{Connection.Tutorial_OPC_UA.Tutorial_CNC_Fanuc_1001_MachineTemperature}}-32)*.5556
    • Within the default field, change the Temperature_UOM to “C”

    • Click save and Test Instance

      • NOTE: This updated the nested CNC_Asset_Info_Instance; this could effect other use cases depending if this child instance is being utilized elsewhere
  2. Output complex Instance to UNS

    • From the Enterprise_CNC_Model_Instance, click Actions, Create Flow

    • From the New Flow Details screen, accept the defaults and click next

    • From the New Flow Sources & Targets screen, set your Reference Type to Output, set Connections to Tutorial_MQTT and map Tutorial_Model_Complex to the Targets panel

    • Click next

    • From the New Flow Settings screen, change the interval to 10 seconds, click enabled and Submit

    • Navigate to your UNS client and review the results

      • Take note - Within the “Simple” topic, we can see the UOM change was reflected in the original CNC_Asset_Info use case.

Tutorial Summary

This exercise focused on the basics of working with Models and Instances. You should be more familiar with how Intelligence Hub Models can help solve real problems around standardization and contextualization with your organization. We covered how to build complex models that involve nesting child models with a parent model. Finally, we covered how to utilize JavaScript expressions to our advantage to solve real problems such as unit of measure conversions, safely at the abstraction layer Intelligence Hub provides.