/** * API Route: Record environment reading * PUT /api/vertical-farm/batch/[batchId]/environment */ import type { NextApiRequest, NextApiResponse } from 'next'; import { getVerticalFarmController } from '../../../../../lib/vertical-farming/controller'; import { ZoneEnvironmentReadings } from '../../../../../lib/vertical-farming/types'; export default async function handler( req: NextApiRequest, res: NextApiResponse ) { if (req.method !== 'PUT') { return res.status(405).json({ success: false, error: 'Method not allowed' }); } try { const { batchId } = req.query; const { temperatureC, humidityPercent, co2Ppm, ppfd, waterTempC, ec, ph, dissolvedOxygenPpm, airflowMs } = req.body; if (!batchId || typeof batchId !== 'string') { return res.status(400).json({ success: false, error: 'Batch ID is required' }); } // Validate required readings if (temperatureC === undefined || humidityPercent === undefined || ec === undefined || ph === undefined) { return res.status(400).json({ success: false, error: 'Missing required fields: temperatureC, humidityPercent, ec, ph' }); } const controller = getVerticalFarmController(); // Access internal state to find the batch const state = controller.toJSON() as any; const batches = state.batches as [string, any][]; const batchEntry = batches.find(([id]) => id === batchId); if (!batchEntry) { return res.status(404).json({ success: false, error: `Batch not found: ${batchId}` }); } const batch = batchEntry[1]; const readings: ZoneEnvironmentReadings = { timestamp: new Date().toISOString(), temperatureC, humidityPercent, co2Ppm: co2Ppm || 800, vpd: calculateVpd(temperatureC, humidityPercent), ppfd: ppfd || 300, dli: (ppfd || 300) * 16 * 3600 / 1000000, // Approximate DLI waterTempC: waterTempC || 20, ec, ph, dissolvedOxygenPpm: dissolvedOxygenPpm || 8, airflowMs: airflowMs || 0.5, alerts: [] }; const alerts = controller.recordEnvironment(batch.zoneId, readings); res.status(200).json({ success: true, data: { readings, alerts, batchId, zoneId: batch.zoneId } }); } catch (error: any) { console.error('Error recording environment:', error); res.status(500).json({ success: false, error: error.message || 'Internal server error' }); } } /** * Calculate Vapor Pressure Deficit */ function calculateVpd(tempC: number, humidityPercent: number): number { // Saturation vapor pressure (kPa) const svp = 0.6108 * Math.exp((17.27 * tempC) / (tempC + 237.3)); // Actual vapor pressure const avp = svp * (humidityPercent / 100); // VPD return Math.round((svp - avp) * 100) / 100; }