const axios = require('axios'); const TIMEOUT = 10000; const HEADERS = { Accept: "application/json, text/plain;q=0.9,*/*;q=0.8" }; // Parametri API const FORECAST_PARAMS = { current: [ 'temperature_2m', 'wind_speed_10m', 'wind_direction_10m', 'wind_gusts_10m', 'precipitation', 'rain', 'relative_humidity_2m', 'pressure_msl' ], hourly: [ 'temperature_2m', 'precipitation_probability', 'precipitation', 'rain', 'wind_speed_10m', 'cloud_cover', 'wind_direction_10m', 'relative_humidity_2m', 'pressure_msl' ] }; const MARINE_PARAMS = { current: [ 'wave_height', 'wave_direction', 'wave_period', 'wave_peak_period', 'ocean_current_velocity', 'ocean_current_direction' ], hourly: [ 'wave_height', 'wave_direction', 'wave_period', 'wave_peak_period', 'ocean_current_velocity', 'ocean_current_direction' ] }; // Unità di misura globali (aggiornate da OpenMeteo) let globalUnits = { forecast: { temperature: '°C', humidity: '%', pressure: 'hPa', windSpeed: 'km/h', windDirection: '°', windGusts: 'km/h', rain: 'mm', precipitation: 'mm' }, waves: { waveHeight: 'm', wavePeriod: 's', waveDirection: '°', wavePeakPeriod: 's' } }; /** * Ottiene le unità di misura globali */ function getUnits() { return globalUnits; } /** * Formatta un valore con la sua unità */ function formatWithUnit(value, unitKey, category = 'forecast') { if (value === null || value === undefined) return 'n/d'; const unit = globalUnits[category]?.[unitKey] || ''; return `${value}${unit}`; } async function getForecast(location, options = { mode: 'both' }) { const mode = options.mode || 'both'; const params = []; const currentParams = FORECAST_PARAMS.current.join(","); const hourlyParams = FORECAST_PARAMS.hourly.join(","); if (mode === 'both' || mode === 'current') { params.push('current=' + currentParams); } if (mode === 'both' || mode === 'hourly') { params.push('hourly=' + hourlyParams); } if (!location?.latitude || !location?.longitude) { console.warn('[OpenMeteo] Coordinate non valide per forecast'); return null; } const api = `https://api.open-meteo.com/v1/forecast?latitude=${location.latitude}&longitude=${location.longitude}&${params.join('&')}`; try { const response = await axios.get(api, { headers: HEADERS, timeout: TIMEOUT, validateStatus: (status) => status === 200 }); const { data } = response; // Aggiorna unità globali da API response if (data.current_units) { globalUnits.forecast = { temperature: data.current_units.temperature_2m || '°C', humidity: data.current_units.relative_humidity_2m || '%', pressure: data.current_units.pressure_msl || 'hPa', windSpeed: data.current_units.wind_speed_10m || 'km/h', windDirection: data.current_units.wind_direction_10m || '°', windGusts: data.current_units.wind_gusts_10m || 'km/h', rain: data.current_units.rain || 'mm', precipitation: data.current_units.precipitation || 'mm' }; } return { timestamp: Date.now(), temperature: data.current?.temperature_2m ?? null, humidity: data.current?.relative_humidity_2m ?? null, pressure: data.current?.pressure_msl ?? null, // Refactored to match sensorsReferences.json hierarchy wind: { speed: data.current?.wind_speed_10m ?? null, direction: data.current?.wind_direction_10m ?? null, gusts: data.current?.wind_gusts_10m ?? null, }, rain: data.current?.rain ?? null, precipitation: data.current?.precipitation ?? null, // Keeping simple properties flat // Unita di misura units: globalUnits.forecast, // Parametri orari hourly: data.hourly ? { time: data.hourly?.time, temperature: data.hourly?.temperature_2m, pressure: data.hourly?.pressure_msl, precipitationProbability: data.hourly?.precipitation_probability, precipitation: data.hourly?.precipitation, rain: data.hourly?.rain, cloudCover: data.hourly?.cloud_cover, windDirection: data.hourly?.wind_direction_10m, humidity: data.hourly?.relative_humidity_2m, windSpeed: data.hourly?.wind_speed_10m } : null, hourlyUnits: data.hourly_units || null }; } catch (error) { console.error(`[OpenMeteo Forecast] Errore: ${error.message}`); return null; } } async function getSeaConditions(location, options = { mode: 'both' }) { const mode = options.mode || 'both'; const params = []; const currentParams = MARINE_PARAMS.current.join(","); const hourlyParams = MARINE_PARAMS.hourly.join(","); if (mode === 'both' || mode === 'current') { params.push('current=' + currentParams); } if (mode === 'both' || mode === 'hourly') { params.push('hourly=' + hourlyParams); } if (!location?.latitude || !location?.longitude) { console.warn('[OpenMeteo] Coordinate non valide per onde'); return null; } const api = `https://marine-api.open-meteo.com/v1/marine?latitude=${location.latitude}&longitude=${location.longitude}&${params.join('&')}&models=ecmwf_wam`; try { const response = await axios.get(api, { headers: HEADERS, timeout: TIMEOUT, validateStatus: (status) => status === 200 }); const { data } = response; // Aggiorna unità globali da API response if (data.current_units) { globalUnits.waves = { waveHeight: data.current_units.wave_height || 'm', wavePeriod: data.current_units.wave_period || 's', waveDirection: data.current_units.wave_direction || '°', wavePeakPeriod: data.current_units.wave_peak_period || 's', currentVelocity: data.current_units.ocean_current_velocity || 'm/s', currentDirection: data.current_units.ocean_current_direction || '°' }; } return { // Refactored to match sensorsReferences.json hierarchy waves: { height: data.current?.wave_height ?? null, period: data.current?.wave_period ?? null, direction: data.current?.wave_direction ?? null, peakPeriod: data.current?.wave_peak_period ?? null }, // Keeping these flat essentially currentDirection: data.current?.ocean_current_direction ?? null, currentVelocity: data.current?.ocean_current_velocity ?? null, // Unità di misura units: globalUnits.waves, // Dati orari per grafici hourly: data.hourly ? { time: data.hourly?.time, waveHeight: data.hourly?.wave_height, wavePeriod: data.hourly?.wave_period, waveDirection: data.hourly?.wave_direction, currentDirection: data.hourly?.ocean_current_direction, currentVelocity: data.hourly?.ocean_current_velocity } : null, hourlyUnits: data.hourly_units || null }; } catch (error) { console.error(`[OpenMeteo Marine] Errore: ${error.message}`); return null; } } module.exports = { getSeaConditions, getForecast, getUnits, formatWithUnit };