Transport API (11 endpoints): - POST /api/transport/seed-acquisition - Record seed acquisition events - POST /api/transport/planting - Record planting events - POST /api/transport/growing - Record growing transport events - POST /api/transport/harvest - Record harvest events - POST /api/transport/distribution - Record distribution events - POST /api/transport/seed-saving - Record seed saving events - POST /api/transport/seed-sharing - Record seed sharing events - GET /api/transport/journey/[plantId] - Get plant journey - GET /api/transport/footprint/[userId] - Get environmental impact - GET /api/transport/verify/[blockHash] - Verify block integrity - GET /api/transport/qr/[id] - Generate QR code data Demand API (6 endpoints): - POST/GET /api/demand/preferences - Consumer preferences - POST /api/demand/signal - Generate demand signal - GET /api/demand/recommendations - Get planting recommendations - GET /api/demand/forecast - Get demand forecast - POST /api/demand/supply - Register supply commitment - POST /api/demand/match - Create market match Vertical Farm API (9 endpoints): - POST /api/vertical-farm/register - Register new farm - GET /api/vertical-farm/[farmId] - Get farm details - GET/POST /api/vertical-farm/[farmId]/zones - Manage zones - GET /api/vertical-farm/[farmId]/analytics - Get farm analytics - POST /api/vertical-farm/batch/start - Start crop batch - GET /api/vertical-farm/batch/[batchId] - Get batch details - PUT /api/vertical-farm/batch/[batchId]/environment - Record environment - POST /api/vertical-farm/batch/[batchId]/harvest - Complete harvest - GET /api/vertical-farm/recipes - List growing recipes
106 lines
2.9 KiB
TypeScript
106 lines
2.9 KiB
TypeScript
/**
|
|
* 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;
|
|
}
|