Re-implement Travel Forecast under OpenMeteo
This commit is contained in:
parent
9ddbef4784
commit
ff30f68013
2 changed files with 40 additions and 22 deletions
|
|
@ -1,13 +1,14 @@
|
||||||
// travel forecast display
|
// travel forecast display
|
||||||
import STATUS from './status.mjs';
|
import STATUS from './status.mjs';
|
||||||
import { safeJson, safePromiseAll } from './utils/fetch.mjs';
|
import { safePromiseAll } from './utils/fetch.mjs';
|
||||||
import { getSmallIcon } from './icons.mjs';
|
import { getSmallIconFromWmoCode } from './icons.mjs';
|
||||||
import { DateTime } from '../vendor/auto/luxon.mjs';
|
import { DateTime } from '../vendor/auto/luxon.mjs';
|
||||||
import WeatherDisplay from './weatherdisplay.mjs';
|
import WeatherDisplay from './weatherdisplay.mjs';
|
||||||
import { registerDisplay } from './navigation.mjs';
|
import { registerDisplay } from './navigation.mjs';
|
||||||
import settings from './settings.mjs';
|
|
||||||
import calculateScrollTiming from './utils/scroll-timing.mjs';
|
import calculateScrollTiming from './utils/scroll-timing.mjs';
|
||||||
import { debugFlag } from './utils/debug.mjs';
|
import { debugFlag } from './utils/debug.mjs';
|
||||||
|
import { temperature } from './utils/units.mjs';
|
||||||
|
import { getAggregatedOpenMeteoForecast } from './utils/weather.mjs';
|
||||||
|
|
||||||
class TravelForecast extends WeatherDisplay {
|
class TravelForecast extends WeatherDisplay {
|
||||||
constructor(navId, elemId, defaultActive) {
|
constructor(navId, elemId, defaultActive) {
|
||||||
|
|
@ -34,28 +35,18 @@ class TravelForecast extends WeatherDisplay {
|
||||||
async getData(weatherParameters, refresh) {
|
async getData(weatherParameters, refresh) {
|
||||||
// super checks for enabled
|
// super checks for enabled
|
||||||
if (!super.getData(weatherParameters, refresh)) return;
|
if (!super.getData(weatherParameters, refresh)) return;
|
||||||
if (!this.weatherParameters?.supportsNoaaDisplays) {
|
|
||||||
this.data = [];
|
|
||||||
this.timing.totalScreens = 0;
|
|
||||||
this.setStatus(STATUS.loaded);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// clear stored data if not refresh
|
// clear stored data if not refresh
|
||||||
if (!refresh) {
|
if (!refresh) {
|
||||||
this.previousData = [];
|
this.previousData = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const temperatureConverter = temperature();
|
||||||
|
|
||||||
const forecastPromises = TravelCities.map(async (city, index) => {
|
const forecastPromises = TravelCities.map(async (city, index) => {
|
||||||
try {
|
try {
|
||||||
// get point then forecast
|
|
||||||
if (!city.point) throw new Error('No pre-loaded point');
|
|
||||||
let forecast;
|
let forecast;
|
||||||
forecast = await safeJson(`https://api.weather.gov/gridpoints/${city.point.wfo}/${city.point.x},${city.point.y}/forecast`, {
|
forecast = await getAggregatedOpenMeteoForecast(city.Latitude, city.Longitude);
|
||||||
data: {
|
|
||||||
units: settings.units.value,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (forecast) {
|
if (forecast) {
|
||||||
// store for the next run
|
// store for the next run
|
||||||
|
|
@ -73,15 +64,23 @@ class TravelForecast extends WeatherDisplay {
|
||||||
}
|
}
|
||||||
return { name: city.Name, error: true };
|
return { name: city.Name, error: true };
|
||||||
}
|
}
|
||||||
// determine today or tomorrow (shift periods by 1 if tomorrow)
|
|
||||||
const todayShift = forecast.properties.periods[0].isDaytime ? 0 : 1;
|
const [todayKey, tomorrowKey] = Object.keys(forecast.aggregatedForecast);
|
||||||
|
const todayForecast = forecast.aggregatedForecast[todayKey];
|
||||||
|
const tomorrowForecast = forecast.aggregatedForecast[tomorrowKey] ?? todayForecast;
|
||||||
|
if (!todayForecast) {
|
||||||
|
throw new Error('No aggregated travel forecast available');
|
||||||
|
}
|
||||||
|
|
||||||
|
const firstHour = todayForecast.hours[0] ?? {};
|
||||||
|
const today = Boolean(firstHour.is_day ?? 1);
|
||||||
// return a pared-down forecast
|
// return a pared-down forecast
|
||||||
return {
|
return {
|
||||||
today: todayShift === 0,
|
today,
|
||||||
high: forecast.properties.periods[todayShift].temperature,
|
high: temperatureConverter(todayForecast.temperature_2m_max),
|
||||||
low: forecast.properties.periods[todayShift + 1].temperature,
|
low: temperatureConverter(tomorrowForecast.temperature_2m_min),
|
||||||
name: city.Name,
|
name: city.Name,
|
||||||
icon: getSmallIcon(forecast.properties.periods[todayShift].icon),
|
icon: getSmallIconFromWmoCode(todayForecast.weather_code, today),
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Unexpected error getting Travel Forecast for ${city.Name}: ${error.message}`);
|
console.error(`Unexpected error getting Travel Forecast for ${city.Name}: ${error.message}`);
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,24 @@ const getOpenMeteoForecast = async (lat, lon) => {
|
||||||
return forecast;
|
return forecast;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getAggregatedOpenMeteoForecast = async (lat, lon) => {
|
||||||
|
const forecast = await getOpenMeteoForecast(lat, lon);
|
||||||
|
if (!forecast) return false;
|
||||||
|
|
||||||
|
const aggregatedForecast = aggregateWeatherForecastData(forecast);
|
||||||
|
if (!aggregatedForecast) {
|
||||||
|
if (debugFlag('verbose-failures')) {
|
||||||
|
console.warn(`Unable to aggregate Open-Meteo forecast for ${lat},${lon}`);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
forecast,
|
||||||
|
aggregatedForecast,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const weatherConditions = [
|
const weatherConditions = [
|
||||||
{ codes: [0], text: ['Clear sky'] },
|
{ codes: [0], text: ['Clear sky'] },
|
||||||
{ codes: [1, 2, 3], text: ['Mainly clear', 'Partly cloudy', 'Overcast'] },
|
{ codes: [1, 2, 3], text: ['Mainly clear', 'Partly cloudy', 'Overcast'] },
|
||||||
|
|
@ -124,6 +142,7 @@ const aggregateWeatherForecastData = (forecastResponse) => {
|
||||||
export {
|
export {
|
||||||
getPoint,
|
getPoint,
|
||||||
getOpenMeteoForecast,
|
getOpenMeteoForecast,
|
||||||
|
getAggregatedOpenMeteoForecast,
|
||||||
aggregateWeatherForecastData,
|
aggregateWeatherForecastData,
|
||||||
getConditionText,
|
getConditionText,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue