Commit c1cf0ef6 by Corey Koval

Receiver handling improvements

parent b3aa7c67
# DF Aggregator
## New Features 1 December 2020:
- Receivers can be added from the WebUI
- Click the + at the bottom of the receiver cards, enter the URL, click save.
Click the refresh button to update the cards and map.
- A list of receiver URLs is now optional. Receivers are saved to the database.
- Receivers are read from the database first. Duplicate receiver URLs are ignored.
- You can mark a receiver as mobile.
- Click the edit icon for the applicable receiver, click the checkbox to mark
it as mobile, then click save.
- You can now delete receivers from the list. This will remove it from the map
and database. No historical data is affected.
- You can now enable/disable LOB collection from individual receivers.
Click the power button to enable/disable.
- Black is enabled, red is disabled.
- If you lose connectivity to a receiver, that particular receiver will be disabled.
Click the power button to try to reconnect.
## Dependencies:
- Python >= 3.6
- [numpy](https://numpy.org/install/)
......
......@@ -46,17 +46,16 @@ class receiver:
self.isAuto = True
# hashed_url = hashlib.md5(station_url.encode('utf-8')).hexdigest()
# self.uid = hashed_url[:5] + hashed_url[-5:]
try:
self.update()
except:
raise IOError
self.update(first_run=True)
self.isActive = True
# Updates receiver from the remote URL
def update(self):
def update(self, first_run=False):
try:
xml_contents = etree.parse(self.station_url)
xml_station_id = xml_contents.find('STATION_ID')
self.station_id = xml_station_id.text
if first_run:
xml_station_id = xml_contents.find('STATION_ID')
self.station_id = xml_station_id.text
xml_doa_time = xml_contents.find('TIME')
self.doa_time = int(xml_doa_time.text)
xml_freq = xml_contents.find('FREQUENCY')
......@@ -81,7 +80,20 @@ class receiver:
except KeyboardInterrupt:
finish()
except:
raise IOError
if first_run:
self.station_id = "Unknown"
self.latitude = 0.0
self.longitude = 0.0
self.heading = 0.0
self.raw_doa = 0.0
self.doa = 0.0
self.frequency = 0.0
self.power = 0.0
self.confidence = 0
self.doa_time = 0
self.isActive = False
print(f"Problem connecting to {self.station_url}, receiver deactivated. Reactivate in WebUI.")
# raise IOError
# Returns receivers properties as a dict,
# useful for passing data to the WebUI
......@@ -102,7 +114,6 @@ class receiver:
confidence = 0
doa_time = 0
isMobile = False
isActive = True
###############################################
# Converts Lat/Lon to polar coordinates
......@@ -473,9 +484,11 @@ def update_cesium():
###############################################
@get('/rx_params')
def rx_params():
write_czml(*process_data(database_name, geofile))
all_rx = {'receivers':{}}
rx_properties = []
for index, x in enumerate(receivers):
x.update()
rx = x.receiver_dict()
rx['uid'] = index
rx_properties.append(rx)
......@@ -497,6 +510,10 @@ def update_rx(action):
index = int(data['uid'])
del_receiver(receivers[index].station_id)
del receivers[index]
elif action == "activate":
index = int(data['uid'])
receivers[index].isActive = data['state']
# print(f"RX {index} changed state to {data['state']}")
else:
action = int(action)
try:
......@@ -564,10 +581,10 @@ def run_receiver(receivers):
for rx in receivers:
try:
rx.update()
if rx.isActive: rx.update()
except IOError:
print("Problem connecting to receiver.")
ms.receiving = False
# ms.receiving = False
time.sleep(1)
if dots > 5:
......@@ -607,8 +624,9 @@ def add_receiver(receiver_url):
[new_rx['station_id']]).fetchone()[0]
receivers[-1].isMobile = bool(mobile)
print("Created new DF Station at " + receiver_url)
except IOError:
ms.receiving = False
except AttributeError:
pass
conn.close()
###############################################
......@@ -716,7 +734,6 @@ if __name__ == '__main__':
###############################################
read_rx_table()
if rx_file:
print("I got a file!")
with open(rx_file, "r") as file2:
receiver_list = file2.readlines()
for x in receiver_list:
......
......@@ -110,6 +110,21 @@ body {
transition: transform 0.5s cubic-bezier(0.77,0.2,0.05,1.0);
}
#add_station {
width: 23px;
height: 23px;
}
#new_rx_div {
position: relative;
background: #d4d4d4;
color: #111;
font-weight: bold;
padding: 5px;
margin: 5px;
vertical-align: middle;
}
.receiver {
position: relative;
background: #d4d4d4;
......@@ -138,6 +153,20 @@ body {
font-size: 23pt;
}
.delete-icon {
display: block;
position: absolute;
top: 5px;
right: 30px;
}
.activate-icon {
display: block;
position: absolute;
top: 5px;
right: 60px;
}
.edit-checkbox {
cursor: pointer;
opacity: 0; /* hide this */
......@@ -146,13 +175,6 @@ body {
height: 20px;
}
.delete-icon {
display: block;
position: absolute;
top: 5px;
right: 30px;
}
.no-select {
-webkit-user-select: none; /* Safari */
-khtml-user-select: none; /* Konqueror HTML */
......
......@@ -15,14 +15,14 @@ function updateRx(callBack, id) {
// ******************************************************
function editReceivers(rx_json, id) {
const receivers = rx_json['receivers'];
var stationUrlHtml =
"<input type=\"hidden\" id=\"url_" + id + "\"/>";
// var stationUrlHtml =
// "<input type=\"hidden\" id=\"url_" + id + "\"/>";
var stationIDhtml =
"Station ID: <a href=\"" + receivers[id].station_url + "\" target=\"_blank\">" + receivers[id].station_id + "</a>";
var manualInfo =
"<input type=\"hidden\" id=\"manual_toggle_" + receivers[id].uid + "\"/>";
// var manualInfo =
// "<input type=\"hidden\" id=\"manual_toggle_" + receivers[id].uid + "\"/>";
var locationHtml =
"Location: " + receivers[id].latitude + "&#176;, " + receivers[id].longitude + "&#176;";
......@@ -33,14 +33,14 @@ function editReceivers(rx_json, id) {
var freqHtml =
"Tuned to " + receivers[id].frequency + " MHz";
var edit_stationUrlHtml =
"Station URL:<input style=\"width: 300px;\" type=\"text\" value=\"" + receivers[id].station_url + "\" name=\"station_url_" + id + "\" />";
// var edit_stationUrlHtml =
// "Station URL:<input style=\"width: 300px;\" type=\"text\" value=\"" + receivers[id].station_url + "\" name=\"station_url_" + id + "\" />";
var edit_stationIDhtml =
"Station ID:<input style=\"width: 105px;\" type=\"text\" value=\"" + receivers[id].station_id + "\" name=\"station_id_" + id + "\" />";
var edit_manualInfo =
"Manually input receiver info: <input id=\"manual_toggle_" + id + "\" type=\"checkbox\" />";
// var edit_manualInfo =
// "Manually input receiver info: <input id=\"manual_toggle_" + id + "\" type=\"checkbox\" />";
var edit_locationHtml =
"Latitude:<input style=\"width: 105px;\" type=\"text\" value=\"" + receivers[id].latitude + "\" name=\"station_lat_" + id + "\" />" +
......@@ -61,21 +61,21 @@ function editReceivers(rx_json, id) {
document.getElementById(id + "-editicon").innerHTML = "save";
document.getElementById(mobile).innerHTML =
"Mobile Receiver: <input " + isMobile + " id=\"mobilerx_toggle_" + id + "\" type=\"checkbox\" />";
document.getElementById(id + "-manual").innerHTML = edit_manualInfo;
document.getElementById(id + "-url").innerHTML = edit_stationUrlHtml;
document.getElementById("manual_toggle_" + id).onchange = function() {
if (document.getElementById("manual_toggle_" + id).checked) {
document.getElementById(id + "-id").innerHTML = edit_stationIDhtml;
document.getElementById(id + "-location").innerHTML = edit_locationHtml;
document.getElementById(id + "-heading").innerHTML = edit_heading;
document.getElementById(id + "-freq").innerHTML = edit_freqHtml;
} else {
document.getElementById(id + "-id").innerHTML = stationIDhtml;
document.getElementById(id + "-location").innerHTML = locationHtml;
document.getElementById(id + "-heading").innerHTML = heading;
document.getElementById(id + "-freq").innerHTML = freqHtml;
}
}
// document.getElementById(id + "-manual").innerHTML = edit_manualInfo;
// // document.getElementById(id + "-url").innerHTML = edit_stationUrlHtml;
// document.getElementById("manual_toggle_" + id).onchange = function() {
// if (document.getElementById("manual_toggle_" + id).checked) {
// document.getElementById(id + "-id").innerHTML = edit_stationIDhtml;
// document.getElementById(id + "-location").innerHTML = edit_locationHtml;
// document.getElementById(id + "-heading").innerHTML = edit_heading;
// document.getElementById(id + "-freq").innerHTML = edit_freqHtml;
// } else {
// document.getElementById(id + "-id").innerHTML = stationIDhtml;
// document.getElementById(id + "-location").innerHTML = locationHtml;
// document.getElementById(id + "-heading").innerHTML = heading;
// document.getElementById(id + "-freq").innerHTML = freqHtml;
// }
// }
} else {
isMobileCheck = document.getElementById("mobilerx_toggle_" + id);
if (isMobileCheck.checked) {
......@@ -128,6 +128,13 @@ function removerx(uid) {
rxcard.remove();
}
// *****************************************
// * Removes ALL of the RX Cards
// *****************************************
function destroyRxCards() {
document.querySelectorAll('.receiver').forEach(e => e.remove());
}
// *******************************************
// * Removes Rx from Backend and Reloads Map
// *******************************************
......@@ -144,7 +151,29 @@ function deleteReceiver(uid) {
clearOld();
fetch("/rx_params/del", otherParams)
.then(res => {
removerx(uid);
// removerx(uid);
loadRx(createReceivers);
loadCzml();
})
}
// *******************************************************
// * Updates Rx active state from Backend and Reloads Map
// *******************************************************
function activateReceiver(uid, state) {
const activate_rx = { "uid": uid, "state": state };
console.log("I'm sending " + state)
const otherParams = {
headers: {
"content-type": "application/json"
},
body: JSON.stringify(activate_rx),
method: "PUT"
};
clearOld();
fetch("/rx_params/activate", otherParams)
.then(res => {
loadRx(refreshRx);
loadCzml();
})
}
......@@ -155,14 +184,14 @@ function deleteReceiver(uid) {
function showReceivers(rx_json, id) {
const receivers = rx_json['receivers'];
var stationUrlHtml =
"<input type=\"hidden\" id=\"url_" + id + "\"/>";
// var stationUrlHtml =
// "<input type=\"hidden\" id=\"url_" + id + "\"/>";
var stationIDhtml =
"Station ID: <a href=\"" + receivers[id].station_url + "\" target=\"_blank\">" + receivers[id].station_id + "</a>";
var manualInfo =
"<input type=\"hidden\" id=\"manual_toggle_" + receivers[id].uid + "\"/>";
// var manualInfo =
// "<input type=\"hidden\" id=\"manual_toggle_" + receivers[id].uid + "\"/>";
var locationHtml =
"Location: " + receivers[id].latitude + "&#176;, " + receivers[id].longitude + "&#176;";
......@@ -175,16 +204,28 @@ function showReceivers(rx_json, id) {
const urlspan = document.getElementById(id + "-url");
const mobilespan = document.getElementById(id + "-mobile");
const manualspan = document.getElementById(id + "-manual");
// const manualspan = document.getElementById(id + "-manual");
const idspan = document.getElementById(id + "-id");
const locationspan = document.getElementById(id + "-location");
const headingspan = document.getElementById(id + "-heading");
const freqspan = document.getElementById(id + "-freq");
document.getElementById(id + "-activate")
.setAttribute('onclick', "activateReceiver(" + receivers[id].uid + ", " + !receivers[id].active + ")");
if (receivers[id].active == true) {
document.getElementById(id + "-activate")
.setAttribute("title", "Click to disable this receiver.");
document.getElementById(id + "-activateicon").style.color = "black";
} else {
document.getElementById(id + "-activateicon").style.color = "red";
document.getElementById(id + "-activate")
.setAttribute("title", "Click to enable this receiver.");
}
document.getElementById(id + "-mobile").innerHTML = "";
document.getElementById(id + "-editicon").innerHTML = "edit";
document.getElementById(id + "-manual").innerHTML = manualInfo;
document.getElementById(id + "-url").innerHTML = stationUrlHtml;
// document.getElementById(id + "-manual").innerHTML = manualInfo;
// document.getElementById(id + "-url").innerHTML = stationUrlHtml;
document.getElementById(id + "-id").innerHTML = stationIDhtml;
document.getElementById(id + "-location").innerHTML = locationHtml;
document.getElementById(id + "-heading").innerHTML = heading;
......@@ -197,12 +238,8 @@ function showReceivers(rx_json, id) {
// * Iterates through Rx objects on page load/Rx add.
// ****************************************************
function createReceivers(rx_json, id) {
var receivers
if (id == true) {
receivers = [rx_json['receivers'][Object.keys(rx_json['receivers']).length - 1]];
} else {
receivers = rx_json['receivers'];
}
destroyRxCards();
let receivers = rx_json['receivers'];
// console.log(receivers);
for (let i = 0; i < Object.keys(receivers).length; i++) {
......@@ -210,9 +247,9 @@ function createReceivers(rx_json, id) {
rxcard.className = "receiver";
rxcard.id = "rx-" + receivers[i].uid;
const urlspan = document.createElement('span');
// const urlspan = document.createElement('span');
const mobilespan = document.createElement('span');
const manualspan = document.createElement('span');
// const manualspan = document.createElement('span');
const idspan = document.createElement('span');
const locationspan = document.createElement('span');
const headingspan = document.createElement('span');
......@@ -221,6 +258,7 @@ function createReceivers(rx_json, id) {
const editiconspan = document.createElement('span');
editiconspan.classList.add("material-icons", "edit-icon", "no-select");
editiconspan.innerHTML = "edit";
editiconspan.id = receivers[i].uid + "-editicon";
const editcheck = document.createElement('input');
editcheck.classList.add("edit-checkbox", "edit-icon");
......@@ -238,28 +276,49 @@ function createReceivers(rx_json, id) {
deletecheck.id = receivers[i].uid + "-delete";
deletecheck.setAttribute('onclick', "deleteReceiver(" + receivers[i].uid + ")");
urlspan.id = receivers[i].uid + "-url";
const activateiconspan = document.createElement('span');
activateiconspan.classList.add("material-icons", "activate-icon", "no-select");
activateiconspan.innerHTML = "power_settings_new";
activateiconspan.id = receivers[i].uid + "-activateicon";
const activatecheck = document.createElement('input');
activatecheck.classList.add("edit-checkbox", "activate-icon");
activatecheck.type = 'checkbox';
activatecheck.id = receivers[i].uid + "-activate";
// const addnewiconspan = document.createElement('span');
// addnewiconspan.classList.add("material-icons", "add-icon", "no-select");
// addnewiconspan.innerHTML = "add_circle_outline"
// addnewiconspan.id="add_station_icon"
//
// const addnewcheck = document.createElement('input');
// addnewcheck.type = 'checkbox';
// addnewcheck.id="add_station";
// addnewcheck.classList.add("edit-checkbox", "add-icon")
// urlspan.id = receivers[i].uid + "-url";
mobilespan.id = receivers[i].uid + "-mobile";
manualspan.id = receivers[i].uid + "-manual";
// manualspan.id = receivers[i].uid + "-manual";
idspan.id = receivers[i].uid + "-id";
locationspan.id = receivers[i].uid + "-location";
headingspan.id = receivers[i].uid + "-heading";
freqspan.id = receivers[i].uid + "-freq";
editiconspan.id = receivers[i].uid + "-editicon";
document.getElementById("menu").insertBefore(rxcard, document.getElementById("add_station"));
rxcard.appendChild(urlspan);
// rxcard.appendChild(urlspan);
rxcard.appendChild(mobilespan);
rxcard.appendChild(manualspan);
// rxcard.appendChild(manualspan);
rxcard.appendChild(idspan);
rxcard.appendChild(locationspan);
rxcard.appendChild(headingspan);
rxcard.appendChild(freqspan);
rxcard.appendChild(editiconspan);
rxcard.appendChild(deleteiconspan);
rxcard.appendChild(activateiconspan);
rxcard.appendChild(editcheck);
rxcard.appendChild(deletecheck);
rxcard.appendChild(activatecheck);
showReceivers(rx_json, i);
}
......
......@@ -37,7 +37,7 @@
loadRx(refreshRx);
clearOld();
loadCzml();
console.log(response);
// console.log(response);
}
})
}
......@@ -45,13 +45,13 @@
function loadCzml() {
var dataSourcePromise = Cesium.CzmlDataSource.load('/static/output.czml');
viewer.dataSources.add(dataSourcePromise);
console.log("Loaded CZML");
// console.log("Loaded CZML");
return dataSourcePromise;
}
function clearOld() {
viewer.dataSources.removeAll(true);
console.log("Cleared old");
// console.log("Cleared old");
}
// Add Cesium OSM Buildings, a global 3D buildings layer.
......@@ -71,7 +71,7 @@
<input id="add_station" class="edit-checkbox add-icon" type="checkbox" style="width: 23px; height: 23px;"/>
<span id="add_station_icon" class="material-icons add-icon no-select">add_circle_outline</span>
<div style="visibility: hidden; height: 0;" id="new_rx_div" style="padding: 0;" class="receiver">
<div style="visibility: hidden; height: 0;" id="new_rx_div" style="padding: 0;">
<span id="new-url">Station URL:
</span>
</div>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment