mirror of
https://github.com/Roslund/sthlm-mesh.git
synced 2026-08-07 09:23:02 +02:00
Merge branch 'main' into fix-map
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
@@ -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 50–100 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 50–100 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 %}}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 -}}
|
||||
@@ -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('<', '<').replaceAll('>', '>').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);
|
||||
});
|
||||
Reference in New Issue
Block a user