216 lines
15 KiB
JavaScript
216 lines
15 KiB
JavaScript
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/data': {
|
||
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: {
|
||
DataRow: {
|
||
type: 'object',
|
||
properties: {
|
||
time: { type: 'string', description: 'ISO8601 timestamp or date' },
|
||
// Environment
|
||
env_temp_c: { type: 'number', description: 'Temperature (°C)' },
|
||
env_temp_f: { type: 'number', description: 'Temperature (°F)' },
|
||
env_temp_min_c: { type: 'number', description: 'Daily min temperature (°C)' },
|
||
env_temp_max_c: { type: 'number', description: 'Daily max temperature (°C)' },
|
||
env_humidity: { type: 'number', description: 'Relative humidity (%)' },
|
||
env_dew_point_c: { type: 'number', description: 'Dew point (°C)' },
|
||
env_heat_index_c: { type: 'number', description: 'Feels like / heat index (°C)' },
|
||
env_pressure_hpa: { type: 'number', description: 'Station pressure (hPa)' },
|
||
env_pressure_slp: { type: 'number', description: 'Sea level pressure (hPa)' },
|
||
env_pressure_rate: { type: 'number', description: 'Pressure change rate (hPa/hr)' },
|
||
env_pressure_trend: { type: 'string', enum: ['Rising','Falling','Stable'], description: 'Pressure trend label' },
|
||
env_abs_humidity: { type: 'number', description: 'Absolute humidity (g/m³)' },
|
||
env_vpd_kpa: { type: 'number', description: 'Vapour pressure deficit (kPa)' },
|
||
env_gas_ohms: { type: 'number', description: 'BME680 gas resistance (Ω)' },
|
||
env_aqi_score: { type: 'number', description: 'Air quality index score (0–100)' },
|
||
env_aqi_label: { type: 'string', enum: ['Excellent','Good','Fair','Poor','Very Poor'] },
|
||
env_frost_risk: { type: 'string', enum: ['None','Low','Moderate','High'] },
|
||
// Light
|
||
light_lux: { type: 'number', description: 'Illuminance (lux)' },
|
||
light_uvi: { type: 'number', description: 'UV index' },
|
||
light_solar_wm2: { type: 'number', description: 'Solar irradiance (W/m²)' },
|
||
light_uv_dose_mj: { type: 'number', description: 'Accumulated UV dose today (mJ/cm²)' },
|
||
light_burn_time_min: { type: 'number', description: 'Time to sunburn skin type 2 (min)' },
|
||
light_cloud_pct: { type: 'number', description: 'Estimated cloud cover (%)' },
|
||
light_cloud_label: { type: 'string', enum: ['Clear','Partly Cloudy','Mostly Cloudy','Overcast'] },
|
||
light_dli: { type: 'number', description: 'Daily light integral (mol/m²/day)' },
|
||
light_daylight_hours: { type: 'number', description: 'Hours above daylight threshold today' },
|
||
light_visibility_km: { type: 'number', description: 'Estimated visibility (km)' },
|
||
light_uvi_max: { type: 'number', description: 'Daily max UV index' },
|
||
light_solar_wm2_sum: { type: 'number', description: 'Daily solar radiation sum (MJ/m²)' },
|
||
// Wind (Open-Meteo)
|
||
wind_speed_kmh: { type: 'number', description: 'Wind speed (km/h)' },
|
||
wind_direction_deg: { type: 'number', description: 'Wind direction (°)' },
|
||
wind_gusts_kmh: { type: 'number', description: 'Wind gusts (km/h)' },
|
||
wind_speed_max_kmh: { type: 'number', description: 'Daily max wind speed (km/h)' },
|
||
wind_gusts_max_kmh: { type: 'number', description: 'Daily max wind gusts (km/h)' },
|
||
// Forecast
|
||
forecast_weathercode: { type: 'number', description: 'WMO weather code' },
|
||
forecast_weather_label: { type: 'string', description: 'Human readable weather label' },
|
||
forecast_weather_icon: { type: 'string', description: 'Local icon path e.g. /icons/01d.png' },
|
||
forecast_precipitation_mm: { type: 'number', description: 'Precipitation (mm)' },
|
||
forecast_precipitation_probability: { type: 'number', description: 'Precipitation probability (%)' },
|
||
forecast_snowfall_mm: { type: 'number', description: 'Snowfall (mm)' },
|
||
forecast_snow_depth_m: { type: 'number', description: 'Snow depth (m)' },
|
||
forecast_cape: { type: 'number', description: 'Convective available potential energy (J/kg)' },
|
||
forecast_freezing_level_m: { type: 'number', description: 'Freezing level altitude (m)' },
|
||
forecast_evapotranspiration_mm:{ type: 'number', description: 'Evapotranspiration (mm)' },
|
||
// Seismic
|
||
seismic_ax: { type: 'number', description: 'Peak acceleration X axis (g)' },
|
||
seismic_ay: { type: 'number', description: 'Peak acceleration Y axis (g)' },
|
||
seismic_az: { type: 'number', description: 'Peak acceleration Z axis (g, includes gravity)' },
|
||
seismic_magnitude: { type: 'number', description: 'Peak seismic magnitude (g, gravity removed)' },
|
||
// Compass
|
||
compass_heading: { type: 'number', description: 'Magnetic heading (°)' },
|
||
compass_x: { type: 'number' },
|
||
compass_y: { type: 'number' },
|
||
compass_z: { type: 'number' },
|
||
// Ground / Accumulation
|
||
ground_distance_cm: { type: 'number', description: 'LIDAR ground distance (cm)' },
|
||
ground_lidar_strength: { type: 'number', description: 'LIDAR signal strength' },
|
||
ground_calibrated_baseline_cm: { type: 'number', description: 'Calibrated baseline distance (cm)' },
|
||
ground_accumulation_depth_cm: { type: 'number', description: 'Snow/flood depth (cm)' },
|
||
ground_accumulation_type: { type: 'string', enum: ['snow','slush','ice','flood'], description: 'Accumulation type' },
|
||
// Lightning
|
||
lightning_distance_km: { type: 'number', description: 'Lightning strike distance (km)' },
|
||
lightning_energy: { type: 'number', description: 'Lightning energy' },
|
||
lightning_strikes_per_hour: { type: 'number', description: 'Strike rate (strikes/hr)' },
|
||
lightning_storm_trend: { type: 'string', enum: ['Approaching','Retreating','Stationary'] },
|
||
lightning_false_positive: { type: 'number', description: '1 if disturber/false positive' },
|
||
lightning_detector_sensitivity:{ type: 'number', description: 'AS3935 noise floor setting (0–7)' },
|
||
// GPS
|
||
gps_lat: { type: 'number', description: 'Latitude (°)' },
|
||
gps_lon: { type: 'number', description: 'Longitude (°)' },
|
||
gps_alt_m: { type: 'number', description: 'Altitude (m)' },
|
||
gps_satellites: { type: 'number', description: 'Satellites in view' },
|
||
gps_speed_kmh: { type: 'number', description: 'Ground speed (km/h)' },
|
||
gps_heading: { type: 'number', description: 'GPS heading (°)' },
|
||
// Sun
|
||
sun_elevation: { type: 'number', description: 'Solar elevation angle (°)' },
|
||
sun_azimuth: { type: 'number', description: 'Solar azimuth (°)' },
|
||
sun_sunrise: { type: 'string', description: 'Sunrise time (ISO8601)' },
|
||
sun_sunset: { type: 'string', description: 'Sunset time (ISO8601)' },
|
||
sun_solar_noon: { type: 'string', description: 'Solar noon (ISO8601)' },
|
||
sun_day_length_hours: { type: 'number', description: 'Day length (hours)' },
|
||
sun_golden_hour_morning_start: { type: 'string' },
|
||
sun_golden_hour_morning_end: { type: 'string' },
|
||
sun_golden_hour_evening_start: { type: 'string' },
|
||
sun_golden_hour_evening_end: { type: 'string' },
|
||
sun_is_day: { type: 'number', description: '1 if daytime' },
|
||
sun_ssn: { type: 'number', description: 'Estimated sunspot number' },
|
||
sun_activity_label: { type: 'string', enum: ['Very Low','Low','Moderate','High','Very High'] },
|
||
// Moon
|
||
moon_phase: { type: 'string', description: 'Moon phase name' },
|
||
moon_illumination_pct: { type: 'number', description: 'Moon illumination (%)' },
|
||
moon_moonrise: { type: 'string', description: 'Moonrise time (ISO8601)' },
|
||
moon_moonset: { type: 'string', description: 'Moonset time (ISO8601)' },
|
||
moon_next_full: { type: 'string', description: 'Next full moon (ISO8601)' },
|
||
moon_next_new: { type: 'string', description: 'Next new moon (ISO8601)' },
|
||
// Season
|
||
season_next_event: { type: 'string', description: 'Next solstice/equinox name' },
|
||
season_next_event_date: { type: 'string' },
|
||
season_last_event: { type: 'string' },
|
||
season_last_event_date: { type: 'string' },
|
||
// Space weather
|
||
space_kp_index: { type: 'number', description: 'Planetary K index (0–9)' },
|
||
space_ap_index: { type: 'number', description: 'Ap geomagnetic index' },
|
||
space_geomagnetic_storm: { type: 'string', enum: ['None','Minor','Moderate','Strong','Severe'] },
|
||
space_solar_wind_speed_kms: { type: 'number', description: 'Solar wind speed (km/s)' },
|
||
space_solar_wind_density: { type: 'number', description: 'Solar wind proton density (p/cm³)' },
|
||
space_solar_wind_temp: { type: 'number', description: 'Solar wind temperature (K)' },
|
||
space_imf_bz: { type: 'number', description: 'IMF Bz component (nT)' },
|
||
space_imf_bt: { type: 'number', description: 'IMF total field Bt (nT)' },
|
||
space_solar_flux_f107: { type: 'number', description: 'Solar flux F10.7 index' },
|
||
// Marine
|
||
wave_height: { type: 'number', description: 'Significant wave height (m)' },
|
||
wave_direction: { type: 'number', description: 'Wave direction (°)' },
|
||
wave_period: { type: 'number', description: 'Wave period (s)' },
|
||
swell_wave_height: { type: 'number', description: 'Swell wave height (m)' },
|
||
swell_wave_direction: { type: 'number', description: 'Swell direction (°)' },
|
||
swell_wave_period: { type: 'number', description: 'Swell period (s)' },
|
||
wind_wave_height: { type: 'number', description: 'Wind wave height (m)' },
|
||
wave_height_max: { type: 'number', description: 'Daily max wave height (m)' },
|
||
// AQ
|
||
pm10: { type: 'number', description: 'PM10 (μg/m³)' },
|
||
pm2_5: { type: 'number', description: 'PM2.5 (μg/m³)' },
|
||
carbon_monoxide: { type: 'number', description: 'CO (μg/m³)' },
|
||
nitrogen_dioxide: { type: 'number', description: 'NO₂ (μg/m³)' },
|
||
sulphur_dioxide: { type: 'number', description: 'SO₂ (μg/m³)' },
|
||
ozone: { type: 'number', description: 'O₃ (μg/m³)' },
|
||
aerosol_optical_depth: { type: 'number' },
|
||
dust: { type: 'number', description: 'Dust (μg/m³)' },
|
||
alder_pollen: { type: 'number', description: 'Alder pollen (grains/m³)' },
|
||
birch_pollen: { type: 'number', description: 'Birch pollen (grains/m³)' },
|
||
grass_pollen: { type: 'number', description: 'Grass pollen (grains/m³)' },
|
||
mugwort_pollen: { type: 'number', description: 'Mugwort pollen (grains/m³)' },
|
||
olive_pollen: { type: 'number', description: 'Olive pollen (grains/m³)' },
|
||
ragweed_pollen: { type: 'number', description: 'Ragweed pollen (grains/m³)' },
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|