Files
Projects-plastic/modified_machine_cycles.js
Marcelo b66cb97f16 MVP
2025-11-28 09:11:59 -06:00

192 lines
6.9 KiB
JavaScript

// ===== MACHINE CYCLES FUNCTION (MODIFIED WITH DB PERSISTENCE) =====
const current = Number(msg.payload) || 0;
let zeroStreak = flow.get("zeroStreak") || 0;
zeroStreak = current === 0 ? zeroStreak + 1 : 0;
flow.set("zeroStreak", zeroStreak);
const prev = flow.get("lastMachineState") ?? 0;
flow.set("lastMachineState", current);
global.set("machineOnline", true); // force ONLINE for now
let productionRunning = !!global.get("productionStarted");
let stateChanged = false;
if (current === 1 && !productionRunning) {
productionRunning = true;
stateChanged = true;
} else if (current === 0 && zeroStreak >= 2 && productionRunning) {
productionRunning = false;
stateChanged = true;
}
global.set("productionStarted", productionRunning);
const stateMsg = stateChanged
? {
_mode: "production-state",
machineOnline: true,
productionStarted: productionRunning
}
: null;
const activeOrder = global.get("activeWorkOrder");
const cavities = Number(global.get("moldActive") || 0);
if (!activeOrder || !activeOrder.id || cavities <= 0) {
// We still want to pass along any state change even if there's no active WO.
return [null, stateMsg, null]; // Added third output for DB sync
}
// Check if tracking is enabled (START button clicked)
const trackingEnabled = !!global.get("trackingEnabled");
if (!trackingEnabled) {
// Cycles are happening but we're not tracking them yet
return [null, stateMsg, null];
}
// only count rising edges (0 -> 1) for production totals
if (prev === 1 || current !== 1) {
// *** NEW: Sync to DB on state changes (throttled) ***
if (stateChanged) {
const dbSyncMsg = createDbSyncMessage(false); // throttled sync
return [null, stateMsg, dbSyncMsg];
}
return [null, stateMsg, null];
}
let cycles = Number(global.get("cycleCount") || 0) + 1;
global.set("cycleCount", cycles);
// ===== PHASE 2: OPERATING TIME TRACKING =====
// Track actual operating time between cycles
const now = Date.now();
const lastCycleTime = global.get("lastCycleTime");
if (lastCycleTime) {
const deltaMs = now - lastCycleTime;
const deltaSec = deltaMs / 1000;
const currentOperatingTime = global.get("operatingTime") || 0;
global.set("operatingTime", currentOperatingTime + deltaSec);
}
global.set("lastCycleTime", now);
// Auto-prompt for scrap when target is reached
const scrapPromptIssuedFor = global.get("scrapPromptIssuedFor");
if (cycles === Number(activeOrder.target) && scrapPromptIssuedFor !== activeOrder.id) {
// Mark that we've prompted for this work order to prevent repeated prompts
global.set("scrapPromptIssuedFor", activeOrder.id);
// Send scrap prompt message
const scrapPromptMsg = {
_mode: "scrap-prompt",
payload: {
workOrderId: activeOrder.id,
cycles: cycles,
target: activeOrder.target,
message: `Target of ${activeOrder.target} cycles reached. Do you have scrap parts to report?`
}
};
// *** NEW: Sync to DB when target is reached (forced) ***
const dbSyncMsg = createDbSyncMessage(true); // forced sync
return [scrapPromptMsg, stateMsg, dbSyncMsg];
}
// *** NEW: Sync to DB on each cycle (throttled) ***
const dbSyncMsg = createDbSyncMessage(false); // throttled sync
return [null, stateMsg, dbSyncMsg];
// ========================================
// HELPER FUNCTION: Create DB Sync Message
// ========================================
function createDbSyncMessage(forceUpdate) {
const now = Date.now();
const lastSync = flow.get("lastSessionSync") || 0;
// Throttle: only sync every 5 seconds unless forced
if (!forceUpdate && (now - lastSync) < 5000) {
return null;
}
flow.set("lastSessionSync", now);
const sessionId = global.get("currentSessionId") || "session_" + Date.now();
global.set("currentSessionId", sessionId);
const activeOrder = global.get("activeWorkOrder");
const activeOrderId = activeOrder ? activeOrder.id : null;
const activeOrderData = activeOrder ? JSON.stringify(activeOrder) : null;
const sessionData = {
session_id: sessionId,
production_start_time: global.get("productionStartTime") || null,
operating_time: global.get("operatingTime") || 0,
last_update_time: now,
tracking_enabled: global.get("trackingEnabled") ? 1 : 0,
cycle_count: global.get("cycleCount") || 0,
active_work_order_id: activeOrderId,
active_work_order_data: activeOrderData,
machine_online: global.get("machineOnline") ? 1 : 0,
production_started: global.get("productionStarted") ? 1 : 0,
last_cycle_time: global.get("lastCycleTime") || null,
last_machine_state: flow.get("lastMachineState") || 0,
created_at: now,
updated_at: now,
is_active: 1
};
// Escape single quotes in JSON data
const escapedOrderData = sessionData.active_work_order_data
? sessionData.active_work_order_data.replace(/'/g, "''")
: null;
// Create upsert query
const query = `
INSERT INTO session_state (
session_id, production_start_time, operating_time, last_update_time,
tracking_enabled, cycle_count, active_work_order_id, active_work_order_data,
machine_online, production_started, last_cycle_time, last_machine_state,
created_at, updated_at, is_active
) VALUES (
'${sessionData.session_id}',
${sessionData.production_start_time},
${sessionData.operating_time},
${sessionData.last_update_time},
${sessionData.tracking_enabled},
${sessionData.cycle_count},
${sessionData.active_work_order_id ? "'" + sessionData.active_work_order_id + "'" : "NULL"},
${escapedOrderData ? "'" + escapedOrderData + "'" : "NULL"},
${sessionData.machine_online},
${sessionData.production_started},
${sessionData.last_cycle_time},
${sessionData.last_machine_state},
${sessionData.created_at},
${sessionData.updated_at},
${sessionData.is_active}
)
ON DUPLICATE KEY UPDATE
production_start_time = VALUES(production_start_time),
operating_time = VALUES(operating_time),
last_update_time = VALUES(last_update_time),
tracking_enabled = VALUES(tracking_enabled),
cycle_count = VALUES(cycle_count),
active_work_order_id = VALUES(active_work_order_id),
active_work_order_data = VALUES(active_work_order_data),
machine_online = VALUES(machine_online),
production_started = VALUES(production_started),
last_cycle_time = VALUES(last_cycle_time),
last_machine_state = VALUES(last_machine_state),
updated_at = VALUES(updated_at),
is_active = VALUES(is_active);
`;
return {
_mode: "session-sync",
topic: query,
sessionData: sessionData
};
}