@@ -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+
164246if __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"\n Exporting 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 )
0 commit comments