Initial commit, 90% there
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
|
||||
with open('/home/mdares/.node-red/flows.json', 'r') as f:
|
||||
flows = json.load(f)
|
||||
|
||||
# Find Work Order buttons node
|
||||
work_order_buttons_node = None
|
||||
for node in flows:
|
||||
if node.get('id') == '9bbd4fade968036d':
|
||||
work_order_buttons_node = node
|
||||
break
|
||||
|
||||
if not work_order_buttons_node:
|
||||
print("✗ Could not find Work Order buttons node")
|
||||
exit(1)
|
||||
|
||||
# Get the current function code
|
||||
func_code = work_order_buttons_node.get('func', '')
|
||||
|
||||
# Find the complete-work-order case and add high scrap detection
|
||||
# Insert the code BEFORE "node.warn('[COMPLETE] Cleared all state flags');"
|
||||
|
||||
high_scrap_code = '''
|
||||
// ============================================================
|
||||
// HIGH SCRAP DETECTION
|
||||
// ============================================================
|
||||
const targetQty = Number(activeOrder.target) || 0;
|
||||
const scrapCount = finalScrapParts;
|
||||
const scrapPercent = targetQty > 0 ? (scrapCount / targetQty) * 100 : 0;
|
||||
|
||||
// Trigger: Scrap > 10% of target quantity
|
||||
let anomalyMsg = null;
|
||||
if (scrapPercent > 10 && targetQty > 0) {
|
||||
const severity = scrapPercent > 25 ? 'critical' : 'warning';
|
||||
|
||||
const highScrapAnomaly = {
|
||||
anomaly_type: 'high-scrap',
|
||||
severity: severity,
|
||||
title: `High Waste Detected`,
|
||||
description: `Work order completed with ${scrapCount} scrap parts (${scrapPercent.toFixed(1)}% of target ${targetQty}). Why is there so much waste?`,
|
||||
data: {
|
||||
scrap_count: scrapCount,
|
||||
target_quantity: targetQty,
|
||||
scrap_percent: Math.round(scrapPercent * 10) / 10,
|
||||
good_parts: finalGoodParts,
|
||||
total_cycles: finalCycleCount
|
||||
},
|
||||
kpi_snapshot: {
|
||||
oee: (msg.kpis && msg.kpis.oee) || global.get("currentKPIs")?.oee || 0,
|
||||
availability: (msg.kpis && msg.kpis.availability) || global.get("currentKPIs")?.availability || 0,
|
||||
performance: (msg.kpis && msg.kpis.performance) || global.get("currentKPIs")?.performance || 0,
|
||||
quality: (msg.kpis && msg.kpis.quality) || global.get("currentKPIs")?.quality || 0
|
||||
},
|
||||
work_order_id: order.id,
|
||||
cycle_count: finalCycleCount,
|
||||
timestamp: Date.now(),
|
||||
status: 'active'
|
||||
};
|
||||
|
||||
node.warn(`[HIGH SCRAP] Detected ${scrapPercent.toFixed(1)}% scrap on work order ${order.id}`);
|
||||
|
||||
// Send to Event Logger (output 5)
|
||||
anomalyMsg = {
|
||||
topic: "anomaly-detected",
|
||||
payload: [highScrapAnomaly]
|
||||
};
|
||||
}
|
||||
'''
|
||||
|
||||
# Find the marker to insert before
|
||||
marker = "node.warn('[COMPLETE] Cleared all state flags');"
|
||||
|
||||
if marker in func_code:
|
||||
# Insert the high scrap code before this marker
|
||||
func_code = func_code.replace(marker, high_scrap_code + '\\n ' + marker)
|
||||
print("✓ Injected high scrap detection code")
|
||||
else:
|
||||
print("✗ Could not find marker to inject code")
|
||||
exit(1)
|
||||
|
||||
# Also need to change the return statement to include the anomaly message
|
||||
old_return = 'return [null, null, null, msg];'
|
||||
new_return = 'return [null, null, null, msg, anomalyMsg];'
|
||||
|
||||
if old_return in func_code:
|
||||
# Only replace the one in complete-work-order case
|
||||
# Split by case first
|
||||
parts = func_code.split('case "complete-work-order":')
|
||||
before = parts[0]
|
||||
after_case = parts[1]
|
||||
|
||||
# Split this case by the next case
|
||||
case_parts = after_case.split('case "get-current-state":', 1)
|
||||
this_case = case_parts[0]
|
||||
rest = case_parts[1] if len(case_parts) > 1 else ''
|
||||
|
||||
# Replace return in this case only
|
||||
this_case = this_case.replace(old_return, new_return)
|
||||
|
||||
# Reconstruct
|
||||
func_code = before + 'case "complete-work-order":' + this_case
|
||||
if rest:
|
||||
func_code += 'case "get-current-state":' + rest
|
||||
|
||||
print("✓ Updated return statement to include anomaly message")
|
||||
else:
|
||||
print("⚠ Could not find return statement to update")
|
||||
|
||||
work_order_buttons_node['func'] = func_code
|
||||
|
||||
# Save flows.json
|
||||
with open('/home/mdares/.node-red/flows.json', 'w') as f:
|
||||
json.dump(flows, f, indent=4)
|
||||
|
||||
print("✓ flows.json updated with high scrap detection")
|
||||
Reference in New Issue
Block a user