[ { "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": false, "width": "25", "collapse": false, "className": "" }, { "id": "fa0582493cd77ae7", "type": "ui_base", "theme": { "name": "theme-dark", "lightTheme": { "default": "#0094CE", "baseColor": "#0094CE", "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", "edited": true, "reset": false }, "darkTheme": { "default": "#097479", "baseColor": "#097479", "baseFont": "-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif", "edited": true, "reset": 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": "#097479", "value": "#097479", "edited": false }, "page-titlebar-backgroundColor": { "value": "#097479", "edited": false }, "page-backgroundColor": { "value": "#111111", "edited": false }, "page-sidebar-backgroundColor": { "value": "#333333", "edited": false }, "group-textColor": { "value": "#0eb8c0", "edited": false }, "group-borderColor": { "value": "#555555", "edited": false }, "group-backgroundColor": { "value": "#333333", "edited": false }, "widget-textColor": { "value": "#eeeeee", "edited": false }, "widget-backgroundColor": { "value": "#097479", "edited": false }, "widget-borderColor": { "value": "#333333", "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": "true", "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 Industrial HMI Dashboard\n \n \n \n\n\n\n
\n \n
\n \n \n \n \n \n \n \n
\n\n \n
\n\n \n
\n
\n \n
\n \n \n \n \n
\n\n \n
\n
Current Work Order
\n
\n
\n
Work Order
\n
\n
\n
\n
SKU
\n
\n
\n
\n
Cycle Time
\n
\n
\n
\n
\n
\n
0%
\n
\n
\n
\n
\n\n \n
\n
\n
Good Parts
\n
0
\n
\n
\n
Scrap Parts
\n
0
\n
\n
\n
\n \n Online\n \n
\n
\n \n Running\n \n
\n
\n
\n\n \n
\n \n
\n
\n
\n\n \n
\n
\n
\n
\n 📋\n Work Orders\n
\n \n
\n
\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
IDSKUDescriptionTarget QtyCompletedProgressStatusDue Date
WO-2024-001SKU-ABC123Plastic Housing - Black20001200\n
\n
\n
\n
In Progress2024-10-15
WO-2024-002SKU-DEF456Cover Panel - White15000\n
\n
\n
\n
Pending2024-10-20
WO-2024-003SKU-GHI789Mounting Bracket - Grey800800\n
\n
\n
\n
Completed2024-09-28
\n
\n
\n
\n\n \n
\n
\n
\n
\n ⚠️\n Report Issue\n
\n
\n
\n
\n
\n \n \n
\n\n
\n \n \n
\n\n
\n \n \n
\n\n
\n \n \n
\n\n
\n \n \n
\n\n
\n \n \n
\n
\n\n
Recent Reports
\n
\n

No recent reports

\n
\n
\n
\n
\n\n \n
\n
\n
\n
\n 📊\n Machine Status & Analytics\n
\n
\n
\n
\n
OEE Trend (Last Hour)
\n
\n \n
\n
\n
\n
Production Rate
\n
\n \n
\n
\n
\n
Quality Metrics
\n
\n \n
\n
\n
\n
Machine State Timeline
\n
\n \n
\n
\n
\n
\n
\n\n \n
\n
\n
\n
\n 🔔\n Notifications\n
\n \n
\n
\n
\n \n
\n \n
\n
Machine Started
\n
2 minutes ago
\n
\n Info\n
\n
\n \n
\n
Work Order Progress: 75%
\n
5 minutes ago
\n
\n Update\n
\n
\n \n
\n
Quality Alert: Scrap rate increasing
\n
15 minutes ago
\n
\n Warning\n
\n
\n
\n
\n
\n\n \n
\n
\n
\n
\n \n Help & Documentation\n
\n
\n
\n
\n
Quick Start Guide
\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
\n\n
\n
Troubleshooting
\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

\n
\n\n
\n
Keyboard Shortcuts
\n \n \n \n \n \n \n \n \n \n \n \n \n \n
F11Toggle Fullscreen
F12Developer Console
Ctrl+RRefresh Dashboard
\n
\n\n
\n
System Information
\n

\n Version: 1.0.0
\n MQTT Broker: localhost:9001
\n Update Rate: 1 second
\n Browser: \n

\n
\n
\n
\n
\n\n \n
\n
\n
\n
\n ⚙️\n Settings\n
\n
\n
\n
\n
Display Settings
\n
\n \n \n
\n
\n \n \n
\n
\n\n
\n
Connection Settings
\n
\n \n \n
\n
\n \n
\n \n Connected\n
\n
\n
\n\n
\n
Data Settings
\n
\n \n \n
\n \n
\n\n
\n
System Actions
\n
\n \n \n \n
\n
\n
\n
\n
\n\n
\n
\n\n \n\n\n", "storeOutMessages": true, "fwdInMessages": true, "resendOnRefresh": true, "templateScope": "local", "className": "", "x": 700, "y": 320, "wires": [ [] ] } ]