Compact Multi-location Weather Display

This flow fetches weather data for a given location from openweathermap.org (you need a free API key) and crams it into a 9 x 4 unit UI template.

Features:

  • Forecasts are shown hourly for up to 6 hours plus today and the next 4 days.
  • Times (and days - Auckland) are the local time, not UTC
  • The background colour blends from cool blue to warm red according to the "Feels Like" temperature.
  • If there are weather alerts the text is shown and icons change colour for the affected period (Tobermory).
  • Required inputs are Location name, latitude & longitude so it should be possible to pick from a map.
  • Optional inputs are subjective cold and hot according to the location (a Greenlander probably feels hot at a lower temperature than a Sri Lankan). Obviously not so easy to derive from a map.
  • The template is HTML and CSS only.

Issues:

  • It's cramped. Very small text.
  • If both rain and snow amounts are predicted, the snow amount is very cramped (Tobermory).
  • But if neither, there is a noticeable gap below the icons (N'Djamena).
  • Sometimes a weather alert is shown which relates to a day beyond the 5 days shown (Juneau).
  • Weather alerts are in the local language? May cause display issues?

Would be nice?

  • A local time digital clock.
  • "Take an umbrella" notication.
  • UV index.

[{"id":"80504545190c9b4d","type":"tab","label":"Weather Demo","disabled":false,"info":"","env":[]},{"id":"1d9a627667e3b8fc","type":"http request","z":"80504545190c9b4d","name":"Openweathermap","method":"GET","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","senderr":false,"x":130,"y":180,"wires":[["cf1bc982dc9e353c"]]},{"id":"cf1bc982dc9e353c","type":"change","z":"80504545190c9b4d","name":"Temp for background colour","rules":[{"t":"set","p":"fudge","pt":"msg","to":"payload.current.feels_like","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":380,"y":180,"wires":[["1b6f730c6ab2223f"]]},{"id":"06c1eecd02273e6a","type":"ui_dropdown","z":"80504545190c9b4d","name":"Available locations","label":"","tooltip":"","place":"Select option","group":"0b2c5ed94dd5b6dc","order":8,"width":0,"height":0,"passthru":true,"multiple":false,"options":[{"label":"Trincomalee, Sri Lanka","value":"Trincomalee","type":"str"},{"label":"Juneau, Alaska","value":"Juneau","type":"str"},{"label":"Tobermory, Scotland","value":"Tobermory","type":"str"},{"label":"Qaqortaq, Greenland","value":"Qaqortaq","type":"str"},{"label":"N'Djamena, Chad","value":"N'Djamena","type":"str"},{"label":"Bangui. Central African Republic","value":"Bangui","type":"str"},{"label":"Auckland. New Zealand","value":"Auckland","type":"str"}],"payload":"","topic":"topic","topicType":"msg","className":"","x":130,"y":120,"wires":[["e01860f95dea2e98"]]},{"id":"e01860f95dea2e98","type":"function","z":"80504545190c9b4d","name":"Setup URL & location","func":"const appid = global.get('openweathermapid');   // Openweathermap API key\n\nconst hot = 32;   // default \"hot\" temperature. Above this the background colour is 100% layer 2\nconst cold= 12;   // default \"cold\" temperature. Below this the background colour is 100% Background\n\nconst locations = {\n\"Tobermory\":      {lat: 56.622149,  long: -6.069254,   coldat:7,   hotat:18},  //Good for weather alerts\n\"Trincomalee\":    {lat: 8.647208,   long: 81.177637},                          //coldat and hotat unspecified\n\"Juneau\":         {lat: 58.357577,  long: -134.569945, coldat:0,   hotat:15},  //Good for weather alerts, checking day names\n\"Qaqortaq\":       {lat: 60.71839,   long: -46.03561,   coldat:-5,  hotat:5},   //Reliably chilly\n\"N'Djamena\":      {lat: 12.10672,   long: 15.0444,     coldat:20,  hotat:30},  //Reliably warm\n\"Bangui\":         {lat: 4.366667,   long: 18.583333,   coldat:20,  hotat:30},  //Reliably warm\n\"Auckland\":       {lat: -36.848461, long: 174.763336,  coldat:10,  hotat:25},  //Good for checking day names\n};\n\n\nmsg = {\n    location: msg.payload,                            // Location name for display\n    lat: locations[msg.payload].lat,                  // Must have\n    long: locations[msg.payload].long,                // Must have\n    coldat: (locations[msg.payload].coldat || cold),  // Subjective \"it feels hot/cold\" levels for location\n    hotat: (locations[msg.payload].hotat || hot ),\n    alertcolor: \"chocolate\",                          // Icons this colour if there is a weather alert\n}\n\nmsg.url=\"https://api.openweathermap.org/data/2.5/onecall?lat=\" + msg.lat + \"&lon=\" + msg.long + \"&units=metric&appid=\" + appid;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":360,"y":120,"wires":[["1d9a627667e3b8fc"]]},{"id":"2c4e9abec36c3fb6","type":"ui_template","z":"80504545190c9b4d","group":"0b2c5ed94dd5b6dc","name":"Weather Widget","order":2,"width":"9","height":"4","format":"<div class=\"weatherwidget rounded\" style=\"--fudge: {{msg.fudge}}; --coldat: {{msg.coldat}}; --hotat: {{msg.hotat}}\">\n    <div class=\"layer1 rounded\" style=\"--fudge: {{msg.fudge}}; --coldat: {{msg.coldat}}; --hotat: {{msg.hotat}}\">\n        <div class=\"layer2 rounded bordered\" style=\"--fudge: {{msg.fudge}}; --coldat: {{msg.coldat}}; --hotat: {{msg.hotat}}\">\n            <div class=\"location\">\n                <span class=\"location\">{{(msg.location || \"no data\")}}</span>\n            </div>\n            <div class=\"temperature\">\n                <div class=\"actual\">\n                    <div class=\"value\">{{msg.payload.current.temp | number:1}}°C</div>\n                </div>\n                <div class=\"feelslike\">\n                    <div class=\"value\">({{msg.payload.current.feels_like |number:0}}°)</div>\n                </div>\n            </div>\n            <div class=\"currentwrapper\">\n                <div class=\"current\">\n                    <div class=\"wind\">\n                        <span>Wind: {{msg.payload.current.wind_knots | number:0}}kt {{msg.payload.current.wind_point}}</span>\n                    </div>\n                    <div class=\"pressure\">\n                        <span>Press: {{msg.payload.current.pressure}}hPa</span>\n                    </div>\n                    <div class=\"humidity\">\n                        <span>Hum: {{msg.payload.current.humidity}}%</span>\n                    </div>\n                </div>\n            </div>\n        \n            <div class=\"comments\">{{msg.comments}}</div>\n                \n            <div class=\"iconswrapper\">\n                <div class=\"hourly\">\n                    <div class=\"icon\">\n                        <div class=\"subtitle time\">{{msg.payload.hourly[1].localtime}}</div>\n                        <i class=\"wi wi-owm-{{msg.payload.hourly[1].weather[0].icon}}\" style=\"{{msg.payload.hourly[1].iconstyle}}\"></i>\n                        <div class=\"subtitle temp\">{{msg.payload.hourly[1].temp | number:0}}°</div>\n                        <div class=\"subtitle rain\">{{msg.payload.hourly[1].rainmm}}</div>\n                        <div class=\"subtitle snow\">{{msg.payload.hourly[1].snowmm}}</div>\n                    </div>\n                    <div class=\"icon\">\n                        <div class=\"subtitle time\">{{msg.payload.hourly[2].localtime}}</div>\n                        <i class=\"wi wi-owm-{{msg.payload.hourly[2].weather[0].icon}}\" style=\"{{msg.payload.hourly[2].iconstyle}}\"></i>\n                        <div class=\"subtitle temp\">{{msg.payload.hourly[2].temp | number:0}}°</div>\n                        <div class=\"subtitle rain\">{{msg.payload.hourly[2].rainmm}}</div>\n                        <div class=\"subtitle snow\">{{msg.payload.hourly[4].snowmm}}</div>\n                    </div>\n                    <div class=\"icon\">\n                        <div class=\"subtitle time\">{{msg.payload.hourly[3].localtime}}</div>\n                        <i class=\"wi wi-owm-{{msg.payload.hourly[3].weather[0].icon}}\" style=\"{{msg.payload.hourly[3].iconstyle}}\"></i>\n                        <div class=\"subtitle temp\">{{msg.payload.hourly[3].temp | number:0}}°</div>\n                        <div class=\"subtitle rain\">{{msg.payload.hourly[3].rainmm}}</div>\n                        <div class=\"subtitle snow\">{{msg.payload.hourly[3].snowmm}}</div>\n                    </div>\n                    <div class=\"icon\">\n                        <div class=\"subtitle time\">{{msg.payload.hourly[4].localtime}}</div>\n                        <i class=\"wi wi-owm-{{msg.payload.hourly[4].weather[0].icon}}\" style=\"{{msg.payload.hourly[4].iconstyle}}\"></i>\n                        <div class=\"subtitle temp\">{{msg.payload.hourly[4].temp | number:0}}°</div>\n                        <div class=\"subtitle rain\">{{msg.payload.hourly[4].rainmm}}</div>\n                        <div class=\"subtitle snow\">{{msg.payload.hourly[4].snowmm}}</div>\n                    </div>\n                    <div class=\"icon\">\n                        <div class=\"subtitle time\">{{msg.payload.hourly[5].localtime}}</div>\n                        <i class=\"wi wi-owm-{{msg.payload.hourly[5].weather[0].icon}}\" style=\"{{msg.payload.hourly[5].iconstyle}}\"></i>\n                        <div class=\"subtitle temp\">{{msg.payload.hourly[5].temp | number:0}}°</div>\n                        <div class=\"subtitle rain\">{{msg.payload.hourly[5].rainmm}}</div>\n                        <div class=\"subtitle snow\">{{msg.payload.hourly[5].snowmm}}</div>\n                    </div>\n                    <div class=\"icon\">\n                        <div class=\"subtitle time\">{{msg.payload.hourly[6].localtime}}</div>\n                        <i class=\"wi wi-owm-{{msg.payload.hourly[6].weather[0].icon}}\" style=\"{{msg.payload.hourly[6].iconstyle}}\"></i>\n                        <div class=\"subtitle temp\">{{msg.payload.hourly[6].temp | number:0}}°</div>\n                        <div class=\"subtitle rain\">{{msg.payload.hourly[6].rainmm}}</div>\n                        <div class=\"subtitle snow\">{{msg.payload.hourly[6].snowmm}}</div>\n                    </div>\n                </div>\n                    \n                <div class=\"daily\">\n                    <div class=\"icon\">\n                        <div class=\"subtitle time\">{{msg.payload.daily[0].day}}</div>\n                        <i class=\"wi wi-owm-{{msg.payload.daily[0].weather[0].icon}}\" style=\"{{msg.payload.daily[1].iconstyle}}\"></i>\n                        <div class=\"subtitle temp\">{{msg.payload.daily[0].temp.max | number:0}}°</div>\n                        <div class=\"subtitle rain\">{{msg.payload.daily[0].rainmm}}</div>\n                        <div class=\"subtitle snow\">{{msg.payload.daily[0].snowmm}}</div>\n                    </div>\n                    <div class=\"icon\">\n                        <div class=\"subtitle time\">{{msg.payload.daily[1].day}}</div>\n                        <i class=\"wi wi-owm-{{msg.payload.daily[1].weather[0].icon}}\" style=\"{{msg.payload.daily[1].iconstyle}}\"></i>\n                        <div class=\"subtitle temp\">{{msg.payload.daily[1].temp.max | number:0}}°</div>\n                        <div class=\"subtitle rain\">{{msg.payload.daily[1].rainmm}}</div>\n                        <div class=\"subtitle snow\">{{msg.payload.daily[1].snowmm}}</div>\n                    </div>\n                    <div class=\"icon\">\n                        <div class=\"subtitle time\">{{msg.payload.daily[2].day}}</div>\n                        <i class=\"wi wi-owm-{{msg.payload.daily[2].weather[0].icon}}\" style=\"{{msg.payload.daily[1].iconstyle}}\"></i>\n                        <div class=\"subtitle temp\">{{msg.payload.daily[2].temp.max | number:0}}°</div>\n                        <div class=\"subtitle rain\">{{msg.payload.daily[2].rainmm}}</div>\n                        <div class=\"subtitle snow\">{{msg.payload.daily[2].snowmm}}</div>\n                    </div>                        \n                    <div class=\"icon\">\n                        <div class=\"subtitle time\">{{msg.payload.daily[3].day}}</div>\n                        <i class=\"wi wi-owm-{{msg.payload.daily[3].weather[0].icon}}\" style=\"{{msg.payload.daily[1].iconstyle}}\"></i>\n                        <div class=\"subtitle temp\">{{msg.payload.daily[3].temp.max | number:0}}°</div>\n                        <div class=\"subtitle rain\">{{msg.payload.daily[3].rainmm}}</div>\n                        <div class=\"subtitle snow\">{{msg.payload.daily[3].snowmm}}</div>\n                    </div>\n                    <div class=\"icon\">\n                        <div class=\"subtitle time\">{{msg.payload.daily[4].day}}</div>\n                        <i class=\"wi wi-owm-{{msg.payload.daily[4].weather[0].icon}}\" style=\"{{msg.payload.daily[1].iconstyle}}\"></i>\n                        <div class=\"subtitle temp\">{{msg.payload.daily[4].temp.max | number:0}}°</div>\n                        <div class=\"subtitle rain\">{{msg.payload.daily[4].rainmm}}</div>\n                        <div class=\"subtitle snow\">{{msg.payload.daily[4].snowmm}}</div>\n                    </div>\n                </div>\n            </div>\n        </div>\n    </div>\n    <div class=\"copyright\"><span>Weather data from openweathermap.org</span></div>\n</div>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":800,"y":180,"wires":[[]]},{"id":"1b6f730c6ab2223f","type":"function","z":"80504545190c9b4d","name":"Adjust output","func":"const alertstyle = \"color: var(--alertcolor)\";\nmsg.debug = {location: msg.location, alerts:{}, days:\"\", hours:\"\"};\nfunction dayName(unixTime){\n  var dateObject = new Date(unixTime * 1000);\n  return dateObject.toLocaleString(\"default\", { weekday: \"short\" })\n}\nfunction timeConvert(UNIX_timestamp){\n    var dateObject = new Date(UNIX_timestamp * 1000);\n    return dateObject.toLocaleString('en', { timezone: msg.payload.timezone, hour12: false, hour: 'numeric'}) + ':00';\n}\nfunction degreesToCompass(deg){\n  if (deg>11.25 && deg<=33.75){return \"NNE\";}\n  else if (deg<=56.25){return \"NE\";}\n  else if (deg<=78.75){return \"ENE\";}\n  else if (deg<=101.25){return \"E\";}\n  else if (deg<=123.75){return \"ESE\";}\n  else if (deg<=146.25){return \"SE\";}\n  else if (deg<=168.75){return \"SSE\";}\n  else if (deg<=191.25){return \"S\";}\n  else if (deg<=213.75){return \"SSW\";}\n  else if (deg<=236.25){return \"SW\";}\n  else if (deg<=258.75){return \"WSW\";}\n  else if (deg<=281.25){return \"W\";}\n  else if (deg<=303.75){return \"WNW\";}\n  else if (deg<=326.25){return \"NW\";}\n  else if (deg<=348.75){return \"NNW\";}\n  else {return \"N\";}\n}\n\n// wind as compass points \nmsg.payload.current.wind_point = degreesToCompass(msg.payload.current.wind_deg);\nmsg.payload.current.wind_knots = msg.payload.current.wind_speed * 1.944;\nmsg.payload.current.wind_mph = msg.payload.current.wind_speed * 2.237;\n\n// Weather alerts\nif (msg.payload.hasOwnProperty('alerts')) {       // There may be several weather alerts but only space to show one\n    msg.comments = msg.payload.alerts[0].event;   // No good way to pick the most urgent\n}\n\n// Get rain & snow qty and alerts for each hour, Adjust display to show local time\n// Not sure if browser timezone is relevant?\nmsg.payload.hourly.forEach(element => {\n    const adjustedtime = element.dt + msg.payload.timezone_offset;\n    element.localtime = timeConvert(adjustedtime);  \n    element.day = dayName(adjustedtime);\n    if (element.hasOwnProperty('rain')) {element.rainmm = Math.round(element.rain[\"1h\"]) + \"mm\";}\n    if (element.hasOwnProperty('snow')) {element.snowmm = Math.round(element.snow[\"1h\"]) + \"mm\";}\n    if (msg.payload.hasOwnProperty('alerts')) {\n        msg.payload.alerts.forEach(alert => {\n            if (element.dt <= alert.end && (element.dt + 3600) >= alert.start) {\n                element.warning = alert.event;\n                element.iconstyle = alertstyle;\n            }\n        });\n    }\n});\n\n// Get rain & snow qty and alerts for each day\nmsg.payload.daily.forEach(element => {\n    const adjustedtime = element.dt + msg.payload.timezone_offset;\n    element.localtime = timeConvert(adjustedtime);\n    element.day = dayName(adjustedtime);\n    if (element.hasOwnProperty('rain')) {\n        element.rainmm = Math.round(element.rain) + \"mm\";\n    }\n    if (element.hasOwnProperty('snow')) {\n        element.snowmm = Math.round(element.snow) + \"mm\";\n    }\n    if (msg.payload.hasOwnProperty('alerts')) {\n        msg.payload.alerts.forEach(alert => {\n            if (element.dt <= alert.end && (element.dt + 86400) >= alert.start) {\n                element.warning = alert.event;\n                element.iconstyle = alertstyle;\n            }\n        });\n    }\n});\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":610,"y":180,"wires":[["2c4e9abec36c3fb6"]]},{"id":"953c086699766456","type":"ui_template","z":"80504545190c9b4d","group":"0b2c5ed94dd5b6dc","name":"CSS","order":3,"width":"0","height":"0","format":"<style>\n:root {\n/* these are the colours of the three layers */\n--background: 126,219,251;\n--r1: 250; --g1: 250; --b1: 147;\n--r2: 255; --g2: 179; --b2: 179;\n/* and text */\n--textcolor: black;\n--alertcolor: chocolate; \n/* You can adjust the blending of colours with this. Suggest 0.4 - 0.6 */\n--blend: 0.5;\n}\n.weatherwidget{\n    position: relative;\n    height: calc(100% - 8px);\n    width: 100%;\n    background-color: rgb(var(--background));\n}\n.weatherwidget .location {\n    position: absolute;\n    top: 0px;\n    left: 5px;\n    width: 100%;\n    font-family: \"Times New Roman\", serif;\n    font-size: 42px;\n    color: var(--textcolor);\n}\n.weatherwidget .temperature {\n    position: absolute;\n    margin-left: 10px;\n    top: 42px;\n    width: 93%;\n    height: 80%;\n    color: var(--textcolor);\n    font-family: calibri, sans-serif;\n}\n.weatherwidget .temperature .actual {\n    position: relative;\n    width: 120px;     \n    margin-left: 0px;\n    min-height: 40px;\n    float:left;\n    top: 0px;\n}\n.weatherwidget .temperature .actual .value {\n    position: absolute;\n    top:0px;\n    left:0px;\n    font-size: 40px;\n}\n.weatherwidget .temperature .feelslike {\n    position:relative;\n    width: 80px;\n    margin-left: 0px;\n    height: 70px;\n    float: left;\n    top:0px;\n}\n.weatherwidget .temperature .feelslike .value {\n    position: absolute;\n    top: 3px;\n    left:0px;\n    font-size: 32px;\n}\n\n.weatherwidget .currentwrapper {\n    position: absolute;\n    width: 180px;\n    right: 10px;\n    top: 0px;\n}\n.weatherwidget .current {\n    position: relative;\n    color: var(--textcolor);\n    font-size: 16px;\n    font-family: verdana, sans-serif;\n}\n.weatherwidget .current .wind {\n    position: absolute;\n    top: 8px;\n    right: 0px;\n}\n.weatherwidget .current .pressure {\n    position: absolute;\n    top: 26px;\n    right:0px;\n}\n.weatherwidget .current .humidity {\n    position: absolute;\n    top: 44px;\n    right: 0px;\n}\n\n.weatherwidget .comments {\n    position: absolute;\n    font-size: 18px;\n    right:10px;\n    top: 64px;\n    color: var(--alertcolor);\n    font-family: verdana, sans-serif;\n}\n\n.weatherwidget .iconswrapper {\n    position: absolute;\n    top: 92px;\n    left: 10px;\n    width: calc(100% - 10px);\n    color: var(--textcolor);\n    text-align: center;\n    font-family: verdana, sans-serif;\n}\n.weatherwidget .iconswrapper .hourly {\n    position: relative;\n    top: 0px;\n    float:left;\n}\n.weatherwidget .iconswrapper .daily {\n    position: relative;\n    top: 0px;\n    float: right;\n}\n.weatherwidget .iconswrapper .icon {\n    float: left;\n    min-width: 40px;\n}\n.weatherwidget .iconswrapper .icon i {\n    padding-bottom: 5px;\n    font-size: 26px;     /* using fa-2x instead makes icon slightly too wide */\n}\n.weatherwidget .iconswrapper .subtitle {\n    font-size: 11px;\n    margin-bottom: 2px;\n}\n.weatherwidget .iconswrapper .subtitle.time {\n    margin-bottom: 5px;\n}\n.weatherwidget .iconswrapper .subtitle.rain {\n    color: blue;\n}\n.weatherwidget .iconswrapper .subtitle.snow {\n    color: white;\n}\n.bordered{\n    box-sizing: border-box;\n    border:4px solid black;\n    margin-bottom: 2px;\n}\n.rounded {\n    border-radius: 10px;\n}\n.weatherwidget .layer1 {\n--r: var(--r1);\n--g: var(--g1);\n--b: var(--b1);\n--start:var(--coldat);\n}\n.weatherwidget .layer2 {\n--r: var(--r2);\n--g: var(--g2);\n--b: var(--b2);\n--start:calc(var(--hotat) - (var(--span)));\n}\n.weatherwidget .layer2, .weatherwidget .layer1 {\n--span: calc((var(--hotat) - var(--coldat)) * var(--blend));\n    position: absolute;\n    width: 100%;\n    height: 100%;\n    top: 0;\n    box-shadow: 4px 4px 28px 0px rgba(0,0,0,0.3) inset;\n    background-color: rgba(var(--r), var(--g), var(--b), calc((var(--fudge) - var(--start)) / var(--span)));\n}\n.weatherwidget .copyright {\n    position: absolute;\n    bottom: -10px;\n    right: 10px;\n    font-size:10px;\n    font-family: verdana, sans-serif;\n    max-height: 15px;\n}\n</style>\n","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":770,"y":120,"wires":[[]]},{"id":"0b2c5ed94dd5b6dc","type":"ui_group","name":"Demo","tab":"4311353dbffb7643","order":1,"disp":true,"width":"10","collapse":false,"className":""},{"id":"4311353dbffb7643","type":"ui_tab","name":"Demo","icon":"dashboard","disabled":false,"hidden":false}]
7 Likes

Just don't eat the snow in Tobermory :rofl:

Why, what did you do? :stuck_out_tongue_winking_eye:

Apparently its Yellow :nauseated_face:

2 Likes

Womble spoor.

1 Like

Hello guys do you have this template modified for Dashboard 2.0. I cannot make it to work with my poor knowledge. Thanks in advance

I started working on it but it's not complete.

If you show us your attempt so far we might be able to fix it between us.

SInce I am not an expert in programming I just copied and pasted the code from dashboard 1 to dashboard 2.0. And of course it did not work. I have no clue of ewhat the differences are sorry

I don't seem to be able to use OWM any more - I generated a new key but I keep getting a 401 response - invalid key.

i can provide you with my apikey temporarly to test if you like.

in anyway it takes some time for the api to get valid. it happened to me too in the past.

I've use it in the past and had 2 other API keys which I also tried. So not sure what's wrong. If you want to pm me your key, I'll just use it for a one-off test.

I intended to create a uibuilder version of this example. :slight_smile:

i just did it.

1 Like

Are you using the "onecall" api?

A sample msg.url
https://api.openweathermap.org/data/3.0/onecall?lat=101.89&lon=7.12&units=metric&appid=0123456789abcdef01234567890abcdef

I was very proud of this dashboard until my other half told me the colours are ugly :astonished_face:

I think if I was doing it now, I'd try to use a single background colour using HSL color space and varying the hue.

1 Like

Weird, that worked.

No, I'm using the v2.5 API

This is direct from their API docs (missing the key obviously)

https://api.openweathermap.org/data/2.5/weather?lat=44.34&lon=10.99&appid=

:rofl:

yes. one call api 3.0

No, onecall 3.0 is a different subscription. Also free but you have to sign up separately.

i am just saying i am using api 3.0 not 2.5.

Your URL works with my appid too