Skip to content

Replace deprecated smhi pmp3g api with new SNOW api#220

Merged
kordianbruck merged 7 commits intoschachmat:masterfrom
nopil3os:master
Apr 12, 2026
Merged

Replace deprecated smhi pmp3g api with new SNOW api#220
kordianbruck merged 7 commits intoschachmat:masterfrom
nopil3os:master

Conversation

@nopil3os
Copy link
Copy Markdown
Contributor

@nopil3os nopil3os commented Apr 8, 2026

SMHI deactivated the pmp3g api this month, breaking the wego backend.

This attempts to rejig it for the new api: https://opendata.smhi.se/metfcst/snow1gv1/introduction

Used Gemini to generate most of this.

@nopil3os nopil3os changed the title with help from gemini: replace deprecated smhi pmp3g api for new SNOW api with help from gemini: replace deprecated smhi pmp3g api with new SNOW api Apr 9, 2026
@nopil3os nopil3os marked this pull request as draft April 10, 2026 14:50
@nopil3os nopil3os marked this pull request as ready for review April 10, 2026 14:52
@kordianbruck
Copy link
Copy Markdown
Collaborator

kordianbruck commented Apr 11, 2026

Can you update your branch please to the latest master? I've fixed the lint warnings in master today.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates the SMHI backend to use the new snow1g API endpoint after the old pmp3g endpoint was deactivated.

Changes:

  • Replaced the SMHI response model/types to match the new SNOW API response shape.
  • Updated parsing logic to read values from the new data object and use the new time field.
  • Switched the SMHI request URL to the snow1g/version/1 endpoint.
Comments suppressed due to low confidence (2)

backends/smhi.go:186

  • The loop over forecast.TimeSeries never updates currentPrediction, so parseCurrent always returns the first timeseries entry regardless of the current time. Update currentPrediction as you iterate (e.g., keep the latest prediction with ts <= now), and then break once ts.After(now) is true.
	for _, prediction := range forecast.TimeSeries {
		ts, err := time.Parse(time.RFC3339, prediction.Time)
		if err != nil {
			log.Fatalf("Failed to parse timestamp: %v\n", err)
		}

		if ts.After(currentTime) {
			break

backends/smhi.go:160

  • ts is parsed from the API timestamp (likely with an explicit timezone), but the day-bucketing logic compares ts.Day() against a separately initialized currentTime (time.Now() earlier). If local time != the API timezone, day boundaries can be off. Consider initializing the “current day” from the first parsed ts (or converting both to the same location with In(...)) so grouping is consistent.
		ts, err := time.Parse(time.RFC3339, prediction.Time)
		if err != nil {
			log.Fatalf("Failed to parse timestamp: %v\n", err)
		}

		if ts.Day() != currentTime.Day() {

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread backends/smhi.go
Comment thread backends/smhi.go Outdated
Comment thread backends/smhi.go Outdated
@kordianbruck kordianbruck changed the title with help from gemini: replace deprecated smhi pmp3g api with new SNOW api Replace deprecated smhi pmp3g api with new SNOW api Apr 11, 2026
@nopil3os
Copy link
Copy Markdown
Contributor Author

nopil3os commented Apr 12, 2026

sorry for the mess. this is the first time I'm doing a PR /o\
I'm not sure about the precipitation. in the old api it was in mm/h and in the new one it's kg/m2. I think that's equivalent?

https://opendata.smhi.se/metfcst/snow1gv1/parameters
https://web.archive.org/web/20231207074455/http://opendata.smhi.se/apidocs/metfcst/parameters.html

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@kordianbruck
Copy link
Copy Markdown
Collaborator

Should be, thanks for the updates. Looks good from what I can tell.

@kordianbruck kordianbruck merged commit 1237276 into schachmat:master Apr 12, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread backends/smhi.go
Comment on lines 175 to +179
var currentPrediction *smhiTimeSeries = forecast.TimeSeries[0]
var currentTime time.Time = time.Now().UTC()

for _, prediction := range forecast.TimeSeries {
ts, err := time.Parse(time.RFC3339, prediction.ValidTime)
ts, err := time.Parse(time.RFC3339, prediction.Time)
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

parseCurrent iterates over forecast.TimeSeries but never updates currentPrediction, so it always returns the first entry regardless of the timestamps. Update currentPrediction inside the loop (e.g., set it to the latest prediction not after currentTime) before breaking so the "current" condition reflects the correct time slot.

Copilot uses AI. Check for mistakes.
Comment thread backends/smhi.go
Comment on lines 151 to 155
break
}

ts, err := time.Parse(time.RFC3339, prediction.ValidTime)
ts, err := time.Parse(time.RFC3339, prediction.Time)
if err != nil {
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Day grouping in parseForecast depends on comparing ts.Day() to currentTime.Day(), but currentTime/day.Date are initialized from time.Now() earlier in the function rather than the first forecast timestamp. If the first prediction.Time is in a different day/timezone than the local clock, this can mis-group days. Consider initializing currentTime/day.Date from the first parsed prediction.Time (and in a consistent timezone) before applying the grouping logic.

Copilot uses AI. Check for mistakes.
Comment thread backends/smhi.go
Comment on lines 51 to 54
const (
// see http://opendata.smhi.se/apidocs/metfcst/index.html
smhiWuri = "https://opendata-download-metfcst.smhi.se/api/category/pmp3g/version/2/geotype/point/lon/%s/lat/%s/data.json"
// API Spec: https://opendata.smhi.se/metfcst/snow1gv1/parameters
smhiWuri = "https://opendata-download-metfcst.smhi.se/api/category/snow1g/version/1/geotype/point/lon/%s/lat/%s/data.json"
)
Copy link

Copilot AI Apr 12, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The old smhiWuri assignment is left in place as a commented-out line. This is effectively dead code and can be confusing to maintainers; consider removing it (or turning it into a proper comment explaining the deprecation) to keep the constant definition unambiguous.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants