[ { "id": "ea088d9e256f2e4a", "type": "tab", "label": "Raspi", "disabled": false, "info": "", "env": [] }, { "id": "ea803f6a2965854b", "type": "mqtt-broker", "name": "Broker fuera casa", "broker": "mqtt.maliountech.com.mx", "port": "1883", "clientid": "raspi-maquina1", "autoConnect": true, "usetls": false, "protocolVersion": 4, "keepalive": "30", "cleansession": false, "autoUnsubscribe": true, "birthTopic": "", "birthQos": "0", "birthRetain": "false", "birthPayload": "", "birthMsg": {}, "closeTopic": "", "closeQos": "0", "closeRetain": "false", "closePayload": "", "closeMsg": {}, "willTopic": "", "willQos": "0", "willRetain": "false", "willPayload": "", "willMsg": {}, "userProps": "", "sessionExpiry": "" }, { "id": "615493954251cda9", "type": "ui_tab", "name": "Home", "icon": "dashboard", "disabled": false, "hidden": false }, { "id": "6fe5cca8f548047a", "type": "ui_group", "name": "HMI Dashboard", "tab": "615493954251cda9", "order": 1, "disp": true, "width": "25", "collapse": false, "className": "" }, { "id": "fa0582493cd77ae7", "type": "ui_base", "theme": { "name": "theme-light", "lightTheme": { "default": "#0094CE", "baseColor": "#0094CE", "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", "edited": false }, "darkTheme": { "default": "#097479", "baseColor": "#097479", "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", "edited": false }, "customTheme": { "name": "Untitled Theme 1", "default": "#4B7930", "baseColor": "#4B7930", "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" }, "themeState": { "base-color": { "default": "#0094CE", "value": "#0094CE", "edited": false }, "page-titlebar-backgroundColor": { "value": "#0094CE", "edited": false }, "page-backgroundColor": { "value": "#fafafa", "edited": false }, "page-sidebar-backgroundColor": { "value": "#ffffff", "edited": false }, "group-textColor": { "value": "#1bbfff", "edited": false }, "group-borderColor": { "value": "#ffffff", "edited": false }, "group-backgroundColor": { "value": "#ffffff", "edited": false }, "widget-textColor": { "value": "#111111", "edited": false }, "widget-backgroundColor": { "value": "#0094ce", "edited": false }, "widget-borderColor": { "value": "#ffffff", "edited": false }, "base-font": { "value": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif" } }, "angularTheme": { "primary": "indigo", "accents": "blue", "warn": "red", "background": "grey", "palette": "light" } }, "site": { "name": "Node-RED Dashboard", "hideToolbar": "false", "allowSwipe": "false", "lockMenu": "false", "allowTempTheme": "true", "dateFormat": "DD/MM/YYYY", "sizes": { "sx": 48, "sy": 48, "gx": 6, "gy": 6, "cx": 6, "cy": 6, "px": 0, "py": 0 } } }, { "id": "d9407fca93d82949", "type": "function", "z": "ea088d9e256f2e4a", "name": "Machine status function", "func": "// Get previous state\nconst previousStatus = global.get(\"machine_status\") || {\n state: 'Running',\n isOnline: true,\n isRunning: true\n};\n\nlet state = previousStatus.state;\n\n// Random transitions\nif (Math.random() < 0.5) {\n state = state === 'Running' ? 'Stopped' : 'Running';\n}\n\n// Create status data\nconst statusData = {\n state: state,\n isOnline: state !== 'Error',\n isRunning: state === 'Running',\n timestamp: new Date().toISOString()\n};\n\n// Store in global\nglobal.set(\"machine_status\", statusData);\n\n// Send to UI\nmsg.payload = statusData;\nmsg.topic = \"pimsa/maquina1/status\";\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 470, "y": 120, "wires": [ [ "aaf07ca380495b06", "c195f94afd7183e6" ] ] }, { "id": "547062128fa6337a", "type": "inject", "z": "ea088d9e256f2e4a", "name": "Machine Data Timer", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "1", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 140, "y": 300, "wires": [ [ "d9407fca93d82949", "207fdc449918affd", "031c7ccb3125177b", "2a35e2907dc04de0" ] ] }, { "id": "4f66d69c5bce7ba0", "type": "mqtt out", "z": "ea088d9e256f2e4a", "name": "MQTT Out - Work Order", "topic": "pimsa/erp/workorder/current", "qos": "1", "retain": "true", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "ea803f6a2965854b", "x": 810, "y": 540, "wires": [] }, { "id": "aaf07ca380495b06", "type": "mqtt out", "z": "ea088d9e256f2e4a", "name": "MQTT Out - Machine Status", "topic": "pimsa/maquina1/status", "qos": "1", "retain": "true", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "ea803f6a2965854b", "x": 820, "y": 120, "wires": [] }, { "id": "fee4e024db51e661", "type": "mqtt out", "z": "ea088d9e256f2e4a", "name": "MQTT Out - Machine OEE", "topic": "pimsa/maquina1/oee", "qos": "0", "retain": "false", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "ea803f6a2965854b", "x": 800, "y": 260, "wires": [] }, { "id": "12c37a80895dcc3e", "type": "mqtt out", "z": "ea088d9e256f2e4a", "name": "MQTT Out - Production", "topic": "pimsa/maquina1/production", "qos": "1", "retain": "false", "respTopic": "", "contentType": "", "userProps": "", "correl": "", "expiry": "", "broker": "ea803f6a2965854b", "x": 810, "y": 400, "wires": [] }, { "id": "207fdc449918affd", "type": "function", "z": "ea088d9e256f2e4a", "name": "OEE Function", "func": "// OEE Function\nconst oeeData = {\n oee: 85 + Math.random() * 15,\n availability: 90 + Math.random() * 10,\n performance: 80 + Math.random() * 20,\n quality: 95 + Math.random() * 5,\n timestamp: new Date().toISOString()\n};\n\n// Store in global context (NEW!)\nglobal.set(\"oeeData\", oeeData);\n\nmsg.payload = oeeData;\nmsg.topic = \"pimsa/maquina1/oee\";\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 440, "y": 260, "wires": [ [ "fee4e024db51e661", "c195f94afd7183e6" ] ] }, { "id": "031c7ccb3125177b", "type": "function", "z": "ea088d9e256f2e4a", "name": "Production Function", "func": "// Production Function with Auto-Reset for Demo\nconst targetQty = 2000;\n\n// Initialize or get current values\nlet goodParts = context.get('goodParts') || 100; // Start at 100 instead of 1200\nlet scrapParts = context.get('scrapParts') || 5;\n\n// Increment production\ngoodParts += Math.floor(Math.random() * 3) + 1;\nscrapParts += Math.floor(Math.random() * 2);\n\n// Calculate progress\nconst progress = Math.min(100, (goodParts / targetQty) * 100);\n\n// Auto-reset when reaching 100% (for continuous demo)\nif (goodParts >= targetQty) {\n goodParts = 100; // Reset to beginning\n scrapParts = 5;\n node.warn(\"Production cycle completed! Resetting for next work order...\");\n}\n\n// Save updated values\ncontext.set('goodParts', goodParts);\ncontext.set('scrapParts', scrapParts);\n\n// Create production data object\nconst productionData = {\n goodParts: goodParts,\n scrapParts: scrapParts,\n totalParts: goodParts + scrapParts,\n progress: progress,\n cycleTime: (45 + Math.random() * 10).toFixed(1) + \"s\",\n timestamp: new Date().toISOString()\n};\n\n// Store in global context (NEW!)\nglobal.set(\"productionData\", productionData);\n\nmsg.payload = productionData;\nmsg.topic = \"pimsa/maquina1/production\";\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 460, "y": 400, "wires": [ [ "12c37a80895dcc3e", "c195f94afd7183e6" ] ] }, { "id": "2a35e2907dc04de0", "type": "function", "z": "ea088d9e256f2e4a", "name": "Work Order Function", "func": "// Work Order Function\nconst workOrder = {\n id: 'WO-2024-001',\n sku: 'SKU-ABC123',\n description: 'Plastic Housing - Black',\n targetQty: 2000,\n dueDate: '2024-10-15'\n};\n\n// Create work order data object\nconst workOrderData = {\n workOrder: workOrder.id,\n sku: workOrder.sku,\n description: workOrder.description,\n targetQty: workOrder.targetQty,\n completedQty: context.get('goodParts') || 1200,\n dueDate: workOrder.dueDate,\n timestamp: new Date().toISOString()\n};\n\n// Store in global context (NEW!)\nglobal.set(\"workOrderData\", workOrderData);\n\nmsg.payload = workOrderData;\nmsg.topic = \"pimsa/erp/workorder/current\";\nreturn msg;", "outputs": 1, "timeout": 0, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 460, "y": 540, "wires": [ [ "4f66d69c5bce7ba0", "c195f94afd7183e6" ] ] }, { "id": "c195f94afd7183e6", "type": "ui_template", "z": "ea088d9e256f2e4a", "group": "6fe5cca8f548047a", "name": "", "order": 0, "width": "25", "height": "25", "format": "\n\n\n
\n \n \n| ID | \nSKU | \nDescription | \nTarget Qty | \nCompleted | \nProgress | \nStatus | \nDue Date | \n
|---|---|---|---|---|---|---|---|
| WO-2024-001 | \nSKU-ABC123 | \nPlastic Housing - Black | \n2000 | \n1200 | \n\n \n \n \n | \n In Progress | \n2024-10-15 | \n
| WO-2024-002 | \nSKU-DEF456 | \nCover Panel - White | \n1500 | \n0 | \n\n \n \n \n | \n Pending | \n2024-10-20 | \n
| WO-2024-003 | \nSKU-GHI789 | \nMounting Bracket - Grey | \n800 | \n800 | \n\n \n \n \n | \n Completed | \n2024-09-28 | \n
No recent reports
\n\n Dashboard View: Main HMI showing real-time machine data, OEE metrics,\n and production counters.
\n Navigation: Use the sidebar on the left to switch between different\n views.
\n Real-time Updates: All data updates automatically via MQTT connection.\n
\n No Data Showing:
\n • Check MQTT broker connection
\n • Verify Node-RED is running
\n • Check browser console (F12)
\n Slow Updates:
\n • Check network connection
\n • Restart local MQTT broker\n
| F11 | \nToggle Fullscreen | \n
| F12 | \nDeveloper Console | \n
| Ctrl+R | \nRefresh Dashboard | \n
\n Version: 1.0.0
\n MQTT Broker: localhost:9001
\n Update Rate: 1 second
\n Browser: \n