Skip to content

Instantly share code, notes, and snippets.

@PaulWieland
Last active October 10, 2024 19:13
Show Gist options
  • Save PaulWieland/b9a57175ac5a5e240c9916bcce136dca to your computer and use it in GitHub Desktop.
Save PaulWieland/b9a57175ac5a5e240c9916bcce136dca to your computer and use it in GitHub Desktop.
Wind Gauge with Compass

This is a dashboard widget for displaying wind speed and direction in one gauge.

The gauge takes three inputs from msg.payload:

  1. speed (number)
  2. speed_unit (string) - Any string you want displayed after the speed, e.g. MPH, KMH, KTS, etc
  3. degrees (0-360 to for compass direction)

An example input node is included. You can replace it with your own data source (e.g. wunderground PWS)

Tested on Safari & Chrome (sorry, I have no access to IE or Edge).

[
{
"id": "409af0a5.b6e3e8",
"type": "inject",
"z": "ed02aad4.a669c8",
"name": "",
"repeat": "2",
"crontab": "",
"once": true,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 150,
"y": 1120,
"wires": [
[
"d12411f0.075428"
]
]
},
{
"id": "a3654026.abf898",
"type": "ui_template",
"z": "ed02aad4.a669c8",
"group": "64704468.613964",
"name": "Wind",
"order": 1,
"width": "4",
"height": "4",
"format": "<!--\npass msg.payload.degrees, msg.payload.speed, msg.payload.speed_unit\n-->\n<script>\n // Watch the incoming message and convert the degrees to a human readable compass direction\n (function(scope){\n scope.$watch('msg', function(msg) {\n if(typeof(msg) === \"object\"){\n // Convert the degrees to cardinal directions\n var deg = msg.payload.degrees;\n var dirs = [\"N\",\"NNE\",\"NE\",\"ENE\",\"E\",\"ESE\",\"SE\",\"SSE\",\"S\",\"SSW\",\"SW\",\"WSW\",\"W\",\"WNW\",\"NW\",\"NNW\",\"N\"];\n var idx = Math.round(deg*(dirs.length-1)/360);\n scope.direction = dirs[idx];\n \n \n // Keep track of the highest speed value, giving it 40 as a rough starting point.\n // Works okay for MPH and KTS, but KMH will show purple at a lower speed than the rest\n scope.max_val = (msg.payload.speed > scope.max_val ? msg.payload.speed : 40);\n \n scope.p_speed = msg.payload.speed;\n scope.p_max_val = scope.max_val;\n var low_colors = [\n '#FFFFFF', // white\n '#d6f7ff', // light blue\n '#85ffd2', // blue green\n '#61ff6e' // green 10mph\n ];\n var high_colors = [\n '#61ff6e', // green 10mph\n '#d5ff61', // green yellow\n '#fffc61', // yellow\n '#ffe561', // yellow orange 20mph\n '#ffcd61', // orange\n '#ffad61', // orange red\n '#ff7661', // red\n '#ff61dd', // red purple\n '#e261ff' // purple\n ];\n \n if(msg.payload.speed <= 10){\n scope.color = low_colors[Math.round(msg.payload.speed*(low_colors.length-1)/10)];\n }else{\n scope.color = high_colors[Math.round(msg.payload.speed*(high_colors.length-1) / scope.max_val)];\n }\n \n //$(\".compass_container\").css(\"background-color\",scope.color);\n }\n \t});\n })(scope);\n \n // Hacks to improve the layout and make it scale\n $(document).ready(function(){\n setTimeout(function () {\n // Remove the auto scrolling from the parent node\n $(\".compass_container\").parent().css(\"overflow\",\"hidden\");\n \n // Adjust the color to match the theme base color by looking up the toolbar header background color;\n $(\".compass_container .triangle\").css(\"border-bottom-color\",$(\"md-toolbar\").css(\"background-color\"));\n \n // Scale the compass into the box that it's being rendered in\n // This CSS hack helps make sure the line & font size scales appropriately\n // Based on the node's grid size\n $(\".compass_container\").each(function(k,v){\n var scaleWidth = $(v).parent().width() / $(v).width();\n var scaleHeight = $(v).parent().height() / $(v).height();\n \n var translateX = ($(v).width() - $(v).parent().width()) / 2;\n var translateY = ($(v).height() - $(v).parent().height()) / 2;\n \n $(v).css(\"transform\",\"translate(-\"+translateX+\"px,-\"+translateY+\"px) scale(\"+scaleWidth+\",\"+scaleHeight+\") \");\n });\n \n $(\".compass_container\").css(\"display\",\"block\"); // Unhide it now that it's resized\n }, 1000);\n });\n</script>\n<style>\n @import url(https://fonts.googleapis.com/css?family=Dosis:200,400,500,600);\n \n .compass_container{\n transition: 1s ease-in-out;\n position: relative;\n display: none;\n width: 500px;\n height: 500px;\n flex-shrink:0;\n border-radius: 100%;\n font-family: 'Dosis';\n font-size: 80px;\n box-shadow: inset 0px 0px 0px 30px #777; \n background-color: {{color}};\n }\n \n .compass_container .compass_header{\n font-weight: bold;\n position: absolute;\n text-align: center;\n width: 100%;\n font-size: 75%;\n top: -15px\n }\n .compass_container .text_container{\n height: 100%;\n width: 100%;\n padding: 0px;\n display: block;\n border-radius: 100%;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n }\n \n .compass_container .arrow{\n transition: 1s ease-in-out;\n width: 100%;\n height: 100%;\n display: block;\n position: absolute;\n top: 0;\n }\n \n .compass_container .arrow .triangle{\n width: 0;\n\t\theight: 0;\n\t\tborder-left: 45px solid transparent;\n\t\tborder-right: 45px solid transparent;\n\t\tborder-bottom: 90px solid black;\n\t\tposition: absolute;\n\t\ttop: -15px;\n\t\tleft: 50%;\n\t\tmargin-left: -45px;\n\t\tz-index: 99;\n }\n</style>\n\n<div class=\"compass_container\" style=\"\">\n <div class=\"compass_header\">N</div>\n \n <div class=\"nr-dashboard-text text_container\">\n \n <div class=\"direction\" style=\"font-size: 120%\">{{direction}}</div>\n <div style=\"flex-direction: row; font-weight: bold;\">\n <span style=\"font-size: 100%\">{{msg.payload.speed}}</span>\n <span style=\"font-size: 75%\">{{msg.payload.speed_unit}}</span>\n </div>\n </div>\n <div class=\"arrow\" style=\"transform: rotate({{msg.payload.degrees}}deg);\">\n <div class=\"triangle\"></div>\n </div>\n</div>",
"storeOutMessages": true,
"fwdInMessages": true,
"resendOnRefresh": false,
"templateScope": "local",
"x": 450,
"y": 1120,
"wires": [
[]
]
},
{
"id": "d12411f0.075428",
"type": "function",
"z": "ed02aad4.a669c8",
"name": "",
"func": "var msg = {\n \"payload\": {\n \"speed\":Math.round(Math.random() * 60),\n \"speed_unit\":\"MPH\",\n \"degrees\":Math.round(Math.random() * 360)\n \n }\n}\nreturn msg;",
"outputs": 1,
"noerr": 0,
"x": 310,
"y": 1120,
"wires": [
[
"a3654026.abf898"
]
]
},
{
"id": "64704468.613964",
"type": "ui_group",
"name": "Default Group",
"tab": "ef22f042.de6a1",
"order": 1,
"disp": true,
"width": "9"
},
{
"id": "ef22f042.de6a1",
"type": "ui_tab",
"name": "Home Tab",
"icon": "dashboard"
}
]
@PaulWieland
Copy link
Author

@RicharddeCrep You're right. The arrow is in the right place on the circle (north wind has the arrow at the top) but the point on the triangle is backward (it should point down, and it points up instead). It wasn't originally like this, somewhere along the line I screwed it up.

Will issue an update to the gist as soon as I have time.

@Nicehavetoo
Copy link

Thank you for sharing this awesome gauge. I modified it a bit to show the direction of my next waypoint.
image
Only I like to change the letter N that indicates north. How can I modify this "N"?
The way I am using the gauge is; I got my heading is up and the arrow points at my waypoint.
I'd like to change the "N" to the value of my heading.

@chuckf201
Copy link

Has this great node been updated to dashboard 2.0?
and
can it be resized to minimize area? I tried this several years ago and the compass became deformed.

@rboeije1
Copy link

rboeije1 commented Oct 8, 2024

I have dashboard version 3.4.0 running on node-red v3.02 if that is what you mean. And I am using this for wind direction.

@rboeije1
Copy link

rboeije1 commented Oct 8, 2024

image
I edited the source a tiny bit, so the N is as high as the band.

@chuckf201
Copy link

Excellent. Will try as soon as I get past this huricane stuff.

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