From 590d274d2d02e41e6e4d2a6013cf4854eb9d07e8 Mon Sep 17 00:00:00 2001 From: Anton Roslund Date: Sun, 21 Sep 2025 22:33:53 +0200 Subject: [PATCH] Add transition status --- .../blog/2025-09-19-switch-to-mediumfast.md | 20 +++ static/js/status/transition-status-gauge.js | 140 ++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 static/js/status/transition-status-gauge.js diff --git a/content/sv/blog/2025-09-19-switch-to-mediumfast.md b/content/sv/blog/2025-09-19-switch-to-mediumfast.md index d43a2ef..cc70953 100644 --- a/content/sv/blog/2025-09-19-switch-to-mediumfast.md +++ b/content/sv/blog/2025-09-19-switch-to-mediumfast.md @@ -10,6 +10,7 @@ För att få ett stabilare mesh där vi har möjlighet att fortsätta växa komm - **Bättre batteritid**: Särskilt viktigt för solcellsdrivna noder - **Högre nodkapacitet**: Plats för fler noder i nätverket + Bilden nedan visar hur en övergång till MediumFast påverkar förbindelser i meshen. I praktiken förväntar vi oss ännu bättre resultat då risken för kollisioner minskar. Bilden är baserad på data från traceroutes och är inte heltäckande. {{< image-compare left="/images/blog/2025-09-19-switch-to-mediumfast-lf.png" right="/images/blog/2025-09-19-switch-to-mediumfast-mf.png" left-alt="LongFast anslutningar" right-alt="MediumFast anslutningar" caption="Jämförelse mellan LongFast (vänster) och MediumFast (höger) anslutningar i Stockholm mesh. Dra reglaget för att se skillnaden." >}} @@ -17,6 +18,20 @@ Bilden nedan visar hur en övergång till MediumFast påverkar förbindelser i m ### Meetup Vi planerar även att köra en meetup den 1:a oktober för att utvärdera övergången till MediumFast. Förhoppningsvis kan vi fira och fokusera på hur meshet blir ännu bättre i framtiden. Mer info kommer. +### Övergångsstatus till MediumFast +Denna mätare visar hur många noder som har växlat till MediumFast-kanalen av det totala antalet noder som hörts idag. + +
+
+
+
+ +
+
+
+
+ + ### Mer teknisk information För fler tekniska detaljer om MediumFast, läs Meshtastics officiella artikel: [Why Your Mesh Should Switch From LongFast](https://meshtastic.org/blog/why-your-mesh-should-switch-from-longfast/) @@ -59,3 +74,8 @@ Stockholm följer trenden. Flertalet andra stora europeiska mesh-nätverk har by Det finns säkert fler som vi inte känner till. Har du koll på andra städer i Europa som har bytt, meddela oss på Discord. + + + + + \ No newline at end of file diff --git a/static/js/status/transition-status-gauge.js b/static/js/status/transition-status-gauge.js new file mode 100644 index 0000000..81f9a92 --- /dev/null +++ b/static/js/status/transition-status-gauge.js @@ -0,0 +1,140 @@ +async function transitionStatusGauge() { + try { + await fetchNodes(); + createTransitionGauge(); + } catch (err) { + console.error('Error creating transition status gauge:', err); + showTransitionGaugeError(); + } +} + +async function createTransitionGauge() { + const canvas = document.getElementById('transitionGauge'); + if (!canvas) { + console.warn('Canvas transitionGauge not found'); + return; + } + + const ctx = canvas.getContext('2d'); + + // Show loading + ctx.font = '16px Arial'; + ctx.fillStyle = 'gray'; + ctx.textAlign = 'center'; + ctx.fillText('Loading...', canvas.width/2, canvas.height/2); + + // Filter nodes heard today (last 24 hours) + const now = new Date(); + const twentyFourHoursAgo = new Date(now.getTime() - 24 * 60 * 60 * 1000); + + const nodesHeardToday = nodes.filter(node => + node.updated_at && + new Date(node.updated_at) >= twentyFourHoursAgo + ); + + if (nodesHeardToday.length === 0) { + showNoDataMessage(ctx, canvas, 'No nodes heard today'); + return; + } + + // Count nodes with MediumFast channel_id + const mediumFastNodes = nodesHeardToday.filter(node => + node.channel_id === 'MediumFast' + ); + + const totalNodes = nodesHeardToday.length; + const mediumFastCount = mediumFastNodes.length; + const transitionPercentage = totalNodes > 0 ? (mediumFastCount / totalNodes) * 100 : 0; + + // Create gauge chart using doughnut chart + const data = [mediumFastCount, totalNodes - mediumFastCount]; + const maxValue = totalNodes; + + new Chart(ctx, { + type: 'doughnut', + data: { + datasets: [{ + data: data, + backgroundColor: [ + getTransitionColor(transitionPercentage), + 'rgba(220, 220, 220, 0.3)' + ], + borderWidth: 0, + cutout: '70%' + }] + }, + options: { + responsive: true, + maintainAspectRatio: false, + rotation: -90, // Start from top + circumference: 180, // Half circle + plugins: { + legend: { + display: false + }, + tooltip: { + enabled: false + } + } + }, + plugins: [{ + afterDraw: function(chart) { + // Add center text showing the counts and percentage + const centerX = chart.width / 2; + const centerY = chart.height / 2 + 20; // Adjust for half circle + + ctx.save(); + ctx.font = 'bold 24px Arial'; + ctx.fillStyle = '#333'; + ctx.textAlign = 'center'; + ctx.fillText(`${mediumFastCount}/${totalNodes}`, centerX, centerY); + + ctx.font = 'bold 18px Arial'; + ctx.fillStyle = getTransitionColor(transitionPercentage); + ctx.fillText(`${transitionPercentage.toFixed(1)}%`, centerX, centerY + 25); + + ctx.font = '12px Arial'; + ctx.fillStyle = '#666'; + ctx.fillText('Använder MediumFast', centerX, centerY + 45); + ctx.restore(); + } + }] + }); + +} + +function getTransitionColor(percentage) { + if (percentage >= 75) { + return 'rgba(1, 163, 23, 0.8)'; // Green - excellent progress + } else if (percentage >= 50) { + return 'rgba(234, 184, 57, 0.8)'; // Yellow - good progress + } else if (percentage >= 25) { + return 'rgba(255, 140, 0, 0.8)'; // Orange - some progress + } else { + return 'rgba(255, 69, 0, 0.8)'; // Red - limited progress + } +} + + +function showTransitionGaugeError() { + const canvas = document.getElementById('transitionGauge'); + if (!canvas) return; + + const ctx = canvas.getContext('2d'); + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.font = '16px Arial'; + ctx.fillStyle = 'red'; + ctx.textAlign = 'center'; + ctx.fillText('Error loading data', canvas.width/2, canvas.height/2); +} + +function showNoDataMessage(ctx, canvas, message) { + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.font = '16px Arial'; + ctx.fillStyle = 'gray'; + ctx.textAlign = 'center'; + ctx.fillText(message, canvas.width/2, canvas.height/2); +} + +// Initialize the transition gauge when the page loads +transitionStatusGauge();