Explorar el Código

Adding gauges using svg-gauge

- Had to do a weird include as the package's `package.json` didn't point
  to the correct file.
- Setting colours for gauges based on values to look fancier.
Jason Tarka hace 4 años
padre
commit
d87e6824d0

+ 12 - 1
web-view/package-lock.json

@@ -10,7 +10,8 @@
       "dependencies": {
         "@types/firebase": "^3.2.1",
         "chart.js": "^3.7.0",
-        "firebase": "^9.6.1"
+        "firebase": "^9.6.1",
+        "svg-gauge": "^1.0.6"
       },
       "devDependencies": {
         "@types/mocha": "^9.0.0",
@@ -2872,6 +2873,11 @@
         "url": "https://github.com/chalk/supports-color?sponsor=1"
       }
     },
+    "node_modules/svg-gauge": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/svg-gauge/-/svg-gauge-1.0.6.tgz",
+      "integrity": "sha512-gRkznVhtS18eOM/GMPDXAvrLZOpqzNVDg4bFAPAEjiDKd1tZHFIe8Bwt3G6TFg/H+pFboetPPI+zoV+bOL26QQ=="
+    },
     "node_modules/tapable": {
       "version": "2.2.1",
       "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
@@ -5807,6 +5813,11 @@
         "has-flag": "^4.0.0"
       }
     },
+    "svg-gauge": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/svg-gauge/-/svg-gauge-1.0.6.tgz",
+      "integrity": "sha512-gRkznVhtS18eOM/GMPDXAvrLZOpqzNVDg4bFAPAEjiDKd1tZHFIe8Bwt3G6TFg/H+pFboetPPI+zoV+bOL26QQ=="
+    },
     "tapable": {
       "version": "2.2.1",
       "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",

+ 2 - 1
web-view/package.json

@@ -14,7 +14,8 @@
   "dependencies": {
     "@types/firebase": "^3.2.1",
     "chart.js": "^3.7.0",
-    "firebase": "^9.6.1"
+    "firebase": "^9.6.1",
+    "svg-gauge": "^1.0.6"
   },
   "devDependencies": {
     "@types/mocha": "^9.0.0",

+ 18 - 2
web-view/src/index.html

@@ -4,15 +4,31 @@
 	<meta charset="UTF-8">
 	<title>Weather Station</title>
 	<style>
-		canvas {
+		#time-series-graphs canvas {
 			max-width: 800px;
 			max-height: 200px;
 			display: block;
 		}
+
+		#gauges > div {
+			display: inline-block;
+			width: 200px;
+			height: 200px;
+		}
+
+		/* The unfilled part of a dial */
+		#gauges .gauge > .dial {
+			stroke-width: 3px;
+		}
+
+		/* The filled part of a dial */
+		#gauges .gauge > .value {
+			stroke-width: 7px;
+		}
 	</style>
 </head>
 <body>
-	<div id="guages"></div>
+	<div id="gauges"></div>
 	<div id="time-series-graphs"></div>
 
 	<!--suppress HtmlUnknownTarget -->

+ 58 - 6
web-view/src/js/consts.ts

@@ -3,34 +3,86 @@ export type FieldInfo = {
 	label: string,
 	unit: string,
 	colour: string,
-	canSpike: boolean
+	canSpike: boolean,
+
+	// Used for gauges
+	minValue: number,
+	maxValue: number,
+	gaugeColours: any,
 }
 
+const Colours = {
+	PaleBlue: '#9999FF',
+	Purple: '#6666BB',
+	Blue: '#3333FF',
+	Green: '#33BB33',
+	Yellow: '#bbbb33',
+	Orange: '#FF6600',
+	Red: '#FF2222',
+};
+
 export const FIELDS: FieldInfo[] = [
 	{
 		key: 'temperature',
 		label: 'Temperature',
-		unit: '*C',
+		unit: '°C',
 		colour: 'rgb(255, 0, 0)',
-		canSpike: true
+		canSpike: true,
+		minValue: -10,
+		maxValue: 30,
+		gaugeColours: {
+			'-10': Colours.PaleBlue,
+			0: Colours.Purple,
+			10: Colours.Blue,
+			20: Colours.Green,
+			25: Colours.Yellow,
+			30: Colours.Orange,
+			100: Colours.Red
+		}
 	}, {
 		key: 'humidity',
 		label: 'Relative Humidity',
 		unit: '%',
 		colour: 'rgb(0, 255, 255)',
-		canSpike: false // Affected by temperature, so can spike
+		canSpike: false, // Affected by temperature, so can spike
+		minValue: 0,
+		maxValue: 100,
+		gaugeColours: {
+			20: Colours.Orange,
+			30: Colours.Yellow,
+			60: Colours.Green,
+			80: Colours.Purple,
+			100: Colours.Blue
+		}
 	}, {
 		key: 'pressure',
 		label: 'Air Pressure',
 		unit: 'hPa',
 		colour: 'rgb(0, 255, 0)',
-		canSpike: false
+		canSpike: false,
+		minValue: 975,
+		maxValue: 1030,
+		gaugeColours: {
+			990: Colours.Blue,
+			1000: Colours.PaleBlue,
+			1010: Colours.Yellow,
+			1030: Colours.Green
+		}
 	}, {
 		key: 'light',
 		label: 'Light',
 		unit: '',
 		colour: 'rgb(255, 255, 0)',
-		canSpike: false // Does spike, but it doesn't matter
+		canSpike: false, // Does spike, but it doesn't matter
+		minValue: 0,
+		maxValue: 8191,
+		gaugeColours: {
+			0: Colours.Blue,
+			1000: Colours.PaleBlue,
+			3000: Colours.Orange,
+			5000: Colours.Yellow,
+			10000: Colours.Yellow
+		}
 	},
 ];
 

+ 48 - 0
web-view/src/js/graphs.ts

@@ -4,6 +4,9 @@ import {FieldInfo, FIELDS} from './consts';
 import {formatTime} from './utils';
 Chart.register(...registerables);
 
+// The package's `package.json` file doesn't point to the right place.
+const Gauge = require('../../node_modules/svg-gauge/dist/gauge.js');
+
 const CANVAS_HEIGHT = 100,
 	CANVAS_WIDTH = 200;
 
@@ -67,3 +70,48 @@ function createGraph(
 	};
 	new Chart(canvas, config);
 }
+
+
+export function createGauges(
+	data:Values,
+	parentElement:HTMLElement
+) {
+	for(let field of FIELDS) {
+		let fieldData = data[field.key];
+		let value = fieldData[fieldData.length - 1].value;
+
+		addGauge(
+			field,
+			value,
+			parentElement
+		);
+	}
+}
+
+function addGauge(
+	field:FieldInfo,
+	value:number,
+	parentElement:HTMLElement
+) {
+	const container = document.createElement('div');
+	parentElement.appendChild(container);
+
+	const rangeIncrement = (field.maxValue - field.minValue) * 0.05;
+
+	const config = {
+		max: field.maxValue >= value ? field.maxValue : value + rangeIncrement,
+		min: field.minValue <= value ? field.minValue : value - rangeIncrement,
+		label: v => `${v.toFixed(0)}${field.unit}`,
+		color: v => {
+			let buckets = Object.keys(field.gaugeColours)
+				.sort((a,b) => parseInt(a) - parseInt(b));
+			for(let bucket of buckets) {
+				let num = parseInt(bucket);
+				if(v < num) return field.gaugeColours[num];
+			}
+			return '#FF6600';
+		}
+	};
+
+	Gauge(container, config).setValue(value);
+}

+ 6 - 1
web-view/src/js/main.ts

@@ -4,7 +4,7 @@ import {getDatabase, onValue, orderByChild, query, ref, startAt} from 'firebase/
 
 
 import {Reading} from './types';
-import {createGraphs} from './graphs';
+import {createGauges, createGraphs} from './graphs';
 import {processData} from './processData';
 
 const app = initializeApp(firebaseConfig);
@@ -16,6 +16,11 @@ async function init() {
 	const readings = await getRecentData(12);
 	const values = processData(readings);
 
+	createGauges(
+		values,
+		document.getElementById('gauges')
+	);
+
 	createGraphs(
 		values,
 		document.getElementById('time-series-graphs')