Merge branch 'main' into fix-map

This commit is contained in:
Anton Roslund
2025-03-16 21:18:30 +01:00
committed by GitHub
9 changed files with 239 additions and 35 deletions
-6
View File
@@ -18,12 +18,6 @@ Might want to allow editing
/* Change the color of the doc rightside sidebar links */
.td-sidebar-toc a { color: grey !important; }
/*
Hide links to the last change commit.
Ugly workaround that leves to colon ":"
*/
.td-page-meta__lastmod a { display: none; }
/* Formating of inline <code> blocks */
code {
background-color: #f0f0f0;
+1 -1
View File
@@ -6,6 +6,6 @@ Add styles or override variables from the theme here.
/* Color and Style */
$primary: #30a552;
$secondary: #0d6efd;;
$secondary: #0d6efd;
$tertiary: #8c68cd;
$warning: #ffc107;
+30 -12
View File
@@ -42,15 +42,33 @@ Det är alltid trevligt att träffas och prata radio. Kolla in våra [Meetups]({
* <h4>Främja aktivitet i meshet.</h4>
{{% /blocks/section %}}
{{% blocks/section color="primary" %}}
{{% blocks/lead color="meshtastic-green" %}}
Kom igång med Meshtastic
{.h1}
För att komma igång rekommenderar vi att följa instruktionerna på den officiella hemsidan: https://meshtastic.org.
{{% /blocks/lead %}}
{{% blocks/section type="row" color="info" %}}
{{% blocks/feature icon="fa-walkie-talkie" title="Införskaffa enhet" %}}
Det finns enheter för olika frekvensband, i Sverige och inom EU är det **868Mhz** som används. Några populära enheter:
[WisMesh Pocket](),
[seeed studio T1000-E](https://www.seeedstudio.com/SenseCAP-Card-Tracker-T1000-E-for-Meshtastic-p-5913.html),
[Heltec LoRa 32](https://heltec.org/project/wifi-lora-32-v3/),
[LILYGO T-Deck Plus](https://lilygo.cc/products/t-deck-plus-1),
[LILYGO T-Beam](https://lilygo.cc/products/t-beam).
{{% /blocks/feature %}}
{{% blocks/feature icon="fa-microchip" title="Flasha firmware" %}}
När du fått din enhet behöver Meshtastic programvaran laddas på. Detta görs enklast via en dator: http://flasher.meshtastic.org/.
Vi rekommenderar den senaste betan, men titta tillbaka regelbundet då utvecklingen går snabbt.
{{% /blocks/feature %}}
{{% blocks/feature icon="fab fa-app-store-ios" title="Konfigurera med appen" %}}
För att konfigurera din en rekommenderas den officiella appen för [iOS](https://apple.co/3Auysep) eller [Android](https://play.google.com/store/apps/details?id=com.geeksville.mesh&pli=1).
I Stockholm använder vi kanal-preseten **Long Fast**. För mer detaljer om enhetskonfiguration se vår sida: [rekommenderade inställningar]({{<ref settings>}}).
{{% /blocks/feature %}}
{{% alert title="Viktigt" color="success" %}}
Vi använder oss av 868mhz på preset Long Range - Fast.
{{% /alert %}}
{{% /blocks/section %}}
<!-- Det finns garanterat bättre sätt att göra detta på... -->
@@ -70,11 +88,11 @@ Vi använder oss av 868mhz på preset Long Range - Fast.
<div class="row g-4">
<div class="col-lg-4">
<div class="card" >
<h3 class="card-header"><b>ROUTER</b></h3>
<img src="/router.jpeg" class="card-img-top" alt="...">
<h3 class="card-header"><b>Client Mute</b></h3>
<img src="/client_mute.jpeg" class="card-img-top" alt="...">
<div class="card-body">
<p class="card-text">En nod placerad högt upp med fri sikt åt alla håll. Använder en optimerad och väl-testad setup. Måste koordineras med övriga meshet.<p>
<a href="/docs/device_role/#router" class="btn btn-primary" style="color: #f9f9f9 !important;">Läs mer</a>
<p class="card-text">För portabla noder eller noder som används inomhus. <b>Notera</b>: En nod inställd på Client Mute kan fortfarande skicka och ta emot meddelanden.<p>
<a href="/docs/device_role/#client-mute" class="btn btn-primary" style="color: #f9f9f9 !important;">Läs mer</a>
</div>
</div>
</div>
@@ -90,11 +108,11 @@ Vi använder oss av 868mhz på preset Long Range - Fast.
</div>
<div class="col-lg-4">
<div class="card" >
<h3 class="card-header"><b>Client Mute</b></h3>
<img src="/client_mute.jpeg" class="card-img-top" alt="...">
<h3 class="card-header"><b>ROUTER</b></h3>
<img src="/router.jpeg" class="card-img-top" alt="...">
<div class="card-body">
<p class="card-text">För portabla noder eller noder som används inomhus. <b>Notera</b>: En nod inställd på Client Mute kan fortfarande skicka och ta emot meddelanden.<p>
<a href="/docs/device_role/#client-mute" class="btn btn-primary" style="color: #f9f9f9 !important;">Läs mer</a>
<p class="card-text">En nod placerad högt upp med fri sikt åt alla håll. Använder en optimerad och väl-testad setup. Måste koordineras med övriga meshet.<p>
<a href="/docs/device_role/#router" class="btn btn-primary" style="color: #f9f9f9 !important;">Läs mer</a>
</div>
</div>
</div>
+2 -1
View File
@@ -5,7 +5,8 @@ weight: 80
Det finns massvis med olika karttjänster, vi rekommenderar Liam Cottles karta:
https://meshtastic.liamcottle.net/
<a href="https://meshtastic.liamcottle.net/"><img src="/featured-background-map.png" width="50%"></a>
<a href="https://meshtastic.liamcottle.net/"><img src="/featured-background-map.png" width="50%"></a>
{{% alert title="Uppmärksamma" color="warning" %}}
För att tillåta andra noder publicera din nod på kartan behöver `lora.config_ok_to_mqtt` vara aktiverat.
+35
View File
@@ -0,0 +1,35 @@
---
title: Meddelanden
linkTitle: Meddelanden
menu: {main: {weight: 50}}
---
<section id="messages" class="pt-0 row td-box td-box--white td-box--height-auto" style="padding-bottom: 0px !important;"x>
<h2 id="senaste-meddelanden" class="pt-3">Senaste meddelanden<a class="td-heading-self-link" href="#senaste-meddelanden" aria-label="Heading self-link"></a></h2>
<div class="btn-toolbar mb-2" role="toolbar" aria-label="Toolbar with button groups">
<div class="btn-group btn-group-sm me-2" role="group" aria-label="Basic radio toggle button group">
<input type="radio" class="btn-check" name="btnradio" id="all" autocomplete="off" checked>
<label class="btn btn-outline-primary" for="all">Alla</label>
</div>
<div class="btn-group btn-group-sm me-2" role="group" aria-label="Basic radio toggle button group">
<input type="radio" class="btn-check" name="btnradio" id="3663385928" autocomplete="off">
<label class="btn btn-outline-primary" for="3663385928" data-bs-toggle="tooltip" data-bs-placement="top" title="Mariehäll Alprosen">Ros1</label>
<input type="radio" class="btn-check" name="btnradio" id="1978245180" autocomplete="off">
<label class="btn btn-outline-primary" for="1978245180" data-bs-toggle="tooltip" data-bs-placement="top" title="SA0CVK 0 (Ny Router)">CVK</label>
<input type="radio" class="btn-check" name="btnradio" id="862351628" autocomplete="off">
<label class="btn btn-outline-primary" for="862351628" data-bs-toggle="tooltip" data-bs-placement="top" title="JwK Bas">JwK</label>
<input type="radio" class="btn-check" name="btnradio" id="2971894662" autocomplete="off">
<label class="btn btn-outline-primary" for="2971894662" data-bs-toggle="tooltip" data-bs-placement="top" title="Stora Älgön 2.0">Älg</label>
</div>
<!-- Info Button with Tooltip -->
<div data-bs-toggle="tooltip" data-bs-placement="right" title="Visar meddelanden mottagna av respektive nod. Användbart för att förstå vilka noder som har hört ett meddelande.">
<span class="badge rounded-pill bg-dark">?</span>
</div>
</div>
<div id="loading"><p>Loading...</p></div>
</section>
<script src="/js/messages.js"></script>
+17 -13
View File
@@ -9,6 +9,23 @@ Grafer och statistik specifikt för Stockholm's meshen.
{{% /blocks/cover %}}
{{% blocks/section color="white" %}}
{{% alert title="Uppmärksamma" color="warning" %}}
Vi hade problem med datainsamlingen den 8/3 vilket påverkar graferna och statistiken.
{{% /alert %}}
## Skapade paket per nod
Grafen nedan visar vilka noder som har skickat flest paket under det senaste dygnet. Vidarebefordrade meddelanden och krypterade paket är inte medräknade.
Datat i grafen är endast en uppskattning och bör inte ses som exakt. Graferna bygger på MQTT-data från ett begränsat antal noder.
Eftersom vi har begränsad bandbredd är det viktigt att hålla nere trafiken. En sändningsvolym på max 50100 paket per dygn är önskvärd.
{{< lazy-img max-width="800px" aspect-ratio="1/1"
src="https://dash.roslund.cloud/render/d-solo/aedo2cbpvy800a/sthlm-mesh?orgId=1&theme=light&panelId=7&width=1000&height=1000&scale=1" >}}
## Packet typer
Fördelningen av olika pakettyper i nätverket under de senaste dygnet. Diagrammet visar hur nätverket används, inklusive meddelanden, positionstelemetri och andra systempaket.
{{< lazy-img max-width="774px" aspect-ratio="774/387"
src="https://dash.roslund.cloud/render/d-solo/aedo2cbpvy800a/sthlm-mesh?orgId=1&theme=light&panelId=6&width=1000&height=500&scale=1" >}}
## Kanalutnyttjande
Den genomsnittliga kanalutnyttjandet i Stockholm under de senaste 7 dygnen. Observera att många noder slutar skicka telemetri vid hög belastning (över 25 %), vilket kan påverka grafens noggrannhet. Trots detta ger gränsvärdena i grafen en god indikation på nätverkets hälsa över tid.
@@ -21,25 +38,12 @@ Antalet meddelande per timme senaste 7 dygnen.
{{< lazy-img max-width="774px" aspect-ratio="774/387"
src="https://dash.roslund.cloud/render/d-solo/aedo2cbpvy800a/sthlm-mesh?orgId=&from=now-7d&to=now&theme=light&panelId=4&width=1000&height=500&scale=1&tz=Europe%2FStockholm" >}}
## Batteri
Visar den genomsnittliga batteri-nivån i meshet senaste 7 dygnen. Grafen försöker exkludera noder som är inkopplade till en strömkälla och som således inte går på batteri.
{{< lazy-img max-width="774px" aspect-ratio="774/387"
src="https://dash.roslund.cloud/render/d-solo/aedo2cbpvy800a/sthlm-mesh?orgId=1&from=now-7d&to=now&theme=light&panelId=2&width=1000&height=500&scale=1&tz=Europe%2FStockholm" >}}
## Packet typer
Fördelningen av olika pakettyper i nätverket under de senaste dygnet. Diagrammet visar hur nätverket används, inklusive meddelanden, positionstelemetri och andra systempaket.
{{< lazy-img max-width="774px" aspect-ratio="774/387"
src="https://dash.roslund.cloud/render/d-solo/aedo2cbpvy800a/sthlm-mesh?orgId=1&theme=light&panelId=6&width=1000&height=500&scale=1" >}}
## Skapade paket per nod
Grafen nedan visar vilka noder som har skickat flest paket under det senaste dygnet. Vidarebefordrade meddelanden och krypterade paket är inte medräknade.
Datat i grafen är endast en uppskattning och bör inte ses som exakt. Graferna bygger på MQTT-data från ett begränsat antal noder.
Eftersom vi har begränsad bandbredd är det viktigt att hålla nere trafiken. En sändningsvolym på max 50100 paket per dygn är önskvärd.
{{< lazy-img max-width="800px" aspect-ratio="1/1"
src="https://dash.roslund.cloud/render/d-solo/aedo2cbpvy800a/sthlm-mesh?orgId=1&theme=light&panelId=7&width=1000&height=1000&scale=1" >}}
{{% /blocks/section %}}
{{% blocks/section color=info %}}
+4 -2
View File
@@ -58,8 +58,6 @@ menu:
- name: "Map"
url: "https://map.sthlm-mesh.se/?lat=59.34338409949693&lng=378.0628967285156&zoom=10"
weight: 80
params:
target: "_blank"
# Everything below this are Site Params
params:
@@ -136,6 +134,10 @@ params:
readingtime:
enable: false
services:
googleAnalytics:
id: G-4LJP3Y6HMZ
module:
hugoVersion:
extended: true
+5
View File
@@ -0,0 +1,5 @@
{{ if and .GitInfo .Site.Params.github_repo -}}
<div class="td-page-meta__lastmod">
{{ T "post_last_mod" }} {{ .Lastmod.Format .Site.Params.time_format_default -}}
</div>
{{ end -}}
+145
View File
@@ -0,0 +1,145 @@
document.addEventListener("DOMContentLoaded", async function () {
const messagesContainer = document.getElementById("messages");
const radioButtons = document.querySelectorAll("input[name='btnradio']");
const loadingDiv = document.getElementById("loading");
const messagesList = document.createElement("div");
messagesList.style="max-height:70vh;overflow: auto;"
messagesContainer.appendChild(messagesList);
const state = {
messages: [],
nodesById: {},
};
radioButtons.forEach(radio => {
radio.addEventListener("change", fetchMessages);
});
async function fetchMessages() {
try {
let url = "https://map.sthlm-mesh.se/api/v1/text-messages?order=desc";
const selectedRadio = document.querySelector("input[name='btnradio']:checked");
//If all is not selected we get 15 messages. If not we get 35 due to duplicates
if (selectedRadio.id !== "all") {
url += `&gateway_id=${selectedRadio.id}`;
url += `&count=15`;
} else {
url += `&count=35`;
}
const response = await fetch(url);
const data = await response.json();
//Filter duplicate messages
state.messages = Array.from(
new Map(data.text_messages.map(msg => [msg.packet_id, msg])).values()
);
// fetch node info
for(const message of state.messages){
await fetchNodeInfo(message.to);
await fetchNodeInfo(message.from);
await fetchNodeInfo(message.gateway_id);
}
updateUI();
} catch (error) {
console.error("Error fetching messages", error);
loadingDiv.innerHTML = `<p style="color: red;">Error fetching messages: ${error.message}</p>`;
}
}
async function fetchNodeInfo(nodeId) {
// do nothing if already fetched
if(nodeId in state.nodesById){
return;
}
// do nothing if broadcast address
if(nodeId.toString() === "4294967295"){
return;
}
try {
const response = await fetch(`https://map.sthlm-mesh.se/api/v1/nodes/${nodeId}`);
const data = await response.json();
const node = data.node;
if(node){
state.nodesById[node.node_id] = node;
}
} catch(e) {
// do nothing
}
}
function updateUI() {
loadingDiv.innerHTML = ""; // Clear the loading message
messagesList.innerHTML = "";
state.messages.slice().reverse().forEach(message => {
const messageDiv = document.createElement("div");
messageDiv.className = "d-flex mb-2";
messageDiv.innerHTML = `
<div class="p-2 flex">
<div class="d-flex rounded-circle shadow text-white justify-content-center align-items-center"
style="width: 48px; height: 48px; background-color: ${getNodeColour(message.from)}; color: #ffffff;">
${getNodeShortName(message.from)}
</div>
</div>
<div class="flex">
<div class="small">
<a target="_blank" href="https://map.sthlm-mesh.se/?node_id=${message.from}" style="color: grey; text-decoration: none;">${getNodeLongName(message.from)}</a>
${message.to !== "4294967295" ? ` → <a target="_blank" href="https://map.sthlm-mesh.se//?node_id=${message.to}" style="color: grey; text-decoration: none;">${getNodeLongName(message.to)}</a>` : ""}
</div>
<div class="px-2 py-1 pb-1 border rounded shadow-sm" style="background-color: #efefef">
<div class="">${escapeMessageText(message.text)}</div>
</div>
<div class="pt-1" style="font-size: 0.65rem;color: grey;">${formatMessageTimestamp(message.created_at)}</div>
</div>
`;
messagesList.appendChild(messageDiv);
});
messagesList.scrollTop = messagesList.scrollHeight;
}
function getNodeColour(nodeId) {
return "#" + (nodeId & 0x00FFFFFF).toString(16).padStart(6, '0');
}
function getNodeHexId(nodeId) {
return "!" + parseInt(nodeId).toString(16);
}
function getNodeShortName(nodeId) {
return state.nodesById[nodeId]?.short_name?.substring(0, 4) ?? "?";
}
function getNodeLongName(nodeId) {
return state.nodesById[nodeId]?.long_name ?? getNodeHexId(nodeId);
}
function getNodeName(nodeId) {
const node = state.nodesById[nodeId];
if(!node){
return getNodeHexId(nodeId);
}
return `[${node.short_name}] ${node.long_name}`;
}
function escapeMessageText(text) {
return text.replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('\n', '<br/>');
}
function formatMessageTimestamp(createdAt) {
const date = new Date(createdAt);
return date.toLocaleString('sv-SE', { hour12: false }).replace(' ', ' ').slice(0, 16);
}
await fetchMessages();
setInterval(fetchMessages, 30000);
});