Files
2025-12-02 16:27:21 +00:00

175 lines
5.3 KiB
Python

#!/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")