Skip to content

Commit

Permalink
feat: You can now select OpenMeteo model per favorite
Browse files Browse the repository at this point in the history
  • Loading branch information
farfromrefug committed Feb 27, 2025
1 parent 1f40a2f commit 239e954
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 63 deletions.
45 changes: 43 additions & 2 deletions app/components/WeatherPage.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
queryTimezone,
renameFavorite,
setFavoriteAqiProvider,
setFavoriteOMProviderModel,
setFavoriteProvider,
toggleFavorite
} from '~/helpers/favorites';
Expand All @@ -53,13 +54,23 @@
import { onIconPackChanged } from '~/services/icon';
import { OWMProvider } from '~/services/providers/owm';
import type { AqiProviderType, DailyData, Hourly, ProviderType, WeatherData } from '~/services/providers/weather';
import { aqi_providers, getAqiProvider, getAqiProviderType, getProviderType, getWeatherProvider, onProviderChanged, providers } from '~/services/providers/weatherproviderfactory';
import {
aqi_providers,
getAqiProvider,
getAqiProviderType,
getOMPreferredModel,
getProviderType,
getWeatherProvider,
onProviderChanged,
providers
} from '~/services/providers/weatherproviderfactory';
import { WeatherProps, mergeWeatherData, onWeatherDataChanged, weatherDataService } from '~/services/weatherData';
import { hideLoading, selectValue, showAlertOptionSelect, showLoading, showPopoverMenu, tryCatch, tryCatchFunction } from '~/utils/ui';
import { isBRABounds } from '~/utils/utils.common';
import { actionBarHeight, colors, fontScale, fonts, onSettingsChanged, windowInset } from '~/variables';
import IconButton from './common/IconButton.svelte';
import ThankYou from '@shared/components/ThankYou.svelte';
import { OpenMeteoModels } from '~/services/providers/om';
const gps: GPS = new GPS();
const gpsAvailable = gps.hasGPS();
Expand Down Expand Up @@ -250,7 +261,7 @@
Object.assign(weatherLocation, timezoneData);
saveWeatherLocation();
}
weatherData = await getWeatherProvider(weatherLocation.provider).getWeather(weatherLocation);
weatherData = await getWeatherProvider(weatherLocation.provider).getWeather(weatherLocation, { model: weatherLocation.omModel });
DEV_LOG && console.log('refreshWeather', timezoneData, weatherLocation.timezone);
if (timezoneData) {
}
Expand Down Expand Up @@ -597,6 +608,16 @@
setWeatherLocationProvider(value, location);
}
}
async function selectOMProviderModel(location: WeatherLocation) {
const value = await selectValue<OpenMeteoModels>(
Object.keys(OpenMeteoModels).map((t) => ({ data: t as OpenMeteoModels, title: OpenMeteoModels[t] })),
location.omModel || getOMPreferredModel(),
{ title: lc('open_meteo_model') }
);
if (value) {
setWeatherLocationOMProviderModel(value, location);
}
}
async function selectProviderAQI(location: WeatherLocation) {
const value = await selectValue<AqiProviderType>(
Expand Down Expand Up @@ -647,6 +668,17 @@
refreshWeather();
}
}
function setWeatherLocationOMProviderModel(model: OpenMeteoModels, location: WeatherLocation = weatherLocation) {
DEV_LOG && console.log('setWeatherLocationOMProviderModel', JSON.stringify(location), provider, isFavorite(location));
location.omModel = model;
saveWeatherLocation();
if (isFavorite(location)) {
setFavoriteOMProviderModel(location, model);
} else if (isCurrentLocation(location)) {
updateProvider();
refreshWeather();
}
}
function setWeatherLocationAQIProvider(provider: AqiProviderType, location: WeatherLocation = weatherLocation) {
location.providerAqi = provider;
saveWeatherLocation();
Expand Down Expand Up @@ -784,6 +816,12 @@
name: lc('provider.title'),
subtitle: lc('provider.' + (favItem?.provider || getProviderType()))
},
{
icon: 'mdi-database',
id: 'om_model',
subtitle: OpenMeteoModels[favItem?.omModel || getOMPreferredModel()],
title: lc('open_meteo_model')
},
{
icon: 'mdi-leaf',
id: 'provider_aqi',
Expand Down Expand Up @@ -876,6 +914,9 @@
case 'provider_aqi':
await selectProviderAQI(favItem);
break;
case 'om_model':
await selectOMProviderModel(favItem);
break;
case 'rename':
result = await prompt({
title: lc('rename'),
Expand Down
20 changes: 10 additions & 10 deletions app/components/settings/Settings.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
import { CheckBox } from '@nativescript-community/ui-checkbox';
import { CollectionView } from '@nativescript-community/ui-collectionview';
import { openFilePicker, saveFile } from '@nativescript-community/ui-document-picker';
import { Label } from '@nativescript-community/ui-label';
import { showBottomSheet } from '@nativescript-community/ui-material-bottomsheet/svelte';
import { confirm, prompt } from '@nativescript-community/ui-material-dialogs';
import { showSnack } from '@nativescript-community/ui-material-snackbar';
import { TextField, TextFieldProperties } from '@nativescript-community/ui-material-textfield';
import { TextView } from '@nativescript-community/ui-material-textview';
import { ApplicationSettings, File, ObservableArray, Page, ScrollView, StackLayout, TouchGestureEventData, Utils, View } from '@nativescript/core';
import { inappItems, presentInAppSponsorBottomsheet } from '@shared/utils/inapp-purchase';
import { Sentry } from '@shared/utils/sentry';
import { showError } from '@shared/utils/showError';
import { navigate } from '@shared/utils/svelte/ui';
Expand All @@ -23,7 +25,6 @@
CHARTS_LANDSCAPE,
CHARTS_PORTRAIT_FULLSCREEN,
DAILY_PAGE_HOURLY_CHART,
DECIMAL_METRICS_TEMP,
DEFAULT_DAILY_DATE_FORMAT,
DEFAULT_HOURLY_ODD_COLORS,
FEELS_LIKE_TEMPERATURE,
Expand All @@ -48,6 +49,7 @@
SETTINGS_METRIC_CM_TO_MM,
SETTINGS_METRIC_TEMP_DECIMAL,
SETTINGS_MIN_UV_INDEX,
SETTINGS_OM_PREFERED_MODEL,
SETTINGS_PROVIDER,
SETTINGS_PROVIDER_AQI,
SETTINGS_SHOW_CURRENT_DAY_DAILY,
Expand Down Expand Up @@ -75,14 +77,12 @@
import { UNITS, UNIT_FAMILIES } from '~/helpers/units';
import { networkService } from '~/services/api';
import { iconService } from '~/services/icon';
import { OM_MODELS } from '~/services/providers/om';
import { aqi_providers, getAqiProviderType, getProviderType, providers } from '~/services/providers/weatherproviderfactory';
import { OpenMeteoModels } from '~/services/providers/om';
import { aqi_providers, getAqiProviderType, getOMPreferredModel, getProviderType, providers } from '~/services/providers/weatherproviderfactory';
import { AVAILABLE_WEATHER_DATA, getWeatherDataTitle, weatherDataService } from '~/services/weatherData';
import { confirmRestartApp, createView, getDateFormatHTMLArgs, hideLoading, openLink, selectValue, showAlertOptionSelect, showLoading, showSliderPopover } from '~/utils/ui';
import { confirmRestartApp, createView, getDateFormatHTMLArgs, hideLoading, openLink, selectValue, showLoading, showSliderPopover } from '~/utils/ui';
import { colors, fonts, iconColor, imperial, metricDecimalTemp, onUnitsChanged, unitCMToMM, unitsSettings, windowInset } from '~/variables';
import IconButton from '../common/IconButton.svelte';
import { inappItems, presentInAppSponsorBottomsheet } from '@shared/utils/inapp-purchase';
import { Label } from '@nativescript-community/ui-label';
const version = __APP_VERSION__ + ' Build ' + __APP_BUILD_NUMBER__;
const storeSettings = {};
</script>
Expand Down Expand Up @@ -379,13 +379,13 @@
title: lc('provider.openmeteo')
},
{
key: 'open_meteo_prefered_model',
key: SETTINGS_OM_PREFERED_MODEL,
id: 'setting',
valueType: 'string',
description: () => OM_MODELS[ApplicationSettings.getString('open_meteo_prefered_model', 'best_match')],
description: () => OpenMeteoModels[getOMPreferredModel()],
title: lc('open_meteo_prefered_model'),
currentValue: () => ApplicationSettings.getString('open_meteo_prefered_model', 'best_match'),
values: Object.keys(OM_MODELS).map((t) => ({ value: t, title: OM_MODELS[t] }))
currentValue: getOMPreferredModel,
values: Object.keys(OpenMeteoModels).map((t) => ({ value: t, title: OpenMeteoModels[t] }))
},
{
type: 'sectionheader',
Expand Down
2 changes: 2 additions & 0 deletions app/helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const SETTINGS_PROVIDER_AQI = 'provider_aqi';
export const SETTINGS_WEATHER_LOCATION = 'weatherLocation';
export const SETTINGS_FAVORITES = 'favorites';
export const SETTINGS_DAILY_DATE_FORMAT = 'daily_date_format';
export const SETTINGS_OM_PREFERED_MODEL = 'open_meteo_prefered_model';

export const DEFAULT_COLOR_THEME = 'default';
export const DEFAULT_LOCALE = 'auto';
Expand All @@ -52,6 +53,7 @@ export const FEELS_LIKE_TEMPERATURE = false;
export const ALWAYS_SHOW_PRECIP_PROB = false;
export const DEFAULT_METRIC_CM_TO_MM = false;
export const DEFAULT_DAILY_DATE_FORMAT = 'DD/MM';
export const DEFAULT_OM_PREFERED_MODEL = 'best_match';

export const WEATHER_DATA_LAYOUT = 'default';

Expand Down
14 changes: 12 additions & 2 deletions app/helpers/favorites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ import { globalObservable } from '@shared/utils/svelte/ui';
import PolygonLookup from 'polygon-lookup';
import { AqiProviderType, ProviderType } from '~/services/providers/weather';
import { SETTINGS_FAVORITES } from './constants';
import { OpenMeteoModels } from '~/services/providers/om';

export const EVENT_FAVORITE = 'favorite'
export const EVENT_FAVORITE = 'favorite';

export interface FavoriteLocation extends WeatherLocation {
isFavorite?: boolean;
Expand Down Expand Up @@ -99,7 +100,16 @@ export async function setFavoriteProvider(item: FavoriteLocation, provider: Prov
const index = favoritesKeys.indexOf(key);
if (index !== -1) {
item.provider = provider;
DEV_LOG && console.log('setFavoriteProvider', provider, JSON.stringify(item));
favorites.setItem(index, item);
globalObservable.notify({ eventName: EVENT_FAVORITE, data: item });
}
}

export async function setFavoriteOMProviderModel(item: FavoriteLocation, model: OpenMeteoModels) {
const key = getFavoriteKey(item);
const index = favoritesKeys.indexOf(key);
if (index !== -1) {
item.omModel = model;
favorites.setItem(index, item);
globalObservable.notify({ eventName: EVENT_FAVORITE, data: item });
}
Expand Down
1 change: 1 addition & 0 deletions app/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@
"o3": "O₃",
"ok": "OK",
"olea": "olive",
"open_meteo_model": "Open-Meteo model",
"open_meteo_prefered_model": "Open-Meteo preferred model",
"open_website": "Open website",
"owm_api_key": "OpenWeather API key",
Expand Down
2 changes: 2 additions & 0 deletions app/services/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { NominatimResult } from '../../typings/nominatim';
import { Photon, PhotonProperties } from '../../typings/photon';
import { AqiProviderType, ProviderType, WeatherData } from './providers/weather';
import { WeatherProps } from './weatherData';
import { OpenMeteoModels } from './providers/om';

type HTTPSOptions = https.HttpsRequestOptions;

Expand Down Expand Up @@ -423,6 +424,7 @@ export interface WeatherLocation {
lon: number;
};
provider?: ProviderType;
omModel?: OpenMeteoModels;
providerAqi?: AqiProviderType;
}
const PHOTON_SUPPORTED_LANGUAGES = ['en', 'de', 'fr'];
Expand Down
94 changes: 47 additions & 47 deletions app/services/providers/om.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { ApplicationSettings } from '@nativescript/core';
import dayjs from 'dayjs';
import { FEELS_LIKE_TEMPERATURE, NB_DAYS_FORECAST, NB_HOURS_FORECAST, NB_MINUTES_FORECAST } from '~/helpers/constants';
import { WeatherDataType, aqiDataIconColors, weatherDataIconColors } from '~/helpers/formatter';
import { getStartOfDay, l } from '~/helpers/locale';
import { Pollutants, getAqiFromPollutants, prepareAirQualityData } from '../airQualityData';
import { Pollutants, prepareAirQualityData } from '../airQualityData';
import { WeatherLocation, request } from '../api';
import { WeatherProps, weatherDataService } from '../weatherData';
import { AirQualityProvider } from './airqualityprovider';
import { Forecast } from './openmeteo';
import { AirQualityCurrently, AirQualityData, CommonAirQualityData, Currently, DailyData, Hourly, MinutelyData, WeatherData } from './weather';
import { WeatherProvider } from './weatherprovider';
import { getOMPreferredModel } from './weatherproviderfactory';
// import { Coord, Dailyforecast, Forecast, MFCurrent, MFForecastResult, MFMinutely, MFWarnings, Probabilityforecast } from './meteofrance';

// const mfApiKey = getString('mfApiKey', MF_DEFAULT_KEY);
Expand All @@ -23,48 +23,48 @@ const KEY_MAPPING = {
ammonia: Pollutants.NH3
};

export const OM_MODELS = {
best_match: 'Best match',
ecmwf_ifs04: 'ECMWF IFS 0.4°',
ecmwf_ifs025: 'ECMWF IFS 0.25°',
ecmwf_aifs025: 'ECMWF AIFS 0.25°',
cma_grapes_global: 'CMA GRAPES Global',
bom_access_global: 'BOM Access Global',
metno_nordic: 'MET Norway Nordic',
metno_seamless: 'MET Norway Nordic Seamless (with ECMWF)',
gfs_seamless: 'GFS Seamless',
gfs_global: 'GFS Global',
gfs_hrrr: 'GFS HRRR',
gfs_graphcast025: 'GFS GraphCast',
icon_seamless: 'DWD Icon Seamless',
icon_global: 'DWD Icon Global',
icon_eu: 'DWD Icon EU',
icon_d2: 'DWD Icon D2',
gem_seamless: 'GEM Seamless',
gem_global: 'GEM Global',
gem_regional: 'GEM Regional',
gem_hrdps_continental: 'GEM HRDPS Continental',
meteofrance_seamless: 'MeteoFrance Seamless',
meteofrance_arpege_world: 'MeteoFrance Arpege World',
meteofrance_arpege_europe: 'MeteoFrance Arpege Europe',
meteofrance_arome_france: ' MeteoFrance Arome France',
meteofrance_arome_france_hd: 'MeteoFrance Arome France HD',
arpae_cosmo_seamless: 'ARPAE Seamless',
arpae_cosmo_2i: 'ARPAE COSMO 2I',
arpae_cosmo_5m: 'ARPAE COSMO 5M',
ukmo_seamless: 'UK Met Office Seamless',
ukmo_global_deterministic_10km: 'UK Met Office Global 10km',
ukmo_uk_deterministic_2km: 'UK Met Office UK 2km',
ncep_nbm_conus: 'NCEP NBM U.S. Conus',
jma_seamless: 'JMA Seamless',
jma_msm: 'JMA MSM',
jma_gsm: 'JMA GSM',
knmi_seamless: 'KNMI Seamless (with ECMWF)',
knmi_harmonie_arome_europe: 'KNMI Harmonie Arome Europe',
knmi_harmonie_arome_netherlands: 'KNMI Harmonie Arome Netherlands',
dmi_seamless: 'DMI Seamless (with ECMWF)',
dmi_harmonie_arome_europe: 'DMI Harmonie Arome Europe'
};
export enum OpenMeteoModels {
best_match = 'Best match',
ecmwf_ifs04 = 'ECMWF IFS 0.4°',
ecmwf_ifs025 = 'ECMWF IFS 0.25°',
ecmwf_aifs025 = 'ECMWF AIFS 0.25°',
cma_grapes_global = 'CMA GRAPES Global',
bom_access_global = 'BOM Access Global',
metno_nordic = 'MET Norway Nordic',
metno_seamless = 'MET Norway Nordic Seamless (with ECMWF)',
gfs_seamless = 'GFS Seamless',
gfs_global = 'GFS Global',
gfs_hrrr = 'GFS HRRR',
gfs_graphcast025 = 'GFS GraphCast',
icon_seamless = 'DWD Icon Seamless',
icon_global = 'DWD Icon Global',
icon_eu = 'DWD Icon EU',
icon_d2 = 'DWD Icon D2',
gem_seamless = 'GEM Seamless',
gem_global = 'GEM Global',
gem_regional = 'GEM Regional',
gem_hrdps_continental = 'GEM HRDPS Continental',
meteofrance_seamless = 'MeteoFrance Seamless',
meteofrance_arpege_world = 'MeteoFrance Arpege World',
meteofrance_arpege_europe = 'MeteoFrance Arpege Europe',
meteofrance_arome_france = ' MeteoFrance Arome France',
meteofrance_arome_france_hd = 'MeteoFrance Arome France HD',
arpae_cosmo_seamless = 'ARPAE Seamless',
arpae_cosmo_2i = 'ARPAE COSMO 2I',
arpae_cosmo_5m = 'ARPAE COSMO 5M',
ukmo_seamless = 'UK Met Office Seamless',
ukmo_global_deterministic_10km = 'UK Met Office Global 10km',
ukmo_uk_deterministic_2km = 'UK Met Office UK 2km',
ncep_nbm_conus = 'NCEP NBM U.S. Conus',
jma_seamless = 'JMA Seamless',
jma_msm = 'JMA MSM',
jma_gsm = 'JMA GSM',
knmi_seamless = 'KNMI Seamless (with ECMWF)',
knmi_harmonie_arome_europe = 'KNMI Harmonie Arome Europe',
knmi_harmonie_arome_netherlands = 'KNMI Harmonie Arome Netherlands',
dmi_seamless = 'DMI Seamless (with ECMWF)',
dmi_harmonie_arome_europe = 'DMI Harmonie Arome Europe'
}

export const API_KEY_VALUES = {
forecast: ({ current, currentData, feelsLikeTemperatures, minutely }: { currentData: WeatherProps[]; feelsLikeTemperatures: boolean; current: boolean; minutely: boolean }) => ({
Expand Down Expand Up @@ -131,11 +131,11 @@ export class OMProvider extends WeatherProvider implements AirQualityProvider {
static id = 'openmeteo';
id = OMProvider.id;
getModels() {
return OM_MODELS;
return OpenMeteoModels;
}

getModelName(key) {
return OM_MODELS[key];
return OpenMeteoModels[key];
}
private static readonly weatherCodeDescription = {
0: l('clear'),
Expand Down Expand Up @@ -288,7 +288,7 @@ export class OMProvider extends WeatherProvider implements AirQualityProvider {
current,
forceModel,
minutely,
model = ApplicationSettings.getString('open_meteo_prefered_model', 'best_match'),
model = getOMPreferredModel(),
warnings,
weatherProps
}: { warnings?: boolean; minutely?: boolean; current?: boolean; model?: string; forceModel?: boolean; weatherProps?: WeatherProps[] } = {}
Expand Down
8 changes: 6 additions & 2 deletions app/services/providers/weatherproviderfactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { createGlobalEventListener, globalObservable } from '@shared/utils/svelt
import { prefs } from '../preferences';
import { AirQualityProvider } from './airqualityprovider';
import { MFProvider } from './mf';
import { OMProvider } from './om';
import { OMProvider, OpenMeteoModels } from './om';
import { OWMProvider } from './owm';
import { AqiProviderType, ProviderType } from './weather';
import { WeatherProvider } from './weatherprovider';
import { AtmoProvider } from './atmo';
import { SETTINGS_PROVIDER, SETTINGS_PROVIDER_AQI } from '~/helpers/constants';
import { DEFAULT_OM_PREFERED_MODEL, SETTINGS_OM_PREFERED_MODEL, SETTINGS_PROVIDER, SETTINGS_PROVIDER_AQI } from '~/helpers/constants';

export enum Providers {
MeteoFrance = 'meteofrance',
Expand Down Expand Up @@ -58,6 +58,10 @@ export function getAqiProviderType(): AqiProviderType {
return requestedProviderType;
}

export function getOMPreferredModel() {
return ApplicationSettings.getString(SETTINGS_OM_PREFERED_MODEL, DEFAULT_OM_PREFERED_MODEL) as OpenMeteoModels;
}

export function getProviderForType(newType: ProviderType): WeatherProvider {
switch (newType) {
case Providers.OpenWeather:
Expand Down

0 comments on commit 239e954

Please sign in to comment.