SondeHub Listeners
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>SondeHub Station Statistics</title>
<meta name="description" content="Live graph showing breakdown of programs and versions contributing telemetry to the SondeHub database." />
<meta name="author" content="Luke Prior" />
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1, maximum-scale=1" />
<script type="text/javascript" language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.0/chart.js"></script>
</head>
<body>
<div id="container">
<canvas id="chartJSContainer" style="display: none;"></canvas>
<div id="loadingGif" style="display: block;">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="margin: auto; background: rgb(255, 255, 255, 0); display: block; shape-rendering: auto;" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid">
<circle cx="50" cy="50" r="32" stroke-width="8" stroke="#00a3d3" stroke-dasharray="50.26548245743669 50.26548245743669" fill="none" stroke-linecap="round">
<animateTransform attributeName="transform" type="rotate" repeatCount="indefinite" dur="1s" keyTimes="0;1" values="0 50 50;360 50 50"></animateTransform>
</circle>
</svg>
</div>
<div>
<button id="update" class="button">MODE</button>
<button id="hide" class="button">VERSIONS</button>
</div>
</div>
</body>
</html>
CSS
.button {
background-color: white;
color: black;
padding: 6px 8px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 10px;
margin: 3px 2px;
transition-duration: 0.4s;
cursor: pointer;
border: 2px solid #555555;
}
.button:hover {
background-color: #555555;
color: white;
}
#container {
width: 100%;
max-width: 90vh;
right: 50%;
bottom: 50%;
transform: translateX(50%) translateY(50%);
position: absolute;
}
JavaScript
var count = [];
var countNested = [];
var countUnique = [];
var countNestedUnique = [];
var empty = [];
var countSelected = true;
var nestedSelected = false;
var stationCount = '';
var programs = [];
var versions = [];
var versionPrograms = [];
var colours = ['#e41a1c', '#377eb8', '#4daf4a', '#984ea3', '#ff7f00', '#ffff33', '#a65628', '#f781bf', '#999999'];
var excluded = ['Sonde Tracker', 'TTGO EMA DTCEA', 'TTGO WX'];
var visibility = {};
var getJSON = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'json';
xhr.onload = function() {
var status = xhr.status;
if (status === 200) {
callback(null, xhr.response);
} else {
callback(status, xhr.response);
}
};
xhr.send();
};
function resizeArray(array, size) {
var dataNew = [];
var sum = array.reduce((a, b) => a + b);
array.forEach(function(item, index) {
var rounded = Math.round(item / sum * size);
dataNew.push(rounded);
});
var difference = dataNew.reduce((a, b) => a + b) - size;
dataNew[0] = dataNew[0] - difference;
return dataNew;
}
const countPlugin = {
id: 'doughnut-centertext',
beforeDraw: function(chart) {
if (chart.config.options.elements.center) {
// Get ctx from string
var ctx = chart.ctx;
var innerRadius = chart._metasets[chart._metasets.length - 2].controller.innerRadius;
if (chart._metasets[chart._metasets.length - 1].controller.innerRadius > 0) {
innerRadius = chart._metasets[chart._metasets.length - 1].controller.innerRadius;
}
// Get options from the center object in options
var centerConfig = chart.config.options.elements.center;
var fontStyle = centerConfig.fontStyle || 'Arial';
var txt = centerConfig.text;
var color = centerConfig.color || '#000';
var maxFontSize = centerConfig.maxFontSize || 75;
var sidePadding = centerConfig.sidePadding || 20;
var sidePaddingCalculated =...