Lots of skeleton and TCP sockets between event/api

This commit is contained in:
30hours 2024-02-09 08:50:13 +00:00
parent 22e51a94e7
commit 61914d0282
7 changed files with 322 additions and 5 deletions

View file

@ -2,10 +2,20 @@
from flask import Flask, Response, render_template, request, redirect, jsonify, send_from_directory from flask import Flask, Response, render_template, request, redirect, jsonify, send_from_directory
import os import os
import sqlite3
import requests import requests
import time
import socket
from util.Sqlite import Sqlite
app = Flask(__name__) app = Flask(__name__)
# init db
# sqlite = Sqlite('./db/3lips.db')
# schema = "api TEXT PRIMARY KEY, timestamp INTEGER NOT NULL"
# sqlite.create_table("data", schema)
# store state data # store state data
servers = [ servers = [
{"name": "radar4", "url": "radar4.30hours.dev"}, {"name": "radar4", "url": "radar4.30hours.dev"},
@ -44,6 +54,11 @@ def serve_static(file):
@app.route("/api") @app.route("/api")
def api(): def api():
api = request.query_string.decode('utf-8')
# timestamp = time.time()*1000
# sqlite.add_entry("data", api, timestamp)
send_data_to_event(api)
urls = request.args.getlist("url") urls = request.args.getlist("url")
data = [{"url": 'http://' + url} for url in urls] data = [{"url": 'http://' + url} for url in urls]
return jsonify(data) return jsonify(data)
@ -54,7 +69,7 @@ def serve_map(file):
public_folder = os.path.join(base_dir, 'map') public_folder = os.path.join(base_dir, 'map')
return send_from_directory(public_folder, file) return send_from_directory(public_folder, file)
# Handle /cesium/ specifically # handle /cesium/ specifically
@app.route('/cesium/') @app.route('/cesium/')
def serve_cesium_index(): def serve_cesium_index():
return redirect('/cesium/index.html') return redirect('/cesium/index.html')
@ -71,5 +86,11 @@ def serve_cesium_content(file):
print(f"Error fetching content from Apache server: {e}") print(f"Error fetching content from Apache server: {e}")
return Response('Error fetching content from Apache server', status=500, content_type='text/plain') return Response('Error fetching content from Apache server', status=500, content_type='text/plain')
def send_data_to_event(data):
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
# Use the service name 'event' as specified in your Docker Compose file
s.connect(('event', 12345))
s.sendall(data.encode())
if __name__ == "__main__": if __name__ == "__main__":
app.run(debug=True) app.run(debug=True)

70
api/util/Sqlite.py Normal file
View file

@ -0,0 +1,70 @@
"""
@file Sqlite.py
@author 30hours
"""
import sqlite3
class Sqlite:
"""
@class Sqlite
@brief A class for interacting with an SQLite database.
@see https://sqlite.org/ for more information on SQLite.
"""
def __init__(self, database_path):
"""
@brief Constructor for the Sqlite class.
@param database_path (str): Path to the SQLite database.
"""
self.connection = sqlite3.connect(database_path)
self.cursor = self.connection.cursor()
def table_exists(self, table_name):
"""
@brief Check if a table if the given name exists in the database.
@param table_name (str): Name of the table.
@return bool: True if the table exists.
"""
self.cursor.execute(f"SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}'")
return self.cursor.fetchone() is not None
def execute_query(self, query, parameters=None):
"""
@brief Execute an SQL query on the database.
@param query (str): SQL query to execute.
@param parameters (tuple, optional): Parameters to bind to the query.
@return None
"""
if parameters:
self.cursor.execute(query, parameters)
else:
self.cursor.execute(query)
self.connection.commit()
def fetch_all_rows(self, query):
"""
@brief Fetch all rows resulting from an SQL query.
@param query (str): SQL query to execute.
@return list: List of tuples representing the result rows.
"""
self.cursor.execute(query)
return self.cursor.fetchall()
def close_connection(self):
"""
@brief Close the SQLite database connection.
@return None
"""
self.connection.close()

View file

@ -0,0 +1,40 @@
"""
@file AdsbAssociator.py
@author 30hours
"""
class AdsbAssociator:
"""
@class AdsbAssociator
@brief A class for associating a detection with ADS-B truth.
@details Uses radar detection data from a blah2 server.
@see blah2 at https://github.com/30hours/blah2.
Uses truth data in delay-Doppler space from an adsb2dd server.
@see adsb2dd at https://github.com/30hours/adsb2dd.
"""
def __init__(self):
"""
@brief Constructor for the AdsbAssociator class.
"""
def process(self, assoc_detections_list):
"""
@brief Associate detections from 2+ radars.
@param assoc_detections_list (list): List of JSON associated detections.
@return str: JSON of associated detections.
"""
def process_1_radar(self, radar_detections, adsb_detections):
"""
@brief Associate detections between 1 radar/truth pair.
@param radar_detections (str): JSON of blah2 radar detections.
@param adsb_detections (str): JSON of adsb2dd truth detections.
@return str: JSON of associated detections.
"""

View file

@ -0,0 +1,32 @@
"""
@file EllipseParametric.py
@author 30hours
"""
class EllipseParametric:
"""
@class EllipseParametric
@brief A class for intersecting ellipses using a parametric approx.
@details Uses associated detections from multiple radars.
@see blah2 at https://github.com/30hours/blah2.
"""
def __init__(self):
"""
@brief Constructor for the EllipseParametric class.
"""
def process(self, assoc_detections):
"""
@brief Perform coord registration using the ellipse parametric method.
@details Generate a (non arc-length) parametric ellipse for each node.
Find
@param radar_detections (str): JSON of blah2 radar detections.
@param adsb_detections (str): JSON of adsb2dd truth detections.
@return str: JSON of associated detections.
"""

View file

@ -1,18 +1,74 @@
import asyncio import asyncio
import sqlite3
import requests
import threading
import socket
from datetime import datetime from datetime import datetime
print('testtttttt', flush=True) from algorithm.associator.AdsbAssociator import AdsbAssociator
from algorithm.coordreg.EllipseParametric import EllipseParametric
from util.Sqlite import Sqlite
# init db
sqlite = Sqlite('./db/3lips.db')
# init event loop
api = []
api_update = []
async def event(): async def event():
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print("Event triggered at: " + timestamp, flush=True) print("Event triggered at: " + timestamp, flush=True)
# Create and run the event loop # main event loop
#for api_x in api:
# request data from API
# response = requests.get(data_i["url_radar_detections"])
# data_i["radar_detections"] =
# API management
#if sqlite.table_exists('data'):
# add new API requests
# rows = sqlite.fetch_all_rows("SELECT * FROM data")
# for row in rows:
# print(row)
# delete old API requests
# update output data on db
# event loop
async def main(): async def main():
# Run the event loop
while True: while True:
await event() await event()
await asyncio.sleep(1) await asyncio.sleep(1)
api = api_update
def start_event_listener():
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
server_socket.bind(('event', 12345))
server_socket.listen()
print("Event listener is waiting for connections...")
while True:
conn, addr = server_socket.accept()
thread = threading.Thread(target=handle_client, args=(conn, addr))
thread.start()
def handle_client(conn, addr):
with conn:
print(f"Connected by {addr}")
while True:
data = conn.recv(1024)
if not data:
break
print(f"Received data: {data.decode()}")
if __name__ == "__main__": if __name__ == "__main__":
threading.Thread(target=start_event_listener).start()
asyncio.run(main()) asyncio.run(main())

View file

@ -1 +1,2 @@
numpy==1.26.4 numpy==1.26.4
requests==2.31.0

97
event/util/Sqlite.py Normal file
View file

@ -0,0 +1,97 @@
"""
@file Sqlite.py
@author 30hours
"""
import sqlite3
class Sqlite:
"""
@class Sqlite
@brief A class for interacting with an SQLite database.
@see https://sqlite.org/ for more information on SQLite.
"""
def __init__(self, database_path):
"""
@brief Constructor for the Sqlite class.
@param database_path (str): Path to the SQLite database.
"""
self.connection = sqlite3.connect(database_path)
self.cursor = self.connection.cursor()
def create_table(self, table_name, schema):
"""
@brief Create a table in the database if it doesn't exist.
@param table_name (str): Name of the table.
@param schema (str): Table schema definition.
@return None
"""
self.cursor.execute(f"CREATE TABLE IF NOT EXISTS {table_name} ({schema});")
self.connection.commit()
def table_exists(self, table_name):
"""
@brief Check if a table if the given name exists in the database.
@param table_name (str): Name of the table.
@return bool: True if the table exists.
"""
self.cursor.execute(f"SELECT name FROM sqlite_master WHERE type='table' AND name='{table_name}'")
return self.cursor.fetchone() is not None
def add_entry(self, table_name, api, timestamp):
"""
@brief Add entry to table.
@param table_name (str): Name of the table.
@param api (str): API URL to add.
@param timestamp (Integer): Timestamp to add.
@return None
"""
connection = sqlite3.connect(self.db_name)
cursor = connection.cursor()
insert_entry_sql = "INSERT INTO {table_name} (api, timestamp) VALUES (?, ?);"
cursor.execute(insert_entry_sql, (api, timestamp))
connection.commit()
def execute_query(self, query, parameters=None):
"""
@brief Execute an SQL query on the database.
@param query (str): SQL query to execute.
@param parameters (tuple, optional): Parameters to bind to the query.
@return None
"""
if parameters:
self.cursor.execute(query, parameters)
else:
self.cursor.execute(query)
self.connection.commit()
def fetch_all_rows(self, query):
"""
@brief Fetch all rows resulting from an SQL query.
@param query (str): SQL query to execute.
@return list: List of tuples representing the result rows.
"""
self.cursor.execute(query)
return self.cursor.fetchall()
def close_connection(self):
"""
@brief Close the SQLite database connection.
@return None
"""
self.connection.close()