[
    {
        "id": "c4495043459c465d",
        "type": "subflow",
        "name": "gather & repeat",
        "info": "",
        "category": "",
        "in": [
            {
                "x": 60,
                "y": 80,
                "wires": [
                    {
                        "id": "e97157a71ff3fc6b"
                    }
                ]
            }
        ],
        "out": [
            {
                "x": 380,
                "y": 80,
                "wires": [
                    {
                        "id": "e97157a71ff3fc6b",
                        "port": 0
                    }
                ]
            }
        ],
        "env": [],
        "meta": {},
        "color": "#DDAA99"
    },
    {
        "id": "e97157a71ff3fc6b",
        "type": "function",
        "z": "c4495043459c465d",
        "name": "gather & repeat",
        "func": "/**\n * This function node receives a monitored DataValue from OPC UA.\n * - msg.payload: Contains the value to be parsed into a float.\n * - msg.sourceTimestamp: Contains the value's timestamp in UTC ISO string format.\n *\n * It outputs messages to the first output with the following payload structure:\n * {\n *   timestamp: new Date(msg.sourceTimestamp),\n *   value: String(parseFloat(msg.payload))\n * }\n *\n * OPC UA only sends data when a value changes. To maintain a steady data stream, this node\n * repeats the last received value every second. The first repeated message is sent 1.5 seconds\n * after the initial message, with timestamps incrementing by the 1-second interval.\n *\n * Key constraints:\n * - Timestamps must always progress forward.\n * - Timing is based solely on OPC UA timestamps to avoid clock skew issues.\n * - Maintain only a single active timer to prevent duplicate messages.\n * - Timers are cleared properly upon node redeploy.\n */\n\nconst INTERVAL_MS = 1000; // 1-second interval for repeats\nconst INITIAL_DELAY_MS = 1500; // 1.5-second initial delay\n\n// Initialize context variables\nlet timer = context.get('timer');\nlet lastSentTimestamp = context.get('lastSentTimestamp') || 0;\nlet lastValue = context.get('lastValue');\nlet nextExpectedTimestamp = context.get('nextExpectedTimestamp') || 0;\n\n// Cleanup on node redeploy\nif (!context.get('initialized')) {\n  node.on('close', function() {\n    if (timer) {\n      clearTimeout(timer);\n      context.set('timer', null);\n    }\n  });\n  context.set('initialized', true);\n}\n\nfunction sendAndSchedule(value, sourceTime) {\n  // Send the message immediately\n  node.send({\n    payload: {\n      timestamp: new Date(sourceTime),\n      value: value\n    }\n  });\n\n  // Update context\n  context.set('lastSentTimestamp', sourceTime);\n  context.set('lastValue', value);\n\n  // Calculate the next expected timestamp\n  const nextTs = sourceTime + INITIAL_DELAY_MS + INTERVAL_MS;\n  context.set('nextExpectedTimestamp', nextTs);\n\n  // Schedule the next repetition\n  const delayUntilNextRepeat = INITIAL_DELAY_MS;\n  timer = setTimeout(() => {\n    sendRepeatedValue(value, nextTs, INTERVAL_MS);\n  }, delayUntilNextRepeat);\n  context.set('timer', timer);\n}\n\nfunction sendRepeatedValue(value, nextTs, interval) {\n  // Send the repeated message\n  node.send({\n    payload: {\n      timestamp: new Date(nextTs),\n      value: value\n    }\n  });\n\n  // Schedule the next repetition\n  const nextNextTs = nextTs + interval;\n  context.set('nextExpectedTimestamp', nextNextTs);\n\n  timer = setTimeout(() => {\n    sendRepeatedValue(value, nextNextTs, interval);\n  }, interval);\n  context.set('timer', timer);\n}\n\nif (msg.payload !== undefined && msg.sourceTimestamp) {\n  // Clear any existing timer\n  if (timer) {\n    clearTimeout(timer);\n    context.set('timer', null);\n  }\n\n  try {\n    let sourceTime = new Date(msg.sourceTimestamp).getTime();\n    const value = \"\" + parseFloat(msg.payload);\n\n    // Ensure timestamps always go forward\n    if (lastSentTimestamp && sourceTime <= lastSentTimestamp) {\n      sourceTime = lastSentTimestamp + 1; // Force it to be strictly greater\n    }\n\n    // Send immediately and schedule the first repeat\n    sendAndSchedule(value, sourceTime);\n  } catch (e) {\n    node.error(\"Error processing message: \" + e.message, msg);\n  }\n}",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 220,
        "y": 80,
        "wires": [
            []
        ]
    },
    {
        "id": "8914237e0d8e46c7",
        "type": "tab",
        "label": "Advanced Coffee Machine Example",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "a872632f0795dffe",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "style": {
            "stroke": "#999999",
            "stroke-opacity": "1",
            "fill": "none",
            "fill-opacity": "1",
            "label": true,
            "label-position": "nw",
            "color": "#a4a4a4"
        },
        "nodes": [
            "5163f0e3c15147e2",
            "9ce44b437e2ed4eb",
            "17f15759ea0b4678",
            "ae2a5d89ca13248d",
            "44eeed6c80419b5f",
            "7b496ba60d331069",
            "1c3d6230a57c852c",
            "c172f527ba188866",
            "ae3fe0588bcec600",
            "83de8924a1f6f2a5",
            "807487cd9637d0e1",
            "e181ef3ed9e6dc40",
            "6c7658b34fce0ac3"
        ],
        "x": 1114,
        "y": 119,
        "w": 432,
        "h": 482
    },
    {
        "id": "23e92d93ed23febc",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "name": "Connection status",
        "style": {
            "stroke": "#ffC000",
            "label": true
        },
        "nodes": [
            "dc5e73eb1991eed3",
            "36b2628c69b87d42",
            "f79e321ce9b22631",
            "46d99d7986a03b57",
            "e975667424fe78b7",
            "dcf7ab764b7d2921"
        ],
        "x": 194,
        "y": 939,
        "w": 812,
        "h": 242
    },
    {
        "id": "b07d4a44ddb86adf",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "name": "Heater",
        "style": {
            "label": true
        },
        "nodes": [
            "3e9be0f18116b2c2",
            "2b573431a25e870f",
            "68e0c3653588a07d",
            "d3b1d8b5c05c2b22",
            "07bde3d3f85f2a40",
            "c369c3262a3b57fa",
            "f1f77b6afa4257f0",
            "20844959a8ea715c"
        ],
        "x": 194,
        "y": 699,
        "w": 812,
        "h": 222
    },
    {
        "id": "62d148a7e9f5c520",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "name": "Current State",
        "style": {
            "label": true
        },
        "nodes": [
            "c9717ac11b53672e",
            "3a8c7eb7dc515e34",
            "798535950531337a"
        ],
        "x": 1054,
        "y": 699,
        "w": 632,
        "h": 82
    },
    {
        "id": "11f19caa7b9760b7",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "name": "Pump",
        "style": {
            "label": true
        },
        "nodes": [
            "f3ba9efdc12e30ce",
            "24ab918428d73e5f",
            "b8ba5e020aa48e2a",
            "7619f93616149cdc"
        ],
        "x": 1054,
        "y": 799,
        "w": 632,
        "h": 122
    },
    {
        "id": "f250c8ad248b028d",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "name": "Process Variables",
        "style": {
            "fill": "#ffffbf",
            "label": true
        },
        "nodes": [
            "517edf10f355e464",
            "d22591b8e78ebe7d",
            "29542b83f026fb7b",
            "684238fb58a91415"
        ],
        "x": 188,
        "y": 53,
        "w": 724,
        "h": 634
    },
    {
        "id": "ec1ab7ca9e060d7f",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "style": {
            "stroke": "#999999",
            "stroke-opacity": "1",
            "fill": "none",
            "fill-opacity": "1",
            "label": true,
            "label-position": "nw",
            "color": "#a4a4a4"
        },
        "nodes": [
            "4cecc03d1a64c091",
            "f6b1e7b0df0fa288",
            "0c098347de28a15d",
            "57622c7f24dacef7",
            "237e980896f1a684",
            "e3c1066f3260a1cb",
            "0597a0ffcdab77cd",
            "6008fa16cda462d5",
            "1fca2f6f28cc4828",
            "2857eb76526322a1",
            "ea1957e0718f21fd",
            "03aa8523b17003d7"
        ],
        "x": 1054,
        "y": 939,
        "w": 812,
        "h": 242
    },
    {
        "id": "230bb82688833807",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "name": "Pooling Read",
        "style": {
            "label": true
        },
        "nodes": [
            "d21be93e03b60165",
            "1832b372c56dc715",
            "5f6eeb0fc5228a66",
            "5e50f3a2da48a03b",
            "fe845d4c6aa473d0",
            "50c33de026727ab2",
            "99b27a72cfb58370",
            "829ce0410d7c3b05",
            "1bea16ead1291025"
        ],
        "x": 194,
        "y": 1419,
        "w": 1172,
        "h": 162
    },
    {
        "id": "54277e0eb0f4eddd",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "name": "Display NAMUR Symbol",
        "style": {
            "label": true
        },
        "nodes": [
            "44225cb3561717c6",
            "61237053c6df429d",
            "2456ee93776095bc"
        ],
        "x": 194,
        "y": 1599,
        "w": 712,
        "h": 82
    },
    {
        "id": "665736b8cbeb246d",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "name": "Synopsis",
        "style": {
            "stroke": "#ffbfbf",
            "fill": "#e3f3d3",
            "label": true
        },
        "nodes": [
            "2c7b916b70107153",
            "eeaa86a8240214df",
            "42fea19e7e56afbc",
            "072413d285aeb40e",
            "f64d872549983d6f",
            "143a262a2cbfe451",
            "a1492e996fe8302a"
        ],
        "x": 194,
        "y": 1719,
        "w": 1012,
        "h": 162
    },
    {
        "id": "a9f1eb481f74dde3",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "name": "Collect data to CSV",
        "style": {
            "stroke": "#3f93cf",
            "fill": "#bfdbef",
            "label": true
        },
        "nodes": [
            "b577d7342c008353",
            "529de43bbcc8ddd4",
            "73a7a87a437b298c",
            "239601af1e96d917",
            "ccd602507a4abc68",
            "b694d72cbaef5d85",
            "af5560e53daca7e6",
            "96aded34d2e12af9",
            "14863b828843ebb1",
            "d95b03beeb91e93e"
        ],
        "x": 204,
        "y": 1219,
        "w": 1122,
        "h": 162
    },
    {
        "id": "517edf10f355e464",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "g": "f250c8ad248b028d",
        "name": "Water Tank",
        "style": {
            "label": true,
            "fill": "#bfdbef"
        },
        "nodes": [
            "5ddf1b5952313443",
            "a66ec0e0a1360f34",
            "9122c1157cbe0b5e",
            "d2a8ee6868d23307",
            "0f373262c51c849b",
            "b4b79354c06cc405"
        ],
        "x": 214,
        "y": 79,
        "w": 672,
        "h": 162
    },
    {
        "id": "d22591b8e78ebe7d",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "g": "f250c8ad248b028d",
        "name": "Milk Tank",
        "style": {
            "label": true
        },
        "nodes": [
            "49367ab61a7d3443",
            "bbfc30b4f5fe5cdd",
            "ab80657e6899a890",
            "c5df8a8624445a8a",
            "da3f9ba191429d15"
        ],
        "x": 214,
        "y": 259,
        "w": 652,
        "h": 122
    },
    {
        "id": "29542b83f026fb7b",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "g": "f250c8ad248b028d",
        "name": "Coffee Beam Tank",
        "style": {
            "label": true
        },
        "nodes": [
            "0ab25a3cc9a2fb4c",
            "f64ae2163a90f520",
            "ffdc07a2a8644ee7",
            "4d754c69f2e0b376",
            "77fa0ee8e20cbe27"
        ],
        "x": 214,
        "y": 399,
        "w": 672,
        "h": 122
    },
    {
        "id": "684238fb58a91415",
        "type": "group",
        "z": "8914237e0d8e46c7",
        "g": "f250c8ad248b028d",
        "name": "Boiler",
        "style": {
            "label": true
        },
        "nodes": [
            "2cfd5287e52e0fb0",
            "400b6980b1a2cd45",
            "4f1eb368f3fb45c1",
            "528f9a8a184a078a",
            "f4abb62d50e829d9",
            "3287809947131ac3",
            "bc32ee4142fc26ab",
            "61068469fd79b1a7"
        ],
        "x": 214,
        "y": 539,
        "w": 632,
        "h": 122
    },
    {
        "id": "5ddf1b5952313443",
        "type": "OpcUa-Client2-Monitor",
        "z": "8914237e0d8e46c7",
        "g": "517edf10f355e464",
        "inputs": 0,
        "output": 2,
        "name": "WaterTankLevel",
        "endpoint": "9593045b235c321c",
        "subscription": "s0",
        "startImmediately": true,
        "nodeId": "/di:DeviceSet/ns1:CoffeeMachineA.kitchen:Parameters.sterfive:WaterTankLevel",
        "samplingInterval": "500",
        "discardOldest": true,
        "queueSize": 10,
        "x": 320,
        "y": 160,
        "wires": [
            [
                "d2a8ee6868d23307",
                "b4b79354c06cc405"
            ]
        ]
    },
    {
        "id": "5163f0e3c15147e2",
        "type": "OpcUa-Client2-Call",
        "z": "8914237e0d8e46c7",
        "g": "a872632f0795dffe",
        "inputs": 1,
        "output": 4,
        "name": "Make Coffee",
        "endpoint": "9593045b235c321c",
        "action": "read",
        "methodId": "/di:DeviceSet/ns1:CoffeeMachineA.di:MethodSet.sterfive:MakeCoffee",
        "objectId": "/di:DeviceSet/ns1:CoffeeMachineA",
        "x": 1450,
        "y": 220,
        "wires": [
            []
        ]
    },
    {
        "id": "9ce44b437e2ed4eb",
        "type": "inject",
        "z": "8914237e0d8e46c7",
        "g": "a872632f0795dffe",
        "name": "Mocha",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "{\"RecipeName\": \"Mocha\"}",
        "payloadType": "json",
        "x": 1230,
        "y": 220,
        "wires": [
            [
                "5163f0e3c15147e2"
            ]
        ]
    },
    {
        "id": "17f15759ea0b4678",
        "type": "OpcUa-Client2-Call",
        "z": "8914237e0d8e46c7",
        "g": "a872632f0795dffe",
        "inputs": 1,
        "output": 4,
        "name": "FillTank",
        "endpoint": "9593045b235c321c",
        "action": "read",
        "methodId": "/di:DeviceSet/ns1:CoffeeMachineA.di:MethodSet.sterfive:FillTank",
        "objectId": "/di:DeviceSet/ns1:CoffeeMachineA",
        "x": 1450,
        "y": 320,
        "wires": [
            []
        ]
    },
    {
        "id": "ae2a5d89ca13248d",
        "type": "inject",
        "z": "8914237e0d8e46c7",
        "g": "a872632f0795dffe",
        "name": "",
        "props": [],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 1230,
        "y": 320,
        "wires": [
            [
                "17f15759ea0b4678"
            ]
        ]
    },
    {
        "id": "2cfd5287e52e0fb0",
        "type": "OpcUa-Client2-Monitor",
        "z": "8914237e0d8e46c7",
        "g": "684238fb58a91415",
        "inputs": 0,
        "output": 2,
        "name": "BoilerTempWater",
        "endpoint": "9593045b235c321c",
        "subscription": "s2",
        "startImmediately": true,
        "nodeId": "/di:DeviceSet/ns1:CoffeeMachineA.kitchen:Parameters.kitchen:BoilerTempWater",
        "samplingInterval": "100",
        "discardOldest": true,
        "queueSize": 10,
        "x": 320,
        "y": 580,
        "wires": [
            [
                "528f9a8a184a078a"
            ]
        ]
    },
    {
        "id": "2c7b916b70107153",
        "type": "OpcUa-Client2-Explore",
        "z": "8914237e0d8e46c7",
        "g": "665736b8cbeb246d",
        "inputs": 1,
        "output": 4,
        "name": "",
        "endpoint": "9593045b235c321c",
        "nodeId": "/di:DeviceSet/ns1:CoffeeMachineA.kitchen:Parameters",
        "outputType": "AliasedBrowsePath",
        "excludeEmpty": false,
        "followOrganizes": true,
        "x": 460,
        "y": 1800,
        "wires": [
            [
                "eeaa86a8240214df",
                "a1492e996fe8302a"
            ]
        ]
    },
    {
        "id": "eeaa86a8240214df",
        "type": "debug",
        "z": "8914237e0d8e46c7",
        "g": "665736b8cbeb246d",
        "name": "debug 8",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 640,
        "y": 1760,
        "wires": []
    },
    {
        "id": "42fea19e7e56afbc",
        "type": "inject",
        "z": "8914237e0d8e46c7",
        "g": "665736b8cbeb246d",
        "name": "AutoStart",
        "props": [],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "1",
        "topic": "",
        "x": 300,
        "y": 1800,
        "wires": [
            [
                "2c7b916b70107153"
            ]
        ]
    },
    {
        "id": "072413d285aeb40e",
        "type": "OpcUa-Client2-Monitor",
        "z": "8914237e0d8e46c7",
        "g": "665736b8cbeb246d",
        "inputs": 1,
        "output": 2,
        "name": "",
        "endpoint": "9593045b235c321c",
        "subscription": "s0",
        "startImmediately": false,
        "nodeId": "",
        "samplingInterval": 1000,
        "discardOldest": true,
        "queueSize": 10,
        "x": 820,
        "y": 1800,
        "wires": [
            [
                "f64d872549983d6f",
                "143a262a2cbfe451"
            ]
        ]
    },
    {
        "id": "f64d872549983d6f",
        "type": "debug",
        "z": "8914237e0d8e46c7",
        "g": "665736b8cbeb246d",
        "name": "debug 11",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1020,
        "y": 1760,
        "wires": []
    },
    {
        "id": "49367ab61a7d3443",
        "type": "OpcUa-Client2-Monitor",
        "z": "8914237e0d8e46c7",
        "g": "d22591b8e78ebe7d",
        "inputs": 0,
        "output": 2,
        "name": "Milk Tank Level",
        "endpoint": "9593045b235c321c",
        "subscription": "s0",
        "startImmediately": true,
        "nodeId": "/di:DeviceSet/ns1:CoffeeMachineA.kitchen:Parameters.sterfive:MilkTankLevel",
        "samplingInterval": "10000",
        "discardOldest": true,
        "queueSize": 10,
        "x": 320,
        "y": 300,
        "wires": [
            [
                "c5df8a8624445a8a",
                "da3f9ba191429d15"
            ]
        ]
    },
    {
        "id": "0ab25a3cc9a2fb4c",
        "type": "OpcUa-Client2-Monitor",
        "z": "8914237e0d8e46c7",
        "g": "29542b83f026fb7b",
        "inputs": 0,
        "output": 2,
        "name": "Coffe Beam Level",
        "endpoint": "9593045b235c321c",
        "subscription": "s0",
        "startImmediately": true,
        "nodeId": "/di:DeviceSet/ns1:CoffeeMachineA.kitchen:Parameters.sterfive:CoffeeBeanLevel",
        "samplingInterval": "10000",
        "discardOldest": true,
        "queueSize": 10,
        "x": 330,
        "y": 440,
        "wires": [
            [
                "4d754c69f2e0b376",
                "77fa0ee8e20cbe27"
            ]
        ]
    },
    {
        "id": "d2a8ee6868d23307",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "517edf10f355e464",
        "name": "round",
        "func": "msg.payload = Math.ceil(msg.payload*10)/10\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 530,
        "y": 160,
        "wires": [
            [
                "9122c1157cbe0b5e",
                "0f373262c51c849b"
            ]
        ]
    },
    {
        "id": "528f9a8a184a078a",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "684238fb58a91415",
        "name": "round",
        "func": "msg.payload = Math.ceil(msg.payload*100)/100\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 530,
        "y": 580,
        "wires": [
            [
                "400b6980b1a2cd45"
            ]
        ]
    },
    {
        "id": "f4abb62d50e829d9",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "684238fb58a91415",
        "name": "round",
        "func": "msg.payload = Math.ceil(msg.payload*100)/100\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 530,
        "y": 580,
        "wires": [
            []
        ]
    },
    {
        "id": "4d754c69f2e0b376",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "29542b83f026fb7b",
        "name": "round",
        "func": "msg.payload = Math.ceil(msg.payload*1)/1;\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 530,
        "y": 440,
        "wires": [
            [
                "f64ae2163a90f520"
            ]
        ]
    },
    {
        "id": "c5df8a8624445a8a",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "d22591b8e78ebe7d",
        "name": "round",
        "func": "msg.payload = Math.ceil(msg.payload*1)/1\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 530,
        "y": 300,
        "wires": [
            [
                "bbfc30b4f5fe5cdd"
            ]
        ]
    },
    {
        "id": "3287809947131ac3",
        "type": "OpcUa-Client2-Monitor",
        "z": "8914237e0d8e46c7",
        "g": "684238fb58a91415",
        "inputs": 0,
        "output": 2,
        "name": "BoilerTempWater",
        "endpoint": "9593045b235c321c",
        "subscription": "s2",
        "startImmediately": true,
        "nodeId": "/di:DeviceSet/ns1:CoffeeMachineA.kitchen:Parameters.kitchen:BoilerTempWater",
        "samplingInterval": "100",
        "discardOldest": true,
        "queueSize": 10,
        "x": 320,
        "y": 580,
        "wires": [
            []
        ]
    },
    {
        "id": "bc32ee4142fc26ab",
        "type": "OpcUa-Client2-Monitor",
        "z": "8914237e0d8e46c7",
        "g": "684238fb58a91415",
        "inputs": 0,
        "output": 2,
        "name": "BoilerTempWater",
        "endpoint": "9593045b235c321c",
        "subscription": "s0",
        "startImmediately": true,
        "nodeId": "/di:DeviceSet/ns1:CoffeeMachineA.kitchen:Parameters.kitchen:BoilerTempWater",
        "samplingInterval": "10000",
        "discardOldest": true,
        "queueSize": 10,
        "x": 320,
        "y": 580,
        "wires": [
            [
                "61068469fd79b1a7"
            ]
        ]
    },
    {
        "id": "f3ba9efdc12e30ce",
        "type": "OpcUa-Client2-Monitor",
        "z": "8914237e0d8e46c7",
        "g": "11f19caa7b9760b7",
        "inputs": 0,
        "output": 2,
        "name": "PumpStatus",
        "endpoint": "9593045b235c321c",
        "subscription": "s2",
        "startImmediately": true,
        "nodeId": "/2:DeviceSet/1:CoffeeMachineA.7:Parameters.17:PumpStatus",
        "samplingInterval": "1000",
        "discardOldest": true,
        "queueSize": 10,
        "x": 1150,
        "y": 840,
        "wires": [
            [
                "b8ba5e020aa48e2a",
                "7619f93616149cdc"
            ]
        ]
    },
    {
        "id": "b8ba5e020aa48e2a",
        "type": "debug",
        "z": "8914237e0d8e46c7",
        "g": "11f19caa7b9760b7",
        "name": "debug 7",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1380,
        "y": 880,
        "wires": []
    },
    {
        "id": "3e9be0f18116b2c2",
        "type": "OpcUa-Client2-Monitor",
        "z": "8914237e0d8e46c7",
        "g": "b07d4a44ddb86adf",
        "inputs": 0,
        "output": 2,
        "name": "Heater Status",
        "endpoint": "9593045b235c321c",
        "subscription": "s2",
        "startImmediately": true,
        "nodeId": "/di:DeviceSet/ns1:CoffeeMachineA.kitchen:Parameters.sterfive:HeaterStatus",
        "samplingInterval": "1000",
        "discardOldest": true,
        "queueSize": 10,
        "x": 290,
        "y": 780,
        "wires": [
            [
                "2b573431a25e870f",
                "20844959a8ea715c"
            ]
        ]
    },
    {
        "id": "2b573431a25e870f",
        "type": "debug",
        "z": "8914237e0d8e46c7",
        "g": "b07d4a44ddb86adf",
        "name": "debug 10",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 520,
        "y": 760,
        "wires": []
    },
    {
        "id": "d3b1d8b5c05c2b22",
        "type": "debug",
        "z": "8914237e0d8e46c7",
        "g": "b07d4a44ddb86adf",
        "name": "debug 12",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 840,
        "y": 840,
        "wires": []
    },
    {
        "id": "07bde3d3f85f2a40",
        "type": "inject",
        "z": "8914237e0d8e46c7",
        "g": "b07d4a44ddb86adf",
        "name": "",
        "props": [
            {
                "p": "serverTimestamp",
                "v": "",
                "vt": "date"
            },
            {
                "p": "sourceTimestamp",
                "v": "",
                "vt": "date"
            },
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "1",
        "payloadType": "str",
        "x": 310,
        "y": 840,
        "wires": [
            [
                "20844959a8ea715c"
            ]
        ]
    },
    {
        "id": "c369c3262a3b57fa",
        "type": "inject",
        "z": "8914237e0d8e46c7",
        "g": "b07d4a44ddb86adf",
        "name": "",
        "props": [
            {
                "p": "serverTimestamp",
                "v": "",
                "vt": "date"
            },
            {
                "p": "sourceTimestamp",
                "v": "",
                "vt": "date"
            },
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "0",
        "payloadType": "str",
        "x": 310,
        "y": 880,
        "wires": [
            [
                "20844959a8ea715c"
            ]
        ]
    },
    {
        "id": "7619f93616149cdc",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "11f19caa7b9760b7",
        "name": "gather & repeat",
        "func": "/**\n * This function node receives a monitored DataValue from OPC UA.\n * - msg.payload: Contains the value to be parsed into a float.\n * - msg.sourceTimestamp: Contains the value's timestamp in UTC ISO string format.\n *\n * It outputs messages to the first output with the following payload structure:\n * {\n *   timestamp: new Date(msg.sourceTimestamp),\n *   value: String(parseFloat(msg.payload))\n * }\n *\n * OPC UA only sends data when a value changes. To maintain a steady data stream, this node\n * repeats the last received value every second. The first repeated message is sent 1.5 seconds\n * after the initial message, with timestamps incrementing by the 1-second interval.\n *\n * Key constraints:\n * - Timestamps must always progress forward.\n * - Timing is based solely on OPC UA timestamps to avoid clock skew issues.\n * - Maintain only a single active timer to prevent duplicate messages.\n * - Timers are cleared properly upon node redeploy.\n */\n\nconst INTERVAL_MS = 1000; // 1-second interval for repeats\nconst INITIAL_DELAY_MS = 1500; // 1.5-second initial delay\n\n// Initialize context variables\nlet timer = context.get('timer');\nlet lastSentTimestamp = context.get('lastSentTimestamp') || 0;\nlet lastValue = context.get('lastValue');\nlet nextExpectedTimestamp = context.get('nextExpectedTimestamp') || 0;\n\n// Cleanup on node redeploy\nif (!context.get('initialized')) {\n  node.on('close', function () {\n    if (timer) {\n      clearTimeout(timer);\n      context.set('timer', null);\n    }\n  });\n  context.set('initialized', true);\n}\n\nfunction sendAndSchedule(value, sourceTime) {\n  // Send the message immediately\n  node.send({\n    payload: {\n      timestamp: new Date(sourceTime),\n      value: value\n    }\n  });\n\n  // Update context\n  context.set('lastSentTimestamp', sourceTime);\n  context.set('lastValue', value);\n\n  // Calculate the next expected timestamp\n  const nextTs = sourceTime + INITIAL_DELAY_MS + INTERVAL_MS;\n  context.set('nextExpectedTimestamp', nextTs);\n\n  // Schedule the next repetition\n  const delayUntilNextRepeat = INITIAL_DELAY_MS;\n  timer = setTimeout(() => {\n    sendRepeatedValue(value, nextTs, INTERVAL_MS);\n  }, delayUntilNextRepeat);\n  context.set('timer', timer);\n}\n\nfunction sendRepeatedValue(value, nextTs, interval) {\n  // Send the repeated message\n  node.send({\n    payload: {\n      timestamp: new Date(nextTs),\n      value: value\n    }\n  });\n\n  // Schedule the next repetition\n  const nextNextTs = nextTs + interval;\n  context.set('nextExpectedTimestamp', nextNextTs);\n\n  timer = setTimeout(() => {\n    sendRepeatedValue(value, nextNextTs, interval);\n  }, interval);\n  context.set('timer', timer);\n}\n\nif (msg.payload !== undefined && msg.sourceTimestamp) {\n  // Clear any existing timer\n  if (timer) {\n    clearTimeout(timer);\n    context.set('timer', null);\n  }\n\n  try {\n    let sourceTime = new Date(msg.sourceTimestamp).getTime();\n    const value = \"\" + parseInt(msg.payload);\n\n    // Ensure timestamps always go forward\n    if (lastSentTimestamp && sourceTime <= lastSentTimestamp) {\n      sourceTime = lastSentTimestamp + 1; // Force it to be strictly greater\n    }\n\n    // Send immediately and schedule the first repeat\n    sendAndSchedule(value, sourceTime);\n  } catch (e) {\n    node.error(\"Error processing message: \" + e.message, msg);\n  }\n}",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "\n",
        "finalize": "",
        "libs": [],
        "x": 1400,
        "y": 840,
        "wires": [
            [
                "24ab918428d73e5f"
            ]
        ]
    },
    {
        "id": "f1f77b6afa4257f0",
        "type": "inject",
        "z": "8914237e0d8e46c7",
        "g": "b07d4a44ddb86adf",
        "name": "Clear ",
        "props": [
            {
                "p": "topic",
                "vt": "str"
            },
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "[]",
        "payload": "[]",
        "payloadType": "str",
        "x": 690,
        "y": 740,
        "wires": [
            [
                "68e0c3653588a07d",
                "d3b1d8b5c05c2b22"
            ]
        ]
    },
    {
        "id": "c9717ac11b53672e",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "62d148a7e9f5c520",
        "name": "enum to string",
        "func": "switch(msg.payload) {\n    case 0:\n      msg.payload = \"Off\";\n      break;\n    case 1:\n      msg.payload =  \"Standby\";\n      break;\n    case 2:\n      msg.payload =  \"Error\";\n      break;\n    case 3:\n      msg.payload =  \"Cleaning\";\n      break;\n    case 4:\n      msg.payload =  \"Serving Coffee\";\n      break;\n    case 5:\n      msg.payload =  \"Under Maintenance\";\n      break;\n    default:\n      msg.payload = msg.payload;\n      break;\n\n}\n// msg.payload =  msg.payload;\nreturn msg;\n\n/*\n\nexport enum EnumCoffeeMachineModeEx {\n  Off = 0,\n  Standby = 1,\n  Error = 2,\n  Cleaning = 3,\n\n  // not in spec !!!\n  ServingCoffee = 4,\n\n  UnderMaintenance = 5, // like filling coffee\n\n}\n*/",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1360,
        "y": 740,
        "wires": [
            [
                "798535950531337a"
            ]
        ]
    },
    {
        "id": "3a8c7eb7dc515e34",
        "type": "OpcUa-Client2-Monitor",
        "z": "8914237e0d8e46c7",
        "g": "62d148a7e9f5c520",
        "inputs": 0,
        "output": 2,
        "name": "CurrentState",
        "endpoint": "9593045b235c321c",
        "subscription": "s2",
        "startImmediately": true,
        "nodeId": "/di:DeviceSet/ns1:CoffeeMachineA.kitchen:Parameters.kitchen:CurrentState",
        "samplingInterval": "100",
        "discardOldest": true,
        "queueSize": 10,
        "x": 1150,
        "y": 740,
        "wires": [
            [
                "c9717ac11b53672e"
            ]
        ]
    },
    {
        "id": "1c3d6230a57c852c",
        "type": "OpcUa-Client2-Call",
        "z": "8914237e0d8e46c7",
        "g": "a872632f0795dffe",
        "inputs": 1,
        "output": 4,
        "name": "Start",
        "endpoint": "9593045b235c321c",
        "action": "read",
        "methodId": "/di:DeviceSet/ns1:CoffeeMachineA.di:MethodSet.sterfive:Start",
        "objectId": "/di:DeviceSet/ns1:CoffeeMachineA",
        "x": 1450,
        "y": 420,
        "wires": [
            []
        ]
    },
    {
        "id": "c172f527ba188866",
        "type": "inject",
        "z": "8914237e0d8e46c7",
        "g": "a872632f0795dffe",
        "name": "",
        "props": [],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 1230,
        "y": 420,
        "wires": [
            [
                "1c3d6230a57c852c"
            ]
        ]
    },
    {
        "id": "83de8924a1f6f2a5",
        "type": "OpcUa-Client2-Call",
        "z": "8914237e0d8e46c7",
        "g": "a872632f0795dffe",
        "inputs": 1,
        "output": 4,
        "name": "Stop",
        "endpoint": "9593045b235c321c",
        "action": "read",
        "methodId": "/di:DeviceSet/ns1:CoffeeMachineA.di:MethodSet.sterfive:Stop",
        "objectId": "/di:DeviceSet/ns1:CoffeeMachineA",
        "x": 1440,
        "y": 520,
        "wires": [
            []
        ]
    },
    {
        "id": "807487cd9637d0e1",
        "type": "inject",
        "z": "8914237e0d8e46c7",
        "g": "a872632f0795dffe",
        "name": "",
        "props": [],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 1230,
        "y": 520,
        "wires": [
            [
                "83de8924a1f6f2a5"
            ]
        ]
    },
    {
        "id": "36b2628c69b87d42",
        "type": "OpcUa-Client2-Read",
        "z": "8914237e0d8e46c7",
        "g": "23e92d93ed23febc",
        "inputs": 1,
        "output": 4,
        "name": "",
        "endpoint": "9593045b235c321c",
        "attributeId": "Value",
        "nodeId": "",
        "outputType": "StatusCode",
        "x": 590,
        "y": 1080,
        "wires": [
            [
                "46d99d7986a03b57",
                "e975667424fe78b7"
            ]
        ]
    },
    {
        "id": "46d99d7986a03b57",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "23e92d93ed23febc",
        "name": "Extract connection  status",
        "func": "msg.payload = `${msg.payload}  -  ${msg.statusCode.toString()}`;\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 830,
        "y": 1080,
        "wires": [
            [
                "dcf7ab764b7d2921"
            ]
        ]
    },
    {
        "id": "e975667424fe78b7",
        "type": "delay",
        "z": "8914237e0d8e46c7",
        "g": "23e92d93ed23febc",
        "name": "",
        "pauseType": "delay",
        "timeout": "1",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 480,
        "y": 980,
        "wires": [
            [
                "f79e321ce9b22631"
            ]
        ]
    },
    {
        "id": "dc5e73eb1991eed3",
        "type": "inject",
        "z": "8914237e0d8e46c7",
        "g": "23e92d93ed23febc",
        "name": "",
        "props": [],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "1",
        "topic": "",
        "x": 290,
        "y": 1100,
        "wires": [
            [
                "36b2628c69b87d42"
            ]
        ]
    },
    {
        "id": "f79e321ce9b22631",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "23e92d93ed23febc",
        "name": "remove payload",
        "func": "msg.payload = null;\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 360,
        "y": 1060,
        "wires": [
            [
                "36b2628c69b87d42"
            ]
        ]
    },
    {
        "id": "6c7658b34fce0ac3",
        "type": "comment",
        "z": "8914237e0d8e46c7",
        "g": "a872632f0795dffe",
        "name": "Buttons",
        "info": "",
        "x": 1190,
        "y": 160,
        "wires": []
    },
    {
        "id": "9326ae6929032e87",
        "type": "comment",
        "z": "8914237e0d8e46c7",
        "name": "Coffee Machine ( visit http://127.0.0.1:1880/dashboard/CoffeeMachineSynopsis )",
        "info": "# Coffee Machine *\n\nThis example demostrate how to \ncreate a Dashboard that interacts \nwith a OPCUA CoffeeMachine\n\n",
        "x": 480,
        "y": 40,
        "wires": []
    },
    {
        "id": "b577d7342c008353",
        "type": "OpcUa-Client2-Explore",
        "z": "8914237e0d8e46c7",
        "g": "a9f1eb481f74dde3",
        "inputs": 1,
        "output": 4,
        "name": "",
        "endpoint": "9593045b235c321c",
        "nodeId": "/di:DeviceSet/ns1:CoffeeMachineA.kitchen:Parameters",
        "outputType": "Value",
        "excludeEmpty": false,
        "followOrganizes": false,
        "x": 460,
        "y": 1260,
        "wires": [
            [
                "af5560e53daca7e6",
                "96aded34d2e12af9"
            ]
        ]
    },
    {
        "id": "529de43bbcc8ddd4",
        "type": "inject",
        "z": "8914237e0d8e46c7",
        "g": "a9f1eb481f74dde3",
        "name": "",
        "props": [],
        "repeat": "10",
        "crontab": "",
        "once": false,
        "onceDelay": "2",
        "topic": "",
        "x": 300,
        "y": 1260,
        "wires": [
            [
                "b577d7342c008353"
            ]
        ]
    },
    {
        "id": "73a7a87a437b298c",
        "type": "csv",
        "z": "8914237e0d8e46c7",
        "g": "a9f1eb481f74dde3",
        "name": "",
        "spec": "rfc",
        "sep": ";",
        "hdrin": "",
        "hdrout": "once",
        "multi": "one",
        "ret": "\\n",
        "temp": "",
        "skip": "0",
        "strings": true,
        "include_empty_strings": "",
        "include_null_values": "",
        "x": 990,
        "y": 1260,
        "wires": [
            [
                "239601af1e96d917",
                "ccd602507a4abc68"
            ]
        ]
    },
    {
        "id": "239601af1e96d917",
        "type": "file",
        "z": "8914237e0d8e46c7",
        "g": "a9f1eb481f74dde3",
        "name": "Append to Output.csv",
        "filename": "/tmp/output.csv",
        "filenameType": "str",
        "appendNewline": false,
        "createDir": false,
        "overwriteFile": "false",
        "encoding": "none",
        "x": 1200,
        "y": 1260,
        "wires": [
            []
        ]
    },
    {
        "id": "ccd602507a4abc68",
        "type": "debug",
        "z": "8914237e0d8e46c7",
        "g": "a9f1eb481f74dde3",
        "name": "debug 13",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1160,
        "y": 1300,
        "wires": []
    },
    {
        "id": "d21be93e03b60165",
        "type": "OpcUa-Client2-Explore",
        "z": "8914237e0d8e46c7",
        "g": "230bb82688833807",
        "inputs": 1,
        "output": 4,
        "name": "",
        "endpoint": "9593045b235c321c",
        "nodeId": "/di:DeviceSet/ns1:CoffeeMachineA.kitchen:Parameters",
        "outputType": "NodeId",
        "excludeEmpty": false,
        "followOrganizes": false,
        "x": 440,
        "y": 1540,
        "wires": [
            [
                "50c33de026727ab2"
            ]
        ]
    },
    {
        "id": "1832b372c56dc715",
        "type": "inject",
        "z": "8914237e0d8e46c7",
        "g": "230bb82688833807",
        "name": "",
        "props": [],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": "2",
        "topic": "",
        "x": 290,
        "y": 1540,
        "wires": [
            [
                "d21be93e03b60165"
            ]
        ]
    },
    {
        "id": "5f6eeb0fc5228a66",
        "type": "OpcUa-Client2-Read",
        "z": "8914237e0d8e46c7",
        "g": "230bb82688833807",
        "inputs": 1,
        "output": 4,
        "name": "",
        "endpoint": "9593045b235c321c",
        "attributeId": "Value",
        "nodeId": "",
        "outputType": "Value",
        "x": 870,
        "y": 1540,
        "wires": [
            [
                "fe845d4c6aa473d0",
                "829ce0410d7c3b05",
                "5e50f3a2da48a03b"
            ]
        ]
    },
    {
        "id": "5e50f3a2da48a03b",
        "type": "debug",
        "z": "8914237e0d8e46c7",
        "g": "230bb82688833807",
        "name": "debug 15",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1260,
        "y": 1460,
        "wires": []
    },
    {
        "id": "fe845d4c6aa473d0",
        "type": "delay",
        "z": "8914237e0d8e46c7",
        "g": "230bb82688833807",
        "name": "",
        "pauseType": "delay",
        "timeout": "2",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": false,
        "allowrate": false,
        "outputs": 1,
        "x": 840,
        "y": 1480,
        "wires": [
            [
                "99b27a72cfb58370"
            ]
        ]
    },
    {
        "id": "50c33de026727ab2",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "230bb82688833807",
        "name": "memorize payload",
        "func": "flow.set(\"p\", msg.payload)\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 630,
        "y": 1540,
        "wires": [
            [
                "5f6eeb0fc5228a66"
            ]
        ]
    },
    {
        "id": "99b27a72cfb58370",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "230bb82688833807",
        "name": "function 3",
        "func": "msg.payload = flow.get(\"p\");\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 955,
        "y": 1480,
        "wires": [
            [
                "5f6eeb0fc5228a66"
            ]
        ],
        "l": false
    },
    {
        "id": "829ce0410d7c3b05",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "230bb82688833807",
        "name": "clean up",
        "func": "msg.timestamp = new Date(); //  new Date(msg.sourceTimestamp);\nmsg.payload.TotalMix = msg.payload.ServedCoffeeCount;\nmsg.payload.timestamp = msg.timestamp;\nmsg.payload.d= msg.timestamp.toISOString();\nmsg.payload.values = [ Math.random()*1000 , Math.random()*1000];\nmsg.payload.titles = [ \"A\", \"B\"]\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1100,
        "y": 1540,
        "wires": [
            [
                "5e50f3a2da48a03b",
                "1bea16ead1291025"
            ]
        ]
    },
    {
        "id": "4cecc03d1a64c091",
        "type": "OpcUa-Client2-Browse",
        "z": "8914237e0d8e46c7",
        "g": "ec1ab7ca9e060d7f",
        "inputs": 1,
        "output": 4,
        "name": "",
        "endpoint": "9593045b235c321c",
        "nodeId": "/di:DeviceSet/ns1:CoffeeMachineA.sterfive:Recipes",
        "referenceTypeId": "HasChild",
        "includeSubtypes": false,
        "browseDirection": "Forward",
        "nodeClassMask": "Object",
        "resultMask": "ReferenceType | BrowseName | TypeDefinition | DisplayName | NodeClass | IsForward",
        "x": 1320,
        "y": 980,
        "wires": [
            [
                "57622c7f24dacef7"
            ]
        ]
    },
    {
        "id": "f6b1e7b0df0fa288",
        "type": "debug",
        "z": "8914237e0d8e46c7",
        "g": "ec1ab7ca9e060d7f",
        "name": "debug 16",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1640,
        "y": 1040,
        "wires": []
    },
    {
        "id": "0c098347de28a15d",
        "type": "inject",
        "z": "8914237e0d8e46c7",
        "g": "ec1ab7ca9e060d7f",
        "name": "",
        "props": [],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "1",
        "topic": "",
        "x": 1150,
        "y": 980,
        "wires": [
            [
                "4cecc03d1a64c091"
            ]
        ]
    },
    {
        "id": "57622c7f24dacef7",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "ec1ab7ca9e060d7f",
        "name": "extract recipe name",
        "func": "msg.payload = msg.payload.map(ref => ref.displayName );\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1510,
        "y": 980,
        "wires": [
            [
                "e3c1066f3260a1cb"
            ]
        ]
    },
    {
        "id": "e3c1066f3260a1cb",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "ec1ab7ca9e060d7f",
        "name": "prepare combo box options",
        "func": "msg.ui_update = {\n    options: msg.payload\n};\nmsg.payload = msg.payload[0].value;\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1240,
        "y": 1060,
        "wires": [
            [
                "f6b1e7b0df0fa288",
                "237e980896f1a684"
            ]
        ]
    },
    {
        "id": "0597a0ffcdab77cd",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "ec1ab7ca9e060d7f",
        "name": "memorize selectedComboValue",
        "func": "// This function is triggered whenever the combo box value changes.\n// It stores the selected value in the flow context.\nflow.set(\"selectedComboValue\", msg.payload);\nreturn null;  // No output required from this node.\n\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1710,
        "y": 1080,
        "wires": [
            []
        ]
    },
    {
        "id": "1fca2f6f28cc4828",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "ec1ab7ca9e060d7f",
        "name": "function 7",
        "func": "// This function is triggered by the button click.\n// It retrieves the stored combo box value and outputs it in msg.payload.\nvar selectedValue = flow.get(\"selectedComboValue\");\n\n// Optionally, add error handling if no value has been selected yet.\nif (typeof selectedValue === 'undefined') {\n    node.warn(\"No combo box value selected yet.\");\n    msg.payload = \"No selection\";\n    return undefined;\n} else {\n    msg.payload = {\n        \"RecipeName\": selectedValue\n    };\n}\n\nreturn msg;\n",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1345,
        "y": 1140,
        "wires": [
            [
                "ea1957e0718f21fd"
            ]
        ],
        "l": false
    },
    {
        "id": "2857eb76526322a1",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "ec1ab7ca9e060d7f",
        "name": "function 8",
        "func": "msg.ui_update = {\n    label: \"Make \" + msg.payload\n}\nmsg.payload= undefined;\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 1115,
        "y": 1140,
        "wires": [
            [
                "6008fa16cda462d5"
            ]
        ],
        "l": false
    },
    {
        "id": "ea1957e0718f21fd",
        "type": "OpcUa-Client2-Call",
        "z": "8914237e0d8e46c7",
        "g": "ec1ab7ca9e060d7f",
        "inputs": 1,
        "output": 4,
        "name": "Make",
        "endpoint": "9593045b235c321c",
        "action": "read",
        "methodId": "/di:DeviceSet/ns1:CoffeeMachineA.di:MethodSet.sterfive:MakeCoffee",
        "objectId": "/di:DeviceSet/ns1:CoffeeMachineA",
        "x": 1450,
        "y": 1140,
        "wires": [
            [
                "03aa8523b17003d7"
            ]
        ]
    },
    {
        "id": "44225cb3561717c6",
        "type": "OpcUa-Client2-Monitor",
        "z": "8914237e0d8e46c7",
        "g": "54277e0eb0f4eddd",
        "inputs": 0,
        "output": 2,
        "name": "",
        "endpoint": "9593045b235c321c",
        "subscription": "s1",
        "startImmediately": true,
        "nodeId": "/di:DeviceSet/ns1:CoffeeMachineA.di:DeviceHealth",
        "samplingInterval": 1000,
        "discardOldest": true,
        "queueSize": 10,
        "x": 320,
        "y": 1640,
        "wires": [
            [
                "61237053c6df429d"
            ]
        ]
    },
    {
        "id": "61237053c6df429d",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "54277e0eb0f4eddd",
        "name": "convert to img,text",
        "func": "switch(msg.payload) {\n    case 0:  // normal\n      msg.payload = {\n        img: \"https://www.svgrepo.com/show/486753/namur-ok.svg\",\n        text: \"normal\"\n      }\n      break;\n    case 1: // failure \n      msg.payload = {\n        img: \"https://www.svgrepo.com/show/486750/namur-failure.svg\",\n        text: \"failure\"\n      }\n      break;\n    case 2: // check function \n      msg.payload = {\n       img: \"https://www.svgrepo.com/show/486749/namur-check-function.svg\",\n       text: \"check function\"\n      }\n      break;\n    case 3: // off-spec \n      msg.payload = {\n          img: \"https://www.svgrepo.com/show/486751/namur-out-of-spec.svg\",\n          text: \"off-spec\"\n      };\n      break;\n    case 4: // maintenance\n      msg.payload = {\n          img: \"https://www.svgrepo.com/show/26897/change-car-oil.svg\",\n          text: \"maintenance-required\"\n      }\n      break;            \n}\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 580,
        "y": 1640,
        "wires": [
            [
                "2456ee93776095bc"
            ]
        ]
    },
    {
        "id": "a1492e996fe8302a",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "665736b8cbeb246d",
        "name": "cleanup",
        "func": "delete msg.payload.TotalMix;\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 640,
        "y": 1800,
        "wires": [
            [
                "072413d285aeb40e"
            ]
        ]
    },
    {
        "id": "dcf7ab764b7d2921",
        "type": "debug",
        "z": "8914237e0d8e46c7",
        "g": "23e92d93ed23febc",
        "name": "debug 14",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 900,
        "y": 1140,
        "wires": []
    },
    {
        "id": "b694d72cbaef5d85",
        "type": "inject",
        "z": "8914237e0d8e46c7",
        "g": "a9f1eb481f74dde3",
        "name": "reset",
        "props": [
            {
                "p": "reset",
                "v": "true",
                "vt": "bool"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": "2",
        "topic": "",
        "x": 390,
        "y": 1340,
        "wires": [
            [
                "14863b828843ebb1"
            ]
        ]
    },
    {
        "id": "af5560e53daca7e6",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "a9f1eb481f74dde3",
        "name": "Add Timpstamp",
        "func": "msg.payload.Timestamp = (new Date()).toISOString()\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 660,
        "y": 1260,
        "wires": [
            [
                "73a7a87a437b298c"
            ]
        ]
    },
    {
        "id": "96aded34d2e12af9",
        "type": "debug",
        "z": "8914237e0d8e46c7",
        "g": "a9f1eb481f74dde3",
        "name": "debug 17",
        "active": false,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 640,
        "y": 1300,
        "wires": []
    },
    {
        "id": "14863b828843ebb1",
        "type": "function",
        "z": "8914237e0d8e46c7",
        "g": "a9f1eb481f74dde3",
        "name": "force reset",
        "func": "msg.reset = true;\ndelete msg.payload;\nreturn msg;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 630,
        "y": 1340,
        "wires": [
            [
                "73a7a87a437b298c",
                "d95b03beeb91e93e"
            ]
        ]
    },
    {
        "id": "03aa8523b17003d7",
        "type": "debug",
        "z": "8914237e0d8e46c7",
        "g": "ec1ab7ca9e060d7f",
        "name": "debug 1",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1640,
        "y": 1140,
        "wires": []
    },
    {
        "id": "d95b03beeb91e93e",
        "type": "file",
        "z": "8914237e0d8e46c7",
        "g": "a9f1eb481f74dde3",
        "name": "remove file",
        "filename": "/tmp/output.csv",
        "filenameType": "str",
        "appendNewline": true,
        "createDir": false,
        "overwriteFile": "delete",
        "encoding": "none",
        "x": 1010,
        "y": 1340,
        "wires": [
            []
        ]
    },
    {
        "id": "44eeed6c80419b5f",
        "type": "ui-button",
        "z": "8914237e0d8e46c7",
        "g": "a872632f0795dffe",
        "group": "0eeeefa89ae3646a",
        "name": "Fill Tank",
        "label": "Filll Tank",
        "order": 7,
        "width": "3",
        "height": "1",
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 1220,
        "y": 360,
        "wires": [
            [
                "17f15759ea0b4678"
            ]
        ]
    },
    {
        "id": "7b496ba60d331069",
        "type": "ui-button",
        "z": "8914237e0d8e46c7",
        "g": "a872632f0795dffe",
        "group": "0eeeefa89ae3646a",
        "name": "Make Mocha",
        "label": "Make Mocha",
        "order": 6,
        "width": "3",
        "height": "1",
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "iconPosition": "left",
        "payload": "{\"RecipeName\":\"Mocha\"}",
        "payloadType": "json",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 1210,
        "y": 260,
        "wires": [
            [
                "5163f0e3c15147e2"
            ]
        ]
    },
    {
        "id": "ae3fe0588bcec600",
        "type": "ui-button",
        "z": "8914237e0d8e46c7",
        "g": "a872632f0795dffe",
        "group": "0eeeefa89ae3646a",
        "name": "Start",
        "label": "Start",
        "order": 4,
        "width": "3",
        "height": "1",
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 1230,
        "y": 460,
        "wires": [
            [
                "1c3d6230a57c852c"
            ]
        ]
    },
    {
        "id": "e181ef3ed9e6dc40",
        "type": "ui-button",
        "z": "8914237e0d8e46c7",
        "g": "a872632f0795dffe",
        "group": "0eeeefa89ae3646a",
        "name": "Stop",
        "label": "Stop",
        "order": 5,
        "width": "3",
        "height": "1",
        "emulateClick": true,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 1230,
        "y": 560,
        "wires": [
            [
                "83de8924a1f6f2a5"
            ]
        ]
    },
    {
        "id": "6008fa16cda462d5",
        "type": "ui-button",
        "z": "8914237e0d8e46c7",
        "g": "ec1ab7ca9e060d7f",
        "group": "837da312967f08dd",
        "name": "Make Coffee",
        "label": "button",
        "order": 1,
        "width": 0,
        "height": 0,
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "",
        "textColor": "",
        "iconColor": "",
        "enableClick": true,
        "enablePointerdown": false,
        "pointerdownPayload": "",
        "pointerdownPayloadType": "str",
        "enablePointerup": false,
        "pointerupPayload": "",
        "pointerupPayloadType": "str",
        "x": 1230,
        "y": 1140,
        "wires": [
            [
                "1fca2f6f28cc4828"
            ]
        ]
    },
    {
        "id": "237e980896f1a684",
        "type": "ui-dropdown",
        "z": "8914237e0d8e46c7",
        "g": "ec1ab7ca9e060d7f",
        "group": "837da312967f08dd",
        "name": "Recipies",
        "label": "Select Beverage:",
        "tooltip": "",
        "order": 2,
        "width": 0,
        "height": 0,
        "passthru": false,
        "multiple": false,
        "chips": false,
        "clearable": false,
        "options": [
            {
                "label": "",
                "value": "",
                "type": "str"
            }
        ],
        "payload": "",
        "topic": "beverage",
        "topicType": "msg",
        "className": "",
        "typeIsComboBox": false,
        "msgTrigger": "onChange",
        "x": 1460,
        "y": 1080,
        "wires": [
            [
                "f6b1e7b0df0fa288",
                "0597a0ffcdab77cd",
                "2857eb76526322a1"
            ]
        ]
    },
    {
        "id": "a66ec0e0a1360f34",
        "type": "ui-chart",
        "z": "8914237e0d8e46c7",
        "g": "517edf10f355e464",
        "group": "0eeeefa89ae3646a",
        "name": "Water Tank Level ",
        "label": "Tank",
        "order": 12,
        "chartType": "line",
        "category": "",
        "categoryType": "none",
        "xAxisLabel": "date",
        "xAxisProperty": "timestamp",
        "xAxisPropertyType": "property",
        "xAxisType": "time",
        "xAxisFormat": "",
        "xAxisFormatType": "{HH}:{mm}:{ss}",
        "xmin": "",
        "xmax": "",
        "yAxisLabel": "",
        "yAxisProperty": "value",
        "yAxisPropertyType": "property",
        "ymin": "0",
        "ymax": "1200",
        "bins": 10,
        "action": "append",
        "stackSeries": false,
        "pointShape": "false",
        "pointRadius": 4,
        "showLegend": true,
        "removeOlder": "10",
        "removeOlderUnit": "60",
        "removeOlderPoints": "500",
        "colors": [
            "#0095ff",
            "#ff0000",
            "#ff7f0e",
            "#2ca02c",
            "#a347e1",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "textColor": [
            "#666666"
        ],
        "textColorDefault": true,
        "gridColor": [
            "#e5e5e5"
        ],
        "gridColorDefault": true,
        "width": "3",
        "height": "4",
        "className": "",
        "interpolation": "smooth",
        "x": 770,
        "y": 200,
        "wires": [
            []
        ]
    },
    {
        "id": "4f1eb368f3fb45c1",
        "type": "ui-chart",
        "z": "8914237e0d8e46c7",
        "g": "684238fb58a91415",
        "group": "0eeeefa89ae3646a",
        "name": "Temperature",
        "label": "Water Temperature",
        "order": 15,
        "chartType": "line",
        "category": "",
        "categoryType": "none",
        "xAxisLabel": "Temperature",
        "xAxisProperty": "timestamp",
        "xAxisPropertyType": "property",
        "xAxisType": "time",
        "xAxisFormat": "",
        "xAxisFormatType": "{HH}:{mm}:{ss}",
        "xmin": "",
        "xmax": "",
        "yAxisLabel": "",
        "yAxisProperty": "value",
        "yAxisPropertyType": "property",
        "ymin": "10",
        "ymax": "150",
        "bins": 10,
        "action": "append",
        "stackSeries": false,
        "pointShape": "line",
        "pointRadius": "1",
        "showLegend": true,
        "removeOlder": "10",
        "removeOlderUnit": "60",
        "removeOlderPoints": "500",
        "colors": [
            "#0095ff",
            "#ff0000",
            "#ff7f0e",
            "#2ca02c",
            "#a347e1",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "textColor": [
            "#6a4444"
        ],
        "textColorDefault": false,
        "gridColor": [
            "#e5e5e5"
        ],
        "gridColorDefault": false,
        "width": "3",
        "height": "4",
        "className": "",
        "interpolation": "smooth",
        "x": 750,
        "y": 620,
        "wires": [
            []
        ]
    },
    {
        "id": "ab80657e6899a890",
        "type": "ui-chart",
        "z": "8914237e0d8e46c7",
        "g": "d22591b8e78ebe7d",
        "group": "0eeeefa89ae3646a",
        "name": "Milk Tank Level ",
        "label": "Tank",
        "order": 13,
        "chartType": "line",
        "category": "",
        "categoryType": "none",
        "xAxisLabel": "date",
        "xAxisProperty": "timestamp",
        "xAxisPropertyType": "property",
        "xAxisType": "time",
        "xAxisFormat": "",
        "xAxisFormatType": "{HH}:{mm}:{ss}",
        "xmin": "",
        "xmax": "",
        "yAxisLabel": "",
        "yAxisProperty": "value",
        "yAxisPropertyType": "property",
        "ymin": "0",
        "ymax": "1200",
        "bins": 10,
        "action": "append",
        "stackSeries": false,
        "pointShape": "false",
        "pointRadius": 4,
        "showLegend": true,
        "removeOlder": "10",
        "removeOlderUnit": "60",
        "removeOlderPoints": "500",
        "colors": [
            "#0095ff",
            "#ff0000",
            "#ff7f0e",
            "#2ca02c",
            "#a347e1",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "textColor": [
            "#666666"
        ],
        "textColorDefault": true,
        "gridColor": [
            "#e5e5e5"
        ],
        "gridColorDefault": true,
        "width": "3",
        "height": "4",
        "className": "",
        "interpolation": "smooth",
        "x": 760,
        "y": 340,
        "wires": [
            []
        ]
    },
    {
        "id": "ffdc07a2a8644ee7",
        "type": "ui-chart",
        "z": "8914237e0d8e46c7",
        "g": "29542b83f026fb7b",
        "group": "0eeeefa89ae3646a",
        "name": "Coffee Beal Level ",
        "label": "Tank",
        "order": 14,
        "chartType": "line",
        "category": "",
        "categoryType": "none",
        "xAxisLabel": "date",
        "xAxisProperty": "timestamp",
        "xAxisPropertyType": "property",
        "xAxisType": "time",
        "xAxisFormat": "",
        "xAxisFormatType": "{HH}:{mm}:{ss}",
        "xmin": "",
        "xmax": "",
        "yAxisLabel": "",
        "yAxisProperty": "value",
        "yAxisPropertyType": "property",
        "ymin": "0",
        "ymax": "600",
        "bins": 10,
        "action": "append",
        "stackSeries": false,
        "pointShape": "false",
        "pointRadius": 4,
        "showLegend": true,
        "removeOlder": "10",
        "removeOlderUnit": "60",
        "removeOlderPoints": "500",
        "colors": [
            "#0095ff",
            "#ff0000",
            "#ff7f0e",
            "#2ca02c",
            "#a347e1",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "textColor": [
            "#666666"
        ],
        "textColorDefault": true,
        "gridColor": [
            "#e5e5e5"
        ],
        "gridColorDefault": true,
        "width": "3",
        "height": "4",
        "className": "",
        "interpolation": "smooth",
        "x": 770,
        "y": 480,
        "wires": [
            []
        ]
    },
    {
        "id": "24ab918428d73e5f",
        "type": "ui-chart",
        "z": "8914237e0d8e46c7",
        "g": "11f19caa7b9760b7",
        "group": "0eeeefa89ae3646a",
        "name": "Pump Status",
        "label": "Pump Status",
        "order": 17,
        "chartType": "line",
        "category": "",
        "categoryType": "none",
        "xAxisLabel": "Pump Status",
        "xAxisProperty": "timestamp",
        "xAxisPropertyType": "property",
        "xAxisType": "time",
        "xAxisFormat": "",
        "xAxisFormatType": "{HH}:{mm}:{ss}",
        "xmin": "",
        "xmax": "",
        "yAxisLabel": "On/Off",
        "yAxisProperty": "value",
        "yAxisPropertyType": "property",
        "ymin": "0",
        "ymax": "1.1",
        "bins": 10,
        "action": "append",
        "stackSeries": false,
        "pointShape": "line",
        "pointRadius": 4,
        "showLegend": true,
        "removeOlder": "10",
        "removeOlderUnit": "60",
        "removeOlderPoints": "500",
        "colors": [
            "#0095ff",
            "#ff0000",
            "#ff7f0e",
            "#2ca02c",
            "#a347e1",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "textColor": [
            "#666666"
        ],
        "textColorDefault": true,
        "gridColor": [
            "#e5e5e5"
        ],
        "gridColorDefault": true,
        "width": "6",
        "height": "4",
        "className": "",
        "interpolation": "step",
        "x": 1590,
        "y": 840,
        "wires": [
            []
        ]
    },
    {
        "id": "68e0c3653588a07d",
        "type": "ui-chart",
        "z": "8914237e0d8e46c7",
        "g": "b07d4a44ddb86adf",
        "group": "0eeeefa89ae3646a",
        "name": "Heater Status Graph",
        "label": "Heater Status",
        "order": 16,
        "chartType": "line",
        "category": "",
        "categoryType": "none",
        "xAxisLabel": "Heater Status",
        "xAxisProperty": "timestamp",
        "xAxisPropertyType": "property",
        "xAxisType": "time",
        "xAxisFormat": "",
        "xAxisFormatType": "{HH}:{mm}:{ss}",
        "xmin": "",
        "xmax": "",
        "yAxisLabel": "On/Off",
        "yAxisProperty": "value",
        "yAxisPropertyType": "property",
        "ymin": "0",
        "ymax": "1.1",
        "bins": 10,
        "action": "append",
        "stackSeries": false,
        "pointShape": "line",
        "pointRadius": "5",
        "showLegend": true,
        "removeOlder": "10",
        "removeOlderUnit": "60",
        "removeOlderPoints": "500",
        "colors": [
            "#0095ff",
            "#ff0000",
            "#ff7f0e",
            "#2ca02c",
            "#a347e1",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "textColor": [
            "#666666"
        ],
        "textColorDefault": true,
        "gridColor": [
            "#e5e5e5"
        ],
        "gridColorDefault": true,
        "width": "6",
        "height": "4",
        "className": "",
        "interpolation": "step",
        "x": 880,
        "y": 800,
        "wires": [
            []
        ]
    },
    {
        "id": "1bea16ead1291025",
        "type": "ui-chart",
        "z": "8914237e0d8e46c7",
        "g": "230bb82688833807",
        "group": "837da312967f08dd",
        "name": "",
        "label": "MultiGraph",
        "order": 3,
        "chartType": "line",
        "category": "labels",
        "categoryType": "property",
        "xAxisLabel": "",
        "xAxisProperty": "timestamp",
        "xAxisPropertyType": "property",
        "xAxisType": "time",
        "xAxisFormat": "",
        "xAxisFormatType": "{HH}:{mm}",
        "xmin": "",
        "xmax": "",
        "yAxisLabel": "",
        "yAxisProperty": "paylof",
        "yAxisPropertyType": "property",
        "ymin": "0",
        "ymax": "1200",
        "bins": 10,
        "action": "append",
        "stackSeries": false,
        "pointShape": "false",
        "pointRadius": 4,
        "showLegend": true,
        "removeOlder": "3",
        "removeOlderUnit": "60",
        "removeOlderPoints": "50",
        "colors": [
            "#0095ff",
            "#ff0000",
            "#ff7f0e",
            "#2ca02c",
            "#a347e1",
            "#d62728",
            "#ff9896",
            "#9467bd",
            "#c5b0d5"
        ],
        "textColor": [
            "#666666"
        ],
        "textColorDefault": true,
        "gridColor": [
            "#e5e5e5"
        ],
        "gridColorDefault": true,
        "width": 6,
        "height": "3",
        "className": "",
        "interpolation": "linear",
        "x": 1270,
        "y": 1540,
        "wires": [
            []
        ]
    },
    {
        "id": "400b6980b1a2cd45",
        "type": "ui-gauge",
        "z": "8914237e0d8e46c7",
        "g": "684238fb58a91415",
        "name": "Temperature",
        "group": "0eeeefa89ae3646a",
        "order": 11,
        "value": "payload",
        "valueType": "msg",
        "width": "3",
        "height": "3",
        "gtype": "gauge-half",
        "gstyle": "needle",
        "title": "Temperature",
        "alwaysShowTitle": false,
        "units": "°C",
        "icon": "thermometer",
        "prefix": "",
        "suffix": "°C",
        "segments": [
            {
                "from": "0",
                "color": "#5cd65c",
                "text": "",
                "textType": "label"
            },
            {
                "from": "60",
                "color": "#ffc800",
                "text": "",
                "textType": "label"
            },
            {
                "from": "90",
                "color": "#ea5353",
                "text": "",
                "textType": "label"
            }
        ],
        "min": 0,
        "max": "120",
        "sizeThickness": 16,
        "sizeGap": 4,
        "sizeKeyThickness": 8,
        "styleRounded": true,
        "styleGlow": false,
        "className": "",
        "x": 750,
        "y": 580,
        "wires": [
            []
        ]
    },
    {
        "id": "9122c1157cbe0b5e",
        "type": "ui-gauge",
        "z": "8914237e0d8e46c7",
        "g": "517edf10f355e464",
        "name": "Water Tank Level",
        "group": "0eeeefa89ae3646a",
        "order": 8,
        "width": "3",
        "height": "3",
        "gtype": "gauge-half",
        "gstyle": "needle",
        "title": "Water Tank Level",
        "units": "mL",
        "icon": "",
        "prefix": "",
        "suffix": "",
        "segments": [
            {
                "from": "0",
                "color": "#ff0000"
            },
            {
                "from": "100",
                "color": "#ffc800"
            },
            {
                "from": "200",
                "color": "#5cd65c"
            },
            {
                "from": "1000",
                "color": "#ffc800"
            },
            {
                "from": "1100",
                "color": "#ea5353"
            }
        ],
        "min": 0,
        "max": "1200",
        "sizeThickness": "60",
        "sizeGap": "6",
        "sizeKeyThickness": 8,
        "styleRounded": true,
        "styleGlow": false,
        "className": "",
        "x": 770,
        "y": 160,
        "wires": [
            []
        ]
    },
    {
        "id": "bbfc30b4f5fe5cdd",
        "type": "ui-gauge",
        "z": "8914237e0d8e46c7",
        "g": "d22591b8e78ebe7d",
        "name": "Milk Level",
        "group": "0eeeefa89ae3646a",
        "order": 9,
        "width": "3",
        "height": "3",
        "gtype": "gauge-half",
        "gstyle": "needle",
        "title": "Milk Level",
        "units": "ùmL",
        "icon": "",
        "prefix": "",
        "suffix": "",
        "segments": [
            {
                "from": "0",
                "color": "#d65c5c"
            },
            {
                "from": "250",
                "color": "#2dd248"
            },
            {
                "from": "1000",
                "color": "#ffc800"
            },
            {
                "from": "1500",
                "color": "#ea5353"
            }
        ],
        "min": 0,
        "max": "1500",
        "sizeThickness": 16,
        "sizeGap": 4,
        "sizeKeyThickness": 8,
        "styleRounded": true,
        "styleGlow": false,
        "className": "",
        "x": 740,
        "y": 300,
        "wires": [
            []
        ]
    },
    {
        "id": "f64ae2163a90f520",
        "type": "ui-gauge",
        "z": "8914237e0d8e46c7",
        "g": "29542b83f026fb7b",
        "name": "Coffee Beam",
        "group": "0eeeefa89ae3646a",
        "order": 10,
        "value": "payload",
        "valueType": "msg",
        "width": "3",
        "height": "3",
        "gtype": "gauge-half",
        "gstyle": "needle",
        "title": "Coffee Beam Level",
        "alwaysShowTitle": false,
        "units": "grams",
        "icon": "",
        "prefix": "",
        "suffix": "",
        "segments": [
            {
                "from": "0",
                "color": "#ffc800",
                "text": "",
                "textType": "label"
            },
            {
                "from": "30",
                "color": "#5cd65c",
                "text": "",
                "textType": "label"
            },
            {
                "from": "470",
                "color": "#ea5353",
                "text": "",
                "textType": "label"
            }
        ],
        "min": 0,
        "max": "600",
        "sizeThickness": 16,
        "sizeGap": 4,
        "sizeKeyThickness": 8,
        "styleRounded": true,
        "styleGlow": false,
        "className": "",
        "x": 750,
        "y": 440,
        "wires": [
            []
        ]
    },
    {
        "id": "798535950531337a",
        "type": "ui-markdown",
        "z": "8914237e0d8e46c7",
        "g": "62d148a7e9f5c520",
        "group": "0eeeefa89ae3646a",
        "name": "",
        "order": 2,
        "width": 0,
        "height": 0,
        "content": "# Status: {{msg.payload}}",
        "className": "",
        "x": 1590,
        "y": 740,
        "wires": [
            []
        ]
    },
    {
        "id": "0f373262c51c849b",
        "type": "ui-template",
        "z": "8914237e0d8e46c7",
        "g": "517edf10f355e464",
        "group": "0eeeefa89ae3646a",
        "page": "",
        "ui": "",
        "name": "SVG Dynamic Tank",
        "order": 3,
        "width": "12",
        "height": "3",
        "head": "",
        "format": "<template>\n  <svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 320 440\" preserveAspectRatio=\"xMidYMid meet\"\n    style=\"display:block;width:100%;height:100%\">\n    <defs>\n      <linearGradient id=\"waterGrad\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n        <stop offset=\"0%\" :stop-color=\"colors.top\" />\n        <stop offset=\"100%\" :stop-color=\"colors.bottom\" />\n      </linearGradient>\n      <linearGradient id=\"glassGrad\" x1=\"0\" y1=\"0\" x2=\"1\" y2=\"0\">\n        <stop offset=\"0%\" stop-color=\"rgba(255,255,255,0.85)\" />\n        <stop offset=\"50%\" stop-color=\"rgba(200,230,240,0.25)\" />\n        <stop offset=\"100%\" stop-color=\"rgba(255,255,255,0.85)\" />\n      </linearGradient>\n      <clipPath id=\"tankClip\">\n        <rect x=\"15\" y=\"20\" width=\"290\" height=\"400\" rx=\"12\" ry=\"12\" />\n      </clipPath>\n    </defs>\n    <rect x=\"15\" y=\"20\" width=\"290\" height=\"400\" rx=\"12\" ry=\"12\" fill=\"url(#glassGrad)\" stroke=\"#05434f\"\n      stroke-width=\"3\" />\n    <g clip-path=\"url(#tankClip)\">\n      <rect x=\"15\" :y=\"waterY\" width=\"290\" :height=\"420 - waterY\" fill=\"url(#waterGrad)\" />\n      <path\n        :d=\"`M -40 ${waterY} Q 20 ${waterY - 8} 80 ${waterY} T 200 ${waterY} T 320 ${waterY} T 440 ${waterY} V ${waterY + 30} H -40 Z`\"\n        :fill=\"colors.wave1\" opacity=\"0.9\">\n        <animateTransform attributeName=\"transform\" type=\"translate\" values=\"-40 0; 0 0; -40 0\" dur=\"4s\"\n          repeatCount=\"indefinite\" />\n      </path>\n      <path\n        :d=\"`M -40 ${waterY + 4} Q 30 ${waterY - 4} 90 ${waterY + 4} T 210 ${waterY + 4} T 330 ${waterY + 4} T 450 ${waterY + 4} V ${waterY + 30} H -40 Z`\"\n        :fill=\"colors.wave2\" opacity=\"0.55\">\n        <animateTransform attributeName=\"transform\" type=\"translate\" values=\"0 0; -40 0; 0 0\" dur=\"3s\"\n          repeatCount=\"indefinite\" />\n      </path>\n    </g>\n    <rect x=\"5\" y=\"184\" width=\"310\" height=\"12\" rx=\"6\" ry=\"6\" fill=\"#1895c2\" />\n    <rect x=\"5\" y=\"294\" width=\"310\" height=\"12\" rx=\"6\" ry=\"6\" fill=\"#1895c2\" />\n    <rect x=\"15\" y=\"20\" width=\"290\" height=\"400\" rx=\"12\" ry=\"12\" fill=\"none\" stroke=\"#05434f\" stroke-width=\"3\" />\n    <text x=\"160\" y=\"230\" text-anchor=\"middle\" dominant-baseline=\"middle\" font-family=\"sans-serif\" font-size=\"42\"\n      font-weight=\"700\" fill=\"#ffffff\" stroke=\"#05434f\" stroke-width=\"1.2\" style=\"paint-order: stroke fill\">{{ level\n      }}%</text>\n  </svg>\n</template>\n\n<script>\n  export default {\n  data() {\n    return { level: 0 };\n  },\n  computed: {\n    waterY() {\n      const l = Math.max(0, Math.min(100, Number(this.level) || 0));\n      return 420 - (l / 100) * 400;\n    },\n    colors() {\n      const l = Number(this.level) || 0;\n      if (l >= 98) return { top: '#f87171', bottom: '#991b1b', wave1: '#f87171', wave2: '#fecaca' };\n      if (l <= 15) return { top: '#fbbf24', bottom: '#b45309', wave1: '#fbbf24', wave2: '#fde68a' };\n      return { top: '#38bdf8', bottom: '#0369a1', wave1: '#38bdf8', wave2: '#7dd3fc' };\n    }\n  },\n  watch: {\n    msg(newMsg) {\n      if (newMsg && typeof newMsg.payload !== 'undefined') {\n        this.level = Math.ceil(Number(newMsg.payload)/10);\n      }\n    }\n  }\n}\n</script>",
        "storeOutMessages": true,
        "passthru": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 770,
        "y": 120,
        "wires": [
            []
        ]
    },
    {
        "id": "2456ee93776095bc",
        "type": "ui-template",
        "z": "8914237e0d8e46c7",
        "g": "54277e0eb0f4eddd",
        "group": "0eeeefa89ae3646a",
        "page": "",
        "ui": "",
        "name": "Namur",
        "order": 1,
        "width": "0",
        "height": "0",
        "head": "",
        "format": "<template>\n    <div> Namur Symbol : \n    <img width=\"20px\" height=\"20px\" :src=\"msg.payload.img\"></img> \n    <span>&nbsp;&nbsp;( {{msg.payload.text}} )</span>\n   </div>\n\n</template>\n",
        "storeOutMessages": true,
        "passthru": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 830,
        "y": 1640,
        "wires": [
            []
        ]
    },
    {
        "id": "143a262a2cbfe451",
        "type": "ui-template",
        "z": "8914237e0d8e46c7",
        "g": "665736b8cbeb246d",
        "group": "09c06667bee47085",
        "page": "",
        "ui": "",
        "name": "CoffeeMachineSynopsis",
        "order": 1,
        "width": "20",
        "height": "12",
        "head": "",
        "format": "    <template>\n      <svg\n        xmlns=\"http://www.w3.org/2000/svg\"\n        xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n        height=\"800px\"\n        width=\"1800px\"\n        version=\"1.1\"\n        id=\"Layer_1\"\n        viewBox=\"0 -220 800 800\"\n        xml:space=\"preserve\"\n        fill=\"none\"\n      >\n        <g id=\"Tank\" transform=\"translate(-210,-20)\">\n          <g id=\"SVGRepo_iconCarrier\">\n            <path\n              style=\"fill: rgba(195, 240, 241, 0.93)\"\n              d=\"M0,400 h190  v-400 h-190 z\"\n            ></path>\n            <path style=\"fill: rgb(95, 196, 217)\" :d=\"`M0,400 h190  v${d} h-190 z`\"></path>\n            <rect\n              x=\"0\"\n              y=\"0\"\n              width=\"190\"\n              height=\"400\"\n              fill=\"none\"\n              stroke=\"rgb(5, 67, 79)\"\n              stroke-width=\"3\"\n              rx=\"0\"\n              ry=\"0\"\n            ></rect>\n            <g>\n              <path\n                stroke=\"#1895c2\"\n                stroke-width=\"20\"\n                stroke-linecap=\"round\"\n                d=\"M-15,280 h210\"\n              />\n              <path\n                stroke=\"#1895c2\"\n                stroke-width=\"20\"\n                stroke-linecap=\"round\"\n                d=\"M-15,170 h210\"\n              />\n            </g>\n          </g>\n        </g>\n        <g id=\"CoffeeBean\" transform=\"translate(200,-150) scale(0.6,0.6)\">\n          <defs>\n            <pattern\n              id=\"coffeeBeanPattern\"\n              patternUnits=\"userSpaceOnUse\"\n              width=\"1224\"\n              height=\"816\"\n              x=\"-150\"\n            >\n              <image\n                href=\"https://images.pexels.com/photos/1695052/pexels-photo-1695052.jpeg\"\n                x=\"0\"\n                y=\"0\"\n                width=\"612\"\n                height=\"408\"\n              />\n            </pattern>\n          </defs>\n          <rect\n            x=\"0\"\n            y=\"0\"\n            width=\"190\"\n            height=\"300\"\n            fill=\"rgba(241, 244, 244, 0.92)\"\n            rx=\"10\"\n            ry=\"10\"\n          ></rect>\n          <rect\n            x=\"0\"\n            :y=\"`${c}`\"\n            width=\"190\"\n            :height=\"`${300 - c}`\"\n            _fill=\"red\"\n            fill=\"url(#coffeeBeanPattern)\"\n            rx=\"0\"\n            ry=\"0\"\n          ></rect>\n          <rect\n            x=\"0\"\n            y=\"0\"\n            width=\"190\"\n            height=\"300\"\n            fill=\"none\"\n            stroke=\"salmon\"\n            stroke-width=\"10\"\n            rx=\"10\"\n            ry=\"10\"\n          ></rect>\n          <path d=\"M 50 300 v 80\" stroke=\"salmon\" stroke-width=\"40\" />\n        </g>\n        <g id=\"cold-pipe\" :class=\"pipeClass\">\n          <!-- Pipe -->\n          <path\n            d=\"M -20 350 h 40 v -250\n               h 120\"\n            stroke=\"blue\"\n          />\n        </g>\n        <g id=\"hot-pipe\" :class=\"redPipeClass\">\n          <!-- Pipe -->\n          <path d=\"M 180 100 h 50 v 100\" stroke=\"red\" />\n        </g>\n\n        <!--Heater -->\n        <g transform=\"translate(150, 100)\">\n           <text x=\"0\" y=\"-32\" font-size=\"12\" fill=\"black\" text-anchor=\"middle\">{{ temperature }}</text>\n\n          <rect x=\"-25\" y=\"-25\" width=\"50\" height=\"50\" fill=\"gray\" />\n          <!-- serpentin -->\n          <path\n            :class=\"heaterClass\"\n            d=\"M -25 0 C -21.875 -5, -18.75 0, -15.625 5 S -12.5 0, -9.375 -5 S -6.25 0, -3.125 5 S 0 0, 3.125 -5 S 6.25 0, 9.375 5 S 12.5 0, 15.625 -5 S 18.75 0, 21.875 5 S 25 0, 25 0\"\n          />\n        </g>\n        <!--Pump -->\n        <g transform=\"translate(90, 100)\">\n          <!-- Pump body -->\n          <rect x=\"-25\" y=\"-25\" width=\"50\" height=\"50\" fill=\"gray\" />\n          <circle x=\"0\" y=\"0\" r=\"17\" stroke=\"blue\" stroke-width=\"5\" />\n          <g :class=\"impellerClass\">\n            <defs>\n              <path\n                id=\"pumpBlade\"\n                d=\"M -14 0 C -2.5 3, 2.5 3, 0 0\"\n                stroke=\"yellow\"\n                stroke-width=\"2\"\n                fill=\"none\"\n              />\n            </defs>\n            <use href=\"#pumpBlade\" transform=\"rotate(0)\" />\n            <use href=\"#pumpBlade\" transform=\"rotate(45)\" />\n            <use href=\"#pumpBlade\" transform=\"rotate(90)\" />\n            <use href=\"#pumpBlade\" transform=\"rotate(135)\" />\n            <use href=\"#pumpBlade\" transform=\"rotate(180)\" />\n            <use href=\"#pumpBlade\" transform=\"rotate(225)\" />\n            <use href=\"#pumpBlade\" transform=\"rotate(270)\" />\n            <use href=\"#pumpBlade\" transform=\"rotate(315)\" />\n          </g>\n        </g>\n        < !--Perco -->\n        <g transform=\"translate(230, 100)\">\n          <!-- Perco body -->\n          <rect :class=\"percoClass\" x=\"-25\" y=\"-25\" rx=\"3\" ry=\"3\" width=\"50\" height=\"50\"\n          fill=\"rgb(241, 222, 11)\" />\n        </g>\n\n        <!--Cup -->\n        <def>\n          <g id=\"cup\">\n            <g id=\"steam-out\" style=\"display: none\">\n              <rect x=\"166.389\" width=\"25.6\" height=\"102.4\" />\n              <rect x=\"115.197\" y=\"25.6\" width=\"25.6\" height=\"76.8\" />\n              <rect x=\"268.772\" y=\"64\" width=\"25.6\" height=\"38.4\" />\n              <rect x=\"217.58\" y=\"38.4\" width=\"25.6\" height=\"64\" />\n            </g>\n            <g id=\"cup-body\">\n              <path\n                d=\"M472.053,287.744c-7.919-52.087-49.041-95.744-100.898-105.762v-41.114c0-7.066-5.726-12.8-12.8-12.8l-307.157-0.026\n    \t\t\tc-7.066,0-12.8,5.717-12.8,12.783v307.149c0,38.4,25.6,63.991,63.983,63.991L307.172,512c38.4,0,63.983-25.6,63.974-63.983\n    \t\t\tv-15.531c47.727-9.754,86.204-45.918,98.347-93.269c2.449-9.515,3.123-15.607,3.866-25.395\n    \t\t\tC473.999,305.271,473.316,296.141,472.053,287.744z M345.563,448.017c0,24.252-14.14,38.383-38.391,38.383l-204.783-0.026\n    \t\t\tc-24.252,0-38.383-14.14-38.383-38.4V153.626l281.557,0.043V448.017z M427.594,368.478\n    \t\t\tc-11.836,15.846-28.262,28.117-46.831,34.918c-3.149,1.152-6.409,2.005-9.609,2.987V208.077l9.609,2.978\n    \t\t\tc3.055,1.306,6.178,2.44,9.173,3.891c5.939,2.859,11.597,6.298,16.87,10.24c18.56,13.875,32.137,33.988,37.897,56.457\n    \t\t\tC452.358,311.441,446.035,343.808,427.594,368.478z\"\n              />\n            </g>\n          </g>\n        </def>\n        <g id=\"cup-medium\" class=\"cup cuphidden\" transform=\"translate(180,160)scale(0.3,0.3)\">\n          <use href=\"#cup\" />\n        </g>\n        <g id=\"cup-small\" class=\"cup cuphidden\" transform=\"translate(190,176)scale(0.2,0.2)\">\n          <use href=\"#cup\" />\n        </g>\n        <g\n          id=\"cup-big\"\n          class=\"cup\"\n          :style=\"cupStyle\"\n          transform=\"translate(150,150)scale(0.4,0.4)\"\n        >\n          <use href=\"#cup\" />\n        </g>\n      </svg>\n\n      <pre id=\"debug\">\n        {{ payload }}\n        {{ { c, d, cupStyle } }}\n      </pre>\n    </template>\n\n    <script>\n    export default {\n      data() {\n        // define variables available component-wide\n        // (in <template> and component functions)\n        return {\n          isVisible: false,\n        };\n      },\n      computed: {\n        payload() {\n          console.log(\"in payload evaluation\");\n          if (!this.msg) {\n            return {\n              WaterTankLevel: 0,\n              CoffeeBeanLevel: 0,\n              CurrentState: 0,\n              PumpStatus: 2,\n              HeaterStatus: 2,\n              GrinderStatus: 1,\n              ValveStatus: 2,\n              BoilerTempWater: 20,\n            };\n          }\n          return this.msg.payload;\n        },\n        cupStyle() {\n          if (!this.payload) {\n            return \"display: none\";\n          }\n          const cupVisible = this.payload.CurrentState === 4;\n          return `display: ${cupVisible ? \"block\" : \"none\"}`;\n        },\n        d() {\n          if (!this.payload) {\n            return 0;\n          }\n          const height = (this.payload.WaterTankLevel || 0) / 10;\n          return (-height / 100) * 400;\n        },\n        c() {\n          if (!this.payload) {\n            return 0;\n          }\n          // L = 0 c= 300\n          return (100 - this.payload.CoffeeBeanLevel / 6) * 3;\n        },\n        impellerClass() {\n          if (!this.payload) {\n            return 0;\n          }\n          return this.payload.PumpStatus == 1 ? \"impeller-rotating\" : \"impellter-fix\";\n        },\n        heaterClass() {\n          if (!this.payload) {\n            return 0;\n          }\n          return this.payload.HeaterStatus == 1 ? \"serpentine-on\" : \"serpentine-off\";\n        },\n        pipeClass() {\n          if (!this.payload) {\n            return \"\";\n          }\n          return this.payload.PumpStatus == 1 ? \"pipe-draining\" : \"pipe-stopped\";\n        },\n        redPipeClass() {\n          if (!this.payload) {\n            return \"\";\n          }\n          return (this.payload.PumpStatus == 1  && this.payload.ValveStatus == 0) ? \"pipe-draining\" : \"pipe-invisible\";\n        },\n\n        percoClass() {\n          if (!this.payload) {\n            return \"\";\n          }\n          return this.payload.GrinderStatus == 1 ? \"percoClass-on\" : \"percoClass-off\";\n        },\n        temperature(){\n            if (!this.payload) return \"\";\n            const t = (this.payload.BoilerTempWater || 0).toFixed(1);\n            return  `${t} °C`;\n        }\n      },\n      methods: {\n        toggleVisibility() {\n          this.isVisible = !this.isVisible;\n        },\n        onButtonClick(buttonName) {\n          alert(`${buttonName} clicked!`);\n          // Add your method logic here\n        },\n      },\n    };\n    </script>\n\n    <style scoped>\n    .pipe-draining {\n      stroke-width: 10;\n      fill: none;\n      stroke-dasharray: 5;\n      animation: pipeAnimation 5s linear infinite;\n    }\n\n    .pipe-stopped {\n      stroke-width: 10;\n      fill: none;\n    }\n    .pipe-invisible {\n      display: none;\n      stroke-width: 0;\n      fill: none;  \n    }\n\n    .impeller-rotating {\n      animation: rotateImpeller 1s linear infinite;\n    }\n\n    .impeller-fix {\n    }\n\n    .cup {\n      fill: white;\n      stroke: black;\n      stroke-width: 2;\n    }\n\n    .serpentine-off {\n      stroke: black;\n      stroke-width: 4;\n      fill: none;\n    }\n\n    .serpentine-on {\n      stroke: red;\n      stroke-width: 4;\n      fill: none;\n      animation: glow 0.5s ease-in-out infinite alternate;\n    }\n\n    .cuphidden {\n      display: none;\n    }\n\n    .percoClass-off {\n    }\n    .percoClass-on {\n      animation: gridding 0.1s linear infinite alternate;\n    }\n    @keyframes gridding {\n      from {\n        transform: rotate(-15deg);\n      }\n      to {\n        transform: rotate(15deg);\n      }\n    }\n\n    @keyframes glow {\n      from {\n        stroke: red;\n        filter: drop-shadow(0 0 5px red);\n      }\n      to {\n        stroke: grey;\n        filter: drop-shadow(0 0 20px red);\n      }\n    }\n\n    @keyframes pipeAnimation {\n      to {\n        stroke-dashoffset: -20;\n      }\n    }\n\n    @keyframes rotateImpeller {\n      from {\n        transform: rotate(0deg);\n      }\n      to {\n        transform: rotate(360deg);\n      }\n    }\n    </style>\n",
        "storeOutMessages": true,
        "passthru": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 1070,
        "y": 1840,
        "wires": [
            []
        ]
    },
    {
        "id": "2b76f36de5725985",
        "type": "trigger",
        "z": "8914237e0d8e46c7",
        "name": "",
        "op1": "1",
        "op2": "0",
        "op1type": "val",
        "op2type": "val",
        "duration": "250",
        "extend": "false",
        "overrideDelay": "false",
        "units": "ms",
        "reset": "",
        "bytopic": "all",
        "topic": "topic",
        "outputs": 1,
        "x": 80,
        "y": 200,
        "wires": [
            []
        ]
    },
    {
        "id": "b4b79354c06cc405",
        "type": "subflow:c4495043459c465d",
        "z": "8914237e0d8e46c7",
        "g": "517edf10f355e464",
        "name": "",
        "x": 560,
        "y": 200,
        "wires": [
            [
                "a66ec0e0a1360f34"
            ]
        ]
    },
    {
        "id": "da3f9ba191429d15",
        "type": "subflow:c4495043459c465d",
        "z": "8914237e0d8e46c7",
        "g": "d22591b8e78ebe7d",
        "name": "",
        "x": 560,
        "y": 340,
        "wires": [
            [
                "ab80657e6899a890"
            ]
        ]
    },
    {
        "id": "77fa0ee8e20cbe27",
        "type": "subflow:c4495043459c465d",
        "z": "8914237e0d8e46c7",
        "g": "29542b83f026fb7b",
        "name": "",
        "x": 560,
        "y": 480,
        "wires": [
            [
                "ffdc07a2a8644ee7"
            ]
        ]
    },
    {
        "id": "61068469fd79b1a7",
        "type": "subflow:c4495043459c465d",
        "z": "8914237e0d8e46c7",
        "g": "684238fb58a91415",
        "name": "",
        "x": 560,
        "y": 620,
        "wires": [
            [
                "4f1eb368f3fb45c1"
            ]
        ]
    },
    {
        "id": "20844959a8ea715c",
        "type": "subflow:c4495043459c465d",
        "z": "8914237e0d8e46c7",
        "g": "b07d4a44ddb86adf",
        "name": "",
        "x": 540,
        "y": 800,
        "wires": [
            [
                "d3b1d8b5c05c2b22",
                "68e0c3653588a07d"
            ]
        ]
    },
    {
        "id": "9593045b235c321c",
        "type": "OpcUa-Endpoint2",
        "name": "",
        "endpoint": "opc.tcp://opcuademo.sterfive.com:26541",
        "securityMode": "None",
        "securityPolicy": "None",
        "userIdentityType": "Anonymous",
        "pkiName": "",
        "useTransport": false,
        "maxChunkCount": 1,
        "maxMessageSize": 8192,
        "receiveBufferSize": 8192,
        "sendBufferSize": 8192,
        "subscriptions": [
            {
                "id": "s0",
                "name": "Default Subscription",
                "isDefault": true,
                "parameters": {
                    "publishingEnabled": true,
                    "requestedLifetimeCount": "1000",
                    "requestedMaxKeepAliveCount": "10",
                    "requestedPublishingInterval": "1000",
                    "maxNotificationsPerPublish": "0",
                    "priority": "100"
                }
            },
            {
                "id": "s1",
                "name": "Slow Subscription",
                "isDefault": true,
                "parameters": {
                    "publishingEnabled": true,
                    "requestedLifetimeCount": "100",
                    "requestedMaxKeepAliveCount": "3",
                    "requestedPublishingInterval": "5000",
                    "maxNotificationsPerPublish": "100",
                    "priority": "10"
                }
            },
            {
                "id": "s2",
                "name": "Fast Subscription",
                "isDefault": true,
                "parameters": {
                    "publishingEnabled": true,
                    "requestedLifetimeCount": "4000",
                    "requestedMaxKeepAliveCount": "50",
                    "requestedPublishingInterval": "250",
                    "maxNotificationsPerPublish": "100",
                    "priority": "200"
                }
            }
        ],
        "namespaceAliases": [
            {
                "namespaceUri": "http://opcfoundation.org/UA/",
                "alias": "ua"
            },
            {
                "namespaceUri": "urn:opcuademo.sterfive.com:NodeOPCUA-Server-for-CTT",
                "alias": "ns1"
            },
            {
                "namespaceUri": "http://opcfoundation.org/UA/DI/",
                "alias": "di"
            },
            {
                "namespaceUri": "http://opcfoundation.org/UA/ADI/",
                "alias": "adi"
            },
            {
                "namespaceUri": "http://opcfoundation.org/UA/AutoID/",
                "alias": "autoId"
            },
            {
                "namespaceUri": "http://opcfoundation.org/UA/MachineVision",
                "alias": "machineVision"
            },
            {
                "namespaceUri": "http://opcfoundation.org/UA/Robotics/",
                "alias": "robotics"
            },
            {
                "namespaceUri": "http://opcfoundation.org/UA/CommercialKitchenEquipment/",
                "alias": "kitchen"
            },
            {
                "namespaceUri": "http://opcfoundation.org/UA/ISA95-JOBCONTROL_V2/",
                "alias": "isa95JobControl"
            },
            {
                "namespaceUri": "http://opcfoundation.org/UA/Dictionary/IRDI",
                "alias": "irdi"
            },
            {
                "namespaceUri": "http://opcfoundation.org/UA/IA/",
                "alias": "ia"
            },
            {
                "namespaceUri": "http://opcfoundation.org/UA/Machinery/",
                "alias": "machinery"
            },
            {
                "namespaceUri": "http://opcfoundation.org/UA/Machinery/Jobs/",
                "alias": "machineryJobs"
            },
            {
                "namespaceUri": "http://opcfoundation.org/UA/MachineTool/",
                "alias": "machineTool"
            },
            {
                "namespaceUri": "http://opcfoundation.org/UA/PackML/",
                "alias": "packML"
            },
            {
                "namespaceUri": "urn://node-opcua-simulator",
                "alias": "ns3"
            },
            {
                "namespaceUri": "http://sterfive.com/UA/CoffeeMachine/",
                "alias": "sterfive"
            }
        ]
    },
    {
        "id": "0eeeefa89ae3646a",
        "type": "ui-group",
        "name": "CoffeeMachineGroup",
        "page": "72c675db46ea859f",
        "width": "28",
        "height": "17",
        "order": 1,
        "showTitle": true,
        "className": "",
        "visible": "true",
        "disabled": "false",
        "groupType": "default"
    },
    {
        "id": "837da312967f08dd",
        "type": "ui-group",
        "name": "Experiment",
        "page": "9d05df9ca7e7c40b",
        "width": 6,
        "height": 1,
        "order": 1,
        "showTitle": true,
        "className": "",
        "visible": "true",
        "disabled": "false",
        "groupType": "default"
    },
    {
        "id": "09c06667bee47085",
        "type": "ui-group",
        "name": "CofeeMachineSynopsisGroup",
        "page": "cb68b56866ae7782",
        "width": "20",
        "height": "12",
        "order": 1,
        "showTitle": false,
        "className": "",
        "visible": "true",
        "disabled": "false",
        "groupType": "default"
    },
    {
        "id": "72c675db46ea859f",
        "type": "ui-page",
        "name": "CoffeeMachinePage",
        "ui": "ba750d2403672175",
        "path": "/CoffeeMachine",
        "icon": "coffee",
        "layout": "grid",
        "theme": "645ffb825f13937f",
        "breakpoints": [
            {
                "name": "Default",
                "px": "0",
                "cols": "3"
            },
            {
                "name": "Tablet",
                "px": "576",
                "cols": "6"
            },
            {
                "name": "Small Desktop",
                "px": "768",
                "cols": "9"
            },
            {
                "name": "Desktop",
                "px": "1024",
                "cols": "12"
            }
        ],
        "order": 4,
        "className": "",
        "visible": "true",
        "disabled": "false"
    },
    {
        "id": "9d05df9ca7e7c40b",
        "type": "ui-page",
        "name": "Coffee Machine Experiment",
        "ui": "ba750d2403672175",
        "path": "/CoffeeMachineExperiment",
        "icon": "home",
        "layout": "grid",
        "theme": "645ffb825f13937f",
        "breakpoints": [
            {
                "name": "Default",
                "px": 0,
                "cols": 3
            },
            {
                "name": "Tablet",
                "px": 576,
                "cols": 6
            },
            {
                "name": "Small Desktop",
                "px": 768,
                "cols": 9
            },
            {
                "name": "Desktop",
                "px": 1024,
                "cols": 12
            }
        ],
        "order": 3,
        "className": "",
        "visible": "true",
        "disabled": "false"
    },
    {
        "id": "cb68b56866ae7782",
        "type": "ui-page",
        "name": "CoffeeMachineSynopsys",
        "ui": "ba750d2403672175",
        "path": "/CoffeeMachineSynopsis",
        "icon": "home",
        "layout": "grid",
        "theme": "645ffb825f13937f",
        "breakpoints": [
            {
                "name": "Default",
                "px": "0",
                "cols": "3"
            },
            {
                "name": "Tablet",
                "px": "576",
                "cols": "6"
            },
            {
                "name": "Small Desktop",
                "px": "768",
                "cols": "9"
            },
            {
                "name": "Desktop",
                "px": "1024",
                "cols": "12"
            }
        ],
        "order": 2,
        "className": "",
        "visible": "true",
        "disabled": "false"
    },
    {
        "id": "ba750d2403672175",
        "type": "ui-base",
        "name": "My Dashboard",
        "path": "/dashboard",
        "appIcon": "",
        "includeClientData": true,
        "acceptsClientConfig": [
            "ui-notification",
            "ui-control"
        ],
        "showPathInSidebar": false,
        "headerContent": "page",
        "navigationStyle": "default",
        "titleBarStyle": "default",
        "showReconnectNotification": true,
        "notificationDisplayTime": 1,
        "showDisconnectNotification": true
    },
    {
        "id": "645ffb825f13937f",
        "type": "ui-theme",
        "name": "Default Theme",
        "colors": {
            "surface": "#ffffff",
            "primary": "#0094CE",
            "bgPage": "#eeeeee",
            "groupBg": "#ffffff",
            "groupOutline": "#cccccc"
        },
        "sizes": {
            "density": "default",
            "pagePadding": "12px",
            "groupGap": "12px",
            "groupBorderRadius": "4px",
            "widgetGap": "12px"
        }
    },
    {
        "id": "dd221095ed7119c7",
        "type": "global-config",
        "env": [],
        "modules": {
            "@opcua/for-node-red": "3.38.1"
        }
    }
]
