Skip to content

Commit 45b79e4

Browse files
committed
Include further updates from SME
1 parent 49fe19b commit 45b79e4

File tree

1 file changed

+79
-68
lines changed

1 file changed

+79
-68
lines changed

articles/iot/tutorial-iot-industrial-solution-architecture.md

Lines changed: 79 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -61,63 +61,6 @@ The following table describes the key components in this solution:
6161
> [!NOTE]
6262
> In a real-world deployment, something as critical as opening a pressure relief valve would be done on-premises. This is just a simple example of how to achieve the digital feedback loop.
6363
64-
## UA Cloud Library
65-
66-
To read OPC UA Information Models directly from Azure Data Explorer, you can import the OPC UA nodes defined in an OPC UA Information Model into a table. You can use the imported information for lookup of more metadata within queries.
67-
68-
First, configure an Azure Data Explorer callout policy for the UA Cloud Library by running the following query on your Azure Data Explorer cluster. Before you start, make sure you're a member of the **AllDatabasesAdmin** role in the cluster, which you can configure in the Azure portal by navigating to the **Permissions** page for your Azure Data Explorer cluster.
69-
70-
```kql
71-
.alter cluster policy callout @'[{"CalloutType": "webapi","CalloutUriRegex": "uacloudlibrary.opcfoundation.org","CanCall": true}]'
72-
```
73-
74-
Then, run the following Azure Data Explorer query from the Azure portal. In the query:
75-
76-
- Replace `<INFORMATION_MODEL_IDENTIFIER_FROM_THE_UA_CLOUD_LIBRARY>` with the unique ID of the Information Model you want to import from the UA Cloud Library. You can find this ID in the URL of the Information Model's page in the UA Cloud Library. For example, the ID of the station nodeset that this tutorial uses is `1627266626`.
77-
- Replace `<HASHED_CLOUD_LIBRARY_CREDENTIALS>` with a basic authorization header has of your UA Cloud Library credentials. Use a tool such as https://www.debugbear.com/basic-auth-header-generator to generate the hash. You can also use the following bash command: `echo -n 'username:password' | base64`.
78-
79-
```kql
80-
let uri='https://uacloudlibrary.opcfoundation.org/infomodel/download/<INFORMATION_MODEL_IDENTIFIER_FROM_THE_UA_CLOUD_LIBRARY>';
81-
let headers=dynamic({'accept':'text/plain', 'Authorization':'Basic <HASHED_CLOUD_LIBRARY_CREDENTIALS>'});
82-
evaluate http_request(uri, headers)
83-
| project title = tostring(ResponseBody.['title']), contributor = tostring(ResponseBody.contributor.name), nodeset = parse_xml(tostring(ResponseBody.nodeset.nodesetXml))
84-
| mv-expand UAVariable=nodeset.UANodeSet.UAVariable
85-
| project-away nodeset
86-
| extend NodeId = UAVariable.['@NodeId'], DisplayName = tostring(UAVariable.DisplayName.['#text']), BrowseName = tostring(UAVariable.['@BrowseName']), DataType = tostring(UAVariable.['@DataType'])
87-
| project-away UAVariable
88-
| take 10000
89-
```
90-
91-
To view a graphical representation of an OPC UA Information Model, you can use the [Kusto Explorer tool](/azure/data-explorer/kusto/tools/kusto-explorer). To render station model, run the following query in Kusto Explorer. For best results, change the `Layout` option to `Grouped` and the `Labels` to `name`:
92-
93-
```kql
94-
let uri='https://uacloudlibrary.opcfoundation.org/infomodel/download/1627266626';
95-
let headers=dynamic({'accept':'text/plain', 'Authorization':'Basic <HASHED_CLOUD_LIBRARY_CREDENTIALS>'});
96-
let variables = evaluate http_request(uri, headers)
97-
| project title = tostring(ResponseBody.['title']), contributor = tostring(ResponseBody.contributor.name), nodeset = parse_xml(tostring(ResponseBody.nodeset.nodesetXml))
98-
| mv-expand UAVariable = nodeset.UANodeSet.UAVariable
99-
| extend NodeId = UAVariable.['@NodeId'], ParentNodeId = UAVariable.['@ParentNodeId'], DisplayName = tostring(UAVariable['DisplayName']), DataType = tostring(UAVariable.['@DataType']), References = tostring(UAVariable.['References'])
100-
| where References !contains "HasModellingRule"
101-
| where DisplayName != "InputArguments"
102-
| project-away nodeset, UAVariable, References;
103-
let objects = evaluate http_request(uri, headers)
104-
| project title = tostring(ResponseBody.['title']), contributor = tostring(ResponseBody.contributor.name), nodeset = parse_xml(tostring(ResponseBody.nodeset.nodesetXml))
105-
| mv-expand UAObject = nodeset.UANodeSet.UAObject
106-
| extend NodeId = UAObject.['@NodeId'], ParentNodeId = UAObject.['@ParentNodeId'], DisplayName = tostring(UAObject['DisplayName']), References = tostring(UAObject.['References'])
107-
| where References !contains "HasModellingRule"
108-
| project-away nodeset, UAObject, References;
109-
let nodes = variables
110-
| project source = tostring(NodeId), target = tostring(ParentNodeId), name = tostring(DisplayName)
111-
| join kind=fullouter (objects
112-
| project source = tostring(NodeId), target = tostring(ParentNodeId), name = tostring(DisplayName)) on source
113-
| project source = coalesce(source, source1), target = coalesce(target, target1), name = coalesce(name, name1);
114-
let edges = nodes;
115-
edges
116-
| make-graph source --> target with nodes on source
117-
```
118-
119-
:::image type="content" source="media/concepts-iot-industrial-solution-architecture/station-graph.png" alt-text="Graph of the station Info Model." lightbox="media/concepts-iot-industrial-solution-architecture/station-graph.png" border="false" :::
120-
12164
## Production line simulation
12265

12366
The solution uses a production line simulation made up of several stations, using the station OPC UA information model, and a simple manufacturing execution system (MES). Both the stations and the MES are containerized for easy deployment.
@@ -151,11 +94,11 @@ The station OPC UA server uses the following OPC UA node IDs for telemetry to th
15194
- i=418 - actual cycle time
15295
- i=434 - pressure
15396

154-
## Digital feedback loop with UA Cloud Commander and UA Cloud Action
97+
### Digital feedback loop with UA Cloud Commander and UA Cloud Action
15598

15699
The solution uses a digital feedback loop to manage the pressure in a simulated station. To implement the feedback loop, the solution triggers a command from the cloud on one of the OPC UA servers in the simulation. The trigger activates when simulated time-series pressure data reaches a certain threshold. You can see the pressure of the assembly machine in the Azure Data Explorer dashboard. The pressure is released at regular intervals for the Seattle production line.
157100

158-
## Install the production line simulation and cloud services
101+
### Install the production line simulation and cloud services
159102

160103
Select the **Deploy** button to deploy all required resources to your Azure subscription:
161104

@@ -180,7 +123,7 @@ curl -sfL https://get.k3s.io | sh
180123

181124
Your VM is now ready to run the production line simulation.
182125

183-
## Run the production line simulation
126+
### Run the production line simulation
184127

185128
In the VM, open a Windows command prompt, enter *wsl*, and press **Enter**. Navigate to the `/mnt/c/ManufacturingOntologies-main/Tools/FactorySimulation` directory and run the **StartSimulation** shell script:
186129

@@ -196,10 +139,84 @@ sudo ./StartSimulation.sh "<Your Event Hubs connection string>"
196139
> [!TIP]
197140
> To prevent WSL and K3s from automatically shutting down, keep your WSL command prompt open.
198141
142+
## UA Cloud Library
143+
144+
To read OPC UA Information Models directly from Azure Data Explorer, you can import the OPC UA nodes defined in an OPC UA Information Model into a table. You can use the imported information for lookup of more metadata within queries.
145+
146+
First, configure an Azure Data Explorer callout policy for the UA Cloud Library by running the following query on your Azure Data Explorer cluster. Before you start, make sure you're a member of the **AllDatabasesAdmin** role in the cluster, which you can configure in the Azure portal by navigating to the **Permissions** page for your Azure Data Explorer cluster.
147+
148+
```kql
149+
.alter cluster policy callout @'[{"CalloutType": "webapi","CalloutUriRegex": "uacloudlibrary.opcfoundation.org","CanCall": true}]'
150+
```
151+
152+
Then, run the following Azure Data Explorer query from the Azure portal. In the query:
153+
154+
- Replace `<INFORMATION_MODEL_IDENTIFIER_FROM_THE_UA_CLOUD_LIBRARY>` with the unique ID of the Information Model you want to import from the UA Cloud Library. You can find this ID in the URL of the Information Model's page in the UA Cloud Library. For example, the ID of the station nodeset that this tutorial uses is `1627266626`.
155+
- Replace `<HASHED_CLOUD_LIBRARY_CREDENTIALS>` with a basic authorization header has of your UA Cloud Library credentials. Use a tool such as https://www.debugbear.com/basic-auth-header-generator to generate the hash. You can also use the following bash command: `echo -n 'username:password' | base64`.
156+
157+
```kql
158+
let uri='https://uacloudlibrary.opcfoundation.org/infomodel/download/<INFORMATION_MODEL_IDENTIFIER_FROM_THE_UA_CLOUD_LIBRARY>';
159+
let headers=dynamic({'accept':'text/plain', 'Authorization':'Basic <HASHED_CLOUD_LIBRARY_CREDENTIALS>'});
160+
evaluate http_request(uri, headers)
161+
| project title = tostring(ResponseBody.['title']), contributor = tostring(ResponseBody.contributor.name), nodeset = parse_xml(tostring(ResponseBody.nodeset.nodesetXml))
162+
| mv-expand UAVariable=nodeset.UANodeSet.UAVariable
163+
| project-away nodeset
164+
| extend NodeId = UAVariable.['@NodeId'], DisplayName = tostring(UAVariable.DisplayName.['#text']), BrowseName = tostring(UAVariable.['@BrowseName']), DataType = tostring(UAVariable.['@DataType'])
165+
| project-away UAVariable
166+
| take 10000
167+
```
168+
169+
To view a graphical representation of an OPC UA Information Model, you can use the [Kusto Explorer tool](/azure/data-explorer/kusto/tools/kusto-explorer). To render station model, run the following query in Kusto Explorer. For best results, change the `Layout` option to `Grouped` and the `Labels` to `name`:
170+
171+
```kql
172+
let uri='https://uacloudlibrary.opcfoundation.org/infomodel/download/1627266626';
173+
let headers=dynamic({'accept':'text/plain', 'Authorization':'Basic <HASHED_CLOUD_LIBRARY_CREDENTIALS>'});
174+
let variables = evaluate http_request(uri, headers)
175+
| project title = tostring(ResponseBody.['title']), contributor = tostring(ResponseBody.contributor.name), nodeset = parse_xml(tostring(ResponseBody.nodeset.nodesetXml))
176+
| mv-expand UAVariable = nodeset.UANodeSet.UAVariable
177+
| extend NodeId = UAVariable.['@NodeId'], ParentNodeId = UAVariable.['@ParentNodeId'], DisplayName = tostring(UAVariable['DisplayName']), DataType = tostring(UAVariable.['@DataType']), References = tostring(UAVariable.['References'])
178+
| where References !contains "HasModellingRule"
179+
| where DisplayName != "InputArguments"
180+
| project-away nodeset, UAVariable, References;
181+
let objects = evaluate http_request(uri, headers)
182+
| project title = tostring(ResponseBody.['title']), contributor = tostring(ResponseBody.contributor.name), nodeset = parse_xml(tostring(ResponseBody.nodeset.nodesetXml))
183+
| mv-expand UAObject = nodeset.UANodeSet.UAObject
184+
| extend NodeId = UAObject.['@NodeId'], ParentNodeId = UAObject.['@ParentNodeId'], DisplayName = tostring(UAObject['DisplayName']), References = tostring(UAObject.['References'])
185+
| where References !contains "HasModellingRule"
186+
| project-away nodeset, UAObject, References;
187+
let nodes = variables
188+
| project source = tostring(NodeId), target = tostring(ParentNodeId), name = tostring(DisplayName)
189+
| join kind=fullouter (objects
190+
| project source = tostring(NodeId), target = tostring(ParentNodeId), name = tostring(DisplayName)) on source
191+
| project source = coalesce(source, source1), target = coalesce(target, target1), name = coalesce(name, name1);
192+
let edges = nodes;
193+
edges
194+
| make-graph source --> target with nodes on source
195+
```
196+
197+
:::image type="content" source="media/concepts-iot-industrial-solution-architecture/station-graph.png" alt-text="Graph of the station Info Model." lightbox="media/concepts-iot-industrial-solution-architecture/station-graph.png" border="false" :::
198+
199199
## Deploy Azure IoT Operations on the edge
200200

201201
Before you deploy, confirm that you started the production line simulation. Then, follow these steps in [Azure IoT Operations deployment details](/azure/iot-operations/deploy-iot-ops/overview-deploy).
202202

203+
You can use VM you deployed earlier to run the production line simulation to deploy Azure IoT Operations.
204+
205+
### Configure your Azure IoT Operations deployment
206+
207+
You can configure your Azure IoT Operations deployment by using the [operations experience](https://iotoperations.azure.com/) web UI. Add the asset endpoints, assets and data flows to route and process the data from the production line simulation.
208+
209+
<!-- TODO: Complete this section with details of require resources including:
210+
211+
opc.tcp://assembly.munich/
212+
opc.tcp://test.munich/
213+
opc.tcp://packaging.munich/
214+
opc.tcp://assembly.seattle/
215+
opc.tcp://test.seattle/
216+
opc.tcp://packaging.seattle/
217+
218+
-->
219+
203220
## Use cases condition monitoring, OEE calculation, anomaly detection, and predictions in Azure Data Explorer
204221

205222
To learn how to create no-code dashboards for condition monitoring, yield or maintenance predictions, or anomaly detection, see the [Azure Data Explorer documentation](/azure/synapse-analytics/data-explorer/data-explorer-overview). There's also a [sample dashboard](https://github.com/digitaltwinconsortium/ManufacturingOntologies/blob/main/Tools/ADXQueries/dashboard-ontologies.json) you can deploy. To learn how to deploy a dashboard, see [Visualize data with Azure Data Explorer dashboards > create from file](/azure/data-explorer/azure-data-explorer-dashboards#to-create-new-dashboard-from-a-file). After you import the dashboard, update its data source. Specify the HTTPS endpoint of your Azure Data Explorer server cluster in the top-right-hand corner of the dashboard. The HTTPS endpoint looks like: `https://<ADXInstanceName>.<AzureRegion>.kusto.windows.net/`.
@@ -237,7 +254,7 @@ For best results, change the `Layout` option to `Grouped`.
237254

238255
## Use Azure Managed Grafana service
239256

240-
You can also use Azure Managed Grafana to create a dashboard on Azure for the solution described in this article. Use Grafana within manufacturing to create dashboards that display real-time data. The following steps show you enable Grafana on Azure, and create a dashboard with the simulated production line data from Azure Data Explorer and the Azure Digital Twins service.
257+
You can also use Azure Managed Grafana to create a dashboard on Azure for the solution described in this article. Use Grafana within manufacturing to create dashboards that display real-time data. The following steps show you enable Grafana on Azure, and create a dashboard with the simulated production line data from Azure Data Explorer.
241258

242259
The following screenshot shows the dashboard:
243260

@@ -282,17 +299,11 @@ Now you're ready to import the provided sample dashboard.
282299

283300
1. Select the *samplegrafanadashboard.json* file that you downloaded and select **Save**. You get an error on the page, because two variables aren't set yet. Go to the settings page of the dashboard.
284301

285-
1. Select **Variables** and update the two URLs with the URL of your Azure Digital Twins service.
286-
287-
1. Navigate back to the dashboard and hit the refresh button. You should now see data (don't forget to hit the save button on the dashboard).
288-
289-
The location variable on the top of the page is automatically filled with data from Azure Digital Twins (the area nodes from ISA95). Here you can select the different locations and see the different datapoints of every factory.
290-
291302
1. If data isn't showing up in your dashboard, navigate to the individual panels and see if the right data source is selected.
292303

293304
### Configure alerts
294305

295-
Within Grafana, it's also possible to create alerts. In this example, we create a low OEE alert for one of the production lines.
306+
Within Grafana, it's also possible to create alerts. In this example, we create a low OEE alert for one of the production lines.
296307

297308
1. Sign in to your Grafana service, and select **Alert rules** in the menu.
298309

0 commit comments

Comments
 (0)