From 55c83868a54b01d242443677cb6d11c046ff605a Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sat, 18 Apr 2026 10:35:00 +0200 Subject: [PATCH 1/3] refactor(weather): use nullish coalescing in weatherflow provider Replace || with ?? for numeric weather fields so valid zero values are preserved instead of being replaced with null. --- .../weather/providers/weatherflow.js | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/defaultmodules/weather/providers/weatherflow.js b/defaultmodules/weather/providers/weatherflow.js index 8a4d18daa8..b99d860477 100644 --- a/defaultmodules/weather/providers/weatherflow.js +++ b/defaultmodules/weather/providers/weatherflow.js @@ -145,11 +145,11 @@ class WeatherFlowProvider { const weather = { date: new Date(), - humidity: current.relative_humidity || null, - temperature: current.air_temperature || null, - feelsLikeTemp: current.feels_like || null, + humidity: current.relative_humidity ?? null, + temperature: current.air_temperature ?? null, + feelsLikeTemp: current.feels_like ?? null, windSpeed: current.wind_avg != null ? convertKmhToMs(current.wind_avg) : null, - windFromDirection: current.wind_direction || null, + windFromDirection: current.wind_direction ?? null, weatherType: this.#convertWeatherType(current.icon), uvIndex: current.uv || null, sunrise: daily.sunrise ? new Date(daily.sunrise * 1000) : null, @@ -175,9 +175,9 @@ class WeatherFlowProvider { for (const forecast of data.forecast.daily) { const weather = { date: new Date(forecast.day_start_local * 1000), - minTemperature: forecast.air_temp_low || null, - maxTemperature: forecast.air_temp_high || null, - precipitationProbability: forecast.precip_probability || null, + minTemperature: forecast.air_temp_low ?? null, + maxTemperature: forecast.air_temp_high ?? null, + precipitationProbability: forecast.precip_probability ?? null, weatherType: this.#convertWeatherType(forecast.icon), precipitationAmount: 0.0, precipitationUnits: "mm", @@ -193,8 +193,8 @@ class WeatherFlowProvider { if (hourDate.getFullYear() === forecastDate.getFullYear() && hourDate.getMonth() === forecastDate.getMonth() && hourDate.getDate() === forecastDate.getDate()) { - weather.uvIndex = Math.max(weather.uvIndex, hour.uv || 0); - weather.precipitationAmount += hour.precip || 0; + weather.uvIndex = Math.max(weather.uvIndex, hour.uv ?? 0); + weather.precipitationAmount += hour.precip ?? 0; } else if (hourDate > forecastDate) { // Check if we've moved to the next day const diffMs = hourDate - forecastDate; @@ -224,14 +224,14 @@ class WeatherFlowProvider { for (const hour of data.forecast.hourly) { const weather = { date: new Date(hour.time * 1000), - temperature: hour.air_temperature || null, - feelsLikeTemp: hour.feels_like || null, - humidity: hour.relative_humidity || null, + temperature: hour.air_temperature ?? null, + feelsLikeTemp: hour.feels_like ?? null, + humidity: hour.relative_humidity ?? null, windSpeed: hour.wind_avg != null ? convertKmhToMs(hour.wind_avg) : null, - windFromDirection: hour.wind_direction || null, + windFromDirection: hour.wind_direction ?? null, weatherType: this.#convertWeatherType(hour.icon), - precipitationProbability: hour.precip_probability || null, - precipitationAmount: hour.precip || 0, + precipitationProbability: hour.precip_probability ?? null, + precipitationAmount: hour.precip ?? 0, precipitationUnits: "mm", uvIndex: hour.uv || null }; From b35495cf5798d94d0f2c070b28c2a2d499759d8a Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sat, 18 Apr 2026 10:35:01 +0200 Subject: [PATCH 2/3] feat(weatherflow): map precipitation in current weather Add precip_accum_local_day and precip_probability to current conditions. Use null-safe checks in template so zero values render correctly. --- defaultmodules/weather/current.njk | 4 ++-- defaultmodules/weather/providers/weatherflow.js | 3 +++ .../modules/default/weather/providers/weatherflow_spec.js | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/defaultmodules/weather/current.njk b/defaultmodules/weather/current.njk index b75966d3b1..7e2bc3d6d5 100644 --- a/defaultmodules/weather/current.njk +++ b/defaultmodules/weather/current.njk @@ -78,11 +78,11 @@
{% endif %} - {% if config.showPrecipitationAmount and current.precipitationAmount %} + {% if config.showPrecipitationAmount and current.precipitationAmount is defined and current.precipitationAmount is not none %} {{ "PRECIP_AMOUNT" | translate }} {{ current.precipitationAmount | unit("precip", current.precipitationUnits) }}
{% endif %} - {% if config.showPrecipitationProbability and current.precipitationProbability %} + {% if config.showPrecipitationProbability and current.precipitationProbability is defined and current.precipitationProbability is not none %} {{ "PRECIP_POP" | translate }} {{ current.precipitationProbability }}% {% endif %} diff --git a/defaultmodules/weather/providers/weatherflow.js b/defaultmodules/weather/providers/weatherflow.js index b99d860477..e94af5109f 100644 --- a/defaultmodules/weather/providers/weatherflow.js +++ b/defaultmodules/weather/providers/weatherflow.js @@ -151,6 +151,9 @@ class WeatherFlowProvider { windSpeed: current.wind_avg != null ? convertKmhToMs(current.wind_avg) : null, windFromDirection: current.wind_direction ?? null, weatherType: this.#convertWeatherType(current.icon), + precipitationAmount: current.precip_accum_local_day ?? null, + precipitationUnits: "mm", + precipitationProbability: current.precip_probability ?? null, uvIndex: current.uv || null, sunrise: daily.sunrise ? new Date(daily.sunrise * 1000) : null, sunset: daily.sunset ? new Date(daily.sunset * 1000) : null diff --git a/tests/unit/modules/default/weather/providers/weatherflow_spec.js b/tests/unit/modules/default/weather/providers/weatherflow_spec.js index 2eb2fdb4a4..f6b28cadcb 100644 --- a/tests/unit/modules/default/weather/providers/weatherflow_spec.js +++ b/tests/unit/modules/default/weather/providers/weatherflow_spec.js @@ -85,6 +85,9 @@ describe("WeatherFlowProvider", () => { expect(result).toBeDefined(); expect(result.temperature).toBe(16); expect(result.humidity).toBe(28); + expect(result.precipitationAmount).toBe(0); + expect(result.precipitationUnits).toBe("mm"); + expect(result.precipitationProbability).toBe(0); expect(result.weatherType).not.toBeNull(); }); From eb0d6ec1ab352634dedb543eb8376b65924f5275 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Sat, 18 Apr 2026 10:35:01 +0200 Subject: [PATCH 3/3] fix(weather): standardize UV field as uvIndex Rename uv_index to uvIndex in weatherapi provider to match the canonical field name used by all other providers. Update all three templates (current, forecast, hourly) to read uvIndex. --- defaultmodules/weather/current.njk | 2 +- defaultmodules/weather/forecast.njk | 2 +- defaultmodules/weather/hourly.njk | 4 ++-- defaultmodules/weather/providers/weatherapi.js | 4 ++-- .../unit/modules/default/weather/providers/weatherapi_spec.js | 2 ++ 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/defaultmodules/weather/current.njk b/defaultmodules/weather/current.njk index 7e2bc3d6d5..3e66d52706 100644 --- a/defaultmodules/weather/current.njk +++ b/defaultmodules/weather/current.njk @@ -38,7 +38,7 @@ {% if config.showUVIndex %}
- {{ current.uv_index }} + {{ current.uvIndex }} {% endif %} diff --git a/defaultmodules/weather/forecast.njk b/defaultmodules/weather/forecast.njk index 50c6bb53d8..1b28ed2d2f 100644 --- a/defaultmodules/weather/forecast.njk +++ b/defaultmodules/weather/forecast.njk @@ -31,7 +31,7 @@ {% endif %} {% if config.showUVIndex %} - {{ f.uv_index }} + {{ f.uvIndex }} {% endif %} diff --git a/defaultmodules/weather/hourly.njk b/defaultmodules/weather/hourly.njk index 05416de7dd..6db7cd2cd8 100644 --- a/defaultmodules/weather/hourly.njk +++ b/defaultmodules/weather/hourly.njk @@ -15,8 +15,8 @@ {{ hour.temperature | roundValue | unit("temperature") }} {% if config.showUVIndex %} - {% if hour.uv_index!=0 %} - {{ hour.uv_index }} + {% if hour.uvIndex!=0 %} + {{ hour.uvIndex }} {% endif %} diff --git a/defaultmodules/weather/providers/weatherapi.js b/defaultmodules/weather/providers/weatherapi.js index 0ffb1821a2..30124b8029 100644 --- a/defaultmodules/weather/providers/weatherapi.js +++ b/defaultmodules/weather/providers/weatherapi.js @@ -351,7 +351,7 @@ class WeatherAPIProvider { weather.precipitationProbability = precipitationProbability; } - weather.uv_index = this.#toNumber(forecastDay.day?.uv); + weather.uvIndex = this.#toNumber(forecastDay.day?.uv); days.push(weather); @@ -410,7 +410,7 @@ class WeatherAPIProvider { const willSnow = this.#toNumber(hourData.will_it_snow) ?? 0; weather.precipitationProbability = (willRain + willSnow) * 50; - weather.uv_index = this.#toNumber(hourData.uv); + weather.uvIndex = this.#toNumber(hourData.uv); hours.push(weather); diff --git a/tests/unit/modules/default/weather/providers/weatherapi_spec.js b/tests/unit/modules/default/weather/providers/weatherapi_spec.js index 413360f61c..e53713cc65 100644 --- a/tests/unit/modules/default/weather/providers/weatherapi_spec.js +++ b/tests/unit/modules/default/weather/providers/weatherapi_spec.js @@ -240,6 +240,7 @@ describe("WeatherAPIProvider", () => { expect(result[0].minTemperature).toBe(-8); expect(result[0].maxTemperature).toBe(-1); expect(result[0].weatherType).toBe("day-sprinkle"); + expect(result[0].uvIndex).toBe(1); expect(result[0].sunrise).toBeInstanceOf(Date); expect(result[0].sunset).toBeInstanceOf(Date); }); @@ -275,6 +276,7 @@ describe("WeatherAPIProvider", () => { expect(result[0].humidity).toBe(85); expect(result[0].windFromDirection).toBe(210); expect(result[0].weatherType).toBe("night-sprinkle"); + expect(result[0].uvIndex).toBe(0); expect(result[0].precipitationProbability).toBe(50); }); });