@@ -3,17 +3,82 @@ import { translate } from "./i18n.js"
33import { reverseGeocode } from "./openstreetmap.js"
44import { Cache } from "./cache.js"
55
6- class WeatherData {
6+ function toFahrenheit ( celsius ) {
7+ return Math . round ( celsius * ( 9 / 5 ) + 32 )
8+ }
9+
10+ class ForecastData {
711 constructor ( data , lang = "en" ) {
812 this . temprature = data . instant . details . air_temperature
13+ this . wind_speed = data . instant . details . wind_speed
14+ this . humidity = data . instant . details . relative_humidity
15+ this . wind_degrees = data . instant . details . wind_from_direction
16+
917 this . symbol_code = data . next_1_hours . summary . symbol_code
18+ this . precipitation = data . next_1_hours . details . precipitation_amount
19+
1020 this . lang = lang
1121 }
1222
1323 prettyName ( ) {
1424 const removeVariant = this . symbol_code . replace ( "_day" , "" ) . replace ( "_night" , "" ) . replace ( "_polar_night" , "" )
1525 return translate ( this . lang , `weather.${ removeVariant } ` ) . replace ( / ^ \w / , c => c . toUpperCase ( ) )
1626 }
27+
28+ feelsLike ( ) {
29+ // Water vapor pressure (e) calculation
30+ const e = ( this . humidity / 100 ) * 6.105 * Math . exp (
31+ ( 17.27 * this . temprature ) / ( 237.7 + this . temprature )
32+ )
33+ // Australian Apparent Temperature formula
34+ const at = this . temprature + 0.33 * e - 0.70 * this . wind_speed - 4.00
35+ return Math . round ( at * 10 ) / 10
36+ }
37+ }
38+
39+ class MetNoWeather {
40+ constructor ( lang = "en" ) {
41+ this . lang = lang
42+ this . entries = [ ]
43+ }
44+
45+ updateEntries ( weatherDataRaw ) {
46+ this . entries = weatherDataRaw . map ( entry => new ForecastData ( entry . data , this . lang ) )
47+ }
48+
49+ getCurrent ( ) {
50+ return this . entries [ 0 ]
51+ }
52+
53+ getNextHours ( ) {
54+ return this . entries . slice ( 1 , this . entries . length )
55+ }
56+
57+ async fetch ( position ) {
58+ const cache = new Cache ( )
59+ const pos = position . coords
60+ const posPrefix = `${ pos . latitude . toFixed ( 2 ) } ,${ pos . longitude . toFixed ( 2 ) } `
61+ const cacheKey = `weatherData_${ posPrefix } `
62+
63+ // Check if weather data is cached (5 minutes)
64+ const cachedWeather = await cache . get ( cacheKey )
65+ if ( cachedWeather ) {
66+ console . log ( "📦 Cache: Fetched weather data from cache" )
67+ this . updateEntries ( cachedWeather )
68+ return
69+ }
70+
71+ const weatherResponse = await http (
72+ "GET" ,
73+ `https://api.met.no/weatherapi/locationforecast/2.0/complete?lat=${ pos . latitude } &lon=${ pos . longitude } `
74+ )
75+
76+ const weatherDataRaw = weatherResponse . properties . timeseries
77+ const slicedData = weatherDataRaw . slice ( 0 , 6 ) // Limit to current + next 5 hours
78+ this . updateEntries ( slicedData )
79+ // Cache weather data for 5 minutes (300 seconds)
80+ cache . set ( cacheKey , slicedData , 300 )
81+ }
1782}
1883
1984export async function getWeather ( items , position , lang ) {
@@ -22,7 +87,6 @@ export async function getWeather(items, position, lang) {
2287 const pos = position . coords
2388 const posPrefix = `${ pos . latitude . toFixed ( 2 ) } ,${ pos . longitude . toFixed ( 2 ) } `
2489
25- const weatherCacheKey = `weatherData_${ posPrefix } `
2690 const locationCacheKey = `weatherLocation_${ posPrefix } `
2791
2892 const wtemp = document . getElementById ( "wtemp" )
@@ -36,28 +100,16 @@ export async function getWeather(items, position, lang) {
36100 }
37101 }
38102
39- // Check if weather data is cached (5 minutes)
40- const cachedWeather = await cache . get ( weatherCacheKey )
41-
42- let weatherData
43- if ( cachedWeather ) {
44- console . log ( "📦 Cache: Fetched weather data from cache" )
45- weatherData = new WeatherData ( cachedWeather , lang || "en" )
46- } else {
47- const weatherResponse = await http (
48- "GET" ,
49- `https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=${ pos . latitude } &lon=${ pos . longitude } `
50- )
51- const weatherDataRaw = weatherResponse . properties . timeseries [ 0 ] . data
52- weatherData = new WeatherData ( weatherDataRaw , lang || "en" )
53- // Cache weather data for 5 minutes (300 seconds)
54- cache . set ( weatherCacheKey , weatherDataRaw , 300 )
55- }
103+ // Use MetNoWeather class to fetch weather data
104+ const weather = new MetNoWeather ( lang || "en" )
105+ await weather . fetch ( position )
106+ const weatherData = weather . getCurrent ( )
56107
57108 document . getElementById ( "wicon" ) . src = `images/weather/${ weatherData . symbol_code } .png`
58109 document . getElementById ( "wdescription" ) . innerText = weatherData . prettyName ( )
110+
59111 if ( items . temp_type === "fahrenheit" ) {
60- wtemp . innerText = `${ Math . round ( weatherData . temprature * ( 9 / 5 ) + 32 ) } °F`
112+ wtemp . innerText = `${ toFahrenheit ( weatherData . temprature ) } °F`
61113 } else {
62114 wtemp . innerText = `${ Math . round ( weatherData . temprature ) } °C`
63115 }
0 commit comments