#!/usr/bin/env python3 import json import uuid # Read flows.json with open('/home/mdares/.node-red/flows.json', 'r') as f: flows = json.load(f) # Read startup recovery function with open('/home/mdares/.node-red/startup_recovery_function.js', 'r') as f: recovery_code = f.read() # Read stop reason UI template with open('/home/mdares/.node-red/stop_reason_ui_template.html', 'r') as f: stop_reason_ui = f.read() # Find DB config and existing dashboard group db_config_id = None home_group_id = None for node in flows: if node.get('type') == 'MySQLdatabase': db_config_id = node['id'] if node.get('type') == 'ui_group' and 'home' in node.get('name', '').lower(): home_group_id = node['id'] # If no home group found, use first ui_group if not home_group_id: for node in flows: if node.get('type') == 'ui_group': home_group_id = node['id'] break print(f"DB config ID: {db_config_id}") print(f"Home group ID: {home_group_id}") # ============================================================================ # CREATE STARTUP RECOVERY TAB AND FLOW # ============================================================================ recovery_tab_id = str(uuid.uuid4()).replace('-', '')[:16] recovery_inject_id = str(uuid.uuid4()).replace('-', '')[:16] recovery_function_id = str(uuid.uuid4()).replace('-', '')[:16] recovery_mysql_id = str(uuid.uuid4()).replace('-', '')[:16] # Create recovery tab recovery_tab = { "id": recovery_tab_id, "type": "tab", "label": "Startup Recovery", "disabled": False, "info": "Automatic session recovery on Node-RED startup" } # Create inject node (runs 5 seconds after startup) recovery_inject = { "id": recovery_inject_id, "type": "inject", "z": recovery_tab_id, "name": "Check on Startup", "props": [ { "p": "mode", "v": "check", "vt": "str" } ], "repeat": "", "crontab": "", "once": True, "onceDelay": "5", "topic": "", "x": 150, "y": 100, "wires": [[recovery_function_id]] } # Create recovery function node recovery_function = { "id": recovery_function_id, "type": "function", "z": recovery_tab_id, "name": "Startup Recovery", "func": recovery_code, "outputs": 2, "noerr": 0, "initialize": "", "finalize": "", "libs": [], "x": 360, "y": 100, "wires": [ [], # Output 1: notifications (not wired for now) [recovery_mysql_id] # Output 2: database queries ] } # Create MySQL node for recovery recovery_mysql = { "id": recovery_mysql_id, "type": "mysql", "z": recovery_tab_id, "mydb": db_config_id, "name": "Recovery DB Query", "x": 570, "y": 100, "wires": [[]] # Results can be processed later if needed } # Add recovery flow nodes flows.extend([recovery_tab, recovery_inject, recovery_function, recovery_mysql]) print("\n✅ Added Startup Recovery flow:") print(f" - New tab: 'Startup Recovery'") print(f" - Inject node (runs 5s after startup)") print(f" - Recovery function with crash recovery logic") print(f" - MySQL node for querying session_state") # ============================================================================ # ADD STOP REASON UI TEMPLATE # ============================================================================ if home_group_id: stop_reason_ui_id = str(uuid.uuid4()).replace('-', '')[:16] stop_reason_template = { "id": stop_reason_ui_id, "type": "ui_template", "z": None, # Will be set based on where home group is "group": home_group_id, "name": "Stop Reason Prompt", "order": 99, # Place at end "width": 0, "height": 0, "format": stop_reason_ui, "storeOutMessages": True, "fwdInMessages": True, "resendOnRefresh": False, "templateScope": "local", "x": 0, "y": 0, "wires": [[]] # Output wires back to Work Order buttons (manual wiring needed) } # Find the tab/flow where the home group belongs for node in flows: if node.get('type') == 'ui_group' and node.get('id') == home_group_id: stop_reason_template['z'] = node.get('z') break flows.append(stop_reason_template) print("\n✅ Added Stop Reason UI Template:") print(f" - ui_template node added to Home dashboard") print(f" - Modal prompt for planned/unplanned stops") print(f" - ID: {stop_reason_ui_id}") print("\n⚠️ NOTE: You need to manually wire:") print(" - Work Order buttons Output 2 → Stop Reason UI (for stop-prompt)") print(" - Stop Reason UI output → Work Order buttons input (for stop-reason action)") else: print("\n⚠️ WARNING: No Home dashboard group found. Stop Reason UI not added.") print(" You'll need to create this manually in the Node-RED editor.") # Write updated flows with open('/home/mdares/.node-red/flows.json', 'w') as f: json.dump(flows, f, indent=4) print("\n✅ flows.json updated successfully!") print("\n📝 Summary of all changes:") print(" ✓ Machine cycles function updated (2→4 outputs)") print(" ✓ Work Order buttons function updated (4→5 outputs)") print(" ✓ 3 MySQL nodes added (State Backup, Anomaly, Session)") print(" ✓ Startup Recovery flow added (new tab)") print(" ✓ Stop Reason UI template added")