Files
weatherfeeder/internal/normalizers/openweather/common.go
Eric Rakestraw 129cebd94d
All checks were successful
ci/woodpecker/push/build-image Pipeline was successful
Updated the normalized observation schema to remove duplicate and/or unnecessary fields
2026-03-17 11:04:51 -05:00

65 lines
1.9 KiB
Go

// FILE: ./internal/normalizers/openweather/common.go
package openweather
import (
"fmt"
"strings"
normcommon "gitea.maximumdirect.net/ejr/weatherfeeder/internal/normalizers/common"
)
// This file holds provider-specific helpers that are shared across multiple
// OpenWeather normalizers (observations today; forecasts/alerts later).
// Keeping these out of observation.go helps preserve the "one normalizer per file"
// convention while avoiding duplication.
// primaryCondition returns the "primary" weather condition from OpenWeather's
// weather array. Per OpenWeather conventions, element [0] is treated as primary.
func primaryCondition(list []owmWeather) (id int, desc string, icon string) {
if len(list) == 0 {
return 0, "", ""
}
w := list[0]
return w.ID, strings.TrimSpace(w.Description), strings.TrimSpace(w.Icon)
}
// inferIsDay determines day/night using the best available upstream signals.
//
// Priority:
// 1. The OpenWeather icon suffix ("d" / "n") when present.
// 2. Sunrise/sunset bounds (unix seconds), if provided.
// 3. Unknown (nil) when no reliable signal is present.
func inferIsDay(icon string, dt, sunrise, sunset int64) *bool {
// Prefer icon suffix.
icon = strings.TrimSpace(icon)
if icon != "" {
last := icon[len(icon)-1]
switch last {
case 'd':
v := true
return &v
case 'n':
v := false
return &v
}
}
// Fall back to sunrise/sunset bounds if provided.
if dt > 0 && sunrise > 0 && sunset > 0 {
v := dt >= sunrise && dt < sunset
return &v
}
return nil
}
// openWeatherStationID returns a stable station identifier for the given response.
// Prefer the OpenWeather city ID when present; otherwise, fall back to coordinates.
func openWeatherStationID(parsed owmResponse) string {
if parsed.ID != 0 {
return fmt.Sprintf("OPENWEATHER(%d)", parsed.ID)
}
// Fallback: synthesize from coordinates.
return normcommon.SynthStationID("OPENWEATHER", parsed.Coord.Lat, parsed.Coord.Lon)
}