|
"func": "var fcdata = {};\nvar units=flow.get('units');\nif (units===undefined)\n{\n units=\"imperial\";\n}\n\nfunction formatTemp(high, low){\n if (units == \"imperial\") {\n if (low){\n temp = parseFloat(high).toFixed() + '/' + parseFloat(low).toFixed()\n }\n else {\n temp = parseFloat(high).toFixed() + '°F'\n }\n }\n else { // metric\n if (low){\n temp = parseFloat(high).toFixed() + '/' + parseFloat(low).toFixed()\n }\n else {\n temp = parseFloat(high).toFixed() + '°C'\n }\n }\n return temp;\n}\n\nfunction dayName(unixTime){\n var dateObject = new Date(unixTime * 1000);\n return dateObject.toLocaleString(flow.get('lang'), { timezone: msg.payload.timezone, weekday: 'short'});\n // If the line above is not producing the correct short weekday names for the language set by 'lang',\n // you can try upgrading to NodeJS version 13 or higher (when full international support was added for the toLocaleString function),\n // or you can use the code below which is an example for French short weekday names.\n/* \n switch (dateObject.toLocaleString('en', { timezone: msg.payload.timezone, weekday: 'short'})) {\n case 'Mon':\n return 'Lun';\n case 'Tue':\n return 'Mar';\n case 'Wed':\n return 'Mer';\n case 'Thu':\n return 'Jeu';\n case 'Fri':\n return 'Ven';\n case 'Sat':\n return 'Sam';\n case 'Sun':\n return 'Dim';\n }\n*/\n}\n\nfunction timeConvert(UNIX_timestamp){\n var dateObject = new Date(UNIX_timestamp * 1000);\n if (flow.get('hour12')) { // 12 hour time format\n return dateObject.toLocaleString('en', { timezone: msg.payload.timezone, hour12: true, hour: 'numeric'}).toLowerCase();\n } else { // 24 hour time format\n return dateObject.toLocaleString('en', { timezone: msg.payload.timezone, hour12: false, hour: 'numeric'}) + ':00';\n } \n}\n\n// prepare forecast data for CSS based ui widget\nfcdata.payload = {\n rowtext: {\n \tdata01: {\n cell01: timeConvert(msg.payload.hourly[1].dt),\n cell02: timeConvert(msg.payload.hourly[2].dt),\n cell03: timeConvert(msg.payload.hourly[3].dt),\n cell04: timeConvert(msg.payload.hourly[4].dt),\n cell05: timeConvert(msg.payload.hourly[5].dt),\n cell06: timeConvert(msg.payload.hourly[6].dt),\n cell07: dayName(msg.payload.daily[1].dt),\n cell08: dayName(msg.payload.daily[2].dt),\n cell09: dayName(msg.payload.daily[3].dt),\n cell10: dayName(msg.payload.daily[4].dt),\n \t},\n \tdata02: {\n cell01: formatTemp(msg.payload.hourly[1].temp),\n cell02: formatTemp(msg.payload.hourly[2].temp),\n cell03: formatTemp(msg.payload.hourly[3].temp),\n cell04: formatTemp(msg.payload.hourly[4].temp),\n cell05: formatTemp(msg.payload.hourly[5].temp),\n cell06: formatTemp(msg.payload.hourly[6].temp),\n cell07: formatTemp(msg.payload.daily[1].temp.max, msg.payload.daily[0].temp.min),\n cell08: formatTemp(msg.payload.daily[2].temp.max, msg.payload.daily[1].temp.min),\n cell09: formatTemp(msg.payload.daily[3].temp.max, msg.payload.daily[2].temp.min),\n cell10: formatTemp(msg.payload.daily[4].temp.max, msg.payload.daily[3].temp.min),\n \t}\n },\n rowicons: {\n \tdata01: {\n \t\tcell01: msg.payload.hourly[1].weather[0].icon,\n \t\tcell02: msg.payload.hourly[2].weather[0].icon,\n \t\tcell03: msg.payload.hourly[3].weather[0].icon,\n \t\tcell04: msg.payload.hourly[4].weather[0].icon,\n \t\tcell05: msg.payload.hourly[5].weather[0].icon,\n \t\tcell06: msg.payload.hourly[6].weather[0].icon,\n \t\tcell07: msg.payload.daily[1].weather[0].icon,\n \t\tcell08: msg.payload.daily[2].weather[0].icon,\n \t\tcell09: msg.payload.daily[3].weather[0].icon,\n \t\tcell10: msg.payload.daily[4].weather[0].icon,\n \t}\n }\n}\n\nreturn fcdata;", |
|
"func": "var icon = {};\n\nvar units = flow.get('units');\nif (units === undefined) {units = 'imperial';}\n\nfunction timeConvert(UNIX_timestamp){\n var dateObject = new Date(UNIX_timestamp * 1000);\n if (flow.get('hour12')) { // 12 hour time format\n return dateObject.toLocaleString('en', { timezone: msg.payload.timezone, hour12: true, hour: 'numeric', minute: '2-digit'}).toLowerCase();\n } else { // 24 hour time format\n return dateObject.toLocaleString('en', { timezone: msg.payload.timezone, hour12: false, hour: 'numeric', minute: '2-digit'});\n } \n}\n\nvar degreesToCardinal = function(deg){\n if (deg>11.25 && deg<=33.75){return \"NNE\";}\n else if (deg>33.75 && deg<56.25){return \"NE\";}\n else if (deg>56.25 && deg<78.75){return \"ENE\";}\n else if (deg>78.75 && deg<101.25){return \"E\";}\n else if (deg>101.25 && deg<123.75){return \"ESE\";}\n else if (deg>123.75 && deg<146.25){return \"SE\";}\n else if (deg>146.25 && deg<168.75){return \"SSE\";}\n else if (deg>168.75 && deg<191.25){return \"S\";}\n else if (deg>191.25 && deg<213.75){return \"SSW\";}\n else if (deg>213.75 && deg<236.25){return \"SW\";}\n else if (deg>236.25 && deg<258.75){return \"WSW\";}\n else if (deg>258.75 && deg<281.25){return \"W\";}\n else if (deg>281.25 && deg<303.75){return \"WNW\";}\n else if (deg>303.75 && deg<326.25){return \"NW\";}\n else if (deg>326.25 && deg<348.75){return \"NNW\";}\n else {return \"N\";}\n}\n\nif (units == \"imperial\")\n{\n msg.payload.current.temp = msg.payload.current.temp.toFixed() + ' °F';\n msg.payload.current.wind_speed = msg.payload.current.wind_speed.toFixed() + ' mph';\n}\nelse // metric units\n{\n msg.payload.current.temp = msg.payload.current.temp.toFixed(1) + ' °C';\n msg.payload.current.wind_speed = msg.payload.current.wind_speed.toFixed(1) + ' m/s';\n}\n\nmsg.payload.current.wind_cardinal = degreesToCardinal(msg.payload.current.wind_deg);\n\nmsg.payload.current.sunrise = timeConvert(msg.payload.current.sunrise);\nmsg.payload.current.sunset = timeConvert(msg.payload.current.sunset);\n\nvar iconString = 'wi-owm-' + msg.payload.current.weather[0].icon + ' wi-4x';\nicon = {\n ui_control: {\n icon: iconString\n }\n}; \n\nreturn [msg, icon];", |
Great starting point for exactly what I was trying to do. I made a version that keeps to the "standard" 6 wide format and also fixed the timezone_offset issue like @greendog99 above.
[{"id":"14aa820b.13759e","type":"tab","label":"Weather Forecast DB","disabled":false,"info":""},{"id":"436a7a6d.7fd094","type":"ui_button","z":"14aa820b.13759e","name":"IconRefresh","group":"39b889b4.225626","order":1,"width":"2","height":"2","passthru":false,"label":"","tooltip":"Refresh","color":"","bgcolor":"","icon":"wb_sunny","payload":"true","payloadType":"bool","topic":"","x":990,"y":260,"wires":[["a0cd9669.84b7b8"]]},{"id":"42ab669b.a1f428","type":"ui_text","z":"14aa820b.13759e","group":"39b889b4.225626","order":2,"width":"4","height":1,"name":"Description","label":"","format":"{{msg.payload.current.weather[0].description}}","layout":"row-center","x":990,"y":60,"wires":[]},{"id":"8a95e317.1f684","type":"ui_text","z":"14aa820b.13759e","group":"39b889b4.225626","order":4,"width":"2","height":1,"name":"Wind","label":"","format":"{{msg.payload.current.wind_speed}}<i class=\"wi wi-darksky-wind\"></i> {{msg.payload.current.wind_cardinal}}","layout":"col-center","x":970,"y":140,"wires":[]},{"id":"7e40c16d.7e00f","type":"ui_text","z":"14aa820b.13759e","group":"39b889b4.225626","order":5,"width":3,"height":1,"name":"SunriseTime","label":"","format":"<i class=\"wi wi-owm-01d\"></i> <i class=\"fa fa-arrow-up\"></i> {{msg.payload.current.sunrise}}","layout":"row-center","x":990,"y":180,"wires":[]},{"id":"ee785c35.6b901","type":"ui_text","z":"14aa820b.13759e","group":"39b889b4.225626","order":6,"width":3,"height":1,"name":"SunsetTime","label":"","format":"<i class=\"wi wi-wu-sunny\"></i> <i class=\"fa fa-arrow-down\"></i> {{msg.payload.current.sunset}}","layout":"row-center","x":990,"y":220,"wires":[]},{"id":"55b3a58b.c12e3c","type":"comment","z":"14aa820b.13759e","name":"OpenWeatherMap One Call API for Weather and Forecast","info":"","x":270,"y":40,"wires":[]},{"id":"7dfcf78c.f0aa88","type":"ui_template","z":"14aa820b.13759e","group":"39b889b4.225626","name":"Forecast2","order":7,"width":"6","height":"4","format":"<div style=\"height: 100%; justify-content: center; align-items: center;\">\n <div layout=\"rowicons\" layout-align=\"space-around start\" ng-repeat=\"data in msg.payload.rowicons\" style=\"font-size:150%;padding-top: 5px;padding-bottom: 5px\">\n <span flex style=\"color: white;text-align: center\"><i class=\"wi wi-owm-{{data.cell01}}\"></i></span>\n <span flex style=\"color: white;text-align: center\"><i class=\"wi wi-owm-{{data.cell02}}\"></i></span>\n <span flex style=\"color: white;text-align: center\"><i class=\"wi wi-owm-{{data.cell03}}\"></i></span>\n <span flex style=\"color: white;text-align: center\"><i class=\"wi wi-owm-{{data.cell04}}\"></i></span>\n <span flex style=\"color: white;text-align: center\"><i class=\"wi wi-owm-{{data.cell05}}\"></i></span>\n <span flex style=\"color: white;text-align: center\"><i class=\"wi wi-owm-{{data.cell06}}\"></i></span>\n </div>\n <div layout=\"rowtext\" layout-align=\"space-around start\" ng-repeat=\"data in msg.payload.rowtext\" style=\"line-height: 150%\">\n <span flex style=\"color: white;text-align: center;\">{{data.cell01}}</span>\n <span flex style=\"color: white;text-align: center\">{{data.cell02}}</span>\n <span flex style=\"color: white;text-align: center\">{{data.cell03}}</span>\n <span flex style=\"color: white;text-align: center\">{{data.cell04}}</span>\n <span flex style=\"color: white;text-align: center\">{{data.cell05}}</span>\n <span flex style=\"color: white;text-align: center\">{{data.cell06}}</span>\n </div>\n <div layout=\"rowicons\" layout-align=\"space-around start\" ng-repeat=\"data in msg.payload.rowicons\" style=\"font-size:150%;padding-top: 5px;padding-bottom: 5px\">\n <span flex style=\"color: #097479;text-align: center\"><i class=\"wi wi-owm-{{data.cell07}}\"></i></span>\n <span flex style=\"color: #097479;text-align: center\"><i class=\"wi wi-owm-{{data.cell08}}\"></i></span>\n <span flex style=\"color: #097479;text-align: center\"><i class=\"wi wi-owm-{{data.cell09}}\"></i></span>\n <span flex style=\"color: #097479;text-align: center\"><i class=\"wi wi-owm-{{data.cell10}}\"></i></span>\n <span flex style=\"color: #097479;text-align: center\"><i class=\"wi wi-owm-{{data.cell11}}\"></i></span>\n <span flex style=\"color: #097479;text-align: center\"><i class=\"wi wi-owm-{{data.cell12}}\"></i></span>\n </div>\n <div layout=\"rowtext\" layout-align=\"space-around start\" ng-repeat=\"data in msg.payload.rowtext\" style=\"line-height: 150%\">\n <span flex style=\"color: #097479;text-align: center\">{{data.cell07}}</span>\n <span flex style=\"color: #097479;text-align: center\">{{data.cell08}}</span>\n <span flex style=\"color: #097479;text-align: center\">{{data.cell09}}</span>\n <span flex style=\"color: #097479;text-align: center\">{{data.cell10}}</span>\n <span flex style=\"color: #097479;text-align: center\">{{data.cell11}}</span>\n <span flex style=\"color: #097479;text-align: center\">{{data.cell12}}</span>\n </div>\n</div>","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","x":980,"y":320,"wires":[[]]},{"id":"203b7411.c828dc","type":"function","z":"14aa820b.13759e","name":"Format forecast data","func":"var fcdata = {};\nvar units=flow.get('units');\nif (units===undefined)\n{\n units=\"imperial\";\n}\n\nfunction formatTemp(high, low){\n if (units == \"imperial\") {\n if (low){\n temp = parseFloat(high).toFixed() + '/' + parseFloat(low).toFixed()\n }\n else {\n temp = parseFloat(high).toFixed() + '°F'\n }\n }\n else { // metric\n// temp = parseFloat(temp).toFixed(1) + '°C'\n if (low){\n temp = parseFloat(high).toFixed() + '/' + parseFloat(low).toFixed()\n }\n else {\n temp = parseFloat(high).toFixed() + '°C'\n }\n }\n return temp;\n}\nfunction dayName(unixTime){\n var d = new Date(unixTime * 1000);\n var weekday = new Array(7);\n weekday[0] = \"Sun\";\n weekday[1] = \"Mon\";\n weekday[2] = \"Tue\";\n weekday[3] = \"Wed\";\n weekday[4] = \"Thu\";\n weekday[5] = \"Fri\";\n weekday[6] = \"Sat\";\n\n return weekday[d.getDay()]\n}\nfunction timeConvert(UNIX_timestamp){\n UNIX_timestamp = UNIX_timestamp + msg.payload.timezone_offset;\n var a = new Date(UNIX_timestamp * 1000);\n var hour = a.getHours();\n var suffix = \" am\";\n if (hour >= 12) {\n hour = hour - 12;\n suffix = \" pm\";\n }\n if (hour === 0) {\n hour = 12;\n }\n var min = a.getMinutes();\n if (min < 10) {min = \"0\" + min;}\n// return hour + ':' + min + suffix;\n return hour + suffix;\n}\n// prepare forecast data for CSS based ui widget\n\nfcdata.payload = {\n rowtext: {\n \tdata01: {\n cell01: timeConvert(msg.payload.hourly[1].dt),\n cell02: timeConvert(msg.payload.hourly[2].dt),\n cell03: timeConvert(msg.payload.hourly[3].dt),\n cell04: timeConvert(msg.payload.hourly[4].dt),\n cell05: timeConvert(msg.payload.hourly[5].dt),\n cell06: timeConvert(msg.payload.hourly[6].dt),\n cell07: dayName(msg.payload.daily[1].dt),\n cell08: dayName(msg.payload.daily[2].dt),\n cell09: dayName(msg.payload.daily[3].dt),\n cell10: dayName(msg.payload.daily[4].dt),\n cell11: dayName(msg.payload.daily[5].dt),\n cell12: dayName(msg.payload.daily[6].dt),\n \t},\n \tdata02: {\n cell01: formatTemp(msg.payload.hourly[1].temp),\n cell02: formatTemp(msg.payload.hourly[2].temp),\n cell03: formatTemp(msg.payload.hourly[3].temp),\n cell04: formatTemp(msg.payload.hourly[4].temp),\n cell05: formatTemp(msg.payload.hourly[5].temp),\n cell06: formatTemp(msg.payload.hourly[6].temp),\n cell07: formatTemp(msg.payload.daily[1].temp.max, msg.payload.daily[0].temp.min),\n cell08: formatTemp(msg.payload.daily[2].temp.max, msg.payload.daily[1].temp.min),\n cell09: formatTemp(msg.payload.daily[3].temp.max, msg.payload.daily[2].temp.min),\n cell10: formatTemp(msg.payload.daily[4].temp.max, msg.payload.daily[3].temp.min),\n cell11: formatTemp(msg.payload.daily[5].temp.max, msg.payload.daily[4].temp.min),\n cell12: formatTemp(msg.payload.daily[6].temp.max, msg.payload.daily[5].temp.min),\n \t}\n },\n rowicons: {\n \tdata01: {\n \t\tcell01: msg.payload.hourly[1].weather[0].icon,\n \t\tcell02: msg.payload.hourly[2].weather[0].icon,\n \t\tcell03: msg.payload.hourly[3].weather[0].icon,\n \t\tcell04: msg.payload.hourly[4].weather[0].icon,\n \t\tcell05: msg.payload.hourly[5].weather[0].icon,\n \t\tcell06: msg.payload.hourly[6].weather[0].icon,\n \t\tcell07: msg.payload.daily[1].weather[0].icon,\n \t\tcell08: msg.payload.daily[2].weather[0].icon,\n \t\tcell09: msg.payload.daily[3].weather[0].icon,\n \t\tcell10: msg.payload.daily[4].weather[0].icon,\n \t\tcell11: msg.payload.daily[5].weather[0].icon,\n \t\tcell12: msg.payload.daily[6].weather[0].icon,\n \t}\n }\n}\n\nreturn fcdata;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":760,"y":320,"wires":[["7dfcf78c.f0aa88"]]},{"id":"ba5abfcf.7fcab","type":"ui_text","z":"14aa820b.13759e","group":"39b889b4.225626","order":3,"width":"2","height":1,"name":"Temperature","label":"","format":"<p style=\"font-size: 200%\">{{msg.payload.current.temp}}</p>","layout":"row-center","x":990,"y":100,"wires":[]},{"id":"7d3441cf.2e59d","type":"http request","z":"14aa820b.13759e","name":"Get OWM data","method":"GET","ret":"obj","paytoqs":true,"url":"https://api.openweathermap.org/data/2.5/onecall","tls":"","persist":false,"proxy":"","authType":"","x":480,"y":160,"wires":[["ebe09ce0.f4949","203b7411.c828dc"]]},{"id":"e6a4aa43.adcb28","type":"inject","z":"14aa820b.13759e","name":"Trigger","repeat":"600","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":120,"y":100,"wires":[["1715e035.8c8a3"]]},{"id":"ebe09ce0.f4949","type":"function","z":"14aa820b.13759e","name":"Format current data","func":"var icon = {};\n\nvar units=flow.get('units');\nif (units===undefined)\n{\n units=\"imperial\";\n}\n\nfunction timeConvert(UNIX_timestamp){\n UNIX_timestamp = UNIX_timestamp + msg.payload.timezone_offset;\n var a = new Date(UNIX_timestamp * 1000);\n var hour = a.getHours();\n var suffix = \" am\";\n if (hour >= 12) {\n hour = hour - 12;\n suffix = \" pm\";\n }\n if (hour === 0) {\n hour = 12;\n }\n var min = a.getMinutes();\n if (min < 10) {min = \"0\" + min;}\n return hour + ':' + min + suffix;\n}\n\nvar degreesToCardinal = function(deg){\nif (deg>11.25 && deg<=33.75){\nreturn \"NNE\";\n }else if (deg>33.75 && deg<56.25){\nreturn \"NE\";\n }else if (deg>56.25 && deg<78.75){\nreturn \"ENE\";\n }else if (deg>78.75 && deg<101.25){\nreturn \"E\";\n }else if (deg>101.25 && deg<123.75){\nreturn \"ESE\";\n }else if (deg>123.75 && deg<146.25){\nreturn \"SE\";\n }else if (deg>146.25 && deg<168.75){\nreturn \"SSE\";\n }else if (deg>168.75 && deg<191.25){\nreturn \"S\";\n }else if (deg>191.25 && deg<213.75){\nreturn \"SSW\";\n }else if (deg>213.75 && deg<236.25){\nreturn \"SW\";\n }else if (deg>236.25 && deg<258.75){\nreturn \"WSW\";\n }else if (deg>258.75 && deg<281.25){\nreturn \"W\";\n }else if (deg>281.25 && deg<303.75){\nreturn \"WNW\";\n }else if (deg>303.75 && deg<326.25){\nreturn \"NW\";\n }else if (deg>326.25 && deg<348.75){\nreturn \"NNW\";\n }else{\nreturn \"N\"; \n }\n}\n\nif (units == \"imperial\")\n{\n msg.payload.current.temp = msg.payload.current.temp.toFixed() + ' °F';\n msg.payload.current.wind_speed = msg.payload.current.wind_speed.toFixed() + ' mph';\n}\nelse // metric units\n{\n msg.payload.current.temp = msg.payload.current.temp.toFixed(1) + ' °C';\n msg.payload.current.wind_speed = msg.payload.current.wind_speed.toFixed(1) + ' m/s';\n}\n\nmsg.payload.current.wind_cardinal = degreesToCardinal(msg.payload.current.wind_deg);\nmsg.payload.current.sunrise = timeConvert(msg.payload.current.sunrise);\nmsg.payload.current.sunset = timeConvert(msg.payload.current.sunset);\n\nvar iconString = 'wi-owm-' + msg.payload.current.weather[0].icon + ' wi-4x';\nicon = {\n ui_control: {\n icon: iconString\n }\n}; \n\nreturn [msg, icon];","outputs":2,"noerr":0,"initialize":"","finalize":"","x":720,"y":160,"wires":[["ba5abfcf.7fcab","8a95e317.1f684","42ab669b.a1f428","7e40c16d.7e00f","ee785c35.6b901"],["436a7a6d.7fd094"]]},{"id":"1715e035.8c8a3","type":"change","z":"14aa820b.13759e","name":"Set location, appid, units","rules":[{"t":"delete","p":"payload","pt":"msg"},{"t":"set","p":"payload.lat","pt":"msg","to":"28.106022","tot":"str"},{"t":"set","p":"payload.lon","pt":"msg","to":"-80.625024","tot":"str"},{"t":"set","p":"payload.appid","pt":"msg","to":"dfc6c3b831db8c482e72540e382d6485","tot":"str"},{"t":"set","p":"payload.units","pt":"msg","to":"imperial","tot":"str"},{"t":"set","p":"units","pt":"flow","to":"payload.units","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":100,"wires":[["7d3441cf.2e59d"]]},{"id":"834afeff.fcada","type":"ui_ui_control","z":"14aa820b.13759e","name":"Update tab","events":"all","x":110,"y":200,"wires":[["5939ef89.2e00e"]]},{"id":"a0cd9669.84b7b8","type":"link out","z":"14aa820b.13759e","name":"Refresh","links":["3db7aa3d.23eed6"],"x":1115,"y":260,"wires":[]},{"id":"3db7aa3d.23eed6","type":"link in","z":"14aa820b.13759e","name":"","links":["a0cd9669.84b7b8"],"x":155,"y":140,"wires":[["1715e035.8c8a3"]]},{"id":"5939ef89.2e00e","type":"switch","z":"14aa820b.13759e","name":"tab focus","property":"tab","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":280,"y":200,"wires":[["1715e035.8c8a3"]]},{"id":"39b889b4.225626","type":"ui_group","z":"","name":"Weather Forecast","tab":"b6ff010e.c244c","order":1,"disp":true,"width":"6","collapse":false},{"id":"b6ff010e.c244c","type":"ui_tab","z":"","name":"Home","icon":"home","order":1,"disabled":false,"hidden":false}]