[
  {
    "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": ""
  }
]