Skip to content

Commit ab99b47

Browse files
committed
include traceroute messages
1 parent 957aa62 commit ab99b47

File tree

3 files changed

+133
-2
lines changed

3 files changed

+133
-2
lines changed

mesh-collectd.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,15 @@ def init_db(db_path="mqtt_messages.db"):
6161
)"""
6262
)
6363

64+
cursor.execute(
65+
"""CREATE TABLE IF NOT EXISTS traceroutes (
66+
id INTEGER PRIMARY KEY AUTOINCREMENT,
67+
from_node TEXT,
68+
to_node TEXT,
69+
timestamp INTEGER
70+
)"""
71+
)
72+
6473
conn.commit()
6574
return conn
6675

@@ -86,6 +95,24 @@ def save_nodeinfo_to_db(conn, node_id, longname=None, shortname=None, hardware=N
8695
except Exception as e:
8796
print(f"Error saving node info: {e}")
8897

98+
def save_traceroute_to_db(conn, route, timestamp):
99+
cursor = conn.cursor()
100+
try:
101+
# Process each consecutive pair in the route
102+
for i in range(len(route) - 1):
103+
from_node = sanitize_string(route[i])
104+
to_node = sanitize_string(route[i + 1])
105+
106+
if 'Unknown' not in [from_node, to_node]:
107+
cursor.execute(
108+
"""INSERT INTO traceroutes (from_node, to_node, timestamp)
109+
VALUES (?, ?, ?)""",
110+
(from_node, to_node, timestamp)
111+
)
112+
conn.commit()
113+
except Exception as e:
114+
print(f"Error saving traceroute info: {e}")
115+
89116

90117
def save_message_to_db(conn, topic, sender, receiver, physical_sender, timestamp, rssi, snr, type):
91118
cursor = conn.cursor()
@@ -129,6 +156,8 @@ def db_worker(queue, db_path):
129156
save_neighbors_to_db(conn, *item[1:])
130157
elif item[0] == "position":
131158
save_nodeinfo_to_db(conn, *item[1:])
159+
elif item[0] == "traceroute":
160+
save_traceroute_to_db(conn, *item[1:])
132161
except Exception as e:
133162
print(f"Database error: {e}")
134163
conn.close()
@@ -241,6 +270,21 @@ def on_message(client, userdata, msg):
241270
f"Node {node_id}: {timestamp} {node_id} Neighbors: {len(neighbors)}"
242271
)
243272

273+
274+
elif msg_type == "traceroute" and "payload" in payload:
275+
route_payload = payload["payload"]
276+
if "route" in route_payload:
277+
route = route_payload["route"]
278+
current_time = int(time.time()) # Get current Unix timestamp
279+
userdata.put(("traceroute", route, current_time))
280+
281+
# Print the route pairs
282+
route_pairs = [f"{route[i]} -> {route[i+1]}"
283+
for i in range(len(route)-1)]
284+
print(f"Traceroute at {timestamp} with pairs:")
285+
for pair in route_pairs:
286+
print(f" {pair}")
287+
244288
elif msg_type == "position" and "payload" in payload:
245289
pos_payload = payload["payload"]
246290
if all(k in pos_payload for k in ["latitude_i", "longitude_i"]):

sqlite2json.py

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,89 @@ def export_to_json(db_path, json_output_path, time_limit_minutes, use_physical_s
160160
conn.close()
161161

162162

163-
# Example usage
163+
def get_node_shortname_and_role(cursor, longname):
164+
"""Get shortname and role for a node by its longname from the nodes table"""
165+
cursor.execute("SELECT shortname, role FROM nodes WHERE longname = ?", (longname,))
166+
result = cursor.fetchone()
167+
if result:
168+
return result[0], result[1] # shortname, role
169+
return longname, None # Return original longname if no match found
170+
171+
def export_traceroutes_to_json(db_path, json_output_path, time_limit_minutes):
172+
try:
173+
conn = sqlite3.connect(db_path)
174+
cursor = conn.cursor()
175+
176+
cutoff_time = int((datetime.now() - timedelta(minutes=time_limit_minutes)).timestamp())
177+
178+
cursor.execute(
179+
"""SELECT from_node, to_node, COUNT(*) as count
180+
FROM traceroutes
181+
WHERE timestamp >= ?
182+
GROUP BY from_node, to_node""",
183+
(cutoff_time,),
184+
)
185+
rows = cursor.fetchall()
186+
187+
connection_counts = defaultdict(int)
188+
valid_connections = []
189+
190+
for row in rows:
191+
from_node, to_node, count = row
192+
valid_connections.append((from_node, to_node, count))
193+
connection_counts[from_node] += 1
194+
connection_counts[to_node] += 1
195+
196+
cytoscape_data = []
197+
processed_nodes = set()
198+
199+
# Add nodes
200+
for node_name in connection_counts.keys():
201+
if node_name not in processed_nodes:
202+
shortname, role = get_node_shortname_and_role(cursor, node_name)
203+
node_id = shortname # Use shortname as node ID
204+
205+
cytoscape_data.append({
206+
"data": {
207+
"id": node_id,
208+
"label": shortname,
209+
"role": role,
210+
"connections": connection_counts[node_name],
211+
"original_name": node_name
212+
}
213+
})
214+
processed_nodes.add(node_name)
215+
216+
# Add edges
217+
for from_node, to_node, count in valid_connections:
218+
from_shortname, _ = get_node_shortname_and_role(cursor, from_node)
219+
to_shortname, _ = get_node_shortname_and_role(cursor, to_node)
220+
221+
cytoscape_data.append({
222+
"data": {
223+
"id": f"{from_shortname}_{to_shortname}",
224+
"source": from_shortname,
225+
"target": to_shortname,
226+
"count": count,
227+
"original_source": from_node,
228+
"original_target": to_node
229+
}
230+
})
231+
232+
with open(json_output_path, "w") as json_file:
233+
json.dump(cytoscape_data, json_file, indent=2)
234+
235+
print(f"Traceroute data successfully exported to {json_output_path}")
236+
237+
except sqlite3.Error as e:
238+
print(f"Database error: {e}")
239+
except Exception as e:
240+
print(f"Error: {e}")
241+
finally:
242+
if conn:
243+
conn.close()
244+
245+
164246
if __name__ == "__main__":
165247
db_path = "mqtt_messages.db"
166248
time_windows = [15, 30, 60, 3 * 60, 24 * 60]
@@ -181,10 +263,12 @@ def export_to_json(db_path, json_output_path, time_limit_minutes, use_physical_s
181263
messages_json = f"{data}/cytoscape_messages_{time_str}.json"
182264
messages_physical_json = f"{data}/cytoscape_messages_physical_{time_str}.json"
183265
neighbors_json = f"{data}/cytoscape_neighbors_{time_str}.json"
266+
traceroutes_json = f"{data}/cytoscape_traceroutes_{time_str}.json" # New file for traceroutes
184267

185268
print(f"\nExporting data for {time_str} time window...")
186269

187-
# Export both variants of message data and neighbor data
270+
# Export all data types
188271
export_to_json(db_path, messages_json, minutes, use_physical_sender=False)
189272
export_to_json(db_path, messages_physical_json, minutes, use_physical_sender=True)
190273
export_neighbors_to_json(db_path, neighbors_json, minutes)
274+
export_traceroutes_to_json(db_path, traceroutes_json, minutes)

webpage/index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
<strong>Map of mesh node connections.</strong> Updated: <span id="whenupdated"></span>
3535
<div class="controls">
3636
<select id="fileSelect">
37+
<option value="data/cytoscape_traceroutes_1h.json">🚇 Traceroutes :: 1 hour</option>
38+
<option value="data/cytoscape_traceroutes_3h.json">🚇 Traceroutes :: 3 hours</option>
39+
<option value="data/cytoscape_traceroutes_24h.json">🚇 Traceroutes :: 24 hours</option>
3740
<option value="data/cytoscape_messages_physical_15min.json">➽ sender ⤑ to :: 15 minutes</option>
3841
<option value="data/cytoscape_messages_physical_30min.json">➽ sender ⤑ to :: 30 minutes</option>
3942
<option value="data/cytoscape_messages_physical_1h.json">➽ sender ⤑ to :: 1 hour</option>

0 commit comments

Comments
 (0)