Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions content.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"fork_info": "Forked by <a class=\"link\" target=\"_blank\" href=\"http://github.com/Roslund/\">Roslund</a>, augmented by dogvisor.",
"title": "STHLM-MESH MAP",
"home_url": "https://sthlm-mesh.se/",
"base_url": "https://map.sthlm-mesh.se/",
"announcement": {
"enabled": true,
"id": "1",
"header": "Viktigt!",
"content": "I Stockholm används LoRa preset <b>Medium Range - Fast</b>. För mer info <a href=\"https://sthlm-mesh.se/blog/2025/övergång-till-mediumfast-den-27-september/\" type=\"button\" class=\"link\">klicka här</a>."
},
"lat": 59.3,
"lng": 378.1,
"zoom": 10,
"description": "En interaktiv karta över Meshtastic-noder i STHLM-MESH.",
"info_blocks": [
{
"header": "Beskrivning",
"content": "Detta är en karta som enbart fokuserar på Stockholm. Den är baserad på Liam Cottle's open source projekt Meshtastic Map, men har flertalet ändringar och nya funktioner som gör att vi bättre kan analysera Meshen i Stockholm."
},
{
"header": "Frågor och svar",
"content": [
{
"header": "Hur får jag min nod att synas på kartan?",
"content": "Din nod behöver anting ha en GPS, ha en fast position inställd, eller att din telefon delar sin position. Utöver detta måste platsdelning vara påslåget under kanalinställningarna för MediumFast kanalen (vanligtvis kanal 0)."
},
{
"header": "Min nod är på fel plats på kartan",
"content": "Detta är troligtvis för att din nod inte delar <b>exakt position</b>. Som standard är positionsprecisionen inställd på ± 3 km, vilket betyder att noden kan befinna sig inom en cirkel med radien 3 kilometer. Du kan ändra positions precisionen i kanalinställningarna. För mer info om positions precisionen, klicka här."
},
{
"header": "Hur kan jag ansluta min nod till MQTT servern?",
"content": "Då vi enbart vill analysera Meshen i stockholm är MQTT servern inte öppen för alla. Endast ett fåtal noder är uppkopplade till MQTT för att kunna analysera trafiken som faktiskt går över LoRa. De noder som är kopplade mot MQTT servern bör: <ul class=\"list-disc list-inside\"><li>Vara på en unik geografisk plats, då vi vill se hur trafiken fördelas</li><li>Ha en stabil fast koppling till internet (via Ethernet eller WiFi)</li><li>Ha hög tillgänglighet</li><li>Ha direktkontakt med flertalet andra noder</li></ul>Tror du att din nod kan bidra, kontakta @Roslund på Discord."
}
]
}
]
}
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ services:
environment:
DATABASE_URL: "mysql://root:password@database:3306/meshtastic-map?connection_limit=100"
MAP_OPTS: "" # add any custom index.js options here
volumes:
- content.json:/app/src/content.json:ro

# publishes mqtt packets via websocket
meshtastic-ws:
Expand Down
66 changes: 60 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"command-line-usage": "^7.0.3",
"compression": "^1.8.1",
"cors": "^2.8.5",
"ejs": "^4.0.1",
"express": "^5.2.1",
"mqtt": "^5.14.1",
"protobufjs": "^7.5.4",
Expand Down
9 changes: 8 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ const statsRoutes = require('./stats.js');
const { PrismaClient } = require("@prisma/client");
const prisma = new PrismaClient();

// Load content
const content = require('./content.json');

// return big ints as string when using JSON.stringify
BigInt.prototype.toJSON = function() {
return this.toString();
Expand Down Expand Up @@ -77,6 +80,10 @@ function formatNodeInfo(node) {

const app = express();

// set view engine to ejs
app.set('view engine', 'ejs');
app.set('views', path.join(__dirname, 'views'));

// enable compression
app.use(compression());

Expand All @@ -87,7 +94,7 @@ app.use('/api', cors());
app.use('/', express.static(path.join(__dirname, 'public')));

app.get('/', async (req, res) => {
res.sendFile(path.join(__dirname, 'public/index.html'));
res.render('index', content);
});

// stats API in separate file
Expand Down
93 changes: 40 additions & 53 deletions src/public/index.html → src/views/index.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,16 @@

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>STHLM-MESH MAP</title>
<meta name="title" content="Meshtastic Map">
<meta name="description" content="An interactive map of all Meshtastic nodes.">
<title><%= title %></title>
<meta name="title" content="<%= title %>">
<meta name="description" content="<%= description %>">
<link rel="icon" type="image/png" href="/icon.png"/>

<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://map.sthlm-mesh.se">
<meta property="og:title" content="STHLM-MESH MAP">
<meta property="og:description" content="An interactive map of all Meshtastic nodes.">
<meta property="og:url" content="<%= base_url %>">
<meta property="og:title" content="<%= title %>">
<meta property="og:description" content="<%= description %>">

<!-- tailwind css -->
<script src="assets/js/tailwindcss/tailwind-v3.4.3-forms-v0.5.7.js"></script>
Expand Down Expand Up @@ -173,9 +173,9 @@

<!-- info -->
<div class="my-auto leading-tight">
<div class="font-bold">Viktigt!</div>
<div class="font-bold"><%- announcement.header %></div>
<div class="text-sm">
<span>I Stockholm används LoRa preset <b>Medium Range - Fast</b>. För mer info <a href="https://sthlm-mesh.se/blog/2025/övergång-till-mediumfast-den-27-september/" type="button" class="link">klicka här</a>.</span>
<span><%- announcement.content %></span>
</div>
</div>

Expand All @@ -191,10 +191,9 @@
</div>

</div>

<!-- header -->
<div class="flex p-3 h-16" style="background-color: 30a552;">

<!-- close mobile search button -->
<div v-if="isShowingMobileSearch" class="my-auto">
<a @click="isShowingMobileSearch = false" href="javascript:void(0)" class="rounded-full">
Expand All @@ -213,7 +212,7 @@

<!-- app info -->
<div v-if="!isShowingMobileSearch" class="my-auto leading-tight">
<a href="https://sthlm-mesh.se"><div class="font-bold" style="color: #ffffff; font-size: 1.25rem;">STHLM-MESH</div></a>
<a href="<%= home_url %>"><div class="font-bold" style="color: #ffffff; font-size: 1.25rem;"><%= title %></div></a>
</div>

<!-- search bar -->
Expand Down Expand Up @@ -356,45 +355,26 @@
<img src="./icon.png" class="mx-auto w-16 h-16 rounded mb-1"/>
<h1 class="font-bold">Meshtastic Map</h1>
<h2>Created by <a class="link" target="_blank" href="https://liamcottle.com">Liam Cottle</a></h2>
<h2>Forked by <a class="link" target="_blank" href="http://github.com/Roslund/">Roslund</a></h2>
<h2><%- fork_info %></h2>
</div>

<!-- Beskrivning -->
<div>
<div class="font-bold mb-2">Beskrivning</div>
<div class="space-y-2">
<div class="bg-gray-100 rounded p-2 border border-gray-200">
<div>Detta är en karta som enbart fokuserar på Stockholm.</div>
<div>Den är baserad på Liam Cottle's open source projekt Meshtastic Map, men har flertalet ändringar och nya funktioner som gör att vi bättre kan analysera Meshen i Stockholm.</div>
</div>
</div>
<br>
<div class="font-bold mb-2">Frågor och svar</div>
<div class="space-y-2">
<div class="bg-gray-100 rounded p-2 border border-gray-200">
<div class="font-semibold">Hur får jag min nod att synas på kartan?</div>
<div>Din nod behöver anting ha en GPS, ha en fast position inställd, eller att din telefon delar sin position.</div>
<div>Utöver detta måste platsdelning vara påslåget under kanalinställningarna för MediumFast kanalen (vanligtvis kanal 0).</div>
</div>
<div class="bg-gray-100 rounded p-2 border border-gray-200">
<div class="font-semibold">Min nod är på fel plats på kartan</div>
<div>Detta är troligtvis för att din nod inte delar <b>exakt position</b>. Som standard är positionsprecisionen inställd på &plusmn; 3 km, vilket betyder att noden kan befinna sig inom en cirkel med radien 3 kilometer.</div>
<div>Du kan ändra positions precisionen i kanalinställningarna. För mer info om positions precisionen, <a href="https://sthlm-mesh.se/docs/position/#position-precision">klicka här</a>.</div>
</div>
<div class="bg-gray-100 rounded p-2 border border-gray-200">
<div class="font-semibold">Hur kan jag ansluta min nod till MQTT servern?</div>
<div>Då vi enbart vill analysera Meshen i stockholm är MQTT servern inte öppen för alla. Endast ett fåtal noder är uppkopplade till MQTT för att kunna analysera trafiken som faktiskt går över LoRa.</div>
<div>De noder som är kopplade mot MQTT servern bör:</div>
<ul class="list-disc list-inside">
<li>Vara på en unik geografisk plats, då vi vill se hur trafiken fördelas</li>
<li>Ha en stabil fast koppling till internet (via Ethernet eller WiFi)</li>
<li>Ha hög tillgänglighet</li>
<li>Ha direktkontakt med flertalet andra noder</li>
</ul>
<div>Tror du att din nod kan bidra, kontakta @Roslund på Discord.</div>
</div>
<% info_blocks.forEach(function(info_block) { %>
<div>
<div class="font-bold mb-2"><%- info_block.header %></div>
<% if (typeof info_block.content == 'string') { info_block.content = [{content: info_block.content}]} %>
<% info_block.content.forEach(function(content_item) { %>
<div class="space-y-2">
<div class="bg-gray-100 rounded p-2 border border-gray-200">
<% if (content_item.header) { %>
<div class="font-semibold"><%- content_item.header %></div>
<% } %>
<div><%- content_item.content %></div>
</div>
</div>
<% }); %>
</div>
</div>
<% }); %>
<!-- legal -->
<div>
<div class="font-bold mb-2">Legal</div>
Expand Down Expand Up @@ -1874,11 +1854,15 @@ <h2 class="font-bold">{{ selectedNodeToShowConnections.short_name }} Connections
methods: {
getAnnouncementId: function() {
// change this when making a new announcement
return "1";
return "<%= announcement.id %>";
},
shouldShowAnnouncement: function() {
const lastSeenAnnouncementId = window.localStorage.getItem("last-seen-announcement-id");
return lastSeenAnnouncementId?.toString() !== this.getAnnouncementId();
<% if (announcement.enabled) { %>
return lastSeenAnnouncementId?.toString() !== this.getAnnouncementId();
<% } else { %>
return false;
<% } %>
},
dismissAnnouncement: function() {
window.localStorage.setItem("last-seen-announcement-id", this.getAnnouncementId());
Expand Down Expand Up @@ -2752,13 +2736,16 @@ <h2 class="font-bold">{{ selectedNodeToShowConnections.short_name }} Connections
[100, 500], // bottom right
];

// create map positioned over Stockholm
// create map positioned according to content.json
var map = L.map('map', {
maxBounds: bounds,
}).setView([
59.3,
378.1,
], 10);
}).setView(
[
<%= lat %>,
<%= lng %>,
],
<%= zoom %>
);

// remove leaflet link
map.attributionControl.setPrefix('');
Expand Down