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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/HELTEC_HT62.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/HELTEC_MESH_NODE_T114.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/HELTEC_V2_0.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/HELTEC_V2_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/HELTEC_V3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/HELTEC_WIRELESS_PAPER.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/HELTEC_WSL_V3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/LILYGO_TBEAM_S3_CORE.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/NANO_G1_EXPLORER.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/NANO_G2_ULTRA.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/NRF52840DK.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/NRF52_PROMICRO_DIY.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/PORTDUINO.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/PRIVATE_HW.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/RAK11310.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/RAK4631.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/RP2040_LORA.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/RPI_PICO.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/TBEAM.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/TBEAM_V0P7.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/TLORA_T3_S3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/public/images/TLORA_V2_1_1P6.png
Binary file added frontend/public/images/TRACKER_T1000_E.png
Binary file added frontend/public/images/T_DECK.png
Binary file added frontend/public/images/T_ECHO.png
Binary file added frontend/public/images/T_WATCH_S3.png
Binary file added frontend/public/images/XIAO.png
Binary file added frontend/public/images/XIAO_BLE.png
Binary file added frontend/public/images/icons/car.png
Binary file added frontend/public/images/icons/clown.png
Binary file added frontend/public/images/icons/computer.png
Binary file added frontend/public/images/icons/favicon.ico
Binary file not shown.
Binary file added frontend/public/images/icons/heltec.png
Binary file added frontend/public/images/icons/house.png
Binary file added frontend/public/images/icons/radio.png
Binary file added frontend/public/images/icons/tower.png
56 changes: 56 additions & 0 deletions memory_data_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ async def save(self):
self.graph = self.graph_node(self.config['server']['node_id'])

if since_last_render >= self.config['server']['intervals']['render']:
self.graph = self.graph_nodes()
static_html_renderer = StaticHTMLRenderer(self.config, copy.deepcopy(self))
await static_html_renderer.render()
end = datetime.now(ZoneInfo(self.config['server']['timezone']))
Expand Down Expand Up @@ -373,3 +374,58 @@ def recursive_graph_node(node_id, start_id="", level=0) -> dict|None:
return node

return recursive_graph_node(node_id, start_id=node_id)

def graph_nodes(self):
graph_data = {
"nodes": [],
"edges": []
}
known_edges = []
known_nodes = []
for id, node in self.nodes.items():
if id not in known_nodes:
if "neighborinfo" not in node:
continue
if not node["neighborinfo"]:
continue
if "neighbors" not in node["neighborinfo"]:
continue
graph_data['nodes'].append(
{
"id": id,
"name": node['longname'],
"height": 30,
"stroke": None,
'fill': {"src": utils.graph_icon(node['longname'])}
}
)
known_nodes.append(id)
for neighbor in node['neighborinfo']['neighbors']:
neigbor_id = utils.convert_node_id_from_int_to_hex(neighbor["node_id"])
edge_key = f"{id}.{neigbor_id}"
if edge_key not in known_edges:
known_edges.append(edge_key)
if neigbor_id in self.nodes:
graph_data["edges"].append(
{"from": id, "to": neigbor_id}
)
for edge in graph_data["edges"]:
to = edge['to']
to_node = None
if to in self.nodes:
to_node = self.nodes[to]
else:
to_node = Node.default_node(to)
if to not in known_nodes:
known_nodes.append(to)
graph_data['nodes'].append(
{
"id": to,
"name": to_node['longname'],
"height": 30,
"stroke": None,
'fill': {"src": utils.graph_icon(to_node['longname'])}
}
)

return graph_data
12 changes: 12 additions & 0 deletions meshtastic_support.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@ class HardwareModel(Enum):
NRF52_PROMICRO_DIY = 63
RADIOMASTER_900_BANDIT_NANO = 64
HELTEC_CAPSULE_SENSOR_V3 = 65
HELTEC_MESH_NODE_T114 = 69
TRACKER_T1000_E = 71
RPI_PICO2 = 79
PRIVATE_HW = 255
XIAO = 81

HARDWARE_PHOTOS = {
HardwareModel.HELTEC_HT62: "HELTEC_HT62.png",
Expand All @@ -99,4 +103,12 @@ class HardwareModel(Enum):
HardwareModel.T_ECHO: "T_ECHO.png",
HardwareModel.T_WATCH_S3: "T_WATCH_S3.png",
HardwareModel.PRIVATE_HW: "PRIVATE_HW.png",
HardwareModel.PORTDUINO: "PORTDUINO.png",
HardwareModel.XIAO: "XIAO.png",
HardwareModel.TBEAM_V0P7: "TBEAM_V0P7.png",
HardwareModel.HELTEC_MESH_NODE_T114: "HELTEC_MESH_NODE_T114.png",
HardwareModel.HELTEC_CAPSULE_SENSOR_V3: "HELTEC_CAPSULE_SENSOR_V3.png",
HardwareModel.TRACKER_T1000_E: "TRACKER_T1000_E.png",
HardwareModel.RPI_PICO2: "RPI_PICO.png",
HardwareModel.NRF52840DK: "NRF52840DK.png"
}
Binary file added public/images/hardware/HELTEC_MESH_NODE_T114.png
Binary file added public/images/hardware/NRF52840DK.png
Binary file added public/images/hardware/PORTDUINO.png
Binary file added public/images/hardware/TBEAM_V0P7.png
Binary file added public/images/hardware/TRACKER_T1000_E.png
Binary file added public/images/hardware/XIAO.png
Binary file added public/images/icons/car.png
Binary file added public/images/icons/clown.png
Binary file added public/images/icons/computer.png
Binary file added public/images/icons/favicon.ico
Binary file not shown.
Binary file added public/images/icons/heltec.png
Binary file added public/images/icons/house.png
Binary file added public/images/icons/radio.png
Binary file added public/images/icons/tower.png
67 changes: 31 additions & 36 deletions templates/static/graph.html.j2
Original file line number Diff line number Diff line change
@@ -1,42 +1,37 @@
{% extends "templates/static/layout.html.j2" %}

{% block title %}Graph{% endblock %}

{% macro graph_node(node) %}
{% if node.neighbors_heard|length > 0 %}
<ol class="pl-4 list-decimal list-inside">
{% for n in node.neighbors_heard %}
<li>
<div>
<a href="node_{{ n['id'] }}.html">
{% if n.shortname and n.shortname != "" %}
{{ n.shortname }}
{% else %}
UNK
{% endif %}
</a>&nbsp;
</div>
{{ graph_node(n) }}
</li>
{% endfor %}
</ol>
{% endif %}
{% endmacro %}

{% block content %}
<h5 class="mb-2 text-gray-500">Graph</h5>
<h1 class="mb-2 text-xl">Graph</h1>
<p class="mb-2">
The graph of nodes connected by neighbors (heard and heard by) as seen on the mesh as seen by
and starting with <a href="node_{{ config['server']['node_id'] }}.html">{{ config['server']['node_id'] }}</a> ({{ config['server']['node_id'] }}).
In the near future, this will be represented as a visual network graph and be interactive.
</p>

<div>
<div>{{ graph['shortname'] }}</div>
<div>{{ graph_node(graph) }}</div>
<div class="w-full h-full" id="container" style="height: 100vh">
</div>

<div id="graph" class="w-full h-96"></div>
<script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.13.0/js/anychart-core.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.13.0/js/anychart-graph.min.js"></script>
<script>
var data = {{ graph|tojson|safe }};
{% raw %}
var chart = anychart.graph(data);
chart.container("container");
chart.nodes().labels().enabled(true);
chart.nodes().labels().format("{%name}");
chart.nodes().labels().fontSize(12);
chart.nodes().labels().fontWeight(600);
chart.draw();
chart.fit();
chart.listen('click', function(e) {
var tag = e.domTarget.tag;
if (tag) {
if (tag.type === 'node') {
var url;
for (var i = 0; i < data.nodes.length; i++) {
if (data.nodes[i].id === tag.id) {
url = "node_" + data.nodes[i].id + ".html";
break;
}
}
window.open(url, '_self');
}
}
});
{% endraw %}
</script>
{% endblock %}
21 changes: 21 additions & 0 deletions utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,24 @@ def filter_dict(d, whitelist):
]
else:
return d # Return the value if it's neither a dict nor a list

def graph_icon(name):
if "qth" in name.lower():
return "/images/icons/house.png"
elif "home" in name.lower():
return "/images/icons/house.png"
elif "base" in name.lower():
return "/images/icons/house.png"
elif "qth" in name.lower():
return "/images/icons/house.png"
elif "mobile" in name.lower():
return "/images/icons/car.png"
elif " hs" in name.lower():
return "/images/icons/tower.png"
elif "edc" in name.lower():
return "/images/icons/heltec.png"
elif "mqtt" in name.lower():
return "/images/icons/computer.png"
elif "bridge" in name.lower():
return "/images/icons/computer.png"
return "/images/icons/radio.png"