Documentation
¶
Overview ¶
Package api provides a client for the KMI/IRM weather API.
The client handles authentication, rate limiting, retries, and error handling. It provides methods to fetch weather forecasts and radar data for Belgium and Netherlands.
Basic usage:
client := api.NewClient(
api.WithLanguage("en"),
api.WithVerbose(true),
)
forecast, err := client.GetForecast(ctx, 50.8503, 4.3517)
Index ¶
- Variables
- func ExitCode(err error) int
- func GetWeatherIcon(wwCode int, dayNight string) string
- type APIError
- type Animation
- type Client
- type ClientOption
- type DailyForecast
- type Forecast
- type ForecastResponse
- type Graph
- type HourlyForecast
- type Module
- type NetworkError
- type Observation
- type ObservationModuleData
- type ParseError
- type RadarFrame
- type RateLimitError
- type RateLimiter
- type RetryTransport
- type SVGChart
- type SVGModuleData
- type UVModuleData
- type Warning
- type WarningType
- type WeatherCode
- type WeatherCondition
- type Wind
Constants ¶
This section is empty.
Variables ¶
var WarningTypeToSlug = map[string]string{
"0": "wind",
"1": "rain",
"2": "ice_or_snow",
"3": "thunder",
"7": "fog",
"9": "cold",
"10": "heat",
"12": "thunder_wind_rain",
"13": "thunderstorm_strong_gusts",
"14": "thunderstorm_large_rainfall",
"15": "storm_surge",
"17": "coldspell",
}
WarningTypeToSlug maps warning type IDs to slug names
var WeatherConditions = map[int]*WeatherCondition{
0: {Code: 0, DayIcon: "sunny", NightIcon: "clear_night", Condition: "Clear"},
1: {Code: 1, DayIcon: "sunny", NightIcon: "clear_night", Condition: "Clear"},
2: {Code: 2, DayIcon: "lightning_rainy", NightIcon: "lightning_rainy", Condition: "Thunderstorm"},
3: {Code: 3, DayIcon: "partlycloudy", NightIcon: "partlycloudy", Condition: "Partly cloudy"},
4: {Code: 4, DayIcon: "pouring", NightIcon: "pouring", Condition: "Heavy rain"},
5: {Code: 5, DayIcon: "lightning_rainy", NightIcon: "lightning_rainy", Condition: "Thunderstorm"},
6: {Code: 6, DayIcon: "pouring", NightIcon: "pouring", Condition: "Heavy rain"},
7: {Code: 7, DayIcon: "lightning_rainy", NightIcon: "lightning_rainy", Condition: "Thunderstorm"},
8: {Code: 8, DayIcon: "snowy_rainy", NightIcon: "snowy_rainy", Condition: "Sleet"},
9: {Code: 9, DayIcon: "snowy_rainy", NightIcon: "snowy_rainy", Condition: "Sleet"},
10: {Code: 10, DayIcon: "lightning_rainy", NightIcon: "lightning_rainy", Condition: "Thunderstorm"},
11: {Code: 11, DayIcon: "snowy", NightIcon: "snowy", Condition: "Snow"},
12: {Code: 12, DayIcon: "snowy", NightIcon: "snowy", Condition: "Snow"},
13: {Code: 13, DayIcon: "lightning_rainy", NightIcon: "lightning_rainy", Condition: "Thunderstorm"},
14: {Code: 14, DayIcon: "cloudy", NightIcon: "cloudy", Condition: "Cloudy"},
15: {Code: 15, DayIcon: "cloudy", NightIcon: "cloudy", Condition: "Cloudy"},
16: {Code: 16, DayIcon: "pouring", NightIcon: "pouring", Condition: "Heavy rain"},
17: {Code: 17, DayIcon: "lightning_rainy", NightIcon: "lightning_rainy", Condition: "Thunderstorm"},
18: {Code: 18, DayIcon: "rainy", NightIcon: "rainy", Condition: "Rain"},
19: {Code: 19, DayIcon: "pouring", NightIcon: "pouring", Condition: "Heavy rain"},
20: {Code: 20, DayIcon: "snowy_rainy", NightIcon: "snowy_rainy", Condition: "Sleet"},
21: {Code: 21, DayIcon: "rainy", NightIcon: "rainy", Condition: "Rain"},
22: {Code: 22, DayIcon: "snowy", NightIcon: "snowy", Condition: "Snow"},
23: {Code: 23, DayIcon: "snowy", NightIcon: "snowy", Condition: "Snow"},
24: {Code: 24, DayIcon: "fog", NightIcon: "fog", Condition: "Fog"},
25: {Code: 25, DayIcon: "fog", NightIcon: "fog", Condition: "Fog"},
26: {Code: 26, DayIcon: "fog", NightIcon: "fog", Condition: "Fog"},
27: {Code: 27, DayIcon: "fog", NightIcon: "fog", Condition: "Fog"},
}
WeatherConditions maps ww codes to their icon/condition pairs
Functions ¶
func GetWeatherIcon ¶
GetWeatherIcon returns the appropriate icon based on ww code and day/night
Types ¶
type Animation ¶
type Animation struct {
LocalisationLayer string `json:"localisationLayer"`
LocalisationLayerRatioX float64 `json:"localisationLayerRatioX"`
LocalisationLayerRatioY float64 `json:"localisationLayerRatioY"`
Speed float64 `json:"speed"` // seconds per frame
Type string `json:"type"` // "10min" (BE) or "5min" (NL)
Unit map[string]string `json:"unit"` // mm/10min or mm/h
Country string `json:"country"`
Sequence []*RadarFrame `json:"sequence"`
Threshold []interface{} `json:"threshold"` // Usually empty
SequenceHint map[string]string `json:"sequenceHint"`
}
Animation contains rain radar animation data
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is the KMI API client
func NewClient ¶
func NewClient(opts ...ClientOption) *Client
NewClient creates a new KMI API client
func (*Client) GetForecast ¶
GetForecast fetches weather forecast for coordinates
type ClientOption ¶
type ClientOption func(*Client)
ClientOption configures the client
func WithHTTPClient ¶
func WithHTTPClient(client *http.Client) ClientOption
WithHTTPClient sets a custom HTTP client
func WithLanguage ¶
func WithLanguage(lang string) ClientOption
WithLanguage sets the language for API responses (nl, fr, en, de)
type DailyForecast ¶
type DailyForecast struct {
DayName map[string]string `json:"dayName"`
Period string `json:"period"`
DayNightPeriod string `json:"day_night"` // "0" night, "1" day
DayNight string `json:"dayNight"` // "d" or "n"
Text map[string]string `json:"text"`
// Belgium specific - seconds from midnight
DawnRiseSeconds *string `json:"dawnRiseSeconds"`
DawnSetSeconds *string `json:"dawnSetSeconds"`
// Netherlands specific - ISO timestamp
Timestamp *string `json:"timestamp"`
// Temperature
TempMin *int `json:"tempMin"`
TempMax *int `json:"tempMax"`
// Weather conditions
WW1 int `json:"ww1"` // Primary weather code (int)
WW2 *int `json:"ww2"` // Secondary weather code
WwEvol *int `json:"wwevol"` // 0=one_way, 1=two_ways, null=stable
// Wind - Beaufort scale
FF1 int `json:"ff1"`
FF2 *int `json:"ff2"`
FFEvol *int `json:"ffevol"`
DD int `json:"dd"` // Encoded direction (add 180° for meteorological)
DDText map[string]string `json:"ddText"`
// Wind details
Wind *Wind `json:"wind"`
// Netherlands specific
WindSpeedKm *int `json:"windSpeedKm"`
UVIndex *float64 `json:"uvIndex"`
SunRiseUTC *int `json:"sunRiseUtc"` // UTC seconds
SunSetUTC *int `json:"sunSetUtc"`
SunRise *int `json:"sunRise"` // Local seconds
SunSet *int `json:"sunSet"`
// Precipitation
PrecipChance json.Number `json:"precipChance"` // int in daily, string in hourly - stored as Number
PrecipQuantity json.Number `json:"precipQuantity"` // Can be string or number
}
DailyForecast represents a daily (or twice-daily) forecast
func (*DailyForecast) ParsePrecipChance ¶
func (d *DailyForecast) ParsePrecipChance() *int
ParsePrecipChance converts PrecipChance to int (handles both int and string)
func (*DailyForecast) ParsePrecipQuantity ¶
func (d *DailyForecast) ParsePrecipQuantity() *float64
ParsePrecipQuantity converts PrecipQuantity to float64
type Forecast ¶
type Forecast struct {
Daily []*DailyForecast `json:"daily"`
Hourly []*HourlyForecast `json:"hourly"`
Warning []*Warning `json:"warning"`
Graph *Graph `json:"graph"`
}
Forecast contains daily and hourly forecast data plus warnings
type ForecastResponse ¶
type ForecastResponse struct {
CityName string `json:"cityName"`
Country string `json:"country"`
Obs *Observation `json:"obs"`
For *Forecast `json:"for"`
Module []Module `json:"module"`
Animation *Animation `json:"animation"`
TodayObsCount int `json:"todayObsCount"`
}
ForecastResponse is the top-level response from getForecasts endpoint
type HourlyForecast ¶
type HourlyForecast struct {
Hour string `json:"hour"` // Local time hour as string
Temp int `json:"temp"`
WW json.Number `json:"ww"` // Weather code as string (e.g., "3")
PrecipChance json.Number `json:"precipChance"` // String
PrecipQuantity json.Number `json:"precipQuantity"` // Can be int or float (mm)
Pressure json.Number `json:"pressure"` // hPa (can be int or string in NL)
WindSpeedKm json.Number `json:"windSpeedKm"` // Can be int or string in NL
WindPeakSpeedKm *int `json:"windPeakSpeedKm"`
WindDirection json.Number `json:"windDirection"` // Encoded, can be int or string
WindDirectionText map[string]string `json:"windDirectionText"`
DayNight string `json:"dayNight"` // "d" or "n"
DateShow *string `json:"dateShow"` // Date label on day transitions
DateShowLocalized map[string]string `json:"dateShowLocalized"`
// Netherlands only
HourUTC *string `json:"hourUtc"`
}
HourlyForecast represents hourly forecast data
func (*HourlyForecast) ParsePrecipChance ¶
func (h *HourlyForecast) ParsePrecipChance() *int
ParsePrecipChance converts PrecipChance to int
func (*HourlyForecast) ParsePrecipQuantity ¶
func (h *HourlyForecast) ParsePrecipQuantity() *float64
ParsePrecipQuantity converts PrecipQuantity to float64
func (*HourlyForecast) ParsePressure ¶
func (h *HourlyForecast) ParsePressure() *int
ParsePressure converts Pressure to int
func (*HourlyForecast) ParseWW ¶
func (h *HourlyForecast) ParseWW() *int
ParseWW converts WW weather code to int (handles both int and string)
func (*HourlyForecast) ParseWindDirection ¶
func (h *HourlyForecast) ParseWindDirection() *int
ParseWindDirection converts WindDirection to int
func (*HourlyForecast) ParseWindSpeedKm ¶
func (h *HourlyForecast) ParseWindSpeedKm() *int
ParseWindSpeedKm converts WindSpeedKm to int
type Module ¶
type Module struct {
Type string `json:"type"` // "svg", "uv", "observation"
Data json.RawMessage `json:"data"` // Raw JSON, parsed based on type
}
Module represents additional data (pollen, UV, observation count, ephemerides)
func (*Module) IsEphemerides ¶
IsEphemerides checks if this SVG module is an ephemerides chart
func (*Module) ParseModuleData ¶
func (m *Module) ParseModuleData() interface{}
ParseModuleData unmarshals the generic Data field based on type
type NetworkError ¶
type NetworkError struct {
Err error
}
NetworkError wraps network/connection errors
func (*NetworkError) Error ¶
func (e *NetworkError) Error() string
func (*NetworkError) ExitCode ¶
func (e *NetworkError) ExitCode() int
func (*NetworkError) Unwrap ¶
func (e *NetworkError) Unwrap() error
type Observation ¶
type Observation struct {
Temp int `json:"temp"`
Timestamp string `json:"timestamp"`
WW int `json:"ww"`
DayNight string `json:"dayNight"` // "d" or "n"
// Netherlands only
WindSpeedKm *int `json:"windSpeedKm"`
WindDirection *int `json:"windDirection"`
WindDirectionText map[string]string `json:"windDirectionText"`
MunicipalityCode *string `json:"municipality_code"`
Municipality *string `json:"municipality"`
}
Observation represents current weather conditions
type ObservationModuleData ¶
type ObservationModuleData struct {
Count int `json:"count"`
Title map[string]string `json:"title"`
}
ObservationModuleData represents observation count module
type ParseError ¶
ParseError indicates JSON parsing failure
func (*ParseError) Error ¶
func (e *ParseError) Error() string
func (*ParseError) ExitCode ¶
func (e *ParseError) ExitCode() int
func (*ParseError) Unwrap ¶
func (e *ParseError) Unwrap() error
type RadarFrame ¶
type RadarFrame struct {
Time string `json:"time"` // ISO 8601
URI string `json:"uri"` // Image URL (getIncaImage or KNMI CDN)
Value json.Number `json:"value"` // Precipitation value (int or float)
Position float64 `json:"position"` // Normalized position (0-1) for timeline
PositionLower float64 `json:"positionLower"`
PositionHigher float64 `json:"positionHigher"`
}
RadarFrame represents a single radar frame in the animation
func (*RadarFrame) ParseTimestamp ¶
func (r *RadarFrame) ParseTimestamp() (*time.Time, error)
ParseTimestamp parses the ISO 8601 timestamp
func (*RadarFrame) ParseValue ¶
func (r *RadarFrame) ParseValue() *float64
ParseValue converts Value to float64
type RateLimitError ¶
RateLimitError indicates rate limit exceeded
func (*RateLimitError) Error ¶
func (e *RateLimitError) Error() string
func (*RateLimitError) ExitCode ¶
func (e *RateLimitError) ExitCode() int
func (*RateLimitError) Unwrap ¶
func (e *RateLimitError) Unwrap() error
type RateLimiter ¶
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter controls request rate to the API using a token bucket algorithm. It is safe for concurrent use.
func NewRateLimiter ¶
func NewRateLimiter(rate int, interval time.Duration) *RateLimiter
NewRateLimiter creates a rate limiter with the specified rate and interval. rate: number of requests allowed per interval interval: time duration for the rate window Example: NewRateLimiter(10, time.Second) allows 10 requests per second
func (*RateLimiter) Allow ¶
func (r *RateLimiter) Allow() bool
Allow returns true if a request can be made immediately without blocking. If true is returned, a token has been consumed.
type RetryTransport ¶
type RetryTransport struct {
Base http.RoundTripper
MaxRetries int
BaseDelay time.Duration
}
RetryTransport wraps http.RoundTripper with retry logic for resilience. Retries on 429 (rate limit) and 5xx errors with exponential backoff + jitter.
func NewRetryTransport ¶
func NewRetryTransport(base http.RoundTripper) *RetryTransport
NewRetryTransport creates a RetryTransport with sensible defaults. Uses http.DefaultTransport as the base if not provided.
type SVGModuleData ¶
SVGModuleData represents SVG-based modules (pollen, ephemerides)
type UVModuleData ¶
type UVModuleData struct {
LevelValue float64 `json:"levelValue"`
Level map[string]string `json:"level"`
Title map[string]string `json:"title"`
}
UVModuleData represents UV index module
type Warning ¶
type Warning struct {
IconCountry string `json:"icon_country"`
WarningType *WarningType `json:"warningType"`
WarningLevel string `json:"warningLevel"` // "1", "2", "3"
Text map[string]string `json:"text"`
FromTimestamp string `json:"fromTimestamp"` // ISO 8601
ToTimestamp string `json:"toTimestamp"`
}
Warning represents a weather warning
type WarningType ¶
WarningType contains warning classification
func (*WarningType) Slug ¶
func (w *WarningType) Slug() string
Slug returns the slug name for this warning type
type WeatherCode ¶
type WeatherCode int
WeatherCode represents a WMO weather code (ww field)
const ( // Clear conditions CodeClearSky WeatherCode = iota CodeMainlyClear CodePartlyCloudy CodeOvercast CodeFog CodeDepositingRimeFog // Drizzle CodeLightDrizzle CodeModerateDrizzle CodeDenseDrizzle CodeLightFreezingDrizzle CodeDenseFreezingDrizzle // Rain CodeSlightRain CodeModerateRain CodeHeavyRain CodeLightFreezingRain CodeHeavyFreezingRain // Snow CodeSlightSnow CodeModerateSnow CodeHeavySnow CodeSnowGrains // Rain showers CodeSlightRainShowers CodeModerateRainShowers CodeViolentRainShowers // Snow showers CodeSlightSnowShowers CodeHeavySnowShowers // Thunderstorm CodeThunderstorm CodeThunderstormSlightHail CodeThunderstormHeavyHail )
func (WeatherCode) Description ¶
func (w WeatherCode) Description(lang string) string
Description returns human-readable description in the specified language. Falls back to English if language not found.
func (WeatherCode) Icon ¶
func (w WeatherCode) Icon() string
Icon returns an emoji representation of the weather code. Returns a default emoji if code is not mapped.
func (WeatherCode) IsPrecipitation ¶
func (w WeatherCode) IsPrecipitation() bool
IsPrecipitation returns true if this code indicates precipitation (drizzle, rain, snow, hail, or thunderstorm).
func (WeatherCode) IsSevere ¶
func (w WeatherCode) IsSevere() bool
IsSevere returns true if this is severe weather (heavy rain, heavy snow, violent showers, or thunderstorm).
func (WeatherCode) IsValid ¶
func (w WeatherCode) IsValid() bool
IsValid returns true if the weather code is a recognized WMO code.
func (WeatherCode) String ¶
func (w WeatherCode) String() string
String returns the description in English (implements fmt.Stringer).
type WeatherCondition ¶
WeatherCode maps the ww codes to condition names The actual rendering depends on both ww code and dayNight ("d" or "n")
func GetWeatherCondition ¶
func GetWeatherCondition(wwCode int) *WeatherCondition
GetWeatherCondition returns the condition for a ww code
type Wind ¶
type Wind struct {
Speed int `json:"speed"` // km/h
PeakSpeed json.Number `json:"peakSpeed"` // Can be null, int, or string - stored as Number
Dir int `json:"dir"` // Encoded direction
DirText map[string]string `json:"dirText"`
}
Wind represents detailed wind information
func (*Wind) ParsePeakSpeed ¶
ParsePeakSpeed converts PeakSpeed to int (handles null, int, string)