From 2f9c9926027701f0119d2d1957f1a5d921e03272 Mon Sep 17 00:00:00 2001 From: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com> Date: Tue, 28 Apr 2026 21:11:59 +0200 Subject: [PATCH] fix(weather): use nearest openmeteo hourly data Open-Meteo updates current_weather every 15 min, but hourly data exists only on full hours. Exact timestamp matching could miss and fall back to index 0, causing midnight values in current weather. Pick the last hourly entry at or before current_weather.time, remove dead hourly-shape fallback code, and simplify mapping. Update tests to guard against index-0 fallback and add hourly-type coverage with frozen time. Fixes #4122 --- defaultmodules/weather/providers/openmeteo.js | 52 +++++-------------- .../weather/providers/openmeteo_spec.js | 5 +- 2 files changed, 16 insertions(+), 41 deletions(-) diff --git a/defaultmodules/weather/providers/openmeteo.js b/defaultmodules/weather/providers/openmeteo.js index 7cc5f43995..ff02cc617e 100644 --- a/defaultmodules/weather/providers/openmeteo.js +++ b/defaultmodules/weather/providers/openmeteo.js @@ -418,46 +418,18 @@ class OpenMeteoProvider { // Add hourly data if available if (parsedData.hourly) { - let h; - const currentTime = parsedData.current_weather.time; - - // Handle both data shapes: object with arrays or array of objects (after transpose) - if (Array.isArray(parsedData.hourly)) { - // Array of objects (after transpose) - const hourlyIndex = parsedData.hourly.findIndex((hour) => hour.time.getTime() === currentTime.getTime()); - h = hourlyIndex !== -1 ? hourlyIndex : 0; - - if (hourlyIndex === -1) { - Log.debug("[openmeteo] Could not find current time in hourly data, using index 0"); - } - - const hourData = parsedData.hourly[h]; - if (hourData) { - current.humidity = hourData.relativehumidity_2m; - current.feelsLikeTemp = hourData.apparent_temperature; - current.rain = hourData.rain; - current.snow = hourData.snowfall ? hourData.snowfall * 10 : undefined; - current.precipitationAmount = hourData.precipitation; - current.precipitationProbability = hourData.precipitation_probability; - current.uvIndex = hourData.uv_index; - } - } else if (parsedData.hourly.time) { - // Object with arrays (before transpose - shouldn't happen in normal flow) - const hourlyIndex = parsedData.hourly.time.findIndex((time) => time === currentTime); - h = hourlyIndex !== -1 ? hourlyIndex : 0; - - if (hourlyIndex === -1) { - Log.debug("[openmeteo] Could not find current time in hourly data, using index 0"); - } - - current.humidity = parsedData.hourly.relativehumidity_2m?.[h]; - current.feelsLikeTemp = parsedData.hourly.apparent_temperature?.[h]; - current.rain = parsedData.hourly.rain?.[h]; - current.snow = parsedData.hourly.snowfall?.[h] ? parsedData.hourly.snowfall[h] * 10 : undefined; - current.precipitationAmount = parsedData.hourly.precipitation?.[h]; - current.precipitationProbability = parsedData.hourly.precipitation_probability?.[h]; - current.uvIndex = parsedData.hourly.uv_index?.[h]; - } + // Open-Meteo updates current_weather every 15 min, but hourly entries only + // exist at full hours — find the last entry at or before the current time. + const currentMs = parsedData.current_weather.time.getTime(); + const hourlyIndex = parsedData.hourly.findLastIndex((hour) => hour.time.getTime() <= currentMs); + const hourData = parsedData.hourly[Math.max(0, hourlyIndex)]; + current.humidity = hourData.relativehumidity_2m; + current.feelsLikeTemp = hourData.apparent_temperature; + current.rain = hourData.rain; + current.snow = hourData.snowfall != null ? hourData.snowfall * 10 : null; + current.precipitationAmount = hourData.precipitation; + current.precipitationProbability = hourData.precipitation_probability; + current.uvIndex = hourData.uv_index; } // Add daily data if available (after transpose, daily is array of objects) diff --git a/tests/unit/modules/default/weather/providers/openmeteo_spec.js b/tests/unit/modules/default/weather/providers/openmeteo_spec.js index 0377a99013..225a970c88 100644 --- a/tests/unit/modules/default/weather/providers/openmeteo_spec.js +++ b/tests/unit/modules/default/weather/providers/openmeteo_spec.js @@ -144,12 +144,15 @@ describe("OpenMeteoProvider", () => { provider.start(); const result = await dataPromise; + const currentHourUnix = Math.floor(currentData.current_weather.time / 3600) * 3600; + const currentHourIndex = currentData.hourly.time.findIndex((time) => time === currentHourUnix); expect(result).toBeDefined(); expect(result.temperature).toBe(8.5); expect(result.windSpeed).toBeCloseTo(4.7, 1); expect(result.windFromDirection).toBe(9); - expect(result.humidity).toBe(83); + expect(result.humidity).toBe(currentData.hourly.relativehumidity_2m[currentHourIndex]); + expect(result.humidity).not.toBe(currentData.hourly.relativehumidity_2m[0]); }); it("should include sunrise and sunset from daily data", async () => {