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"
}
]
@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