mirror of
https://github.com/30hours/3lips.git
synced 2024-11-18 12:33:58 +00:00
Input handling and general cleanup
This commit is contained in:
parent
2ac180714e
commit
ad19fe9754
11 changed files with 129 additions and 38 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
**/__pycache__/
|
||||
save/
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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)
|
|
@ -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:'));
|
||||
}
|
||||
|
|
|
@ -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
26
config/config.yml
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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],
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
numpy==1.26.4
|
||||
requests==2.31.0
|
||||
requests==2.31.0
|
||||
PyYAML==6.0.1
|
Loading…
Reference in a new issue