first commit
All checks were successful
Meshtastic Map - See local Meshtastic Nodes / deploy (push) Successful in 1s

This commit is contained in:
david 2025-04-13 17:20:22 -07:00
commit 92b5a0894d
4 changed files with 149 additions and 0 deletions

View File

@ -0,0 +1,30 @@
name: Meshtastic Map - See local Meshtastic Nodes
on:
push:
branches:
- main
jobs:
deploy:
runs-on: pirf
steps:
- name: Checkout code
run: |
cd ~/apps/mesh-map
git fetch
git checkout main
git pull origin main
- name: Stop existing screen session, if running
run: |
if screen -list | grep -q "mesh_map_server"; then
echo "Stopping existing screen session..."
screen -S mesh_map_server -X quit
fi
- name: Start server in screen session
run: |
cd ~/apps/mesh-map
setsid screen -dmS mesh_map_server bash -c 'python3 -m http.server 8083 > server.log 2>&1'
echo "Server started in detached screen session"

0
README.md Normal file
View File

36
app.py Normal file
View File

@ -0,0 +1,36 @@
from flask import Flask, render_template, jsonify
import meshtastic.serial_interface
import meshtastic
import threading
import time
app = Flask(__name__)
node_locations = {}
MY_NODE_ID = "!934f4430"
# MY_NODE_NUM = 2471445552
iface = meshtastic.serial_interface.SerialInterface()
# iface.nodes.clear()
@app.route("/")
def index():
return render_template("map.html")
@app.route("/nodes")
def nodes():
data = {}
nodes = iface.nodes.items()
for node_id, node in nodes:
num = node.get('num')
user = node.get('user')
position = node.get('position')
deviceMetrics = node.get('deviceMetrics')
return jsonify({
# "myNodeNum": MY_NODE_NUM,
"myNodeId": MY_NODE_ID,
"nodes": dict(nodes)
})
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)

83
templates/map.html Normal file
View File

@ -0,0 +1,83 @@
<!DOCTYPE html>
<html>
<head>
<title>Meshtastic Map</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
</head>
<body>
<div id="map" style="height: 100vh;"></div>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script>
var map = L.map('map').setView([0, 0], 2);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
let myCoords = null;
const getNodeDesc = (node) =>{
const deviceMetrics = node?.deviceMetrics
const hopsAway = node?.hopsAway ?? 'N/A';
const lastHeard = node?.lastHeard;
const num = node?.num;
const position = node?.position;
const snr = node?.snr ?? 'N/A';
const user = node?.user;
const lat = position?.latitude
const lon = position?.longitude
return `
Id: ${user.id}<br/>
Hops Away: ${hopsAway}<br/>
S/N: ${snr} dbM<br/>
Loc: ${lat}, ${lon}
`
}
const updateNodes= async() => {
const res = await fetch('/nodes');
const json = await res.json();
const myNodeId = json['myNodeId']
// const myNodeNum = json['myNodeNum']
const nodes = json['nodes']
let myNode = null;
// const my
// Object.entries(nodes).forEach()
Object.entries(nodes).forEach(([id, node]) => {
if (id == myNodeId) {
console.log("found")
myNode = node;
}
const deviceMetrics = node?.deviceMetrics
const hopsAway = node?.hopsAway;
const lastHeard = node?.lastHeard;
const num = node?.num;
const position = node?.position;
const snr = node?.snr;
const user = node?.user;
const lat = position?.latitude
const lon = position?.longitude
if (lat && lon) {
L.marker([lat, lon]).addTo(map)
.bindPopup(getNodeDesc(node));
if (id == myNodeId && myCoords != [lat, lon]) {
myCoords = [lat, lon];
map.setView([lat, lon], 15);
}
}
})
}
updateNodes();
center();
setInterval(updateNodes, 10000);
</script>
</body>
</html>