Weather API from OpenMeteo.com
My Skynet2.net LCARS sites has a weather page that pulls basic information for the viewer. Here is the script I used to get the API working. You will note FontAwesome icons are indicated, this was to show the "weather image" of the current conditions.
My 25th Century LCARS Site (Picard) - Just because I love the color scheme
My 24th Century LCARS Site (TNG) - This "display" site is used on an old touchscreen computer in our common area
const CACHE_KEY = 'weatherData';
const CACHE_EXPIRATION = 15 * 60 * 1000; // 15 minutes in milliseconds
function updateLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(position => {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
updateWeather(latitude, longitude);
}, error => console.error(error));
} else {
console.error("Geolocation is not supported by this browser.");
}
}
function getCardinalDirection(windDegrees) {
const cardinalDirections = [{
direction: "N",
degrees: [348.75, 11.25]
},
{
direction: "NE",
degrees: [11.25, 33.75]
},
{
direction: "E",
degrees: [33.75, 56.25]
},
{
direction: "SE",
degrees: [56.25, 78.75]
},
{
direction: "S",
degrees: [78.75, 101.25]
},
{
direction: "SW",
degrees: [101.25, 123.75]
},
{
direction: "W",
degrees: [123.75, 146.25]
},
{
direction: "NW",
degrees: [146.25, 348.75]
},
];
for (const direction of cardinalDirections) {
if (windDegrees >= direction.degrees[0] && windDegrees < direction.degrees[1]) {
return direction.direction;
}
}
return "N";
}
const isDayDescriptions = {
"0": "NIGHT",
"1": "DAY",
};
const weatherCodeDescriptions = {
"0": "CLEAR SKY",
"1": "MOSTLY CLEAR",
"2": "PARTLY CLOUDY",
"3": "OVERCAST",
"45": "FOG",
"48": "RIME FOG",
"51": "SLIGHT DRIZZLE",
"53": "MODERATE DRIZZLE",
"55": "HEAVY DRIZZLE",
"61": "LIGHT RAIN",
"63": "MODERATE RAIN",
"65": "HEAVY RAIN",
"66": "LIGHT FREEZING RAIN",
"67": "HEAVY FREEZING RAIN",
"71": "LIGHT SNOW",
"73": "MODERATE SNOW",
"75": "HEAVY SNOW",
"77": "SNOW GRAINS",
"80": "LIGHT SHOWERS",
"81": "MODERATE SHOWERS",
"82": "HEAVY SHOWERS",
"85": "LIGHT SNOW SHOWERS",
"86": "HEAVY SNOW SHOWERS",
"95": "THUNDERSTORMS",
"96": "THUNDERSTORMS W/ LIGHT HAIL",
"99": "THUNDERSTORMS W/ HEAVY HAIL",
};
const weatherCodeIcons = {
"0": {
"DAY": "fa-solid fa-sun",
"NIGHT": "fa-solid fa-moon",
},
"1": {
"DAY": "fa-solid fa-sun",
"NIGHT": "fa-solid fa-moon",
},
"2": {
"DAY": "fa-solid fa-cloud-sun",
"NIGHT": "fa-solid fa-cloud-moon",
},
"3": "fa-solid fa-cloud",
"45": "fa-solid fa-smog",
"48": "fa-solid fa-smog",
"51": "fa-solid fa-cloud-rain",
"53": "fa-solid fa-cloud-rain",
"55": "fa-solid fa-cloud-rain",
"61": "fa-solid fa-cloud-rain",
"63": "fa-solid fa-cloud-rain",
"65": "fa-solid fa-cloud-showers-heavy",
"66": "fa-solid fa-cloud-rain",
"67": "fa-solid fa-cloud-showers-heavy",
"71": "fa-regular fa-snowflake",
"73": "fa-solid fa-cloud-meatball",
"75": "fa-solid fa-cloud-meatball",
"77": "fa-regular fa-snowflake",
"80": "fa-solid fa-cloud-rain",
"81": "fa-solid fa-cloud-rain",
"82": "fa-solid fa-cloud-showers-heavy",
"85": "fa-solid fa-cloud-rain",
"86": "fa-solid fa-cloud-showers-heavy",
"95": "fa-solid fa-cloud-bolt",
"96": "fa-solid fa-cloud-bolt",
"99": "fa-solid fa-cloud-bolt",
};
function updateWeather(latitude, longitude) {
const cachedData = JSON.parse(localStorage.getItem(CACHE_KEY));
const currentTime = new Date().getTime();
if (cachedData && currentTime - cachedData.timestamp < CACHE_EXPIRATION) {
console.log('Using cached data');
displayWeather(cachedData.data);
} else {
console.log('Fetching new data');
const url = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}¤t=temperature_2m,relative_humidity_2m,apparent_temperature,is_day,precipitation,rain,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m&hourly=dew_point_2m,precipitation_probability&temperature_unit=fahrenheit&wind_speed_unit=mph&precipitation_unit=inch&timezone=auto&forecast_days=1`;
fetch(url)
.then(response => response.json())
.then(data => {
localStorage.setItem(CACHE_KEY, JSON.stringify({ timestamp: currentTime, data }));
displayWeather(data);
})
.catch(error => console.error(error));
}
}
function displayWeather(data) {
const isDayCode = data.current.is_day;
const isDayDescription = isDayDescriptions[isDayCode];
const weatherCode = data.current.weather_code;
const weatherCodeStr = weatherCode.toString();
console.log("Weather Code String:", weatherCodeStr);
console.log("Is Day Code:", isDayCode);
const weatherDescription = weatherCodeDescriptions[weatherCodeStr];
const dewpoint = data.hourly.dew_point_2m[0];
const precipProbability = data.hourly.precipitation_probability[0];
let weatherIconClass;
if (typeof weatherCodeIcons[weatherCodeStr] === "object") {
// If the value is an object, use the day or night key
weatherIconClass = weatherCodeIcons[weatherCodeStr][isDayDescriptions[isDayCode]];
} else {
// If the value is a string, use that directly
weatherIconClass = weatherCodeIcons[weatherCodeStr];
}
console.log("Weather Icon Class:", weatherIconClass); // Debug log
document.getElementById("lat").textContent = data.latitude;
document.getElementById("lon").textContent = data.longitude;
document.getElementById("timezone").textContent = data.timezone;
document.getElementById("elevation").textContent = data.elevation;
document.getElementById("time").textContent = data.current.time;
document.getElementById("interval").textContent = data.current.interval;
document.getElementById("current-temp").textContent = data.current.temperature_2m;
document.getElementById("humidity").textContent = data.current.relative_humidity_2m;
document.getElementById("dewpoint").textContent = dewpoint;
document.getElementById("apparent-temp").textContent = data.current.apparent_temperature;
document.getElementById("precipitation").textContent = data.current.precipitation;
document.getElementById("precip-probability").textContent = precipProbability;
document.getElementById("rain").textContent = data.current.rain;
document.getElementById("wx-icon").innerHTML = ``;
document.getElementById("wx-code").textContent = weatherDescription || "Unknown code";
document.getElementById("isday").textContent = isDayDescription || "Unknown";
document.getElementById("cloud").textContent = data.current.cloud_cover;
document.getElementById("wind-speed").textContent = data.current.wind_speed_10m;
document.getElementById("wind-direct").textContent = data.current.wind_direction_10m;
document.getElementById("wind-gusts").textContent = data.current.wind_gusts_10m;
const windDirection = getCardinalDirection(data.current.wind_direction_10m);
document.getElementById("wind-direct").textContent = windDirection;
fetch(`https://nominatim.openstreetmap.org/reverse?lat=${data.latitude}&lon=${data.longitude}&format=json`)
.then(response => response.json())
.then(data => {
if (data.address) {
const city = data.address.city || data.address.town || "";
const state = data.address.state || "";
const locationString = `${city}, ${state}`;
document.getElementById("location").textContent = locationString;
} else {
console.error("Location not found");
}
})
.catch(error => console.error(error));
}
// Call the updateLocation function to start the process
updateLocation();
setInterval(updateLocation, CACHE_EXPIRATION);