From 6a2f130e3a17dca5d3d6d70172ca6740ff0d7474 Mon Sep 17 00:00:00 2001 From: Kharisma Date: Thu, 2 Jul 2026 13:55:02 +0700 Subject: [PATCH] upload project flutter --- railway-scheduler/worker.js | 92 ++++++++++++++++++++++++------------- 1 file changed, 61 insertions(+), 31 deletions(-) diff --git a/railway-scheduler/worker.js b/railway-scheduler/worker.js index 930ea29..7b1c233 100644 --- a/railway-scheduler/worker.js +++ b/railway-scheduler/worker.js @@ -81,6 +81,10 @@ function toDate(value) { } function normalizeKandangKey(kandangId, kandangNama) { + const name = String(kandangNama || '').toLowerCase(); + if (name.includes('kandang 1') || name.includes('kandang1') || name.includes('kandang_1')) return 'kandang1'; + if (name.includes('kandang 2') || name.includes('kandang2') || name.includes('kandang_2')) return 'kandang2'; + const rawId = String(kandangId || '').toLowerCase(); const rawNama = String(kandangNama || '').toLowerCase(); const merged = `${rawId} ${rawNama}`; @@ -136,27 +140,53 @@ function resolveTargetKandangIds(jadwal, kandangMap) { } function detectJenisPanen(jadwal, jadwalOrder) { - // jadwalOrder 0 = urutan pertama = PAGI - // jadwalOrder 1+ = urutan selanjutnya = SORE (atau sesuai jam) + + // Prioritas 1: baca langsung dari Firebase + const tipe = String( + jadwal.tipeJadwal || + jadwal.tipe_jadwal || + jadwal.keterangan || + '' + ) + .toLowerCase() + .trim(); + + if (tipe.includes('pagi')) { + return 'pagi'; + } + + if (tipe.includes('sore')) { + return 'sore'; + } + + // Fallback untuk data lama if (jadwalOrder === 0) { return 'pagi'; } - - // Untuk jadwal ke-2+, check jam: < 12 = pagi, >= 12 = sore - const jam = String(jadwal.jam || '09:00'); - const hour = Number(jam.split(':')[0] || 9); - - return hour < 12 ? 'pagi' : 'sore'; + + return 'sore'; } function resolveInfraPath(kandangId, kandangData) { if (kandangData && kandangData.infraPath) { - return String(kandangData.infraPath); + const path = String(kandangData.infraPath).toLowerCase(); + if (path.includes('2')) return 'infra2'; + if (path.includes('1')) return 'infra1'; + return path; + } + + if (kandangData && kandangData.nama) { + const nama = String(kandangData.nama).toLowerCase(); + if (nama.includes('2') || nama.includes('dua')) return 'infra2'; + if (nama.includes('1') || nama.includes('satu')) return 'infra1'; } const id = String(kandangId || '').toLowerCase(); - if (id.includes('1')) return 'infra1'; - if (id.includes('2')) return 'infra2'; + if (id.length < 15) { + if (id.includes('2')) return 'infra2'; + if (id.includes('1')) return 'infra1'; + } + return 'infra1'; } @@ -211,21 +241,28 @@ async function updateRiwayatSummary({ kandangId, kandangNama, jumlahTelur, dateK }); } -async function resetSensorAfterEvening(todayKey) { - const lockKey = 'evening_sensor_reset'; +async function resetSensorAfterEvening(todayKey, nowHHMM) { + const lockKey = `evening_sensor_reset_${nowHHMM.replace(':', '')}`; const gotLock = await acquireRunLock(todayKey, lockKey); if (!gotLock) { - console.log('[skip] Sensor reset sudah dieksekusi hari ini'); + console.log('[skip] Sensor & snapshot reset sudah dieksekusi untuk menit ini'); return; } await admin.database().ref('data').update({ - infra1: 0, - infra2: 0, - last_reset_by_scheduler: new Date().toISOString(), + infra1: 0, + infra2: 0, + last_reset_by_scheduler: new Date().toISOString(), }); - console.log('[ok] Sensor infra1/infra2 di-reset otomatis setelah jadwal sore'); + // PERINTAH RESET KE ESP32 + await admin.database().ref('kontrol').update({ + reset_counter: true + }); + + await admin.database().ref(`panen_snapshot/${todayKey}`).remove(); + + console.log('[ok] Sensor infra1/infra2 dan snapshot panen di-reset otomatis setelah jadwal sore'); } async function writeRiwayat({ @@ -381,7 +418,7 @@ async function migrateLegacyRiwayatData(kandangMap) { cleanupUpdates[legacyKey] = null; continue; } - + const inferredKandangId = await inferTargetForGlobalRecord(record, kandangMap); if (inferredKandangId) { await recordsRef.push().set({ @@ -523,10 +560,10 @@ async function runForSchedule(jadwalId, jadwal, dataSensor, kandangMap, todayKey } for (const kandangId of targetKandangIds) { - const lockKey = `${jenisPanen}_${kandangId}`; + const lockKey = `${jenisPanen}_${kandangId}_${jam.replace(/:/g, '')}`; const gotLock = await acquireRunLock(todayKey, lockKey); if (!gotLock) { - console.log(`[skip] ${jadwalId}/${kandangId}: slot ${jenisPanen} sudah dieksekusi hari ini`); + console.log(`[skip] ${jadwalId}/${kandangId}: slot ${jenisPanen} pada jam ${jam} sudah dieksekusi hari ini`); continue; } @@ -562,7 +599,7 @@ async function runForSchedule(jadwalId, jadwal, dataSensor, kandangMap, todayKey const pagiSnapRef = admin.database().ref(`panen_snapshot/${todayKey}/pagi/${kandangId}`); const pagiSnap = await pagiSnapRef.get(); const nilaiPagi = pagiSnap.exists() ? Number(pagiSnap.val() || 0) : 0; - const delta = Math.max(sensorValue - nilaiPagi, 0); + const delta = sensorValue >= nilaiPagi ? (sensorValue - nilaiPagi) : sensorValue; await admin.database().ref(`panen_snapshot/${todayKey}/sore`).update({ [kandangId]: sensorValue, @@ -584,13 +621,6 @@ async function runForSchedule(jadwalId, jadwal, dataSensor, kandangMap, todayKey console.log(`[ok] Sore ${kandangNama}: ${delta} telur (${sensorValue}-${nilaiPagi})`); } - - // Jika ini jadwal terakhir, reset snapshot untuk hari ini - if (jadwalOrder === totalJadwal - 1) { - const snapshotRef = admin.database().ref(`panen_snapshot/${todayKey}`); - await snapshotRef.remove(); - console.log(`[ok] Reset snapshot panen untuk hari ${todayKey} (jadwal terakhir selesai)`); - } } async function runTick() { @@ -655,7 +685,7 @@ async function runTick() { } if (hasEveningRun) { - await resetSensorAfterEvening(todayKey); + await resetSensorAfterEvening(todayKey, nowHHMM); } } @@ -732,4 +762,4 @@ async function bootstrap() { bootstrap().catch((e) => { console.error('[fatal] bootstrap failed:', e.message); process.exit(1); -}); +}); \ No newline at end of file