Input handling and general cleanup

This commit is contained in:
30hours 2024-03-17 07:56:53 +00:00
parent 2ac180714e
commit ad19fe9754
11 changed files with 129 additions and 38 deletions

1
.gitignore vendored
View file

@ -1 +1,2 @@
**/__pycache__/
save/

View file

@ -13,4 +13,4 @@ EXPOSE 5000
ENV FLASK_APP=api.py
# run Gunicorn instead of the default Flask development server
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--timeout", "60", "main:app"]
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--timeout", "60", "api:app"]

View file

@ -9,21 +9,32 @@ import os
import requests
import time
import asyncio
import yaml
from common.Message import Message
app = Flask(__name__)
# init config file
try:
with open('config/config.yml', 'r') as file:
config = yaml.safe_load(file)
radar_data = config['radar']
except FileNotFoundError:
print("Error: Configuration file not found.")
except yaml.YAMLError as e:
print("Error reading YAML configuration:", e)
# store state data
servers = [
{"name": "radar4", "url": "radar4.30hours.dev"},
{"name": "radar5", "url": "radar5.30hours.dev"},
{"name": "radar6", "url": "radar6.30hours.dev"}
]
servers = []
for radar in radar_data:
if radar['name'] and radar['url']:
servers.append({'name': radar['name'], 'url': radar['url']})
associators = [
{"name": "ADSB Associator", "id": "adsb-associator"}
]
# todo: ellipse conic int (analytic), SX, arc length
localisations = [
{"name": "Ellipse Parametric (Mean)", "id": "ellipse-parametric-mean"},
{"name": "Ellipse Parametric (Min)", "id": "ellipse-parametric-min"},
@ -31,11 +42,19 @@ localisations = [
{"name": "Ellipsoid Parametric (Min)", "id": "ellipsoid-parametric-min"},
{"name": "Spherical Intersection", "id": "spherical-intersection"}
]
adsbs = [
{"name": "adsb.30hours.dev", "url": "adsb.30hours.dev"},
{"name": "None", "url": ""}
]
# store valid ids
valid = {}
valid['servers'] = [item['url'] for item in servers]
valid['associators'] = [item['id'] for item in associators]
valid['localisations'] = [item['id'] for item in localisations]
valid['adsbs'] = [item['url'] for item in adsbs]
# message received callback
async def callback_message_received(msg):
print(f"Callback: Received message in main.py: {msg}", flush=True)
@ -58,6 +77,20 @@ def serve_static(file):
@app.route("/api")
def api():
api = request.query_string.decode('utf-8')
# input protection
servers_api = request.args.getlist('server')
associators_api = request.args.getlist('associator')
localisations_api = request.args.getlist('localisation')
adsbs_api = request.args.getlist('adsb')
if not all(item in valid['servers'] for item in servers_api):
return 'Invalid server'
if not all(item in valid['associators'] for item in associators_api):
return 'Invalid associator'
if not all(item in valid['localisations'] for item in localisations_api):
return 'Invalid localisation'
if not all(item in valid['adsbs'] for item in adsbs_api):
return 'Invalid ADSB']
# send to event handler
try:
reply_chunks = message_api_request.send_message(api)
reply = ''.join(reply_chunks)

View file

@ -179,6 +179,27 @@ if (cesiumCredit) {
return pointEntity;
}
function is_localhost(ip) {
if (ip === 'localhost') {
return true;
}
ip = ip.replace(/^https?:\/\//, "");
const localRanges = ['127.0.0.1', '192.168.0.0/16', '10.0.0.0/8', '172.16.0.0/12'];
const ipToInt = ip => ip.split('.').reduce((acc, octet) => (acc << 8) + +octet, 0) >>> 0;
return localRanges.some(range => {
const [rangeStart, rangeSize = 32] = range.split('/');
const start = ipToInt(rangeStart);
const end = (start | (1 << (32 - +rangeSize))) >>> 0;
return ipToInt(ip) >= start && ipToInt(ip) <= end;
});
}
// global vars
var adsb_url;
var adsbEntities = {};
@ -193,13 +214,14 @@ window.addEventListener('load', function () {
// add radar points
const radar_names = new URLSearchParams(
window.location.search).getAll('server');
console.log(radar_names);
var radar_config_url = radar_names.map(
url => `http://${url}/api/config`);
if (this.window.location.protocol === "https:") {
radar_config_url = radar_config_url.map(
radar_config_url.forEach(function(url) {
if (!is_localhost(url)) {
radar_config_url = radar_config_url.map(
url => url.replace(/^http:/, 'https:'));
}
}
});
var style_radar = {};
style_radar.color = 'rgba(0, 0, 0, 1.0)';
style_radar.pointSize = 10;
@ -241,19 +263,16 @@ window.addEventListener('load', function () {
}
})
.catch(error => {
// Handle errors during fetch
console.error('Error during fetch:', error);
});
});
// get detection data URL
// get truth URL
adsb_url = new URLSearchParams(
window.location.search).get('adsb').split('&');
adsb_url = adsb_url.map(
url => `http://${url}/data/aircraft.json`);
if (this.window.location.protocol === "https:") {
if (!is_localhost(adsb_url[0])) {
adsb_url = adsb_url.map(
url => url.replace(/^http:/, 'https:'));
}

View file

@ -1,3 +1,4 @@
Flask==3.0.1
gunicorn==21.2.0
requests==2.31.0
PyYAML==6.0.1

26
config/config.yml Normal file
View file

@ -0,0 +1,26 @@
radar:
- name: radar4
url: radar4.30hours.dev
- name: radar5
url: radar5.30hours.dev
- name: radar6
url: radar6.30hours.dev
associate:
adsb:
tar1090: 'adsb.30hours.dev'
tDelete: 5
localisation:
ellipse:
nSamples: 100
threshold: 500
nDisplay: 50
ellipsoid:
nSamples: 60
threshold: 500
nDisplay: 50
3lips:
save: true
tDelete: 60

View file

@ -16,6 +16,7 @@ services:
networks:
- 3lips
volumes:
- ./config:/app/config
- ./common:/app/common
container_name: 3lips-api
@ -28,6 +29,7 @@ services:
networks:
- 3lips
volumes:
- ./config:/app/config
- ./common:/app/common
- ./test:/app/test
- ./save:/app/save
@ -41,4 +43,4 @@ services:
image: cesium-apache
networks:
- 3lips
container_name: 3lips-cesium
container_name: 3lips-cesium

View file

@ -49,15 +49,11 @@ class EllipseParametric:
for target in assoc_detections:
print(target, flush=True)
target_samples = {}
target_samples[target] = {}
for radar in assoc_detections[target]:
print(radar["radar"], flush=True)
print(radar["delay"], flush=True)
# create ellipsoid for radar
ellipsoid = next((
item for item in self.ellipsoids

View file

@ -46,15 +46,11 @@ class EllipsoidParametric:
for target in assoc_detections:
print(target, flush=True)
target_samples = {}
target_samples[target] = {}
for radar in assoc_detections[target]:
print(radar["radar"], flush=True)
print(radar["delay"], flush=True)
# create ellipsoid for radar
ellipsoid = next((
item for item in self.ellipsoids
@ -142,9 +138,6 @@ class EllipsoidParametric:
output[target] = {}
output[target]["points"] = []
print('test', flush=True)
print(samples_intersect, flush=True)
for i in range(len(samples_intersect)):
samples_intersect[i] = Geometry.ecef2lla(
samples_intersect[i][0],

View file

@ -13,6 +13,7 @@ import copy
import json
import hashlib
import os
import yaml
from algorithm.associator.AdsbAssociator import AdsbAssociator
from algorithm.localisation.EllipseParametric import EllipseParametric
@ -23,19 +24,36 @@ from common.Message import Message
from data.Ellipsoid import Ellipsoid
from algorithm.geometry.Geometry import Geometry
# init config file
try:
with open('config/config.yml', 'r') as file:
config = yaml.safe_load(file)
nSamplesEllipse = config['localisation']['ellipse']['nSamples']
thresholdEllipse = config['localisation']['ellipse']['threshold']
nDisplayEllipse = config['localisation']['ellipse']['nDisplay']
nSamplesEllipsoid = config['localisation']['ellipsoid']['nSamples']
thresholdEllipsoid = config['localisation']['ellipsoid']['threshold']
nDisplayEllipsoid = config['localisation']['ellipsoid']['nDisplay']
tDeleteAdsb = config['associate']['adsb']['tDelete']
save = config['3lips']['save']
tDelete = config['3lips']['tDelete']
except FileNotFoundError:
print("Error: Configuration file not found.")
except yaml.YAMLError as e:
print("Error reading YAML configuration:", e)
# init event loop
api = []
# init config
tDelete = 60
tDelete = tDelete
adsbAssociator = AdsbAssociator()
ellipseParametricMean = EllipseParametric("mean", 150, 500)
ellipseParametricMin = EllipseParametric("min", 150, 500)
ellipsoidParametricMean = EllipsoidParametric("mean", 60, 800)
ellipsoidParametricMin = EllipsoidParametric("min", 60, 800)
ellipseParametricMean = EllipseParametric("mean", nSamplesEllipse, thresholdEllipse)
ellipseParametricMin = EllipseParametric("min", nSamplesEllipse, thresholdEllipse)
ellipsoidParametricMean = EllipsoidParametric("mean", nSamplesEllipsoid, thresholdEllipsoid)
ellipsoidParametricMin = EllipsoidParametric("min", nSamplesEllipsoid, thresholdEllipsoid)
sphericalIntersection = SphericalIntersection()
adsbTruth = AdsbTruth(5)
save = True
adsbTruth = AdsbTruth(tDeleteAdsb)
saveFile = '/app/save/' + str(int(time.time())) + '.ndjson'
async def event():
@ -139,6 +157,9 @@ async def event():
for key, value in associated_dets.items()
if isinstance(value, list) and len(value) >= 3
}
if associated_dets_3_radars:
print('Detections from 3 or more radars availble.')
print(associated_dets_3_radars)
associated_dets_2_radars = {
key: value
for key, value in associated_dets.items()
@ -176,7 +197,7 @@ async def event():
[x_rx, y_rx, z_rx],
radar["radar"]
)
points = localisation.sample(ellipsoid, radar["delay"]*1000, 50)
points = localisation.sample(ellipsoid, radar["delay"]*1000, nDisplayEllipse)
for i in range(len(points)):
lat, lon, alt = Geometry.ecef2lla(points[i][0], points[i][1], points[i][2])
if item["localisation"] == "ellipsoid-parametric-mean" or \
@ -239,8 +260,6 @@ def short_hash(input_string, length=10):
# message received callback
async def callback_message_received(msg):
#print(f"Callback: Received message in event.py: {msg}", flush=True)
timestamp = int(time.time()*1000)
# update timestamp if API entry exists

View file

@ -1,2 +1,3 @@
numpy==1.26.4
requests==2.31.0
requests==2.31.0
PyYAML==6.0.1