From f9e89fe826e6c3da97caf558cc0a7eeb3ae90a56 Mon Sep 17 00:00:00 2001 From: Wizznu Date: Tue, 2 Jun 2026 08:10:01 +0700 Subject: [PATCH] fix: Ensure sequential watering by adding explicit OFF for other pots and increased delays --- railway-worker/worker.js | 66 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/railway-worker/worker.js b/railway-worker/worker.js index 32e5710..953f321 100644 --- a/railway-worker/worker.js +++ b/railway-worker/worker.js @@ -199,10 +199,40 @@ const wateringWorker = new Worker( console.log(` Target: ${sensorData.batasBawah}% β†’ ${sensorData.batasAtas}%`); } + // Log queue status for debugging + try { + const queueCounts = await wateringQueue.getJobCounts(); + console.log(`\n πŸ“Š QUEUE STATUS AT JOB START:`); + console.log(` Active jobs: ${queueCounts.active}`); + console.log(` Waiting jobs: ${queueCounts.waiting}`); + console.log(` ⚠️ If > 1 active, sequential watering WILL FAIL!`); + } catch (queueError) { + console.warn(` ⚠️ Could not get queue status: ${queueError.message}`); + } + try { const BREAK_BETWEEN_POTS_MS = 30000; // 30 seconds break between pots const potCount = potNumbers.length; + // ==================== SAFETY: Turn OFF all pot valves at start ==================== + // Ensure clean state - all pots OFF before starting sequential watering + console.log(`\nπŸ›‘οΈ SAFETY: Ensuring all pot valves are OFF at start...`); + const safetyOffUpdates = { + mosvet_3: false, // Pot 1 + mosvet_4: false, // Pot 2 + mosvet_5: false, // Pot 3 + mosvet_6: false, // Pot 4 + mosvet_7: false, // Pot 5 + }; + try { + await updateFirebaseSmart('aktuator', safetyOffUpdates, 2); + console.log(`βœ… All pot valves confirmed OFF`); + } catch (safetyError) { + console.warn(`⚠️ Safety OFF attempt failed: ${safetyError.message}`); + } + console.log(`⏳ Waiting 2 seconds to stabilize initial state...`); + await sleep(2000); // 2 second delay to ensure all pots really OFF + if (String(type || '').startsWith('waktu_')) { const scheduleTime = job.data.scheduleTime || 'jadwal'; const potText = potCount > 1 ? `pot ${potNumbers.join(', ')}` : `pot ${potNumbers[0]}`; @@ -237,6 +267,21 @@ const wateringWorker = new Worker( console.log(` β•‘ POT ${pot} [${potSequence}/${potCount}]`.padEnd(40) + ` β•‘`); console.log(` β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•`); + // IMPORTANT: Turn OFF all OTHER pots first to ensure only current pot is ON + const offOthersUpdates = {}; + for (const otherPot of potNumbers) { + if (otherPot !== pot && otherPot >= 1 && otherPot <= 5) { + offOthersUpdates[`mosvet_${otherPot + 2}`] = false; // Turn OFF other pots + } + } + + if (Object.keys(offOthersUpdates).length > 0) { + console.log(` πŸ”΄ Turn OFF other pots: ${Object.keys(offOthersUpdates).join(', ')}`); + await updateFirebaseSmart('aktuator', offOthersUpdates, 2); + console.log(` ⏳ Waiting 1 second before turning ON current pot...`); + await sleep(1000); // 1 second delay to ensure all pots OFF before turning ON new one + } + // Turn ON pumps + current pot valve const onUpdates = {}; if (pompaAir) onUpdates['mosvet_1'] = true; @@ -337,6 +382,8 @@ const wateringWorker = new Worker( // Break 30 detik sebelum pot berikutnya (jika ada) if (potIndex < potCount - 1) { + console.log(` ⏳ Waiting 2 seconds to stabilize...`); + await sleep(2000); // 2 second stabilization after pot OFF console.log(`\n ⏸️ BREAK 30 DETIK sebelum POT ${potNumbers[potIndex + 1]}...`); for (let breakTime = 30; breakTime > 0; breakTime--) { if (breakTime % 10 === 0 || breakTime <= 5) { @@ -422,6 +469,25 @@ wateringWorker.on('failed', (job, err) => { console.error(`❌ Worker failed job ${job?.id}:`, err.message); }); +// ⚠️ IMPORTANT: Verify worker concurrency is actually 1 +console.log(`\nπŸ”§ WATERING WORKER CONFIGURATION:`); +console.log(` Concurrency: ${config.worker.concurrency} (MUST BE 1 FOR SEQUENTIAL MODE)`); +console.log(` Lock Duration: ${config.worker.lockDuration}ms`); +console.log(` Remove on Complete: Keep 100 completed jobs`); +console.log(` Remove on Fail: Keep 50 failed jobs`); + +if (config.worker.concurrency !== 1) { + console.error(`❌ CRITICAL: Worker concurrency is NOT 1! This will break sequential watering!`); + console.error(` Current value: ${config.worker.concurrency}`); + console.error(` Please fix config.worker.concurrency = 1`); +} + +console.log(`\nπŸ’§ SEQUENTIAL WATERING MODE ENABLED:`); +console.log(` - Pots will be watered ONE AT A TIME`); +console.log(` - 30 second break between each pot`); +console.log(` - Applies to: Jadwal (Waktu Mode) + Threshold (Sensor Mode)`); +console.log(` - Only 1 job can run at a time (concurrency=1)\n`); + // ==================== WAKTU MODE (TIME SCHEDULER) ==================== let lastScheduleCheck = {};