export const spec = { openapi: '3.0.0', info: { title: 'Weather Station', version: '1.0.0', description: 'Hyperlocal weather station — sensor data, forecasts, celestial & space weather', }, servers: [{ url: 'http://localhost:3000' }], paths: { '/api/position': { get: { summary: 'Station position', description: 'Latest GPS position and altitude', responses: { 200: { description: 'Last known position', content: { 'application/json': { schema: { $ref: '#/components/schemas/Position' } } } } } } }, '/api/current': { get: { summary: 'Current conditions', description: 'Latest reading of all metrics — sensor, forecast, celestial & space weather merged into a single flat object', parameters: [ { name: 'fields', in: 'query', required: false, schema: { type: 'string' }, description: 'Comma-separated list of fields to return. Omit for all.' } ], responses: { 200: { description: 'Current conditions', content: { 'application/json': { schema: { $ref: '#/components/schemas/DataRow' } } } } } } }, '/api/hourly': { get: { summary: 'Hourly data', description: 'Hourly aggregated sensor data merged with Open-Meteo hourly forecast, celestial positions and space weather. Defaults to today.', parameters: [ { name: 'start', in: 'query', required: false, schema: { type: 'string', format: 'date-time' }, description: 'ISO8601 start timestamp. Defaults to today 00:00.' }, { name: 'end', in: 'query', required: false, schema: { type: 'string', format: 'date-time' }, description: 'ISO8601 end timestamp. Defaults to now.' }, { name: 'fields', in: 'query', required: false, schema: { type: 'string' }, description: 'Comma-separated list of fields to return. Omit for all.' }, ], responses: { 200: { description: 'Array of hourly rows', content: { 'application/json': { schema: { type: 'array', items: { $ref: '#/components/schemas/DataRow' } } } } } } } }, '/api/daily': { get: { summary: 'Daily data', description: 'Daily aggregated sensor data (mean/min/max) merged with Open-Meteo daily forecast and celestial events. Defaults to today.', parameters: [ { name: 'start', in: 'query', required: false, schema: { type: 'string', format: 'date-time' }, description: 'ISO8601 start timestamp. Defaults to today 00:00.' }, { name: 'end', in: 'query', required: false, schema: { type: 'string', format: 'date-time' }, description: 'ISO8601 end timestamp. Defaults to now.' }, { name: 'fields', in: 'query', required: false, schema: { type: 'string' }, description: 'Comma-separated list of fields to return. Omit for all.' }, ], responses: { 200: { description: 'Array of daily rows', content: { 'application/json': { schema: { type: 'array', items: { $ref: '#/components/schemas/DataRow' } } } } } } } }, }, components: { schemas: { Position: { type: 'object', properties: { latitude: { type: 'number', description: 'Latitude (°)' }, longitude: { type: 'number', description: 'Longitude (°)' }, altitude: { type: 'number', description: 'Altitude (m)' }, } }, DataRow: { type: 'object', properties: { time: { type: 'string', format: 'date-time', description: 'ISO8601 timestamp' }, // Environment temperature: { type: 'number', description: 'Temperature (°C)' }, env_temp_min_c: { type: 'number', description: 'Daily min temperature (°C)' }, env_temp_max_c: { type: 'number', description: 'Daily max temperature (°C)' }, humidity: { type: 'number', description: 'Relative humidity (%)' }, humidity_abs: { type: 'number', description: 'Absolute humidity (g/m³)' }, dew_point: { type: 'number', description: 'Dew point (°C)' }, heat_index: { type: 'number', description: 'Feels like / heat index (°C)' }, vapor_pressure_deficit: { type: 'number', description: 'Vapour pressure deficit (kPa)' }, pressure_hpa: { type: 'number', description: 'Station pressure (hPa)' }, pressure_slp: { type: 'number', description: 'Sea level pressure (hPa)' }, pressure_rate: { type: 'number', description: 'Pressure change rate (hPa/hr)' }, pressure_trend: { type: 'string', enum: ['Rising','Falling','Stable'], description: 'Pressure trend label' }, frost_risk: { type: 'string', enum: ['None','Low','Moderate','High'], description: 'Frost risk level' }, air_quality: { type: 'number', description: 'Air quality index score (0–100)' }, air_quality_label: { type: 'string', enum: ['Excellent','Good','Fair','Poor','Very Poor'] }, // Light & Solar lux: { type: 'number', description: 'Illuminance (lux)' }, uv_index: { type: 'number', description: 'UV index' }, uv_index_max: { type: 'number', description: 'Daily max UV index' }, uv_dose: { type: 'number', description: 'Accumulated UV dose today (mJ/cm²)' }, solar_wm2: { type: 'number', description: 'Solar irradiance (W/m²)' }, daily_light_integral: { type: 'number', description: 'Daily light integral (mol/m²/day)' }, clouds: { type: 'number', description: 'Cloud cover fraction (0–1)' }, visibility: { type: 'number', description: 'Estimated visibility (km)' }, daylight: { type: 'number', description: 'Hours of daylight' }, // Weather label: { type: 'string', description: 'Human readable weather label' }, icon: { type: 'string', description: 'OWM icon code e.g. 01d' }, raining: { type: 'string', enum: ['True','False'] }, precipitation: { type: 'number', description: 'Precipitation (mm)' }, precipitation_chance: { type: 'number', description: 'Precipitation probability (%)' }, accumulation: { type: 'number', description: 'Accumulated precipitation (mm)' }, storm_trend: { type: 'number', description: '1=worsening, 0=stable, -1=improving' }, // Wind wind_speed: { type: 'number', description: 'Wind speed (km/h)' }, wind_gusts: { type: 'number', description: 'Wind gusts (km/h)' }, wind_direction: { type: 'number', description: 'Wind direction (°)' }, // Lightning lightning_rate: { type: 'number', description: 'Strike rate (strikes/hr)' }, lightning_distance: { type: 'number', description: 'Lightning strike distance (km)' }, // Sun sun_elevation: { type: 'number', description: 'Solar elevation angle (°)' }, sun_azimuth: { type: 'number', description: 'Solar azimuth (°)' }, sunrise: { type: 'string', format: 'date-time', description: 'Sunrise time' }, sunset: { type: 'string', format: 'date-time', description: 'Sunset time' }, daytime: { type: 'boolean', description: 'True if between sunrise and sunset' }, // Moon moon_phase: { type: 'string', description: 'Moon phase name' }, moon_illumination: { type: 'number', description: 'Moon illumination (%)' }, moon_elevation: { type: 'number', description: 'Moon elevation (°)' }, moon_azimuth: { type: 'number', description: 'Moon azimuth (°)' }, moonrise: { type: 'string', format: 'date-time', description: 'Moonrise time' }, moonset: { type: 'string', format: 'date-time', description: 'Moonset time' }, moon_new: { type: 'string', format: 'date-time', description: 'Next new moon' }, moon_full: { type: 'string', format: 'date-time', description: 'Next full moon' }, // Seismic seismic_magnitude: { type: 'number', description: 'Peak seismic magnitude (g)' }, // Ground ground_distance: { type: 'number', description: 'LIDAR ground distance (cm)' }, // GPS latitude: { type: 'number', description: 'Latitude (°)' }, longitude: { type: 'number', description: 'Longitude (°)' }, altitude: { type: 'number', description: 'Altitude (m)' }, } } } } }