[ { "id": "monster_tab_demo", "type": "tab", "label": "Monster Dashboard Demo", "disabled": false, "info": "Dashboard-focused example for monster output visualization" }, { "id": "ui_base_monster_demo", "type": "ui-base", "name": "EVOLV Demo", "path": "/dashboard", "appIcon": "", "includeClientData": true, "acceptsClientConfig": [ "ui-notification", "ui-control" ], "showPathInSidebar": false, "headerContent": "page", "navigationStyle": "default", "titleBarStyle": "default" }, { "id": "ui_theme_monster_demo", "type": "ui-theme", "name": "EVOLV Monster Theme", "colors": { "surface": "#ffffff", "primary": "#4f8582", "bgPage": "#efefef", "groupBg": "#ffffff", "groupOutline": "#d8d8d8" }, "sizes": { "density": "default", "pagePadding": "14px", "groupGap": "14px", "groupBorderRadius": "6px", "widgetGap": "12px" } }, { "id": "ui_page_monster_demo", "type": "ui-page", "name": "Monster Demo", "ui": "ui_base_monster_demo", "path": "/monster-demo", "icon": "science", "layout": "grid", "theme": "ui_theme_monster_demo", "breakpoints": [ { "name": "Default", "px": "0", "cols": "12" } ], "order": 1, "className": "" }, { "id": "ui_group_monster_ctrl", "type": "ui-group", "name": "Monster Inputs", "page": "ui_page_monster_demo", "width": "6", "height": "1", "order": 1, "showTitle": true, "className": "" }, { "id": "ui_group_monster_obs", "type": "ui-group", "name": "Monster Output", "page": "ui_page_monster_demo", "width": "12", "height": "1", "order": 2, "showTitle": true, "className": "" }, { "id": "monster_node_demo", "type": "monster", "z": "monster_tab_demo", "name": "Monster Demo", "samplingtime": "24", "minvolume": "5", "maxweight": "23", "nominalFlowMin": "1000", "flowMax": "6000", "maxRainRef": "10", "minSampleIntervalSec": "60", "emptyWeightBucket": "8.3", "aquon_sample_name": "112150", "uuid": "", "supplier": "monster", "category": "monster", "assetType": "sampling-cabinet", "model": "monster-standard", "unit": "m3/h", "enableLog": false, "logLevel": "error", "positionVsParent": "atEquipment", "positionIcon": "⊥", "hasDistance": false, "distance": "", "x": 900, "y": 260, "wires": [ [ "monster_parse_output" ], [ "monster_debug_influx" ], [ "monster_debug_parent" ] ] }, { "id": "monster_flow_inject", "type": "inject", "z": "monster_tab_demo", "group": "ui_group_monster_ctrl", "name": "Flow 1800 m3/h", "props": [ { "p": "payload" } ], "repeat": "5", "crontab": "", "once": true, "onceDelay": "1", "topic": "", "payload": "1800", "payloadType": "num", "x": 170, "y": 180, "wires": [ [ "monster_build_flow" ] ] }, { "id": "monster_build_flow", "type": "function", "z": "monster_tab_demo", "name": "Build input_q", "func": "msg.topic = 'input_q';\nmsg.payload = { value: Number(msg.payload), unit: 'm3/h' };\nreturn Number.isFinite(msg.payload.value) ? msg : null;", "outputs": 1, "noerr": 0, "x": 380, "y": 180, "wires": [ [ "monster_node_demo" ] ] }, { "id": "monster_start_inject", "type": "inject", "z": "monster_tab_demo", "group": "ui_group_monster_ctrl", "name": "Manual Start", "props": [ { "p": "topic", "vt": "str" }, { "p": "payload" } ], "repeat": "", "crontab": "", "once": false, "onceDelay": "0.1", "topic": "i_start", "payload": "true", "payloadType": "bool", "x": 160, "y": 240, "wires": [ [ "monster_node_demo" ] ] }, { "id": "monster_rain_inject", "type": "inject", "z": "monster_tab_demo", "group": "ui_group_monster_ctrl", "name": "Seed rain_data", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": true, "onceDelay": "2", "topic": "", "payload": "", "payloadType": "date", "x": 160, "y": 300, "wires": [ [ "monster_build_rain" ] ] }, { "id": "monster_build_rain", "type": "function", "z": "monster_tab_demo", "name": "Build rain_data", "func": "const now = new Date();\nconst mk = (offset, rain, prob) => {\n const d = new Date(now.getTime() + offset * 3600 * 1000);\n return { t: d.toISOString().slice(0, 13) + ':00', rain, prob };\n};\nconst rows = [mk(-1, 0.2, 20), mk(0, 0.8, 40), mk(1, 1.1, 60), mk(2, 0.5, 30)];\nmsg.topic = 'rain_data';\nmsg.payload = [\n {\n latitude: 51.71,\n longitude: 4.81,\n hourly: {\n time: rows.map(r => r.t),\n precipitation: rows.map(r => r.rain),\n precipitation_probability: rows.map(r => r.prob)\n }\n }\n];\nreturn msg;", "outputs": 1, "noerr": 0, "x": 380, "y": 300, "wires": [ [ "monster_node_demo" ] ] }, { "id": "monster_schedule_inject", "type": "inject", "z": "monster_tab_demo", "group": "ui_group_monster_ctrl", "name": "Seed monsternametijden", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "", "once": true, "onceDelay": "3", "topic": "", "payload": "", "payloadType": "date", "x": 190, "y": 360, "wires": [ [ "monster_build_schedule" ] ] }, { "id": "monster_build_schedule", "type": "function", "z": "monster_tab_demo", "name": "Build monsternametijden", "func": "const now = new Date();\nconst next = new Date(now.getTime() + 24 * 3600 * 1000);\nconst end = new Date(next.getTime() + 24 * 3600 * 1000);\nmsg.topic = 'monsternametijden';\nmsg.payload = [\n {\n SAMPLE_NAME: '112150',\n DESCRIPTION: 'demo schedule',\n SAMPLED_DATE: next.toISOString().slice(0, 19).replace('T', ' '),\n START_DATE: next.toISOString().slice(0, 19).replace('T', ' '),\n END_DATE: end.toISOString().slice(0, 19).replace('T', ' ')\n }\n];\nreturn msg;", "outputs": 1, "noerr": 0, "x": 410, "y": 360, "wires": [ [ "monster_node_demo" ] ] }, { "id": "monster_parse_output", "type": "function", "z": "monster_tab_demo", "name": "Parse monster output", "func": "const p = (msg && msg.payload && typeof msg.payload === 'object') ? msg.payload : {};\nconst now = Date.now();\nconst q = Number(p.q);\nconst total = Number(p.m3Total);\nconst bucket = Number(p.bucketVol);\nconst rem = Number(p.pulsesRemaining);\nconst m3PerPulse = Number(p.m3PerPuls || p.m3PerPulse);\nconst status = `running=${Boolean(p.running)} | pulse=${Boolean(p.pulse)} | m3PerPuls=${Number.isFinite(m3PerPulse) ? m3PerPulse : 'n/a'} | missed=${Number(p.missedSamples || 0)}`;\nreturn [\n Number.isFinite(q) ? { topic: 'q_m3h', payload: q, timestamp: now } : null,\n Number.isFinite(total) ? { topic: 'm3_total', payload: total, timestamp: now } : null,\n Number.isFinite(bucket) ? { topic: 'bucket_l', payload: bucket, timestamp: now } : null,\n Number.isFinite(rem) ? { topic: 'pulses_remaining', payload: rem, timestamp: now } : null,\n Number.isFinite(m3PerPulse) ? { topic: 'm3_per_pulse', payload: m3PerPulse, timestamp: now } : null,\n { topic: 'status', payload: status }\n];", "outputs": 6, "noerr": 0, "x": 1130, "y": 260, "wires": [ [ "monster_chart_q" ], [ "monster_chart_m3total" ], [ "monster_chart_bucket" ], [ "monster_chart_remaining" ], [ "monster_chart_m3pulse" ], [ "monster_text_status" ] ] }, { "id": "monster_chart_q", "type": "ui-chart", "z": "monster_tab_demo", "group": "ui_group_monster_obs", "name": "Flow q", "label": "Flow q (m3/h)", "order": 1, "width": 6, "height": 4, "chartType": "line", "category": "topic", "categoryType": "msg", "xAxisType": "time", "xAxisPropertyType": "timestamp", "yAxisPropertyType": "msg", "yAxisProperty": "payload", "removeOlder": "30", "removeOlderUnit": "60", "showLegend": false, "action": "append", "x": 1370, "y": 120, "wires": [] }, { "id": "monster_chart_m3total", "type": "ui-chart", "z": "monster_tab_demo", "group": "ui_group_monster_obs", "name": "m3 Total", "label": "m3Total (m3)", "order": 2, "width": 6, "height": 4, "chartType": "line", "category": "topic", "categoryType": "msg", "xAxisType": "time", "xAxisPropertyType": "timestamp", "yAxisPropertyType": "msg", "yAxisProperty": "payload", "removeOlder": "30", "removeOlderUnit": "60", "showLegend": false, "action": "append", "x": 1380, "y": 180, "wires": [] }, { "id": "monster_chart_bucket", "type": "ui-chart", "z": "monster_tab_demo", "group": "ui_group_monster_obs", "name": "Bucket Volume", "label": "Bucket (L)", "order": 3, "width": 6, "height": 4, "chartType": "line", "category": "topic", "categoryType": "msg", "xAxisType": "time", "xAxisPropertyType": "timestamp", "yAxisPropertyType": "msg", "yAxisProperty": "payload", "removeOlder": "30", "removeOlderUnit": "60", "showLegend": false, "action": "append", "x": 1380, "y": 240, "wires": [] }, { "id": "monster_chart_remaining", "type": "ui-chart", "z": "monster_tab_demo", "group": "ui_group_monster_obs", "name": "Pulses Remaining", "label": "Pulses Remaining", "order": 4, "width": 6, "height": 4, "chartType": "line", "category": "topic", "categoryType": "msg", "xAxisType": "time", "xAxisPropertyType": "timestamp", "yAxisPropertyType": "msg", "yAxisProperty": "payload", "removeOlder": "30", "removeOlderUnit": "60", "showLegend": false, "action": "append", "x": 1400, "y": 300, "wires": [] }, { "id": "monster_chart_m3pulse", "type": "ui-chart", "z": "monster_tab_demo", "group": "ui_group_monster_obs", "name": "m3 per pulse", "label": "m3PerPuls", "order": 5, "width": 6, "height": 4, "chartType": "line", "category": "topic", "categoryType": "msg", "xAxisType": "time", "xAxisPropertyType": "timestamp", "yAxisPropertyType": "msg", "yAxisProperty": "payload", "removeOlder": "30", "removeOlderUnit": "60", "showLegend": false, "action": "append", "x": 1390, "y": 360, "wires": [] }, { "id": "monster_text_status", "type": "ui-text", "z": "monster_tab_demo", "group": "ui_group_monster_obs", "name": "Sampling status", "label": "Status", "order": 6, "width": 12, "height": 1, "format": "{{msg.payload}}", "layout": "row-spread", "x": 1380, "y": 420, "wires": [] }, { "id": "monster_debug_influx", "type": "debug", "z": "monster_tab_demo", "name": "Influx output", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "x": 1130, "y": 320, "wires": [] }, { "id": "monster_debug_parent", "type": "debug", "z": "monster_tab_demo", "name": "Parent output", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "x": 1130, "y": 360, "wires": [] } ]