[ { "id": "monster_api_tab", "type": "tab", "label": "Monster API + Dashboard", "disabled": false, "info": "Full monster orchestration example with API integrations. Credentials are placeholders." }, { "id": "ui_base_monster_api", "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_api", "type": "ui-theme", "name": "Monster API 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_api", "type": "ui-page", "name": "Monster API", "ui": "ui_base_monster_api", "path": "/monster-api", "icon": "science", "layout": "grid", "theme": "ui_theme_monster_api", "breakpoints": [ { "name": "Default", "px": "0", "cols": "12" } ], "order": 1, "className": "" }, { "id": "ui_group_monster_api_ctrl", "type": "ui-group", "name": "Input", "page": "ui_page_monster_api", "width": "6", "height": "1", "order": 1, "showTitle": true, "className": "" }, { "id": "ui_group_monster_api_obs", "type": "ui-group", "name": "Output", "page": "ui_page_monster_api", "width": "12", "height": "1", "order": 2, "showTitle": true, "className": "" }, { "id": "monster_api_node", "type": "monster", "z": "monster_api_tab", "name": "Monster API", "samplingtime": "24", "minvolume": "5", "maxweight": "23", "nominalFlowMin": "1000", "flowMax": "6000", "maxRainRef": "10", "minSampleIntervalSec": "60", "emptyWeightBucket": "8.3", "aquon_sample_name": "112150", "enableLog": false, "logLevel": "error", "positionVsParent": "atEquipment", "positionIcon": "⊥", "hasDistance": false, "distance": "", "x": 980, "y": 320, "wires": [ [ "monster_api_parse_output", "monster_api_zinfo_prepare" ], [ "monster_api_dbg_influx" ], [ "monster_api_dbg_parent" ] ] }, { "id": "monster_api_info", "type": "comment", "z": "monster_api_tab", "name": "Template only: set credentials/URLs before production", "info": "All secrets in this flow are placeholders. Replace with env vars or credential nodes.", "x": 260, "y": 80, "wires": [] }, { "id": "monster_api_inj_flow", "type": "inject", "z": "monster_api_tab", "group": "ui_group_monster_api_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_api_build_flow" ] ] }, { "id": "monster_api_build_flow", "type": "function", "z": "monster_api_tab", "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": 390, "y": 180, "wires": [ [ "monster_api_node" ] ] }, { "id": "monster_api_inj_start", "type": "inject", "z": "monster_api_tab", "group": "ui_group_monster_api_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_api_node" ] ] }, { "id": "monster_api_weather_trigger", "type": "inject", "z": "monster_api_tab", "name": "Weather fetch (daily)", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "55 07 * * *", "once": false, "onceDelay": "", "topic": "", "payload": "", "payloadType": "date", "x": 190, "y": 420, "wires": [ [ "monster_api_weather_http" ] ] }, { "id": "monster_api_weather_http", "type": "http request", "z": "monster_api_tab", "name": "Open-Meteo", "method": "GET", "ret": "txt", "paytoqs": "ignore", "url": "https://api.open-meteo.com/v1/forecast?latitude=51.71&longitude=4.81&hourly=precipitation,precipitation_probability&timezone=Europe%2FBerlin&past_days=1&forecast_days=2", "tls": "", "persist": false, "proxy": "", "insecureHTTPParser": false, "authType": "", "senderr": false, "headers": [], "x": 380, "y": 420, "wires": [ [ "monster_api_weather_json" ] ] }, { "id": "monster_api_weather_json", "type": "json", "z": "monster_api_tab", "name": "rain_data", "property": "payload", "action": "", "pretty": false, "x": 550, "y": 420, "wires": [ [ "monster_api_weather_topic" ] ] }, { "id": "monster_api_weather_topic", "type": "change", "z": "monster_api_tab", "name": "topic rain_data", "rules": [ { "t": "set", "p": "topic", "pt": "msg", "to": "rain_data", "tot": "str" } ], "x": 720, "y": 420, "wires": [ [ "monster_api_node" ] ] }, { "id": "monster_api_aquon_trigger", "type": "inject", "z": "monster_api_tab", "name": "Aquon fetch (daily)", "props": [ { "p": "payload" } ], "repeat": "", "crontab": "15 07 * * *", "once": false, "onceDelay": "", "topic": "", "payload": "", "payloadType": "date", "x": 180, "y": 500, "wires": [ [ "monster_api_sftp_get" ] ] }, { "id": "monster_api_sftp_get", "type": "sftp in", "z": "monster_api_tab", "sftp": "monster_api_sftp_cfg", "operation": "get", "filename": "wsBD_MONSTERNAMETIJDEN.csv", "localFilename": "./.node-red/node_modules/typicals/monster/config/monsternametijden.csv", "name": "Aquon schedule", "x": 380, "y": 500, "wires": [ [ "monster_api_file_in" ] ] }, { "id": "monster_api_file_in", "type": "file in", "z": "monster_api_tab", "name": "read monsternametijden", "filename": "./.node-red/node_modules/typicals/monster/config/monsternametijden.csv", "filenameType": "str", "format": "utf8", "chunk": false, "sendError": false, "encoding": "none", "allProps": false, "x": 590, "y": 500, "wires": [ [ "monster_api_csv" ] ] }, { "id": "monster_api_csv", "type": "csv", "z": "monster_api_tab", "name": "monsternametijden", "sep": ",", "hdrin": true, "hdrout": "all", "multi": "mult", "ret": "\\n", "temp": "SAMPLE_NAME,DESCRIPTION,SAMPLED_DATE,START_DATE,END_DATE", "skip": "0", "strings": true, "include_empty_strings": "", "include_null_values": "", "x": 780, "y": 500, "wires": [ [ "monster_api_schedule_topic" ] ] }, { "id": "monster_api_schedule_topic", "type": "change", "z": "monster_api_tab", "name": "topic monsternametijden", "rules": [ { "t": "set", "p": "topic", "pt": "msg", "to": "monsternametijden", "tot": "str" } ], "x": 990, "y": 500, "wires": [ [ "monster_api_node" ] ] }, { "id": "monster_api_zinfo_prepare", "type": "function", "z": "monster_api_tab", "name": "Z-Info prepare on run stop", "func": "const p=(msg&&msg.payload&&typeof msg.payload==='object')?msg.payload:{};\nconst runningNow=Boolean(p.running);\nconst runningPrev=Boolean(context.get('runningPrev'));\ncontext.set('runningPrev',runningNow);\nif(!(runningPrev && !runningNow)){\n return null;\n}\nconst today=new Date();\nconst day=String(today.getDate()).padStart(2,'0');\nconst month=String(today.getMonth()+1).padStart(2,'0');\nconst year=today.getFullYear();\nconst yesterdayDate=new Date(today.getTime()-24*3600*1000);\nconst yDay=String(yesterdayDate.getDate()).padStart(2,'0');\nconst yMonth=String(yesterdayDate.getMonth()+1).padStart(2,'0');\nconst yYear=yesterdayDate.getFullYear();\nmsg.zinfoDateFrom=`${yYear}-${yMonth}-${yDay}`;\nmsg.zinfoDateUntil=`${year}-${month}-${day}`;\nmsg.zinfoData={\n m3Total:Number(p.m3Total||0),\n pulse:Math.max(0,Math.floor(Number(p.m3PerPuls||p.m3PerPulse||0)))\n};\nmsg.payload='grant_type=password&username=__SET_ZINFO_USERNAME__&password=__SET_ZINFO_PASSWORD__&client_id=__SET_ZINFO_CLIENT_ID__&client_secret=__SET_ZINFO_CLIENT_SECRET__';\nmsg.headers=msg.headers||{};\nmsg.headers['content-type']='application/x-www-form-urlencoded';\nreturn msg;", "outputs": 1, "noerr": 0, "x": 1260, "y": 320, "wires": [ [ "monster_api_zinfo_token" ] ] }, { "id": "monster_api_zinfo_token", "type": "http request", "z": "monster_api_tab", "name": "Z-Info token", "method": "POST", "ret": "txt", "paytoqs": "ignore", "url": "https://__SET_ZINFO_HOST__/WSR/zi_wsr.svc/token", "tls": "", "persist": false, "proxy": "", "insecureHTTPParser": false, "authType": "", "senderr": false, "headers": [], "x": 1450, "y": 320, "wires": [ [ "monster_api_zinfo_token_json" ] ] }, { "id": "monster_api_zinfo_token_json", "type": "json", "z": "monster_api_tab", "name": "token json", "property": "payload", "action": "", "pretty": false, "x": 1630, "y": 320, "wires": [ [ "monster_api_zinfo_import_builder" ] ] }, { "id": "monster_api_zinfo_import_builder", "type": "function", "z": "monster_api_tab", "name": "Build Z-Info import", "func": "const token=msg.payload&&msg.payload.access_token;\nconst z=msg.zinfoData||{};\nconst from=msg.zinfoDateFrom;\nconst until=msg.zinfoDateUntil;\nconst ns='__SET_ZINFO_NAMESPACE__';\nmsg.payload={\n import:{\n algemeen:{\n AanleverendeOrganisatie:'NL.25',\n Versie:'IMm2018',\n Batchid:`ZI_PA_NL.25_${Date.now()}.json`,\n Systeembron:'WBD/NEERSG',\n Systeemdoel:'HWH/Z-info',\n Opmerking:'template'\n },\n data:[{\n Meetwaarden:[\n {mepid:`${ns}.F021.m3`,dbmDtm:from,dbmTijd:'06:00',demDtm:until,demTijd:'06:00',mwdWaarde:`${Number(z.m3Total||0)}`,mwdWaardeAN:'',nMwd:'',mwdOpmerk:'template'},\n {mepid:`${ns}.Q000.PULS`,dbmDtm:from,dbmTijd:'06:00',demDtm:until,demTijd:'06:00',mwdWaarde:`${Number(z.pulse||0)}`,mwdWaardeAN:'',nMwd:'',mwdOpmerk:'template'}\n ]\n }]\n }\n};\nmsg.headers=msg.headers||{};\nif(token){msg.headers.authorization='Bearer '+token;}\nmsg.headers['content-type']='application/json';\nreturn msg;", "outputs": 1, "noerr": 0, "x": 1830, "y": 320, "wires": [ [ "monster_api_zinfo_import_put" ] ] }, { "id": "monster_api_zinfo_import_put", "type": "http request", "z": "monster_api_tab", "name": "Z-Info import PUT", "method": "PUT", "ret": "txt", "paytoqs": "ignore", "url": "https://__SET_ZINFO_HOST__/WSR/zi_wsr.svc/json/NL.25/importmwd/pa/?gebruiker=__SET_ZINFO_USER__", "tls": "", "persist": false, "proxy": "", "insecureHTTPParser": false, "authType": "", "senderr": false, "headers": [], "x": 2040, "y": 320, "wires": [ [ "monster_api_dbg_zinfo" ] ] }, { "id": "monster_api_dbg_zinfo", "type": "debug", "z": "monster_api_tab", "name": "Z-Info response", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "targetType": "full", "x": 2250, "y": 320, "wires": [] }, { "id": "monster_api_parse_output", "type": "function", "z": "monster_api_tab", "name": "Parse output for dashboard", "func": "const p=(msg&&msg.payload&&typeof msg.payload==='object')?msg.payload:{};\nconst now=Date.now();\nconst m3PerPuls=Number(p.m3PerPuls||p.m3PerPulse);\nreturn [\n Number.isFinite(Number(p.q))?{topic:'q_m3h',payload:Number(p.q),timestamp:now}:null,\n Number.isFinite(Number(p.m3Total))?{topic:'m3_total',payload:Number(p.m3Total),timestamp:now}:null,\n Number.isFinite(Number(p.bucketVol))?{topic:'bucket_l',payload:Number(p.bucketVol),timestamp:now}:null,\n Number.isFinite(m3PerPuls)?{topic:'m3_per_pulse',payload:m3PerPuls,timestamp:now}:null,\n {topic:'status',payload:`running=${Boolean(p.running)} | pulse=${Boolean(p.pulse)} | m3PerPuls=${Number.isFinite(m3PerPuls)?m3PerPuls:'n/a'} | missed=${Number(p.missedSamples||0)}`}\n];", "outputs": 5, "noerr": 0, "x": 1240, "y": 220, "wires": [ [ "monster_api_chart_q" ], [ "monster_api_chart_total" ], [ "monster_api_chart_bucket" ], [ "monster_api_chart_pulse" ], [ "monster_api_text_status" ] ] }, { "id": "monster_api_chart_q", "type": "ui-chart", "z": "monster_api_tab", "group": "ui_group_monster_api_obs", "name": "q", "label": "Flow q (m3/h)", "order": 1, "width": 6, "height": 4, "chartType": "line", "category": "topic", "categoryType": "msg", "xAxisType": "time", "xAxisPropertyType": "timestamp", "yAxisProperty": "payload", "yAxisPropertyType": "msg", "removeOlder": "30", "removeOlderUnit": "60", "showLegend": false, "action": "append", "x": 1470, "y": 120, "wires": [] }, { "id": "monster_api_chart_total", "type": "ui-chart", "z": "monster_api_tab", "group": "ui_group_monster_api_obs", "name": "m3Total", "label": "m3Total", "order": 2, "width": 6, "height": 4, "chartType": "line", "category": "topic", "categoryType": "msg", "xAxisType": "time", "xAxisPropertyType": "timestamp", "yAxisProperty": "payload", "yAxisPropertyType": "msg", "removeOlder": "30", "removeOlderUnit": "60", "showLegend": false, "action": "append", "x": 1480, "y": 180, "wires": [] }, { "id": "monster_api_chart_bucket", "type": "ui-chart", "z": "monster_api_tab", "group": "ui_group_monster_api_obs", "name": "bucket", "label": "Bucket (L)", "order": 3, "width": 6, "height": 4, "chartType": "line", "category": "topic", "categoryType": "msg", "xAxisType": "time", "xAxisPropertyType": "timestamp", "yAxisProperty": "payload", "yAxisPropertyType": "msg", "removeOlder": "30", "removeOlderUnit": "60", "showLegend": false, "action": "append", "x": 1480, "y": 240, "wires": [] }, { "id": "monster_api_chart_pulse", "type": "ui-chart", "z": "monster_api_tab", "group": "ui_group_monster_api_obs", "name": "m3PerPuls", "label": "m3PerPuls", "order": 4, "width": 6, "height": 4, "chartType": "line", "category": "topic", "categoryType": "msg", "xAxisType": "time", "xAxisPropertyType": "timestamp", "yAxisProperty": "payload", "yAxisPropertyType": "msg", "removeOlder": "30", "removeOlderUnit": "60", "showLegend": false, "action": "append", "x": 1490, "y": 300, "wires": [] }, { "id": "monster_api_text_status", "type": "ui-text", "z": "monster_api_tab", "group": "ui_group_monster_api_obs", "name": "status", "label": "Status", "order": 5, "width": 12, "height": 1, "format": "{{msg.payload}}", "layout": "row-spread", "x": 1460, "y": 360, "wires": [] }, { "id": "monster_api_dashboardapi", "type": "dashboardapi", "z": "monster_api_tab", "name": "dashboard template", "x": 1430, "y": 420, "wires": [ [ "monster_api_grafana_post" ] ] }, { "id": "monster_api_grafana_post", "type": "http request", "z": "monster_api_tab", "name": "Grafana dashboard API", "method": "POST", "ret": "txt", "paytoqs": "ignore", "url": "https://__SET_GRAFANA_HOST__/api/dashboards/db", "tls": "", "persist": false, "proxy": "", "insecureHTTPParser": false, "authType": "", "senderr": false, "headers": [], "x": 1650, "y": 420, "wires": [ [ "monster_api_dbg_dashboard" ] ] }, { "id": "monster_api_dbg_dashboard", "type": "debug", "z": "monster_api_tab", "name": "dashboard API response", "active": false, "tosidebar": true, "console": false, "tostatus": false, "complete": "false", "targetType": "full", "x": 1870, "y": 420, "wires": [] }, { "id": "monster_api_dbg_influx", "type": "debug", "z": "monster_api_tab", "name": "influx output", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "x": 1240, "y": 460, "wires": [] }, { "id": "monster_api_dbg_parent", "type": "debug", "z": "monster_api_tab", "name": "parent output", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "true", "targetType": "full", "x": 1230, "y": 500, "wires": [] }, { "id": "monster_api_sftp_cfg", "type": "sftp", "host": "__SET_AQUON_SFTP_HOST__", "port": "22", "username": "__SET_AQUON_SFTP_USERNAME__", "password": "__SET_AQUON_SFTP_PASSWORD__", "hmac": [], "cipher": [] } ]