ViX Posted October 20 Share Posted October 20 (edited) Script uses openweathermap data so you must get API key for this to work. There's quite many supported languages. Just change lang=fi to your needs. Line let url = CONFIG.weatherURL + "?appid=" + CONFIG.OpenWeatherAPIkey + "&lat=" + CONFIG.lat + "&lon=" + CONFIG.lon + "&units=metric&lang=fi"; I have virtual text components 201 and 202. Change those values to what you have. let CONFIG = { OpenWeatherAPIkey: "GetYourOwnAPIkey", // Sign up to openweathermap.org. And get your APIkey. weatherURL: "https://api.openweathermap.org/data/2.5/weather", // Don't touch Debug: false, // Prints out where script is going every 30secs. RebootEveryDay: false, // Reboots every day. // Location // Get your local the coordinates: https://www.latlong.net/ // Test location lat: 75.977, lon: 64.96, }; // Don't touch below! print("Script has started. The first relay action in 30 seconds."); let cHour = null; let GetWeather = true; let Executed = false; let WeatherLastDate = 0; function getWeatherURL() { let url = CONFIG.weatherURL + "?appid=" + CONFIG.OpenWeatherAPIkey + "&lat=" + CONFIG.lat + "&lon=" + CONFIG.lon + "&units=metric&lang=fi"; if (CONFIG.Debug === true) { print("Weather URL: " + url); } return (url); } function padStart(num, targetLength, padString) { let str = num.toString(); while (str.length < targetLength) { str = padString ? padString + str : " " + str; } return str; } // Function to update Shelly number virtual component function updateTextComponent(component_id, value) { // print("Updating component ID: " + component_id + " with value: " + value); Shelly.call( "Text.Set", { "id": component_id, "value": value }, function(result, error_code, error_message) { if (error_code !== 0) { print("Error updating text component: " + error_message); } else { if (CONFIG.Debug === true) { print("Text component updated. ID: " + component_id + ", Value: " + value); } } } ); } function setWeatherIcon(response, error_code, error_message) { if (error_code !== 0) { // HTTP call to error service failed // TODO: retry logic print("Weather data NOT succesfull"); print("Error ", error_code ); Error = true; GetWeather = false; let now = new Date(); WeatherLastDate = new Date(now + (60*15*1000)); // Add 15min to date return; } if (response.code === 200) { // Haku onnistui let weatherData = JSON.parse(response.body); response = null; // Vapautetaan muistia; updateTextComponent(201, "https://openweathermap.org/img/wn/" + weatherData.weather[0].icon + "@2x.png") updateTextComponent(202, weatherData.main.temp.toFixed(0) + "°C " + weatherData.weather[0].description) WeatherLastDate = new Date(weatherData.dt); WeatherLastDate = WeatherLastDate + (60*15); // Add 15min to date if (CONFIG.Debug === true) { print(weatherData.weather[0].icon); print(weatherData.main.temp.toFixed(0) + "°C " + weatherData.weather[0].description) print(WeatherLastDate); } Executed = true; } } Timer.set(30000, true, function () { let hour = new Date().getHours(); let minute = new Date().getMinutes(); // Clock turns 17 -> 18 get new data if (cHour != hour && hour == 18 && Executed == true) { if (CONFIG.Debug === true) { print("It's 18. Let's get new data."); } cHour = null; Error = false; PricesLastDate = 0; priceData = null; GetWeather = true; Executed = false; if (CONFIG.RebootEveryDay === true) { Shelly.call("Shelly.Reboot"); } } // Weather data is old. New data is neened. if ((WeatherLastDate * 1000) < Date.now()) { print(WeatherLastDate +" "+ Date.now()); if (CONFIG.Debug === true) { print("Weather data old. Now we need new weather data."); } Error = false; WeatherLastDate = 0; GetWeather = true; } // This hour is already taken care of. else { if (CONFIG.Debug === true) { print(padStart(hour, 2, "0") + ":" + padStart(minute, 2, "0")); } return; } // Get weather data if (GetWeather === true) { Shelly.call("HTTP.GET", { url: getWeatherURL() , timeout: 15, ssl_ca: "*" }, setWeatherIcon); } }); Edited October 20 by ViX Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
If_then_else Posted October 21 Share Posted October 21 I had this API running on my Home Assistant last year and was happy with it. Until at some point the number of queries (month) in the free package was limited and I switched to another weather API provider. My question now would be which API package are you using to run this interesting script? Is the free package suitable for long-term operation (months/years) with no cost? Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
ViX Posted October 21 Author Share Posted October 21 Hello https://developer.yr.no/ or https://www.weatherapi.com/ Might be usable too. Yr.no works fine, but it gives way too much info on each query for shelly. That amount of data might be just fine for Home Assistant. BUT if you exceed 1000000 calls/month I think you should put some timers to slow calls down. Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
wooly Posted October 21 Share Posted October 21 why you do not put outside an UNI with sensors and get your local real measurements ? Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
ViX Posted October 24 Author Share Posted October 24 (edited) Made same code with AccuWeather. Accuweather have nicer icons 😀 But keep update interval quite slow because Accuweather gives just 50 polls per day (for free). Get your location code, API key and set your language to fit your needs. let CONFIG = { AccuWeatherAPIkey: "API", // Sign up to accuweather.com. And get your APIkey. weatherURL: "https://dataservice.accuweather.com/currentconditions/v1/", // Don't touch Debug: false, // Prints out where script is going every 30secs. RebootEveryDay: false, // Reboots every day. // Location // Seinäjoki location: "134269", // <-- Get this code from accuweather lang: "fi", // Set language }; // Don't touch below! print("Script has started. The first relay action in 30 seconds."); let cHour = null; let GetWeather = true; let Executed = false; let WeatherLastDate = 0; function getWeatherURL() { // let url = CONFIG.weatherURL + CONFIG.location + "?apikey=" + CONFIG.AccuWeatherAPIkey + "&language=" + CONFIG.lang + "&details=false"; if (CONFIG.Debug === true) { print("Weather URL: " + url); } return (url); } function padStart(num, targetLength, padString) { let str = num.toString(); while (str.length < targetLength) { str = padString ? padString + str : " " + str; } return str; } // Function to update Shelly number virtual component function updateTextComponent(component_id, value) { // print("Updating component ID: " + component_id + " with value: " + value); Shelly.call( "Text.Set", { "id": component_id, "value": value }, function(result, error_code, error_message) { if (error_code !== 0) { print("Error updating text component: " + error_message); } else { if (CONFIG.Debug === true) { print("Text component updated. ID: " + component_id + ", Value: " + value); } } } ); } function setWeatherIcon(response, error_code, error_message) { if (response.code !== 200 || error_code !== 0) { // HTTP call to error service failed // TODO: retry logic print("Weather data NOT succesfull"); print("Error ", error_code); print("Response ", response.code); Error = true; GetWeather = false; let now = new Date(); WeatherLastDate = new Date(now + (60 * 90 * 1000)); // Add 90min to date print(WeatherLastDate); updateTextComponent(202, "CODE " + response.code + " ERROR " + error_code); return; } if (response.code === 200) { // Haku onnistui let weatherData = JSON.parse(response.body); response = null; // Vapautetaan muistia; updateTextComponent(201, "https://www.accuweather.com/images/weathericons/" + weatherData[0].WeatherIcon + ".svg"); updateTextComponent(202, weatherData[0].Temperature.Metric.Value.toFixed(0) + "°C " + weatherData[0].WeatherText); WeatherLastDate = new Date(weatherData[0].EpochTime); WeatherLastDate = (WeatherLastDate + (60 * 65)) * 1000; // Add 65min to date if (CONFIG.Debug === true) { print(weatherData[0].EpochTime); print(WeatherLastDate / 1000); print(weatherData[0].WeatherIcon); print(weatherData[0].Temperature.Metric.Value.toFixed(0) + "°C"); print(weatherData[0].WeatherText); } Executed = true; weatherData = null; // Vapautetaan muistia; } } Timer.set(45000, true, function () { let hour = new Date().getHours(); let minute = new Date().getMinutes(); // Clock turns 17 -> 18 get new data if (cHour !== hour && hour === 18 && Executed === true) { if (CONFIG.Debug === true) { print("It's 18. Let's get new data."); } cHour = null; Error = false; PricesLastDate = 0; priceData = null; GetWeather = true; Executed = false; if (CONFIG.RebootEveryDay === true) { Shelly.call("Shelly.Reboot"); } } // Weather data is old. New data is neened. if (WeatherLastDate < Date.now()) { if (CONFIG.Debug === true) { print(WeatherLastDate + " " + Date.now()); print("Weather data old. Now we need new weather data."); } Error = false; WeatherLastDate = 0; GetWeather = true; Executed = false; } // This hour is already taken care of. else { if (CONFIG.Debug === true) { print(padStart(hour, 2, "0") + ":" + padStart(minute, 2, "0")); } return; } // Get weather data if (GetWeather === true) { Shelly.call("HTTP.GET", { url: getWeatherURL() , timeout: 15, ssl_ca: "*" }, setWeatherIcon); } }); Make Text -> image And Text -> Label Virtual components. And your set index numbers to these lines updateTextComponent(202, "CODE " + response.code + " ERROR " + error_code); updateTextComponent(201, "https://www.accuweather.com/images/weathericons/" + weatherData[0].WeatherIcon + ".svg"); updateTextComponent(202, weatherData[0].Temperature.Metric.Value.toFixed(0) + "°C " + weatherData[0].WeatherText); Edited October 25 by ViX Minor errors Quote Translate Revert translation? English (American) Finnish French German Italian Portuguese (European) Spanish Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.