Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
D
df-aggregator
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Oleksandr Barabash
df-aggregator
Commits
fccc8af0
Commit
fccc8af0
authored
Dec 23, 2020
by
Corey Koval
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Code cleanup, added GPL Banner
parent
407266ab
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
145 additions
and
59 deletions
+145
-59
df-aggregator.py
df-aggregator.py
+53
-43
cardsmenu.js
static/cardsmenu.js
+16
-0
interest_areas.js
static/interest_areas.js
+16
-0
receiver_configurator.js
static/receiver_configurator.js
+16
-0
cesium.tpl
views/cesium.tpl
+44
-16
No files found.
df-aggregator.py
View file @
fccc8af0
#!/usr/bin/env python3
# df-aggregator, networked radio direction finding software.
# Copyright (C) 2020 Corey Koval
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
import
vincenty
as
v
import
numpy
as
np
import
math
...
...
@@ -20,8 +36,6 @@ from czml3.properties import Position, Polyline, PolylineOutlineMaterial, Color,
from
multiprocessing
import
Process
,
Queue
from
bottle
import
route
,
run
,
request
,
get
,
post
,
put
,
response
,
redirect
,
template
,
static_file
response
.
set_header
(
'Cache-Control'
,
'no-cache, no-store, must-revalidate, max-age=0'
)
DBSCAN_Q
=
Queue
()
DBSCAN_WAIT_Q
=
Queue
()
DATABASE_EDIT_Q
=
Queue
()
...
...
@@ -310,29 +324,28 @@ def process_data(database_name):
conn
.
close
()
return
likely_location
,
intersect_list
,
ellipsedata
###############################################
# Checks interesections stored in the database
# against a lat/lon/radius and removes items
# inside exclusion areas.
###############################################
#######################################################################
# Checks interesections stored in the database against a lat/lon/radius
# and removes items inside exclusion areas.
#######################################################################
def
purge_database
(
type
,
lat
,
lon
,
radius
):
conn
=
sqlite3
.
connect
(
database_name
)
c
=
conn
.
cursor
()
c
.
execute
(
"SELECT latitude, longitude, id FROM intersects"
)
intersect_list
=
c
.
fetchall
()
conn
.
close
()
delete_these
=
[]
purge_count
=
0
for
x
in
intersect_list
:
if
type
==
"exclusion"
:
distance
=
v
.
inverse
(
x
[
0
:
2
],
(
lat
,
lon
))[
0
]
if
distance
<
radius
:
command
=
"DELETE FROM intersects WHERE id=?"
DATABASE_EDIT_Q
.
put
((
command
,
(
x
[
2
],),
False
))
# DATABASE_RETURN.get(timeout=1)
delete_these
.
append
((
x
[
2
],))
purge_count
+=
1
elif
type
==
"aoi"
:
pass
command
=
"DELETE FROM intersects WHERE id=?"
DATABASE_EDIT_Q
.
put
((
command
,
delete_these
,
False
))
# DATABASE_RETURN.get(timeout=1)
DATABASE_EDIT_Q
.
put
((
"done"
,
None
,
False
))
print
(
f
"I purged {purge_count} intersects."
)
...
...
@@ -394,13 +407,13 @@ def run_aoi_rules():
else
:
keep_list
.
append
((
in_aoi
,
id
))
command
=
(
"DELETE from intersects WHERE id=?"
,
del_list
)
DATABASE_EDIT_Q
.
put
((
"bulk"
,
command
,
True
))
command
=
"DELETE from intersects WHERE id=?"
DATABASE_EDIT_Q
.
put
((
command
,
del_list
,
True
))
DATABASE_RETURN
.
get
()
DATABASE_EDIT_Q
.
put
((
"done"
,
None
,
False
))
command
=
(
"UPDATE intersects SET aoi_id=? WHERE id=?"
,
keep_list
)
DATABASE_EDIT_Q
.
put
((
"bulk"
,
command
,
True
))
command
=
"UPDATE intersects SET aoi_id=? WHERE id=?"
DATABASE_EDIT_Q
.
put
((
command
,
keep_list
,
True
))
DATABASE_RETURN
.
get
()
DATABASE_EDIT_Q
.
put
((
"done"
,
None
,
False
))
...
...
@@ -470,7 +483,7 @@ def write_czml(best_point, all_the_points, ellipsedata):
color_property
=
{
"color"
:{
"rgba"
:
[
*
rgb
,
255
]}}
all_point_packets
.
append
(
Packet
(
id
=
str
(
x
[
1
])
+
", "
+
str
(
x
[
0
]),
point
=
{
**
point_properties
,
**
color_property
},
position
=
{
"cartographicDegrees"
:
[
x
[
0
],
x
[
1
],
2
0
]},
position
=
{
"cartographicDegrees"
:
[
x
[
0
],
x
[
1
],
0
]},
))
if
len
(
best_point
)
>
0
:
...
...
@@ -560,16 +573,18 @@ def write_rx_czml():
billboard
=
{
**
rx_properties
,
**
rx_icon
},
position
=
{
"cartographicDegrees"
:
[
x
.
longitude
,
x
.
latitude
,
15
]}))
output
=
Document
([
top
]
+
receiver_point_packets
+
lob_packets
)
return
str
(
output
)
output
=
json
.
dumps
(
json
.
loads
(
str
(
Document
([
top
]
+
receiver_point_packets
+
lob_packets
))),
separators
=
(
','
,
':'
))
# output = str(Document([top] + receiver_point_packets + lob_packets))
return
output
###############################################
# Writes aoi.czml used by the WebUI
###############################################
@get
(
"/aoi.czml"
)
def
wr_aoi_czml
():
response
.
set_header
(
'Cache-Control'
,
'no-cache, no-store, must-revalidate, max-age=0'
)
aoi_packets
=
[]
top
=
Preamble
(
name
=
"
Receiver
s"
)
top
=
Preamble
(
name
=
"
AOI
s"
)
area_of_interest_properties
=
{
"granularity"
:
0.008722222
,
"height"
:
0
,
...
...
@@ -617,8 +632,9 @@ def wr_aoi_czml():
ellipse
=
{
**
aoi_properties
,
**
aoi_info
},
position
=
{
"cartographicDegrees"
:
[
aoi
[
'longitude'
],
aoi
[
'latitude'
],
0
]}))
output
=
Document
([
top
]
+
aoi_packets
)
return
str
(
output
)
output
=
json
.
dumps
(
json
.
loads
(
str
(
Document
([
top
]
+
aoi_packets
))),
separators
=
(
','
,
':'
))
# output = str(Document([top] + aoi_packets))
return
output
###############################################
# CLears the screen if debugging is off.
...
...
@@ -638,8 +654,9 @@ def clear(debugging):
###############################################
@route
(
'/static/<filepath:path>'
,
name
=
'static'
)
def
server_static
(
filepath
):
response
=
static_file
(
filepath
,
root
=
'./static'
)
response
.
set_header
(
'Cache-Control'
,
'no-cache, no-store, must-revalidate, max-age=0'
)
return
static_file
(
filepath
,
root
=
'./static'
)
return
response
###############################################
# Loads the main page of the WebUI
...
...
@@ -726,7 +743,7 @@ def update_rx(action):
elif
action
==
"del"
:
index
=
int
(
data
[
'uid'
])
command
=
"DELETE FROM receivers WHERE station_id=?"
DATABASE_EDIT_Q
.
put
((
command
,
[
int
(
data
[
'uid'
])
],
True
))
DATABASE_EDIT_Q
.
put
((
command
,
[
(
index
,),
],
True
))
DATABASE_RETURN
.
get
(
timeout
=
1
)
DATABASE_EDIT_Q
.
put
((
"done"
,
None
,
False
))
# del_receiver(receivers[index].station_id)
...
...
@@ -782,11 +799,11 @@ def handle_interest_areas(action):
add_aoi
(
aoi_type
,
lat
,
lon
,
radius
)
elif
action
==
"del"
:
command
=
"UPDATE intersects SET aoi_id=? WHERE aoi_id=?"
DATABASE_EDIT_Q
.
put
((
command
,
(
-
1
,
data
[
'uid'
])
,
True
))
DATABASE_EDIT_Q
.
put
((
command
,
[(
-
1
,
data
[
'uid'
]),]
,
True
))
DATABASE_RETURN
.
get
(
timeout
=
1
)
to_table
=
str
(
data
[
'uid'
]
)
to_table
=
(
str
(
data
[
'uid'
]),
)
command
=
"DELETE FROM interest_areas WHERE uid=?"
DATABASE_EDIT_Q
.
put
((
command
,
to_table
,
True
))
DATABASE_EDIT_Q
.
put
((
command
,
[
to_table
,]
,
True
))
DATABASE_RETURN
.
get
(
timeout
=
1
)
DATABASE_EDIT_Q
.
put
((
"done"
,
None
,
False
))
elif
action
==
"purge"
:
...
...
@@ -838,7 +855,6 @@ def run_receiver(receivers):
intersection
=
list
(
intersection
)
avg_conf
=
np
.
mean
([
receivers
[
x
]
.
confidence
,
receivers
[
y
]
.
confidence
])
intersection
.
append
(
avg_conf
)
# intersection.append(in_aoi)
intersection
=
np
.
array
([
intersection
])
if
intersection
.
any
()
!=
None
:
intersect_list
=
np
.
concatenate
((
intersect_list
,
intersection
),
axis
=
0
)
...
...
@@ -853,7 +869,7 @@ def run_receiver(receivers):
command
=
'''INSERT INTO intersects
(time, latitude, longitude, num_parents, confidence, aoi_id)
VALUES (?,?,?,?,?,?)'''
DATABASE_EDIT_Q
.
put
((
command
,
to_table
,
True
))
DATABASE_EDIT_Q
.
put
((
command
,
(
to_table
,)
,
True
))
DATABASE_RETURN
.
get
(
timeout
=
1
)
# Loop to compute intersections for a single receiver and update all receivers
...
...
@@ -890,22 +906,20 @@ def run_receiver(receivers):
intersection
=
list
(
intersection
)
avg_conf
=
np
.
mean
([
conf_rxa
,
conf_rxb
])
intersection
.
append
(
avg_conf
)
# if intersection:
keep
,
in_aoi
=
check_aoi
(
*
intersection
[
0
:
2
])
if
keep
:
# print(intersection)
keep_count
+=
1
to_table
=
[
current_time
,
round
(
intersection
[
0
],
5
),
round
(
intersection
[
1
],
5
),
1
,
intersection
[
2
],
in_aoi
]
command
=
'''INSERT INTO intersects
(time, latitude, longitude, num_parents, confidence, aoi_id)
VALUES (?,?,?,?,?,?)'''
DATABASE_EDIT_Q
.
put
((
command
,
to_table
,
True
))
DATABASE_EDIT_Q
.
put
((
command
,
(
to_table
,)
,
True
))
DATABASE_RETURN
.
get
(
timeout
=
1
)
print
(
f
"Computed and kept {keep_count} intersections."
)
command
=
"INSERT INTO lobs VALUES (?,?,?,?,?,?)"
DATABASE_EDIT_Q
.
put
((
command
,
current_doa
,
True
))
DATABASE_EDIT_Q
.
put
((
command
,
[
current_doa
,]
,
True
))
DATABASE_RETURN
.
get
(
timeout
=
1
)
DATABASE_EDIT_Q
.
put
((
"done"
,
None
,
False
))
...
...
@@ -913,7 +927,6 @@ def run_receiver(receivers):
if
rx
.
isActive
:
rx
.
update
()
except
IOError
:
print
(
"Problem connecting to receiver."
)
# ms.receiving = False
time
.
sleep
(
1
)
if
dots
>
5
:
...
...
@@ -978,7 +991,7 @@ def add_receiver(receiver_url):
new_rx
[
'mobile'
],
new_rx
[
'single'
],
new_rx
[
'latitude'
],
new_rx
[
'longitude'
]]
command
=
"INSERT OR IGNORE INTO receivers VALUES (?,?,?,?,?,?,?)"
DATABASE_EDIT_Q
.
put
((
command
,
to_table
,
True
))
DATABASE_EDIT_Q
.
put
((
command
,
[
to_table
,]
,
True
))
DATABASE_RETURN
.
get
(
timeout
=
1
)
DATABASE_EDIT_Q
.
put
((
"done"
,
None
,
False
))
mobile
=
c
.
execute
(
"SELECT isMobile FROM receivers WHERE station_id = ?"
,
...
...
@@ -1025,7 +1038,7 @@ def update_rx_table():
latitude=?,
longitude=?
WHERE station_id = ?'''
DATABASE_EDIT_Q
.
put
((
command
,
to_table
,
True
))
DATABASE_EDIT_Q
.
put
((
command
,
[
to_table
,]
,
True
))
# try:
DATABASE_RETURN
.
get
(
timeout
=
1
)
# except:
...
...
@@ -1044,7 +1057,7 @@ def add_aoi(aoi_type, lat, lon, radius):
uid
=
(
prev_uid
+
1
)
if
prev_uid
!=
None
else
0
to_table
=
[
uid
,
aoi_type
,
lat
,
lon
,
radius
]
command
=
'INSERT INTO interest_areas VALUES (?,?,?,?,?)'
DATABASE_EDIT_Q
.
put
((
command
,
to_table
,
True
))
DATABASE_EDIT_Q
.
put
((
command
,
[
to_table
,]
,
True
))
DATABASE_RETURN
.
get
(
timeout
=
1
)
DATABASE_EDIT_Q
.
put
((
"done"
,
None
,
False
))
...
...
@@ -1098,6 +1111,7 @@ def database_writer():
lob REAL)'''
)
conn
.
commit
()
while
True
:
# items should be list of lists
command
,
items
,
reply
=
DATABASE_EDIT_Q
.
get
()
if
command
==
"done"
:
conn
.
commit
()
...
...
@@ -1107,12 +1121,8 @@ def database_writer():
if
reply
:
DATABASE_RETURN
.
put
(
True
)
break
elif
command
==
"bulk"
:
c
.
executemany
(
items
[
0
],
items
[
1
])
if
reply
:
DATABASE_RETURN
.
put
(
True
)
else
:
c
.
execute
(
command
,
items
)
c
.
execute
many
(
command
,
items
)
if
reply
:
DATABASE_RETURN
.
put
(
True
)
...
...
static/cardsmenu.js
View file @
fccc8af0
// df-aggregator, networked radio direction finding software.
// Copyright (C) 2020 Corey Koval
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
var
stationUrlHtml_new
=
document
.
createElement
(
'input'
);
stationUrlHtml_new
.
type
=
'text'
;
stationUrlHtml_new
.
id
=
'url-new'
;
...
...
static/interest_areas.js
View file @
fccc8af0
// df-aggregator, networked radio direction finding software.
// Copyright (C) 2020 Corey Koval
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// *************************************************
// * Gets AOI data from backend
// *************************************************
...
...
static/receiver_configurator.js
View file @
fccc8af0
// df-aggregator, networked radio direction finding software.
// Copyright (C) 2020 Corey Koval
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
// Update Map every n milliseconds
var
refreshrate
=
5000
;
var
autoRefresh
=
setInterval
(
function
()
{
reloadRX
();
},
refreshrate
);
...
...
views/cesium.tpl
View file @
fccc8af0
<!DOCTYPE html>
<!-- df-aggregator, networked radio direction finding software. =
Copyright (C) 2020 Corey Koval
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. -->
<html
lang=
"en"
>
<head>
<meta
http-equiv=
"Cache-Control"
content=
"no-cache, no-store, must-revalidate"
>
...
...
@@ -20,14 +37,13 @@
</div>
<script>
var
transmittersDataSource
=
new
Cesium
.
CzmlDataSource
;
var
receiversDataSource
=
new
Cesium
.
CzmlDataSource
;
var
aoiDataSource
=
new
Cesium
.
CzmlDataSource
;
var
transmittersDataSource
=
new
Cesium
.
CzmlDataSource
()
;
var
receiversDataSource
=
new
Cesium
.
CzmlDataSource
()
;
var
aoiDataSource
=
new
Cesium
.
CzmlDataSource
()
;
// Your access token can be found at: https://cesium.com/ion/tokens.
Cesium
.
Ion
.
defaultAccessToken
=
'{
{
access_token
}
}'
;
var
viewer
=
new
Cesium
.
Viewer
(
'cesiumContainer'
,
{
// terrainProvider: Cesium.createWorldTerrain(),
homeButton
:
false
,
timeline
:
false
,
});
...
...
@@ -35,8 +51,10 @@
clockStep
:
Cesium
.
ClockStep
.
SYSTEM_CLOCK_MULTIPLIER
});
viewer
.
clock
.
shouldAnimate
=
true
;
// var hpr = new Cesium.HeadingPitchRange(0.0, 1.57, 5000.0);
viewer
.
zoomTo
(
loadAllCzml
());
var
hpr
=
new
Cesium
.
HeadingPitchRange
(
0.0
,
-
1.57
,
0.0
);
// viewer.zoomTo(loadAllCzml(), hpr);
viewer
.
flyTo
(
loadAllCzml
(),
{
'offset'
:
hpr
}
);
var
scene
=
viewer
.
scene
;
if
(
!
scene
.
pickPositionSupported
)
{
...
...
@@ -210,31 +228,41 @@
function
loadTxCzml
()
{
transmittersDataSource
.
load
(
'/output.czml'
);
Cesium
.
when
(
transmittersDataSource
,
function
(
dataSource1
){
viewer
.
dataSources
.
add
(
dataSource1
);
return
dataSource1
;
});
viewer
.
dataSources
.
add
(
transmittersDataSource
);
return
transmittersDataSource
;
// let promise1 = Cesium.CzmlDataSource.load('/output.czml');
// Cesium.when(promise1, function(dataSource1){
// viewer.dataSources.add(dataSource1);
// return dataSource1;
// });
}
function
loadRxCzml
()
{
receiversDataSource
.
load
(
'/receivers.czml'
);
viewer
.
dataSources
.
add
(
receiversDataSource
);
// console.log("Loaded CZML");
return
receiversDataSource
;
// let promise1 = Cesium.CzmlDataSource.load('/receivers.czml');
// Cesium.when(promise1, function(dataSource1){
// viewer.dataSources.add(dataSource1);
// return dataSource1;
// });
}
function
loadAoiCzml
()
{
aoiDataSource
.
load
(
'/aoi.czml'
);
viewer
.
dataSources
.
add
(
aoiDataSource
);
// console.log("Loaded CZML");
return
aoiDataSource
;
// let promise1 = Cesium.CzmlDataSource.load('/aoi.czml');
// Cesium.when(promise1, function(dataSource1){
// viewer.dataSources.add(dataSource1);
// return dataSource1;
// });
}
function
loadAllCzml
()
{
let
rx
=
loadRxCzml
();
let
aoi
=
loadAoiCzml
();
let
tx
=
loadTxCzml
();
return
rx
;
loadAoiCzml
();
loadTxCzml
();
return
loadRxCzml
();
}
function
clearOld
()
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment