Skip to content

Instantly share code, notes, and snippets.

@djiwondee
Last active May 27, 2023 22:52
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save djiwondee/b5b7d5da14d24e71de447e6aa290937e to your computer and use it in GitHub Desktop.
Save djiwondee/b5b7d5da14d24e71de447e6aa290937e to your computer and use it in GitHub Desktop.
Dashboard with current conditions and forecast

Node-red Flow showing Node-red ui OpenweatherMap based condition and forecast

I was looking for implementation examples for the Openweathermap nodes together with the nice set of icons created by Erik Flowers. Within that exercise I've recognized there are not so much example available. So let me share my current implementation.

Bildschirmfoto 2019-03-09 um 15 36 58

Note: I'm using Node-red on a RaspberryPi. So my flow is implemented and tested on that platform.

Pre-requisites

Icons and CSS

You need to install the required library with more the 200 icons and the related CSS content. Go to GitHub and follow the instruction of Paul Reeds setup.

Note: Since a small subset of weather icons are already embedded into node-red, you only need to follow this instruction if you would like to add much more out of the more than 200 available icons. Otherwise just adding <i class="wi wi-forecast-io-rain"> to a dashboard template node to displays the icons in the same way as e. g. Font Awsome.

Create a free OpenWeather account and obtain an API Key

Accessing the free OpenweatherMap data an API key is required. To obtain an API key go to OpenWeatherMap, sign in and request a key.

Note: It could take a couple of hours until you get an email from OpenWeather with the API key.

Install node-red-nodes for openweathermap

I made some very good experiences with node-red-node-openweathermap.

Comments

I do not claim to have written the most efficient code, especially in the function nodes. My main topic were to find a good way to map OpenweatherMap icon code to Erik Flowers icons. The Mapping provided there seems not exactly match the code provided by the OpenWeatherMap API. For the mapping itself I decide to use the map object in JavaScript, e. g. :

const owIconMap = new Map();

owIconMap.set('01d', 'wi-day-sunny'); // clear sky
owIconMap.set('02d', 'wi-day-cloudy'); // few clouds
owIconMap.set('03d', 'wi-cloud'); // scattered clouds
owIconMap.set('04d', 'wi-cloudy'); // broken clouds
owIconMap.set('09d', 'wi-day-showers'); // shower rain
owIconMap.set('10d', 'wi-day-rain'); // rain
owIconMap.set('11d', 'wi-thunderstorm'); // thunderstorm
owIconMap.set('13d', 'wi-snow'); // snow
owIconMap.set('50d', 'wi-fog'); // mist
...
// assign WeatherIcon name based on OpenWeather API response icon 

conditionIcon.payload = owIconMap.get(msg.payload.icon);

A second point was how to provide a good style to show the forecast. The API response for the forecast is a nested array with 5 day forecast that includes weather data every 3 hours. My example is only displaying 10 intervals across the next 30 hours. I run a second small RaspberryPI with a 3.5" display in my living room, only showing the ui dashboard with weather data. For that reason I decide to setup a small ui page for that.

Bildschirmfoto 2019-03-09 um 15 35 39

My forecast right now may not look really nice. But I've chosen this setup dealing with the limitation of the display size.

Note: Depending on your own locale and preferred language you may need to change the country code in parameter section of the openweather node in addition to API key and location of recidence.

[
{
"id": "eb760bbb.8e5ec",
"type": "inject",
"z": "2b034a6e.a0f896",
"name": "Refresh Timer",
"topic": "Refresh Timer",
"payload": "true",
"payloadType": "bool",
"repeat": "3600",
"crontab": "",
"once": false,
"onceDelay": "",
"x": 170,
"y": 1680,
"wires": [
[
"12bb121.d7787ee",
"e54c1170.c13488",
"f6657c5c.2621a8"
]
]
},
{
"id": "74cb77c.92dd108",
"type": "ui_button",
"z": "2b034a6e.a0f896",
"name": "Weather Refresh",
"group": "99a4dc86.46d248",
"order": 1,
"width": 0,
"height": 0,
"passthru": false,
"label": "Aktualisieren",
"tooltip": "Wetterdaten aktualisieren",
"color": "",
"bgcolor": "",
"icon": "fa-refresh",
"payload": "true",
"payloadType": "bool",
"topic": "",
"x": 140,
"y": 1760,
"wires": [
[
"12bb121.d7787ee",
"e54c1170.c13488",
"f6657c5c.2621a8"
]
]
},
{
"id": "4d90e53a.37962c",
"type": "ui_text",
"z": "2b034a6e.a0f896",
"group": "b12941f.1cd05c",
"order": 1,
"width": "4",
"height": "1",
"name": "Condition Txt",
"label": "",
"format": "{{msg.payload.detail}}",
"layout": "row-center",
"x": 1020,
"y": 1680,
"wires": []
},
{
"id": "89a4bed9.5b467",
"type": "function",
"z": "2b034a6e.a0f896",
"name": "Prepare Dashboard Data",
"func": "var windDirection = {};\nvar windDirectionIcon = {};\nvar windSpeed = {};\nvar windSpeedIcon = {};\nvar sunRise = {};\nvar sunSet = {};\nvar conditionIcon = {};\nvar date = new Date ();\n\n/* function for converting meteorogical degree to text */\n\nvar degToCard = function(deg){\nif (deg>11.25 && deg<=33.75){\nreturn \"Nord-Nord-Ost\";\n }else if (deg>33.75 && deg<56.25){\nreturn \"Nord-Ost\";\n }else if (deg>56.25 && deg<78.75){\nreturn \"Ost-Nord-Ost\";\n }else if (deg>78.75 && deg<101.25){\nreturn \"Ost\";\n }else if (deg>101.25 && deg<123.75){\nreturn \"Ost-Süd-Ost\";\n }else if (deg>123.75 && deg<146.25){\nreturn \"Süd-Ost\";\n }else if (deg>146.25 && deg<168.75){\nreturn \"Süd-Süd-Ost\";\n }else if (deg>168.75 && deg<191.25){\nreturn \"Süd\";\n }else if (deg>191.25 && deg<213.75){\nreturn \"Süd-Süd-West\";\n }else if (deg>213.75 && deg<236.25){\nreturn \"Süd-West\";\n }else if (deg>236.25 && deg<258.75){\nreturn \"West-Süd-West\";\n }else if (deg>258.75 && deg<281.25){\nreturn \"West\";\n }else if (deg>281.25 && deg<303.75){\nreturn \"West-Nord-West\";\n }else if (deg>303.75 && deg<326.25){\nreturn \"Nord-West\";\n }else if (deg>326.25 && deg<348.75){\nreturn \"Nord-Nord-West\";\n }else{\nreturn \"Nord\"; \n }\n}\n\n/* function for converting meteorogical degree to weather icons */\n\nvar degToCardIcon = function(deg){\nif (deg>11.25 && deg<=33.75){\nreturn \"wi-from-nne\";\n }else if (deg>33.75 && deg<56.25){\nreturn \"wi-from-ne\";\n }else if (deg>56.25 && deg<78.75){\nreturn \"wi-from-ene\";\n }else if (deg>78.75 && deg<101.25){\nreturn \"wi-from-e\";\n }else if (deg>101.25 && deg<123.75){\nreturn \"wi-from-ese\";\n }else if (deg>123.75 && deg<146.25){\nreturn \"wi-from-se\";\n }else if (deg>146.25 && deg<168.75){\nreturn \"wi-from-sse\";\n }else if (deg>168.75 && deg<191.25){\nreturn \"wi-from-s\";\n }else if (deg>191.25 && deg<213.75){\nreturn \"wi-from-ssw\";\n }else if (deg>213.75 && deg<236.25){\nreturn \"wi-from-sw\";\n }else if (deg>236.25 && deg<258.75){\nreturn \"wi-from-wsw\";\n }else if (deg>258.75 && deg<281.25){\nreturn \"wi-from-w\";\n }else if (deg>281.25 && deg<303.75){\nreturn \"wi-from-wnw\";\n }else if (deg>303.75 && deg<326.25){\nreturn \"wi-from-nw\";\n }else if (deg>326.25 && deg<348.75){\nreturn \"wi-from-nnw\";\n }else{\nreturn \"wi-from-n\"; \n }\n}\n\n/* Function for converting wind speed into Beaufort scale icon */\n\nvar speedToCardIcon = function(speed){\nif (speed>0.5 && speed<=1.5){\nreturn \"wi-wind-beaufort-1\";\n }else if (speed>1.5 && speed<=3.3){\nreturn \"wi-wind-beaufort-2\";\n }else if (speed>3.3 && speed<=5.5){\nreturn \"wi-wind-beaufort-3\";\n }else if (speed>5.5 && speed<=7.9){\nreturn \"wi-wind-beaufort-4\";\n }else if (speed>7.9 && speed<=10.7){\nreturn \"wi-wind-beaufort-5\";\n }else if (speed>10.7 && speed<=13.8){\nreturn \"wi-wind-beaufort-6\";\n }else if (speed>13.8 && speed<=17.1){\nreturn \"wi-wind-beaufort-7\";\n }else if (speed>17.1 && speed<=20.7){\nreturn \"wi-wind-beaufort-8\";\n }else if (speed>20.7 && speed<=24.4){\nreturn \"wi-wind-beaufort-9\";\n }else if (speed>24.4 && speed<=28.4){\nreturn \"wi-wind-beaufort-10\";\n }else if (speed>28.4 && speed<=32.6){\nreturn \"wi-wind-beaufort-11\";\n }else if (speed>32.6){\nreturn \"wi-wind-beaufort-12\";\n }else{\nreturn \"wi-wind-beaufort-0\"; \n }\n}\n\n/* Function for Time Conversions */\n\nfunction timeConverter(UNIX_timestamp){\n var a = new Date(UNIX_timestamp * 1000);\n var hour = a.getHours();\n var min = a.getMinutes();\n if (min < 10) {min = \"0\" + min;}\n else {min = min;}\n var sec = a.getSeconds();\n if (sec < 10) {sec = \"0\" + sec;}\n else {sec = sec;}\n \n var time = hour + ':' + min + ':' + sec ;\n return time;\n}\n\n/* Convert OpenWeeather Map Icon to https://erikflowers.github.io/weather-icons/ */\n\nconst owIconMap = new Map();\n\nowIconMap.set('01d', 'wi-day-sunny'); // clear sky\nowIconMap.set('02d', 'wi-day-cloudy'); // few clouds\nowIconMap.set('03d', 'wi-cloud'); // scattered clouds\nowIconMap.set('04d', 'wi-cloudy'); // broken clouds\nowIconMap.set('09d', 'wi-day-showers'); // shower rain\nowIconMap.set('10d', 'wi-day-rain'); // rain\nowIconMap.set('11d', 'wi-thunderstorm'); // thunderstorm\nowIconMap.set('13d', 'wi-snow'); // snow\nowIconMap.set('50d', 'wi-fog'); // mist\nowIconMap.set('01n', 'wi-night-clear'); // clear sky\nowIconMap.set('02n', 'wi-night-alt-cloudy'); // few clouds\nowIconMap.set('03n', 'wi-cloud'); // scattered clouds\nowIconMap.set('04n', 'wi-cloudy'); // broken clouds\nowIconMap.set('09n', 'wi-night-alt-showers'); // shower rain\nowIconMap.set('10n', 'wi-night-alt-rain'); // rain\nowIconMap.set('11n', 'wi-thunderstorm'); // thunderstorm\nowIconMap.set('13n', 'wi-snow'); // snow\nowIconMap.set('50n', 'wi-fog'); // mist\n\nconditionIcon.topic = \"ConditionIcon\";\nconditionIcon.payload = owIconMap.get(msg.payload.icon);\n\nwindDirection.topic = \"WindDirection\";\nwindDirection.payload = degToCard(msg.payload.winddirection);\n\nwindDirectionIcon.topic = \"WindDirectionIcon\";\nwindDirectionIcon.payload = degToCardIcon(msg.payload.winddirection);\n\nwindSpeed.topic = \"WindSpeed\";\nwindSpeed.payload = msg.payload.windspeed + \" m/s\"; /* \" + windDirection.payload; */\n\nwindSpeedIcon.topic = \"WindSpeedIcon\";\nwindSpeedIcon.payload = speedToCardIcon(msg.payload.windspeed);\n\nsunRise.topic = \"SunRise\";\nsunRise.payload = timeConverter(msg.payload.sunrise);\n\nsunSet.topic = \"SunRet\";\nsunSet.payload = timeConverter(msg.payload.sunset);\n\nowIconMap.clear(); //freeing resource\n\nreturn [conditionIcon, windSpeedIcon, windSpeed, windDirection, windDirectionIcon, sunRise, sunSet];",
"outputs": 7,
"noerr": 0,
"x": 710,
"y": 1840,
"wires": [
[
"d0990bb3.6ee1f8"
],
[
"6bfd9bef.141194"
],
[
"49e2e33e.486c14"
],
[],
[
"a8c65467.d3352"
],
[
"393c1d0b.05766a"
],
[
"d2011150.f678f"
]
]
},
{
"id": "49e2e33e.486c14",
"type": "ui_text",
"z": "2b034a6e.a0f896",
"group": "8da50f69.44fe38",
"order": 2,
"width": "2",
"height": "1",
"name": "WindSpeed",
"label": "",
"format": "{{msg.payload}}",
"layout": "row-center",
"x": 1010,
"y": 1840,
"wires": []
},
{
"id": "393c1d0b.05766a",
"type": "ui_text",
"z": "2b034a6e.a0f896",
"group": "5a4d76d2.5ae128",
"order": 4,
"width": "2",
"height": "1",
"name": "Sunrise",
"label": "",
"format": "{{msg.payload}}",
"layout": "col-center",
"x": 1000,
"y": 1980,
"wires": []
},
{
"id": "d2011150.f678f",
"type": "ui_text",
"z": "2b034a6e.a0f896",
"group": "5a4d76d2.5ae128",
"order": 6,
"width": "2",
"height": "1",
"name": "Sunset",
"label": "",
"format": "{{msg.payload}}",
"layout": "col-center",
"x": 1000,
"y": 2060,
"wires": []
},
{
"id": "a767f2cc.5f3478",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "5a4d76d2.5ae128",
"name": "Sunrise Icon",
"order": 3,
"width": "1",
"height": "1",
"format": "<link rel=\"stylesheet\" href=\"/weather-icons/mycss/weather-icons.min.css\">\n<div style=\"display: flex;height: 100%;justify-content: left;align-items: center;\">\n<i class=\"fa-2x wi wi-sunrise\"></i>\n</div> ",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1010,
"y": 1940,
"wires": [
[]
]
},
{
"id": "7dfa615d.50546",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "5a4d76d2.5ae128",
"name": "Sunset Icon",
"order": 5,
"width": "1",
"height": "1",
"format": "<link rel=\"stylesheet\" href=\"/weather-icons/mycss/weather-icons.min.css\">\n<div style=\"display: flex;height: 100%;justify-content: left;align-items: center;\">\n<i class=\"fa-2x wi wi-sunset\"></i>\n</div> ",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1010,
"y": 2020,
"wires": [
[]
]
},
{
"id": "a8c65467.d3352",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "8da50f69.44fe38",
"name": "WindDirection icon",
"order": 3,
"width": "1",
"height": "1",
"format": "<link rel=\"stylesheet\" href=\"/weather-icons/mycss/weather-icons-wind.css\">\n<div style=\"display: flex;height: 100%;justify-content: center;align-items: center;\">\n<i class=\"fa-2x wi wi-wind {{msg.payload}}\"></i>\n</div> ",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1030,
"y": 1880,
"wires": [
[]
]
},
{
"id": "e54c1170.c13488",
"type": "openweathermap",
"z": "2b034a6e.a0f896",
"name": "Current Weather",
"wtype": "current",
"lon": "8.01",
"lat": "50.01",
"city": "",
"country": "",
"language": "de",
"x": 400,
"y": 1680,
"wires": [
[
"89a4bed9.5b467",
"4d90e53a.37962c"
]
]
},
{
"id": "6bfd9bef.141194",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "8da50f69.44fe38",
"name": "WindSpeed Icon",
"order": 1,
"width": "1",
"height": "1",
"format": "<link rel=\"stylesheet\" href=\"/weather-icons/mycss/weather-icons-wind.css\">\n<div style=\"display: flex;height: 100%;justify-content: left;align-items: center;\">\n<i class=\"fa-2x wi wi-wind {{msg.payload}}\"></i>\n</div>",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1030,
"y": 1800,
"wires": [
[]
]
},
{
"id": "480a6cbf.880804",
"type": "debug",
"z": "2b034a6e.a0f896",
"name": "Forecast debug",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "payload",
"x": 1020,
"y": 2480,
"wires": []
},
{
"id": "5af8efb7.126a98",
"type": "comment",
"z": "2b034a6e.a0f896",
"name": "Open Weather API für aktuelles Wetter und Forecast",
"info": "",
"x": 510,
"y": 1600,
"wires": []
},
{
"id": "d0990bb3.6ee1f8",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "14584712.7a2929",
"name": "Condition Icon",
"order": 1,
"width": "2",
"height": "2",
"format": "<link rel=\"stylesheet\" href=\"/weather-icons/mycss/weather-icons.min.css\">\n<div style=\"display: flex;height: 100%;justify-content: center;align-items: center;\">\n<i class=\"fa-4x wi {{msg.payload}}\"></i>\n</div>",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1020,
"y": 1720,
"wires": [
[]
]
},
{
"id": "f6657c5c.2621a8",
"type": "openweathermap",
"z": "2b034a6e.a0f896",
"name": "5 Day Forecast",
"wtype": "forecast",
"lon": "8.02",
"lat": "50.01",
"city": "",
"country": "",
"language": "de",
"x": 380,
"y": 2140,
"wires": [
[
"25b2dc06.cd7bdc",
"e58a247.3094b58",
"c5b71946.ca4de",
"480a6cbf.880804"
]
]
},
{
"id": "25b2dc06.cd7bdc",
"type": "function",
"z": "2b034a6e.a0f896",
"name": "Prepare Forecast Icon",
"func": "var wfcIcon1 = {};\nvar wfcIcon2 = {}; \nvar wfcIcon3 = {};\nvar wfcIcon4 = {};\nvar wfcIcon5 = {};\nvar wfcIcon6 = {};\nvar wfcIcon7 = {};\nvar wfcIcon8 = {};\n\n\nvar date = new Date ();\n\n/* Function for Time Conversions */\n\nfunction timeConverter(UNIX_timestamp){\n var a = new Date(UNIX_timestamp * 1000);\n var hour = a.getHours();\n var min = a.getMinutes();\n if (min < 10) {min = \"0\" + min;}\n else {min = min;}\n var sec = a.getSeconds();\n if (sec < 10) {sec = \"0\" + sec;}\n else {sec = sec;}\n \n var time = hour + ':' + min; /* + ':' + sec ;*/\n return time;\n}\n\n/* Convert OpenWeeather Map Icon to https://erikflowers.github.io/weather-icons/ */\n\nconst owIconMap = new Map();\n\nowIconMap.set('01d', 'wi-day-sunny'); // clear sky\nowIconMap.set('02d', 'wi-day-cloudy'); // few clouds\nowIconMap.set('03d', 'wi-cloud'); // scattered clouds\nowIconMap.set('04d', 'wi-cloudy'); // broken clouds\nowIconMap.set('09d', 'wi-day-showers'); // shower rain\nowIconMap.set('10d', 'wi-day-rain'); // rain\nowIconMap.set('11d', 'wi-thunderstorm'); // thunderstorm\nowIconMap.set('13d', 'wi-snow'); // snow\nowIconMap.set('50d', 'wi-fog'); // mist\nowIconMap.set('01n', 'wi-night-clear'); // clear sky\nowIconMap.set('02n', 'wi-night-alt-cloudy'); // few clouds\nowIconMap.set('03n', 'wi-cloud'); // scattered clouds\nowIconMap.set('04n', 'wi-cloudy'); // broken clouds\nowIconMap.set('09n', 'wi-night-alt-showers'); // shower rain\nowIconMap.set('10n', 'wi-night-alt-rain'); // rain\nowIconMap.set('11n', 'wi-thunderstorm'); // thunderstorm\nowIconMap.set('13n', 'wi-snow'); // snow\nowIconMap.set('50n', 'wi-fog'); // mist\n\nwfcIcon1.topic = msg.payload[0].dt_txt;\nwfcIcon1.payload = owIconMap.get(msg.payload[0].weather[0].icon);\n\nwfcIcon2.topic = msg.payload[1].dt_txt;\nwfcIcon2.payload = owIconMap.get(msg.payload[1].weather[0].icon);\n\nwfcIcon3.topic = msg.payload[2].dt_txt;\nwfcIcon3.payload = owIconMap.get(msg.payload[2].weather[0].icon);\n\nwfcIcon4.topic = msg.payload[3].dt_txt;\nwfcIcon4.payload = owIconMap.get(msg.payload[3].weather[0].icon);\n\nwfcIcon5.topic = msg.payload[4].dt_txt;\nwfcIcon5.payload = owIconMap.get(msg.payload[4].weather[0].icon);\n\nwfcIcon6.topic = msg.payload[5].dt_txt;\nwfcIcon6.payload = owIconMap.get(msg.payload[5].weather[0].icon);\n\nwfcIcon7.topic = msg.payload[6].dt_txt;\nwfcIcon7.payload = owIconMap.get(msg.payload[6].weather[0].icon);\n\nwfcIcon8.topic = msg.payload[7].dt_txt;\nwfcIcon8.payload = owIconMap.get(msg.payload[7].weather[0].icon);\n\n\nowIconMap.clear(); //freeing resource\n\nreturn [wfcIcon1, wfcIcon2, wfcIcon3, wfcIcon4, wfcIcon5, wfcIcon6, wfcIcon7, wfcIcon8];",
"outputs": 8,
"noerr": 0,
"x": 720,
"y": 2200,
"wires": [
[
"39139188.be2256"
],
[
"c24820ec.48ca8"
],
[
"764a58c0.442438"
],
[
"6eab6954.c57d38"
],
[
"c756059d.18796"
],
[
"53046826.3645"
],
[
"229014e6.b0e14c"
],
[
"fd1a001d.2fc35"
]
]
},
{
"id": "39139188.be2256",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "5e0d6747.b726b",
"name": "WFc Icon 1",
"order": 2,
"width": "1",
"height": "1",
"format": "<link rel=\"stylesheet\" href=\"/weather-icons/mycss/weather-icons.min.css\">\n<div style=\"display: flex;height: 100%;justify-content: center;align-items: center;\">\n<i class=\"fa-1x wi {{msg.payload}}\"></i>\n</div>",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1010,
"y": 2140,
"wires": [
[]
]
},
{
"id": "c24820ec.48ca8",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "5e0d6747.b726b",
"name": "WFc Icon 2",
"order": 3,
"width": "1",
"height": "1",
"format": "<link rel=\"stylesheet\" href=\"/weather-icons/mycss/weather-icons.min.css\">\n<div style=\"display: flex;height: 100%;justify-content: center;align-items: center;\">\n<i class=\"fa-1x wi {{msg.payload}}\"></i>\n</div>",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1010,
"y": 2180,
"wires": [
[]
]
},
{
"id": "764a58c0.442438",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "5e0d6747.b726b",
"name": "WFc Icon 3",
"order": 4,
"width": "1",
"height": "1",
"format": "<link rel=\"stylesheet\" href=\"/weather-icons/mycss/weather-icons.min.css\">\n<div style=\"display: flex;height: 100%;justify-content: center;align-items: center;\">\n<i class=\"fa-1x wi {{msg.payload}}\"></i>\n</div>",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1010,
"y": 2220,
"wires": [
[]
]
},
{
"id": "6eab6954.c57d38",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "5e0d6747.b726b",
"name": "WFc Icon 4",
"order": 5,
"width": "1",
"height": "1",
"format": "<link rel=\"stylesheet\" href=\"/weather-icons/mycss/weather-icons.min.css\">\n<div style=\"display: flex;height: 100%;justify-content: center;align-items: center;\">\n<i class=\"fa-1x wi {{msg.payload}}\"></i>\n</div>",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1010,
"y": 2260,
"wires": [
[]
]
},
{
"id": "c756059d.18796",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "5e0d6747.b726b",
"name": "WFc Icon 5",
"order": 6,
"width": "1",
"height": "1",
"format": "<link rel=\"stylesheet\" href=\"/weather-icons/mycss/weather-icons.min.css\">\n<div style=\"display: flex;height: 100%;justify-content: center;align-items: center;\">\n<i class=\"fa-1x wi {{msg.payload}}\"></i>\n</div>",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1010,
"y": 2300,
"wires": [
[]
]
},
{
"id": "53046826.3645",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "5e0d6747.b726b",
"name": "WFc Icon 6",
"order": 7,
"width": "1",
"height": "1",
"format": "<link rel=\"stylesheet\" href=\"/weather-icons/mycss/weather-icons.min.css\">\n<div style=\"display: flex;height: 100%;justify-content: center;align-items: center;\">\n<i class=\"fa-1x wi {{msg.payload}}\"></i>\n</div>",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1010,
"y": 2340,
"wires": [
[]
]
},
{
"id": "229014e6.b0e14c",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "5e0d6747.b726b",
"name": "WFc Icon 7",
"order": 8,
"width": "1",
"height": "1",
"format": "<link rel=\"stylesheet\" href=\"/weather-icons/mycss/weather-icons.min.css\">\n<div style=\"display: flex;height: 100%;justify-content: center;align-items: center;\">\n<i class=\"fa-1x wi {{msg.payload}}\"></i>\n</div>",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1010,
"y": 2380,
"wires": [
[]
]
},
{
"id": "fd1a001d.2fc35",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "5e0d6747.b726b",
"name": "WFc Icon 8",
"order": 9,
"width": "1",
"height": "1",
"format": "<link rel=\"stylesheet\" href=\"/weather-icons/mycss/weather-icons.min.css\">\n<div style=\"display: flex;height: 100%;justify-content: center;align-items: center;\">\n<i class=\"fa-1x wi {{msg.payload}}\"></i>\n</div>",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1010,
"y": 2420,
"wires": [
[]
]
},
{
"id": "e58a247.3094b58",
"type": "function",
"z": "2b034a6e.a0f896",
"name": "Prepare Forecast Data",
"func": "var fcdata = {};\n\nfcdata.payload = {\n forecast: {\n dt00: {\n dt_txt: msg.payload[0].dt_txt,\n temp_min: msg.payload[0].main.temp_min,\n temp_max: msg.payload[0].main.temp_max,\n temp: msg.payload[0].main.temp,\n desc: msg.payload[0].weather[0].description\n },\n dt01: {\n dt_txt: msg.payload[1].dt_txt,\n temp_min: msg.payload[1].main.temp_min,\n temp_max: msg.payload[1].main.temp_max,\n temp: msg.payload[1].main.temp,\n desc: msg.payload[1].weather[0].description\n },\n dt02: {\n dt_txt: msg.payload[2].dt_txt,\n temp_min: msg.payload[2].main.temp_min,\n temp_max: msg.payload[2].main.temp_max,\n temp: msg.payload[2].main.temp,\n desc: msg.payload[2].weather[0].description\n },\n dt03: {\n dt_txt: msg.payload[3].dt_txt,\n temp_min: msg.payload[3].main.temp_min,\n temp_max: msg.payload[3].main.temp_max,\n temp: msg.payload[3].main.temp,\n desc: msg.payload[3].weather[0].description\n },\n dt04: {\n dt_txt: msg.payload[4].dt_txt,\n temp_min: msg.payload[4].main.temp_min,\n temp_max: msg.payload[4].main.temp_max,\n temp: msg.payload[4].main.temp,\n desc: msg.payload[4].weather[0].description\n },\n dt05: {\n dt_txt: msg.payload[5].dt_txt,\n temp_min: msg.payload[5].main.temp_min,\n temp_max: msg.payload[5].main.temp_max,\n temp: msg.payload[5].main.temp,\n desc: msg.payload[5].weather[0].description\n },\n dt06: {\n dt_txt: msg.payload[6].dt_txt,\n temp_min: msg.payload[6].main.temp_min,\n temp_max: msg.payload[6].main.temp_max,\n temp: msg.payload[6].main.temp,\n desc: msg.payload[6].weather[0].description\n },\n dt07: {\n dt_txt: msg.payload[7].dt_txt,\n temp_min: msg.payload[7].main.temp_min,\n temp_max: msg.payload[7].main.temp_max,\n temp: msg.payload[7].main.temp,\n desc: msg.payload[7].weather[0].description\n }\n }\n}\n\n\n\nreturn fcdata;",
"outputs": 1,
"noerr": 0,
"x": 720,
"y": 2480,
"wires": [
[]
]
},
{
"id": "770400c.08ade8",
"type": "ui_template",
"z": "2b034a6e.a0f896",
"group": "5e0d6747.b726b",
"name": "Forecast",
"order": 1,
"width": "8",
"height": "1",
"format": "<div layout=\"row\" layout-align=\"space-around start\" ng-repeat=\"data in msg.payload.row\">\n <span flex style=\"color: white\">{{data.cell01}}</span>\n <span flex style=\"color: white\">{{data.cell02}}</span>\n <span flex style=\"color: white\">{{data.cell03}}</span>\n <span flex style=\"color: white\">{{data.cell04}}</span>\n <span flex style=\"color: white\">{{data.cell05}}</span>\n <span flex style=\"color: white\">{{data.cell06}}</span>\n <span flex style=\"color: white\">{{data.cell07}}</span>\n <span flex style=\"color: white\">{{data.cell08}}</span>\n</div>",
"storeOutMessages": true,
"fwdInMessages": true,
"templateScope": "local",
"x": 1000,
"y": 2600,
"wires": [
[]
]
},
{
"id": "c5b71946.ca4de",
"type": "function",
"z": "2b034a6e.a0f896",
"name": "Prepare forecast for UI widget",
"func": "var fcdata = {};\n\n// prepare forecast data for CSS based ui widget\n\nfcdata.payload = {\n row: {\n \tdata01: {\n \t\tcell01: msg.payload[0].dt_txt.substring(11, 16),\n \t\tcell02: msg.payload[1].dt_txt.substring(11, 16),\n \t\tcell03: msg.payload[2].dt_txt.substring(11, 16),\n \t\tcell04: msg.payload[3].dt_txt.substring(11, 16),\n \t\tcell05: msg.payload[4].dt_txt.substring(11, 16),\n \t\tcell06: msg.payload[5].dt_txt.substring(11, 16),\n \t\tcell07: msg.payload[6].dt_txt.substring(11, 16),\n \t\tcell08: msg.payload[7].dt_txt.substring(11, 16)\n \t},\n \tdata02: {\n \t\tcell01: msg.payload[0].main.temp,\n \t\tcell02: msg.payload[1].main.temp,\n \t\tcell03: msg.payload[2].main.temp,\n \t\tcell04: msg.payload[3].main.temp,\n \t\tcell05: msg.payload[4].main.temp,\n \t\tcell06: msg.payload[5].main.temp,\n \t\tcell07: msg.payload[6].main.temp,\n \t\tcell08: msg.payload[7].main.temp\n \t}\n }\n}\n\nreturn fcdata;",
"outputs": 1,
"noerr": 0,
"x": 760,
"y": 2620,
"wires": [
[
"770400c.08ade8"
]
]
},
{
"id": "99a4dc86.46d248",
"type": "ui_group",
"z": "",
"name": "Masterswitches",
"tab": "258c6649.0213da",
"order": 6,
"disp": false,
"width": "6",
"collapse": false
},
{
"id": "b12941f.1cd05c",
"type": "ui_group",
"z": "",
"name": "Condition",
"tab": "eb94216d.968598",
"order": 5,
"disp": false,
"width": "4",
"collapse": false
},
{
"id": "8da50f69.44fe38",
"type": "ui_group",
"z": "",
"name": "Wind",
"tab": "eb94216d.968598",
"order": 4,
"disp": false,
"width": "4",
"collapse": false
},
{
"id": "5a4d76d2.5ae128",
"type": "ui_group",
"z": "",
"name": "Luftfeuchtigkeit",
"tab": "258c6649.0213da",
"order": 4,
"disp": false,
"width": "6",
"collapse": false
},
{
"id": "14584712.7a2929",
"type": "ui_group",
"z": "",
"name": "Condition",
"tab": "eb94216d.968598",
"order": 2,
"disp": false,
"width": "2",
"collapse": false
},
{
"id": "5e0d6747.b726b",
"type": "ui_group",
"z": "",
"name": "Forecast",
"tab": "eb94216d.968598",
"order": 6,
"disp": false,
"width": "8",
"collapse": false
},
{
"id": "258c6649.0213da",
"type": "ui_tab",
"z": "",
"name": "Home",
"icon": "home",
"order": 1
},
{
"id": "eb94216d.968598",
"type": "ui_tab",
"z": "",
"name": "Wetterstation",
"icon": "fa-thermometer-half",
"order": 5,
"disabled": false,
"hidden": false
}
]
@chuckf201
Copy link

I enjoy the completeness of your flow however I have blank tabs. I've converted mps to MPH (imperial) do I have to remap the icons also?

@djiwondee
Copy link
Author

djiwondee commented Mar 26, 2019

@chuckf201
you may have to change the calculation for the beaufort value for the wind speed. In addition to that please check the api call to open weather. As far as I remember there is a parameter for continental vs imperial metric.

The empty tabs are caused due to the fact I’ve only copied the open weather part of my larger flow in node-red

@DonatoD
Copy link

DonatoD commented Jun 8, 2019

Hi, I'm completly new on this "weather project" and I'm still learning. I don't understand how I can use the icons I downloaded from the web site. Usually I use to refer directly to the web site inside the template node. But if I'm not wrong, you refer to one your own directory where ypu put all the icons set. This is what I would like do, too. Can you kindly explain me how to proceed?
Thanks a lot

@djiwondee
Copy link
Author

Hello @DonatoD,

... you refer to one your own directory where ypu put all the icons set. This is what I would like do, too. Can you kindly explain me how to proceed?

First: You definitely need to clone the repository to your local installation. What are you using? A raspberryPi like I do? As written above please follow the instruction of Paul Reeds setup. In my case this clones repo looks like this:

image

Second: Don't forget to point node-red to that directory for static CSS and content to be displayed by editing your node-red settings file, usually nano /home/pi/.node-red/settings.js as follows, and type the full path to node-red public directory (in my case /home/pi/.node-red/public where below the subdirectory weather-icons contains the repository with icons and CSS:

image

Don't miss the comma at the end of the line.

With that setup a ui_template node of the node-red dashboard can refer to that repository with code like this:

<link rel="stylesheet" href="/weather-icons/mycss/weather-icons.min.css">
<div style="display: flex;height: 100%;justify-content: center;align-items: center;">
<i class="fa-2x wi {{msg.payload}}"></i>
</div>

Hope this helps!

@DonatoD
Copy link

DonatoD commented Jun 16, 2019

Thanks a lot. I'm trying but without successing!!! I'm using both, a windows PC or a raspberry Pi. I don't want to bother you, but if you have time I would appreciate a little step by step guide. Often in the forums a lot of things are taken for granted, and for new learner like me it's complicated!!!
Really thanks

@djiwondee
Copy link
Author

@DonatoD , can you please describe where you are stucking in you setup in particular? Were you at least able to clone the repository to your local system?

@kickersdoener
Copy link

Ich nehme mal an, dass du Deutsch sprichst?
Ich hab versucht dein Projekt nachzumachen allerdings funktioniert das ganze bei mir nicht so ganz. Dazu muss ich sagen, dass ich noch ein Anfänger in Node-Red bin
image
so sieht des bei mir aus.
ich hab die icons in diesem Verzeichnis abgelegt "/home/pi/.node-red/public/" und den public Ordner zum static directory gemacht.
Hast du irgendwelche Ideen was ich falsch mache?

Danke schon mal im voraus.

@kickersdoener
Copy link

nachdem ich alles auf dark gestellt habe sieht es immerhin so aus
image
allerdings hab ich immer noch keine Icons oder so

@djiwondee
Copy link
Author

Hallo @kickersdoener,

da bist Du ja schon weiter gekommen! In der Tat findet das UI Dashboard die CSS files nicht. Zu Fehlersuche würde ich Dir zunächst die folgenden Vorschläge machen:

  • Hast Du in Node-red mal in das Debug Fenster geschaut, ob da grundsätzlich Fehlermeldungen auftauchen
  • Hast Du mal ein Debug-Node an die ui Template nodes angedockt und im Debug Fenster geschaut
  • Gib auf der Raspi Konsole mal node-red-log ein und refreshe die Webseite mit der Wetterstation im Browser und schaue danach auf der Raspi Konsole, ob dort eine Fehlermeldung ausgegebene wird
  • Auch die Browser bieten üblicher Weise einen Webinspektor an, mit denen man Webseiten debugged kann. Auch hier kannst Du mal schauen, ob eine Fehlermeldung oder Warnung ausgegeben wird.

@kickersdoener
Copy link

oh man ich habs endlich ich bin einfach nur Dumm... Tippfehler...

@kickersdoener
Copy link

trotzdem danke

@bluenazgul
Copy link

Screenshot (1)
bei mir schaut das so aus, hast du einen Tipp, wie ich es so angeordnet bekomme, wie bei dir gezeigt?

So wie es derzeit ist, gefällt es mir garnicht

@djiwondee
Copy link
Author

Hallo @bluenazgul,

bei mir schaut das so aus, weil ich es auf einem kleinen Raspi-Display laufen habe:

image

Nod-red UI-Dashboard rendert das dynamisch in Abhängigkeit der Display-Größe. Wenn ich das in einem normalen Browser öffne, dann sieht es auch so aus:

image

Wenn Du das fix haben willst, dann muss Du mit festen Widthund Size in den properties des Dashboards, Dashboard Group und den Nodes selber arbeiten.

image

Alternativ kannst Du auch ein UI-Template zusammenstellen, in dem Du das alles mit HTML/CSS ausrichten kannst. Ist halt etwas mehr Arbeit.

Btw.: Wie Du vielleicht oben gesehen hast, habe ich bei mir auch etwas an der Schrift, Rundung und Maßeinheit gefeilt, wegen der besseren Lesbarkeit auf meinem kleine Display. Hier der Code der Node Prepare forecast for UI widget dazu:

var fcdata = {};

// prepare forecast data for CSS based ui widget

fcdata.payload = {
  row: {
    // time  
  	data01: {
  		cell01: msg.payload[0].dt_txt.substring(11, 13),
  		cell02: msg.payload[1].dt_txt.substring(11, 13),
  		cell03: msg.payload[2].dt_txt.substring(11, 13),
  		cell04: msg.payload[3].dt_txt.substring(11, 13),
  		cell05: msg.payload[4].dt_txt.substring(11, 13),
  		cell06: msg.payload[5].dt_txt.substring(11, 13),
  		cell07: msg.payload[6].dt_txt.substring(11, 13),
  		cell08: msg.payload[7].dt_txt.substring(11, 13)
  	},
  	// temperature
  	data02: {
  		cell01: Math.round(msg.payload[0].main.temp) + " °C",
  		cell02: Math.round(msg.payload[1].main.temp) + " °C",
  		cell03: Math.round(msg.payload[2].main.temp) + " °C",
  		cell04: Math.round(msg.payload[3].main.temp) + " °C",
  		cell05: Math.round(msg.payload[4].main.temp) + " °C",
  		cell06: Math.round(msg.payload[5].main.temp) + " °C",
  		cell07: Math.round(msg.payload[6].main.temp) + " °C",
  		cell08: Math.round(msg.payload[7].main.temp) + " °C"
  	}
  }
}

return fcdata;

Der Slider bei der Windrose ist vielleicht auch Fehler von UI Dashboard. Den bekommt man weg, indem man die Windrose über die CSS-Klasse verkleinert:

<link rel="stylesheet" href="/addons/red/weather-icons/mycss/weather-icons-wind.css">
<div style="display: flex;height: 100%;justify-content: center;align-items: center;">
<i class="fa-lg wi wi-wind {{msg.payload}}"></i>
</div> 

Weitere Erklärung dazu siehe hier. Damit hättest Du auch noch mehr Möglichkeiten, Deine Anzeige zu variieren.

@bluenazgul
Copy link

Vielen vielen danke @djiwondee

image
image
ich hab mir das alles mal zusammen gefügt und zurecht geschoben.

Mal schauen ob ich deine Anzeigen für "Wohnzimmer" und "Außen" auch noch hin bekomme.

Derzeit sieht meine Außen anzeige noch so aus
image

Erfüllt seinen Zweck, sieht aber kacke aus, aber dafür komplett selber "gebastelt"

Vieleicht magst du die beiden anzeigen ja auch einmal posten, vieleicht bekomme ich "Wohnzimmer" mit meinem Fritz Dect Repeater ja auch so schön ausgelesen.

Diesen habe ich momentan noch so:
image

Dan Node Red für mich noch Neuland ist und ich noch nicht so recht weiß wie ich min und max Werte erfassen kann.

@djiwondee
Copy link
Author

Hallo @bluenazgul,

da bist Du ja schon sehr weit gekommen! Ich weiß nicht, wo Du die Min/Max Werte für Deine Wohnung oder Außenbereich generell ausliest. Die Anzeige wie in meinem Beispiel ist ein simples ui_text - Dashboard Widget

[
    {
        "id": "9780514e.f2ed8",
        "type": "ui_text",
        "z": "42c1b736.4b581",
        "group": "17291f9c.71d378",
        "order": 4,
        "width": 1,
        "height": 1,
        "name": "Min Temp Wohnzimmer",
        "label": "▼",
        "format": "{{msg.payload}}",
        "layout": "col-center",
        "x": 2010,
        "y": 1120,
        "wires": []
    },
    {
        "id": "4bb61b.29c921e4",
        "type": "ui_text",
        "z": "42c1b736.4b581",
        "group": "17291f9c.71d378",
        "order": 5,
        "width": 2,
        "height": 1,
        "name": "Max Temp Wohnzimmer",
        "label": "▲",
        "format": "{{msg.payload}}",
        "layout": "col-center",
        "x": 2010,
        "y": 1180,
        "wires": []
    },
    {
        "id": "55879895.414918",
        "type": "ui_text",
        "z": "42c1b736.4b581",
        "group": "17291f9c.71d378",
        "order": 1,
        "width": 3,
        "height": 1,
        "name": "Innen",
        "label": "Wohnzimmer",
        "format": "{{msg.payload}} °C",
        "layout": "col-center",
        "x": 1970,
        "y": 100,
        "wires": []
    },
    {
        "id": "17291f9c.71d378",
        "type": "ui_group",
        "z": "",
        "name": "Container",
        "tab": "d4f13986.04113",
        "order": 7,
        "disp": false,
        "width": "8",
        "collapse": false
    },
    {
        "id": "d4f13986.04113",
        "type": "ui_tab",
        "z": "",
        "name": "Wetterstation",
        "icon": "fa-thermometer-half",
        "order": 6,
        "disabled": false,
        "hidden": false
    }
]

Meine Min/Max-Werte kommen direkt aus meiner Netatmo-Wetterstation und ich brauch sie nur noch anzuzeigen. In Node-Red kannst Du im sog. Context Werte persistieren, um mit diesen in Function-Nodes Berechnungen anzustellen. So kannst Du Min/Max selbst kalkulieren, wenn die Fritz-Box das nicht schon macht und diese Werte über seine TR-064 Interface ausgibt. Ein gutes Beispiel für Min/Max Brechung ist das hier.

@bluenazgul
Copy link

Vielen dank @djiwondee

image

Dank deiner Infos konnte ich anhand des Context Beispiels die Anzeige für "Wohnzimmer" bei mir umsetzten, die "Außen" Daten hole ich komplett auch von openweathermap ab.

Hier meine "Innen" Funktion:

[
    {
        "id": "18481f34.1dd671",
        "type": "ui_text",
        "z": "9c440742.57a998",
        "group": "8c211b94.9c2f38",
        "order": 3,
        "width": 2,
        "height": 1,
        "name": "Min Temp Wohnzimmer",
        "label": "▼",
        "format": "{{msg.bounds.min}} °C",
        "layout": "col-center",
        "x": 900,
        "y": 1500,
        "wires": []
    },
    {
        "id": "1aa8e98a.795f46",
        "type": "ui_text",
        "z": "9c440742.57a998",
        "group": "8c211b94.9c2f38",
        "order": 4,
        "width": 2,
        "height": 1,
        "name": "Max Temp Wohnzimmer",
        "label": "▲",
        "format": "{{msg.bounds.max}} °C",
        "layout": "col-center",
        "x": 900,
        "y": 1540,
        "wires": []
    },
    {
        "id": "59c792b6.f5035c",
        "type": "ui_text",
        "z": "9c440742.57a998",
        "group": "8c211b94.9c2f38",
        "order": 1,
        "width": 4,
        "height": 1,
        "name": "Innen",
        "label": "Wohnzimmer",
        "format": "{{msg.payload}} °C",
        "layout": "col-center",
        "x": 840,
        "y": 1460,
        "wires": []
    },
    {
        "id": "54886e30.79e0f",
        "type": "function",
        "z": "9c440742.57a998",
        "name": "Min/Max Werte erstellen",
        "func": "// Create a new empty object 'newMsg' to return at the end\n// then fill it with another empty object 'bounds'\nvar newMsg={bounds:{}}; // create\n\n// Create two local variables min and max initialised from the persistent \n// context variables of the same names where these values exist, or else\n// seed with values we know are off the scale\nvar min=context.get('min') || 100;\nvar max=context.get('max') || -100;\n\n// Set an element 'topic' and give the value the string 'temperature'\nnewMsg.topic = 'temperature';\n// Set the payload element to the incoming message payload temperature\nnewMsg.payload = msg.fritztemp\n\n// update the min and max, comparing the incoming values to the context\nif (msg.fritztemp < min) {\n   newMsg.bounds.min = msg.fritztemp;\n   context.set('min', msg.fritztemp);\n} else {\n   newMsg.bounds.min = min;\n}\nif (msg.fritztemp > max) {\n   newMsg.bounds.max = msg.fritztemp;\n   context.set('max', msg.fritztemp);\n} else {\n   newMsg.bounds.max = max;\n}\n\n// and finally return the new object 'newMsg'\nreturn newMsg;",
        "outputs": 1,
        "noerr": 0,
        "x": 620,
        "y": 1460,
        "wires": [
            [
                "2a052e16.137402",
                "59c792b6.f5035c",
                "18481f34.1dd671",
                "1aa8e98a.795f46"
            ]
        ]
    },
    {
        "id": "7413ecf3.4419c4",
        "type": "link in",
        "z": "9c440742.57a998",
        "name": "Wohnzimmer Temp in",
        "links": [
            "2d722d3a.77d302"
        ],
        "x": 165,
        "y": 1460,
        "wires": [
            [
                "a2915bf9.6cdad8"
            ]
        ]
    },
    {
        "id": "2a052e16.137402",
        "type": "debug",
        "z": "9c440742.57a998",
        "name": "",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "x": 840,
        "y": 1420,
        "wires": []
    },
    {
        "id": "a2915bf9.6cdad8",
        "type": "change",
        "z": "9c440742.57a998",
        "name": "",
        "rules": [
            {
                "t": "move",
                "p": "payload",
                "pt": "msg",
                "to": "fritztemp",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 330,
        "y": 1460,
        "wires": [
            [
                "54886e30.79e0f"
            ]
        ]
    },
    {
        "id": "8c211b94.9c2f38",
        "type": "ui_group",
        "z": "",
        "name": "Wetterstation",
        "tab": "2a75a7ef.66fcb8",
        "order": 1,
        "disp": false,
        "width": "8",
        "collapse": false
    },
    {
        "id": "2a75a7ef.66fcb8",
        "type": "ui_tab",
        "z": "",
        "name": "Wetterstation",
        "icon": "fa-thermometer-half",
        "order": 1,
        "disabled": false,
        "hidden": false
    }
]

Ob und wie gut das ganze funktioniert muss ich erstmal test.

Hab vielen dank für deine Arbeit und Hilfestellung

@SA7BNT
Copy link

SA7BNT commented Apr 17, 2020

Hallo, ich habe irgendwie immer noch das Problem das ich Grad Celsius (Symbol) bei mir nicht angezeigt wird. Woran könnte das liegen??

Mit freundlichen Grüßen
Tim

Bildschirmfoto 2020-04-17 um 08 41 21

@djiwondee
Copy link
Author

Hallo Tim,
das Grad-Symbol ist keine Grafik, sondern ein Zeichen von der Tastatur. Vielleicht ist für Grad Celsius auch kein Platz mehr zur rechten Seite jeder Zahl. Wenn dem so ist, dann empfehle ich die Zahlen auf halbe Grad zu runden.

@SA7BNT
Copy link

SA7BNT commented Apr 17, 2020

Hallo Tim,
das Grad-Symbol ist keine Grafik, sondern ein Zeichen von der Tastatur. Vielleicht ist für Grad Celsius auch kein Platz mehr zur rechten Seite jeder Zahl. Wenn dem so ist, dann empfehle ich die Zahlen auf halbe Grad zu runden.

Hallo djiwondee,
Danke für deine Antwort. Ich habe dem mal mehr space gegeben, doch es scheint nicht daran zu liegen. Hättest du noch eine Idee :(
Bildschirmfoto 2020-04-17 um 09 28 05
Bildschirmfoto 2020-04-17 um 09 31 56

@SA7BNT
Copy link

SA7BNT commented Apr 17, 2020

Hallo Tim,
das Grad-Symbol ist keine Grafik, sondern ein Zeichen von der Tastatur. Vielleicht ist für Grad Celsius auch kein Platz mehr zur rechten Seite jeder Zahl. Wenn dem so ist, dann empfehle ich die Zahlen auf halbe Grad zu runden.

Hallo djiwondee,
Danke für deine Antwort. Ich habe dem mal mehr space gegeben, doch es scheint nicht daran zu liegen. Hättest du noch eine Idee :(
Bildschirmfoto 2020-04-17 um 09 28 05
Bildschirmfoto 2020-04-17 um 09 31 56

@djiwondee
Copy link
Author

Ich habe dem mal mehr space gegeben

wenn Du das gemacht hast und die Rundungsfunktion nutzt, wieso stehen da noch Dezimalzahlen?

So sieht meine Funktion aus

var forecastData = {};

// prepare forecast data for CSS based ui widget

forecastData.payload = {
  row: {
    // time  
  	data01: {
  		cell01: msg.payload[0].dt_txt.substring(11, 13),
  		cell02: msg.payload[1].dt_txt.substring(11, 13),
  		cell03: msg.payload[2].dt_txt.substring(11, 13),
  		cell04: msg.payload[3].dt_txt.substring(11, 13),
  		cell05: msg.payload[4].dt_txt.substring(11, 13),
  		cell06: msg.payload[5].dt_txt.substring(11, 13),
  		cell07: msg.payload[6].dt_txt.substring(11, 13),
  		cell08: msg.payload[7].dt_txt.substring(11, 13)
  	},
  	// temperature
  	data02: {
  		cell01: Math.round(msg.payload[0].main.temp) + " °C",
  		cell02: Math.round(msg.payload[1].main.temp) + " °C",
  		cell03: Math.round(msg.payload[2].main.temp) + " °C",
  		cell04: Math.round(msg.payload[3].main.temp) + " °C",
  		cell05: Math.round(msg.payload[4].main.temp) + " °C",
  		cell06: Math.round(msg.payload[5].main.temp) + " °C",
  		cell07: Math.round(msg.payload[6].main.temp) + " °C",
  		cell08: Math.round(msg.payload[7].main.temp) + " °C"
  	}
  }
}

return forecastData;

Und so mein Display:

image

Da bin ich im Moment überfragt. Browser Cache leeren/Browser Reload? Auf meinem kleinen Raspi stoße ich das aller 20 min mit einem Shell script an:

image

@SA7BNT
Copy link

SA7BNT commented Apr 17, 2020

Ich weis nicht was es war, aber ich habe jetzt mal aus deinem Post denn String eingefügt und damit klappt es jetzt. Allerdings sah meiner nicht wirklich anders aus. Strange.
Jetzt läuft es aber.

Danke für deine Hilfe.

@janoschjg
Copy link

oh man ich habs endlich ich bin einfach nur Dumm... Tippfehler...

Hallo zusammen,
kann mir bitte jemand verraten was genau der Tippfehler war bzw. wie sich das Anzeigen von "blank"-Tabs lösen lässt.
Vielen Dank im Voraus!

@carefulcomputer
Copy link

Hi, I am trying to use this however, css doesn't seem to be loading (given that weather icons from paul reed are already integrated in node-red https://github.com/Paul-Reed/weather-icons-lite ).
I am at Node-red 1.0.5, and I directly imported your flows (and set location, key in appropriate nodes). This is what my dashboard looks like..
image

@djiwondee
Copy link
Author

djiwondee commented May 4, 2020

Hello @qwertangel,

please have first a look on this! It seems that another user had the same problem with the same symptoms as you.

Sorry, missed it is a German response. So please for troubleshooting I would first make the following suggestions:

  • Have you looked in the debug window in Node-red to see if there are any error messages
  • Have you ever docked a debug node to the ui template nodes and looked in the debug window
  • On the Raspi console, enter node-red-log and refresh the web page with the weather station in the browser and then look on the Raspi console to see if an error message is displayed
  • Also the browsers usually offer a web inspector to debug websites. Here you can also see if an error message or warning is displayed.

In addition to that, you may need to adjust your link-rel href-settings in the ui-template node. Please see this example.

@carefulcomputer
Copy link

@djiwondee , thanks for response. Yes I looked at that message (thanks to google translate :-) ). However, these weather icons and css do not need to be installed separately anymore. They are already merged into base node-red (I am on 1.0.5). I spot checked few css classes and they are already defined in .node-red/node_modules/node-red-dashboard/dist/css/app.min.css. So I presume install instruction and path to css/icons need to be updated in your template nodes. I am not that good in dashboard widgets so can't fix it my own. Can you please check ?

@djiwondee
Copy link
Author

Hello @qwertangel,

weather icons and css do not need to be installed separately anymore. They are already merged into base node-red

You are partly right with that. What has been merged into node-red is not the full set of available weather-icons as of available icons. So if you would like to include things like

  • Beaufort Wind Scale
  • Wind Cardinals
  • Night-time
  • Miscellaneous (e. g. sun/moon-rise/-set)

you will probably not being fine with.

@toph86
Copy link

toph86 commented Dec 30, 2021

Hey guys,

i'm new to using node-red on my raspberry pi 4 and working my way through tutorials and excample codes like the one above.
I ran into the same issue as described in german and english:
After deploying the code, the icons are not displayed.
I think the answer is, that not all weather-icons are included in node-red as last writen by djiwondee ...

You are partly right with that. What has been merged into node-red is not the full set of available weather-icons as of available icons. So if you would like to include things like ...

How do install the full set of available weather-icons?
I did try to follow the instructions given here: https://github.com/Paul-Reed/weather-icons but struggle with the installation (probably due to lack of experience).
Are more detailed instructions on how to install this on a raspberry pi with node-red (version 2.1.4) available somewhere?

@kickersdoener: Du standest ja scheinbar vor dem gleichen Problem und hast es gelöst (https://gist.github.com/djiwondee/b5b7d5da14d24e71de447e6aa290937e#gistcomment-2958103).
Kannst du mir evtl. Hilfe beim installieren aller weather-icons geben?

Thanks in advance to all & best regards.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment