diff --git a/gauge-group.html b/gauge-group.html
new file mode 100644
index 0000000..c62ccda
--- /dev/null
+++ b/gauge-group.html
@@ -0,0 +1,93 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/gauge-group.js b/gauge-group.js
new file mode 100644
index 0000000..99b303a
--- /dev/null
+++ b/gauge-group.js
@@ -0,0 +1,132 @@
+var path = require('path');
+
+module.exports = function (RED) {
+ var counter = 0;
+ function ButtonGroupNode(config) {
+ const iid = ++counter;
+ var ui = undefined;
+ try {
+ var node = this;
+ if (ui === undefined) {
+ ui = RED.require("node-red-dashboard")(RED);
+ }
+ RED.nodes.createNode(this, config);
+
+ var sizes = ui.getSizes();
+
+ var widthPx = (config.gaugewidth * sizes.sx) - (sizes.gx * 2);
+
+ var heightPx = (config.gaugeheight * sizes.sy) - (sizes.gy * 2);
+
+ var html = `
+
+
+ `;
+
+ var done = ui.addWidget({
+ node: node,
+ order: config.order,
+ group: config.group,
+ width: config.width,
+ height: config.height,
+ format: html,
+ templateScope: 'local',
+ emitOnlyNewValues: false,
+ forwardInputMessages: false,
+ storeFrontEndInputAsState: false,
+ convertBack: function (value) {
+ return value;
+ },
+ beforeEmit: function (msg, value) {
+ return { msg: { iid: iid, width: widthPx, height: heightPx, marginX: sizes.gx, marginY: sizes.gy, gauges: value, socketid: msg.socketid } };
+ },
+ initController: function ($scope, events) {
+ let gauges = [];
+ const opts = {
+ angle: 0, // The span of the gauge arc
+ lineWidth: 0.4, // The line thickness
+ radiusScale: 1, // Relative radius
+ pointer: {
+ length: 0.6, // // Relative to gauge radius
+ strokeWidth: 0.07, // The thickness
+ color: '#000000' // Fill color
+ },
+ limitMax: true, // If false, max value increases automatically if value > maxValue
+ limitMin: true, // If true, the min value of the gauge will be fixed
+ colorStart: '#6FADCF', // Colors
+ colorStop: '#8FC0DA', // just experiment with them
+ strokeColor: '#E0E0E0', // to see which ones work best for you
+ generateGradient: true,
+ highDpiSupport: true, // High resolution support
+ percentColors: undefined,
+ };
+
+ $scope.$watch('msg', function (msg) {
+ if (!msg) {
+ return;
+ }
+ var target = $(`#gauge-${msg.iid}`);
+
+ if (gauges.length < msg.gauges.length) {
+ const difference = msg.gauges.length - gauges.length;
+ for (let i = 0; i < difference; i++) {
+ const obj = {
+ canvas: undefined,
+ gauge: undefined,
+ label: undefined
+ }
+ const canvasId = `gauge-${msg.iid}-${i}-canvas`;
+ const labelId = `gauge-${msg.iid}-${i}-label`;
+ target.append(`
+
+ `);
+
+ obj.canvas = $(`#${canvasId}`)[0];
+ obj.label = $(`#${labelId}`)[0];
+
+ let modifiedOpts = Object.assign({}, opts);
+
+ modifiedOpts.percentColors = msg.gauges[i].smoothColors;
+
+ obj.gauge = new Gauge(obj.canvas).setOptions(modifiedOpts);
+ obj.gauge.setMinValue(0);
+
+ gauges.push(obj);
+ }
+ } else if (gauges.length > msg.gauges.length) {
+ const difference = gauges.length - msg.gauges.length;
+ for (let i = 0; i < difference; i++) {
+ const obj = gauges.pop();
+ obj.canvas.remove();
+ }
+ }
+
+ for (let i = 0; i < gauges.length; i++) {
+ gauges[i].gauge.maxValue = msg.gauges[i].max;
+ gauges[i].gauge.set(msg.gauges[i].value);
+ gauges[i].label.innerHTML = msg.gauges[i].label;
+ }
+ });
+ }
+ });
+ } catch (e) {
+ console.log(e)
+ }
+ node.on('close', done);
+ }
+ RED.nodes.registerType("ui_gauge_group", ButtonGroupNode);
+
+ var uipath = 'ui';
+ if (RED.settings.ui) { uipath = RED.settings.ui.path; }
+ var fullPath = path.join('/', uipath, '/ui-gauge-group/*').replace(/\\/g, '/');
+ RED.httpNode.get(fullPath, function (req, res) {
+ var options = {
+ root: __dirname + '/lib/',
+ dotfiles: 'deny'
+ };
+ res.sendFile(req.params[0], options)
+ });
+}
\ No newline at end of file
diff --git a/lib/gauge.min.js b/lib/gauge.min.js
new file mode 100644
index 0000000..1b77c1c
--- /dev/null
+++ b/lib/gauge.min.js
@@ -0,0 +1 @@
+(function(){function t(t,i){for(var e in i)m.call(i,e)&&(t[e]=i[e]);function s(){this.constructor=t}return s.prototype=i.prototype,t.prototype=new s,t.__super__=i.prototype,t}var i,e,s,n,o,p,a,h,r,l,g,c,u,d=[].slice,m={}.hasOwnProperty,x=[].indexOf||function(t){for(var i=0,e=this.length;ithis.gp.length)for(e=n=0,r=t.length-this.gp.length;0<=r?nthis.maxValue?this.options.limitMax?l=this.maxValue:this.maxValue=l+1:l=this.minValue)&&(!this.options.limitMax||d<=this.maxValue)&&(r=(n=d.font||t.font).match(l)[0],c=n.slice(r.length),o=parseFloat(r)*this.displayScale,this.ctx.font=o+c,u=this.getAngle(d.label)-3*Math.PI/2,this.ctx.rotate(u),this.ctx.fillText(g(d.label,t.fractionDigits),0,-s-this.lineWidth/2),this.ctx.rotate(-u)):(!this.options.limitMin||d>=this.minValue)&&(!this.options.limitMax||d<=this.maxValue)&&(u=this.getAngle(d)-3*Math.PI/2,this.ctx.rotate(u),this.ctx.fillText(g(d,t.fractionDigits),0,-s-this.lineWidth/2),this.ctx.rotate(-u));return this.ctx.restore()},M.prototype.renderTicks=function(t,i,e,s){var n,o,a,h,r,l,p,c,u,d,g,m,x,f,v,y,V,w,S,M;if(t!=={}){for(l=t.divisions||0,w=t.subDivisions||0,a=t.divColor||"#fff",f=t.subColor||"#fff",h=t.divLength||.7,y=t.subLength||.2,u=parseFloat(this.maxValue)-parseFloat(this.minValue),d=parseFloat(u)/parseFloat(t.divisions),v=parseFloat(d)/parseFloat(t.subDivisions),n=parseFloat(this.minValue),o=0+v,r=(c=u/400)*(t.divWidth||1),V=c*(t.subWidth||1),m=[],S=p=0,g=l+1;pthis.maxValue&&(h=this.maxValue),d=this.radius*this.options.radiusScale,m.height&&(this.ctx.lineWidth=this.lineWidth*m.height,u=this.lineWidth/2*(m.offset||1-m.height),d=this.radius*this.options.radiusScale+u),this.ctx.strokeStyle=m.strokeStyle,this.ctx.beginPath(),this.ctx.arc(0,0,d,this.getAngle(r),this.getAngle(h),!1),this.ctx.stroke();else void 0!==this.options.customFillStyle?i=this.options.customFillStyle(this):null!==this.percentColors?i=this.getColorForValue(this.displayedValue,this.options.generateGradient):void 0!==this.options.colorStop?((i=0===this.options.gradientType?this.ctx.createRadialGradient(g,e,9,g,e,70):this.ctx.createLinearGradient(0,0,g,0)).addColorStop(0,this.options.colorStart),i.addColorStop(1,this.options.colorStop)):i=this.options.colorStart,this.ctx.strokeStyle=i,this.ctx.beginPath(),this.ctx.arc(g,e,l,(1+this.options.angle)*Math.PI,t,!1),this.ctx.lineWidth=this.lineWidth,this.ctx.stroke(),this.ctx.strokeStyle=this.options.strokeColor,this.ctx.beginPath(),this.ctx.arc(g,e,l,t,(2-this.options.angle)*Math.PI,!1),this.ctx.stroke(),this.ctx.save(),this.ctx.translate(g,e);for(this.options.renderTicks&&this.renderTicks(this.options.renderTicks,g,e,l),this.ctx.restore(),this.ctx.translate(g,e),n=0,a=(c=this.gp).length;nthis.maxValue?this.options.limitMax?this.value=this.maxValue:this.maxValue=this.value:this.value