node-red-contrib-iiot-opcua
Version:
An Industrial IoT OPC UA toolbox contribution package for Node-RED based on node-opcua.
350 lines • 14.8 kB
JSON
[
{
"id": "9e98528a1a8ac073",
"type": "tab",
"label": "IIoT OPC UA Flex Server",
"disabled": false,
"info": ""
},
{
"id": "9964c6a855d14944",
"type": "OPCUA-IIoT-Server-Command",
"z": "9e98528a1a8ac073",
"commandtype": "restart",
"nodeId": "",
"name": "warm restart with defaults",
"x": 330,
"y": 140,
"wires": [
[
"46ba6b0a0309a386"
]
]
},
{
"id": "bcc7e7a7012979b1",
"type": "OPCUA-IIoT-Inject",
"z": "9e98528a1a8ac073",
"injectType": "inject",
"payload": "",
"payloadType": "date",
"topic": "",
"repeat": "",
"crontab": "",
"once": false,
"startDelay": "",
"name": "",
"addressSpaceItems": [],
"x": 140,
"y": 140,
"wires": [
[
"9964c6a855d14944"
]
]
},
{
"id": "96d5b418c0761ba8",
"type": "debug",
"z": "9e98528a1a8ac073",
"name": "",
"active": false,
"console": "false",
"complete": "false",
"x": 690,
"y": 140,
"wires": []
},
{
"id": "46ba6b0a0309a386",
"type": "OPCUA-IIoT-Flex-Server",
"z": "9e98528a1a8ac073",
"port": "55380",
"endpoint": "",
"acceptExternalCommands": true,
"maxAllowedSessionNumber": "",
"maxConnectionsPerEndpoint": "",
"maxAllowedSubscriptionNumber": "",
"alternateHostname": "",
"name": "",
"showStatusActivities": false,
"showErrors": true,
"allowAnonymous": true,
"individualCerts": false,
"isAuditing": false,
"serverDiscovery": true,
"users": [],
"xmlsets": [],
"publicCertificateFile": "",
"privateCertificateFile": "",
"registerServerMethod": "1",
"discoveryServerEndpointUrl": "",
"capabilitiesForMDNS": "",
"maxNodesPerRead": "",
"maxNodesPerBrowse": "",
"delayToClose": "",
"addressSpaceScript": "function constructAlarmAddressSpace(server, addressSpace, eventObjects, done) {\n // server = the created node-opcua server\n // addressSpace = script placeholder\n // eventObjects = to hold event variables in memory from this script\n \n // internal global sandbox objects are \n // node = node of the flex server, \n // coreServer = core iiot server object for debug and access to nodeOPCUA,\n // and scriptObjects to hold variables and functions\n const LocalizedText = opcua.LocalizedText\n const namespace = addressSpace.getOwnNamespace()\n\n coreServer.internalDebugLog('init dynamic address space')\n node.warn('construct new address space for OPC UA')\n \n // from here - see the node-opcua docs how to build address sapces\n let tanks = namespace.addObject({\n browseName: 'Tanks',\n description: 'The Object representing some tanks',\n organizedBy: addressSpace.rootFolder.objects,\n notifierOf: addressSpace.rootFolder.objects.server\n })\n \n let oilTankLevel = namespace.addVariable({\n browseName: 'OilTankLevel',\n displayName: [\n new LocalizedText({text: 'Oil Tank Level', locale: 'en-US'}),\n new LocalizedText({text: 'Öl Tank Füllstand', locale: 'de-DE'})\n ],\n description: 'Fill level in percentage (0% to 100%) of the oil tank',\n propertyOf: tanks,\n dataType: 'Double',\n eventSourceOf: tanks\n })\n \n // ---------------------------------------------------------------------------------\n // Let's create a exclusive Limit Alarm that automatically raise itself\n // when the tank level is out of limit\n // ---------------------------------------------------------------------------------\n let exclusiveLimitAlarmType = addressSpace.findEventType('ExclusiveLimitAlarmType')\n \n let oilTankLevelCondition = namespace.instantiateExclusiveLimitAlarm(exclusiveLimitAlarmType, {\n componentOf: tanks,\n conditionSource: oilTankLevel,\n browseName: 'OilTankLevelCondition',\n displayName: [\n new LocalizedText({text: 'Oil Tank Level Condition', locale: 'en-US'}),\n new LocalizedText({text: 'Öl Tank Füllstand Bedingung', locale: 'de-DE'})\n ],\n description: 'ExclusiveLimitAlarmType Condition',\n conditionName: 'OilLevelCondition',\n optionals: [\n 'ConfirmedState', 'Confirm' // confirm state and confirm Method\n ],\n inputNode: oilTankLevel, // the letiable that will be monitored for change\n highHighLimit: 0.9,\n highLimit: 0.8,\n lowLimit: 0.2\n })\n \n // --------------------------------------------------------------\n // Let's create a second letiable with no Exclusive alarm\n // --------------------------------------------------------------\n let gasTankLevel = namespace.addVariable({\n browseName: 'GasTankLevel',\n displayName: [\n new LocalizedText({text: 'Gas Tank Level', locale: 'en-US'}),\n new LocalizedText({text: 'Gas Tank Füllstand', locale: 'de-DE'})\n ],\n description: 'Fill level in percentage (0% to 100%) of the gas tank',\n propertyOf: tanks,\n dataType: 'Double',\n eventSourceOf: tanks\n })\n \n // byte variable with value\n if(scriptObjects.oilTankNumber === undefined || scriptObjects.oilTankNumber === null) {\n scriptObjects.oilTankNumber = 100\n }\n \n let oilTankNumber = namespace.addVariable({\n nodeId: \"s=OilTankNumber\",\n browseName: 'OilTankNumber',\n displayName: [\n new LocalizedText({text: 'Oil Tank Number', locale: 'en-US'}),\n new LocalizedText({text: 'Öl Tank Nummer', locale: 'de-DE'})\n ],\n description: 'Number of the oil tank',\n propertyOf: tanks,\n dataType: 'Byte',\n value: {\n get: function () {\n return new opcua.Variant({\n dataType: 'Byte',\n value: scriptObjects.oilTankNumber\n })\n },\n set: function (variant) {\n scriptObjects.oilTankNumber = variant.value\n return opcua.StatusCodes.Good\n }\n }\n })\n \n let nonExclusiveLimitAlarmType = addressSpace.findEventType('NonExclusiveLimitAlarmType')\n \n let gasTankLevelCondition = namespace.instantiateNonExclusiveLimitAlarm(nonExclusiveLimitAlarmType, {\n componentOf: tanks,\n conditionSource: gasTankLevel,\n browseName: 'GasTankLevelCondition',\n displayName: [\n new LocalizedText({text: 'Gas Tank Level Condition', locale: 'en-US'}),\n new LocalizedText({text: 'Gas Tank Füllstand Bedingung', locale: 'de-DE'})\n ],\n description: 'NonExclusiveLimitAlarmType Condition',\n conditionName: 'GasLevelCondition',\n optionals: [\n 'ConfirmedState', 'Confirm' // confirm state and confirm Method\n ],\n inputNode: gasTankLevel, // the letiable that will be monitored for change\n highHighLimit: 0.9,\n highLimit: 0.8,\n lowLimit: 0.2\n })\n \n // variable with value\n if(scriptObjects.testReadWrite === undefined || scriptObjects.testReadWrite === null) {\n scriptObjects.testReadWrite = 1000.0\n }\n \n let myVariables = namespace.addObject({\n browseName: 'MyVariables',\n description: 'The Object representing some variables',\n organizedBy: addressSpace.rootFolder.objects,\n notifierOf: addressSpace.rootFolder.objects.server\n })\n \n if(coreServer.core) {\n namespace.addVariable({\n componentOf: myVariables,\n nodeId: 'ns=1;s=TestReadWrite',\n browseName: 'TestReadWrite',\n displayName: [\n new LocalizedText({text: 'Test Read and Write', locale: 'en-US'}),\n new LocalizedText({text: 'Test Lesen Schreiben', locale: 'de-DE'})\n ],\n dataType: 'Double',\n value: {\n get: function () {\n return new opcua.Variant({\n dataType: 'Double',\n value: scriptObjects.testReadWrite\n })\n },\n set: function (variant) {\n scriptObjects.testReadWrite = parseFloat(variant.value)\n return opcua.StatusCodes.Good\n }\n }\n \n })\n \n let memoryVariable = namespace.addVariable({\n componentOf: myVariables,\n nodeId: 'ns=1;s=free_memory',\n browseName: 'FreeMemory',\n displayName: [\n new LocalizedText({text: 'Free Memory', locale: 'en-US'}),\n new LocalizedText({text: 'ungenutzer RAM', locale: 'de-DE'})\n ],\n dataType: 'Double',\n \n value: {\n get: function () {\n return new opcua.Variant({\n dataType: 'Double',\n value: coreServer.core.availableMemory()\n })\n }\n }\n })\n addressSpace.installHistoricalDataNode(memoryVariable)\n \n }\n\n // hold event objects in memory \n eventObjects.oilTankLevel = oilTankLevel\n eventObjects.oilTankLevelCondition = oilTankLevelCondition\n \n eventObjects.gasTankLevel = gasTankLevel\n eventObjects.gasTankLevelCondition = gasTankLevelCondition\n \n done()\n}",
"x": 530,
"y": 140,
"wires": [
[
"96d5b418c0761ba8"
]
]
},
{
"id": "895e562a824a0479",
"type": "catch",
"z": "9e98528a1a8ac073",
"name": "",
"scope": null,
"x": 140,
"y": 80,
"wires": [
[
"63360aecbe74d5b6"
]
]
},
{
"id": "63360aecbe74d5b6",
"type": "debug",
"z": "9e98528a1a8ac073",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"targetType": "full",
"statusVal": "",
"statusType": "auto",
"x": 290,
"y": 80,
"wires": []
},
{
"id": "eacec11f14c4433f",
"type": "OPCUA-IIoT-Response",
"z": "9e98528a1a8ac073",
"name": "",
"compressStructure": true,
"showStatusActivities": false,
"showErrors": false,
"activateFilters": false,
"filters": [],
"x": 610,
"y": 300,
"wires": [
[
"2399803ef436a77a"
]
]
},
{
"id": "d1773b9e76702806",
"type": "debug",
"z": "9e98528a1a8ac073",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"x": 450,
"y": 240,
"wires": []
},
{
"id": "93ba75eb6c9818bc",
"type": "OPCUA-IIoT-Write",
"z": "9e98528a1a8ac073",
"connector": "77fdc29e.3c49ec",
"name": "",
"justValue": false,
"showStatusActivities": false,
"showErrors": true,
"x": 450,
"y": 300,
"wires": [
[
"eacec11f14c4433f"
]
]
},
{
"id": "524dd108ec40ea9f",
"type": "OPCUA-IIoT-Inject",
"z": "9e98528a1a8ac073",
"injectType": "write",
"payload": "",
"payloadType": "date",
"topic": "",
"repeat": "",
"crontab": "",
"once": true,
"startDelay": "",
"name": "inject",
"addressSpaceItems": [
{
"name": "",
"nodeId": "ns=1;s=OilTankNumber",
"datatypeName": "Byte"
},
{
"name": "",
"nodeId": "ns=1;s=TestReadWrite",
"datatypeName": "Double"
}
],
"x": 130,
"y": 300,
"wires": [
[
"b8470569c6b35699"
]
]
},
{
"id": "b8470569c6b35699",
"type": "function",
"z": "9e98528a1a8ac073",
"name": "values to",
"func": "let uint8 = new Uint8Array([2])\nmsg.valuesToWrite = [uint8[0], 20.33];\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 280,
"y": 300,
"wires": [
[
"93ba75eb6c9818bc",
"d1773b9e76702806"
]
]
},
{
"id": "48e3bf891e6340b4",
"type": "OPCUA-IIoT-Inject",
"z": "9e98528a1a8ac073",
"injectType": "write",
"payload": "",
"payloadType": "date",
"topic": "",
"repeat": "",
"crontab": "",
"once": false,
"startDelay": "",
"name": "inject",
"addressSpaceItems": [
{
"name": "",
"nodeId": "ns=1;s=OilTankNumber",
"datatypeName": "Byte"
},
{
"name": "",
"nodeId": "ns=1;s=TestReadWrite",
"datatypeName": "Double"
}
],
"x": 130,
"y": 380,
"wires": [
[
"1cdb7115d3474b87"
]
]
},
{
"id": "1cdb7115d3474b87",
"type": "OPCUA-IIoT-Read",
"z": "9e98528a1a8ac073",
"attributeId": "13",
"maxAge": 1,
"depth": 1,
"connector": "77fdc29e.3c49ec",
"name": "",
"justValue": true,
"showStatusActivities": false,
"showErrors": false,
"parseStrings": false,
"historyDays": 1,
"x": 290,
"y": 380,
"wires": [
[
"735c8353fde5aa91"
]
]
},
{
"id": "4dc62287dda5244e",
"type": "debug",
"z": "9e98528a1a8ac073",
"name": "",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "true",
"x": 630,
"y": 380,
"wires": []
},
{
"id": "2399803ef436a77a",
"type": "debug",
"z": "9e98528a1a8ac073",
"name": "",
"active": false,
"console": "false",
"complete": "false",
"x": 770,
"y": 300,
"wires": []
},
{
"id": "735c8353fde5aa91",
"type": "OPCUA-IIoT-Response",
"z": "9e98528a1a8ac073",
"name": "",
"compressStructure": true,
"showStatusActivities": false,
"showErrors": false,
"activateUnsetFilter": false,
"activateFilters": false,
"negateFilter": false,
"filters": [],
"x": 470,
"y": 380,
"wires": [
[
"4dc62287dda5244e"
]
]
},
{
"id": "77fdc29e.3c49ec",
"type": "OPCUA-IIoT-Connector",
"discoveryUrl": "",
"endpoint": "opc.tcp://localhost:55380",
"keepSessionAlive": true,
"loginEnabled": false,
"securityPolicy": "None",
"securityMode": "None",
"name": "LOCAL FLEX 80",
"showErrors": true,
"publicCertificateFile": "",
"privateKeyFile": "",
"defaultSecureTokenLifetime": "",
"endpointMustExist": false,
"autoSelectRightEndpoint": false,
"strategyMaxRetry": "",
"strategyInitialDelay": "",
"strategyMaxDelay": "",
"strategyRandomisationFactor": "",
"requestedSessionTimeout": "",
"connectionStartDelay": "",
"reconnectDelay": ""
}
]