From 3af701a59883adcba77aced76039e0b30c367bcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Pleva=C4=8D?= Date: Mon, 9 Oct 2023 14:45:39 +0200 Subject: [PATCH] Support for station edit --- station/recorder.py | 19 ++++- web/API/stations.php | 47 ++++++++--- web/CONTROLLERS/targets.php | 36 +++++++++ web/DAL/target.php | 13 ++- web/VIEWS/blocks/target-item.html | 7 ++ web/VIEWS/observation.html | 17 +++- web/VIEWS/station.html | 55 +++++++++++++ web/VIEWS/targets.html | 127 ++++++++++++++++++++++++++++++ web/index.php | 2 +- web/seeds.php | 20 +++-- web/static/js/dashboard.js | 6 +- web/static/js/station.js | 58 ++++++++++++++ 12 files changed, 381 insertions(+), 26 deletions(-) create mode 100644 web/CONTROLLERS/targets.php create mode 100644 web/VIEWS/blocks/target-item.html create mode 100644 web/VIEWS/targets.html create mode 100644 web/static/js/station.js diff --git a/station/recorder.py b/station/recorder.py index 853e958..6de8317 100644 --- a/station/recorder.py +++ b/station/recorder.py @@ -6,6 +6,7 @@ from simplecom import simplecom from pathlib import Path import config import time +import datetime # A recursive function to remove the folder def del_folder(path): @@ -47,8 +48,12 @@ class recorder(threading.Thread): time.sleep(50) + realStart = datetime.datetime.utcnow().timestamp() + os.system(f"satdump record {baseband} --source {self.job['receiver']['params']['radio']} --samplerate {fs} --frequency {self.job['transmitter']['centerFrequency']} --gain {self.job['receiver']['params']['gain']} --baseband_format s8 --timeout {recordTime}") + realEnd = datetime.datetime.utcnow().timestamp() + print(f"Recorder for job {self.job['target']['name']} stoped") puller.setRecorded(self.job["id"]) @@ -63,9 +68,21 @@ class recorder(threading.Thread): adir = f"artefacts/{self.job['id']}" os.makedirs(adir) + replacements = { + "{baseband}": str(baseband) + ".s8", + "{fs}": str(fs), + "{artefactDir}": str(adir), + "{freq}": str(self.job['transmitter']['centerFrequency']), + "{targetNum}": ''.join(x for x in self.job['target']['name'] if x.isdigit()), + "{target}": self.job['target']['name'], + "{start}": str(realStart), + "{end}": str(realEnd) + } + for pipe in self.job["proccessPipe"]: #ok now replace - pipe = pipe.replace("{baseband}", str(baseband) + ".s8").replace("{fs}", str(fs)).replace("{artefactDir}", str(adir)).replace("{freq}", str(self.job['transmitter']['centerFrequency'])) + for k, v in replacements.items(): + pipe = pipe.replace(k, v) os.system(pipe) diff --git a/web/API/stations.php b/web/API/stations.php index 8e2401b..7d7825d 100644 --- a/web/API/stations.php +++ b/web/API/stations.php @@ -39,17 +39,6 @@ return $res; } - function keys($params) { - $stations = new \wsos\database\core\table(\DAL\station::class); - - $res = []; - foreach ($stations->getAll()->values as $station) { - $res[] = ["name" => $station->name->get(), "key" => $station->apiKey->get()]; - } - - return $res; - } - function add($params) { $stations = new \wsos\database\core\table(\DAL\station::class); @@ -66,5 +55,41 @@ $myStation->commit(); + return ["id" => $myStation->id->get()]; + } + + function update($params) { + $stations = new \wsos\database\core\table(\DAL\station::class); + + $myStation = new \DAL\station(); + $myStation->id->set($params["id"]); + $myStation->fetch(); + + $myStation->name->set($params["name"]); + $myStation->description->set($params["description"]); + $myStation->locator->set([ + "gps" => [ + "lat" => floatval($params["lat"]), + "lon" => floatval($params["lon"]), + "alt" => floatval($params["alt"]) + ] + ]); + + $myStation->commit(); + + return ["id" => $myStation->id->get()]; + } + + function apiRegenerate($params) { + $stations = new \wsos\database\core\table(\DAL\station::class); + + $myStation = new \DAL\station(); + $myStation->id->set($params["id"]); + $myStation->fetch(); + + $myStation->apiKey->regenerate(); + + $myStation->commit(); + return ["id" => $myStation->id->get()]; } \ No newline at end of file diff --git a/web/CONTROLLERS/targets.php b/web/CONTROLLERS/targets.php new file mode 100644 index 0000000..68edaa4 --- /dev/null +++ b/web/CONTROLLERS/targets.php @@ -0,0 +1,36 @@ +get("templateLoader"); + $context = $container->get("context"); + $auth = $container->get("auth"); + + // to show this page user must be logined + $auth->requireLogin(); + + $context["targets"] = new \wsos\structs\vector(); + + $targets = (new \wsos\database\core\table(\DAL\target::class))->getAll(); + + foreach ($targets->values as $target) { + + $last = (new \wsos\database\core\table(\DAL\observation::class))->query("transmitter.target.id = ?", [$target->id->get()], "DESC end", 1); + $last = $last->len() > 0 ? "ago " . $last->values[0]->end->strDelta() : "never"; + + $observations = (new \wsos\database\core\table(\DAL\observation::class))->count("transmitter.target.id = ?", [$target->id->get()]); + + $context["targets"]->append([ + "name" => $target->name->get(), + "orbit" => $target->orbit->get(), + "type" => $target->type->get()->name->get(), + "last" => $last, + "observations" => $observations + ]); + } + + $context["targets"] = $context["targets"]->values; + + + $templates->load("targets.html"); + $templates->render($context); + $templates->show(); \ No newline at end of file diff --git a/web/DAL/target.php b/web/DAL/target.php index 232cf2e..f60e5cc 100644 --- a/web/DAL/target.php +++ b/web/DAL/target.php @@ -5,12 +5,23 @@ public \wsos\database\types\text $name; // noaa19, jonHAM, ... , ... public \wsos\database\types\reference $type; // sat, groundStation, ... public \wsos\database\types\text $description; + public \wsos\database\types\enum $orbit; public \wsos\database\types\json $locator; // TLE, GPS or URL locator if avaible - function __construct($id = null, $name = "", $type = null, $description = "", $locator = []) { + function __construct($id = null, $name = "", $type = null, $description = "", $orbit = "", $locator = []) { parent::__construct($id); $this->name = new \wsos\database\types\text($name); $this->type = new \wsos\database\types\reference($type, \DAL\targetType::class); + + $this->orbit = new \wsos\database\types\enum($orbit, [ + "leo", + "meo", + "geo", + "sso", + "gto", + "none", + "other" + ], "other"); $this->description = new \wsos\database\types\text($description); $this->locator = new \wsos\database\types\json($locator); diff --git a/web/VIEWS/blocks/target-item.html b/web/VIEWS/blocks/target-item.html new file mode 100644 index 0000000..7fa10f6 --- /dev/null +++ b/web/VIEWS/blocks/target-item.html @@ -0,0 +1,7 @@ + + {% BIND item.name %} + {% BIND item.type %} + {% BIND item.orbit %} + {% BIND item.last %} + {% BIND item.observations %} + \ No newline at end of file diff --git a/web/VIEWS/observation.html b/web/VIEWS/observation.html index 7cd7946..f9c3378 100644 --- a/web/VIEWS/observation.html +++ b/web/VIEWS/observation.html @@ -214,6 +214,13 @@ return parts[parts.length - 1].toLowerCase(); } + const getMeta = (url, cb) => { + const img = new Image(); + img.onload = () => cb(null, img); + img.onerror = (err) => cb(err); + img.src = url; + }; + function art(el) { var url = el.getAttribute("value"); var name = el.innerHTML; @@ -221,7 +228,15 @@ document.getElementById("artefact-title").innerHTML = name; if (extension(name) == "png" || extension(name) == "jpg" ) { - document.getElementById("artefact-body") .innerHTML = ""; + getMeta(url, (err, img) => { + var ratio = img.naturalWidth / img.naturalHeight; + + if (ratio < 1) { // height is bigger + document.getElementById("artefact-body") .innerHTML = ""; + } else { // width is bigger + document.getElementById("artefact-body") .innerHTML = ""; + } + }); } else if (extension(name) == "json" || extension(name) == "txt" ) { var request = new XMLHttpRequest(); request.open('GET', url, true); diff --git a/web/VIEWS/station.html b/web/VIEWS/station.html index fe7722f..71cfaed 100644 --- a/web/VIEWS/station.html +++ b/web/VIEWS/station.html @@ -141,6 +141,60 @@ +
+
+
+
+

Station basic info

+
+
+
Name
+ +
+
+
+
+
Description
+ +
+
+

Station location

+
+
+
Latitude
+ +
+
+
Longitude
+ +
+
+
Altitude [m]
+ +
+
+ +

API Key

+

API key is used for access to YAGS server from others programs like yags-station.

+
+ + Regenerate API Key + +
+
+ +
+
+ @@ -148,6 +202,7 @@ + diff --git a/web/VIEWS/targets.html b/web/VIEWS/targets.html new file mode 100644 index 0000000..29f70d9 --- /dev/null +++ b/web/VIEWS/targets.html @@ -0,0 +1,127 @@ + + + {% INCLUDE layout/head.html %} + +
+ {% BINDINCLUDE layout/header.html logined %} + + + +
+
+
+ + +
+
+
+

Sats, Stations, HABs, ...

+
+
+ + + + + + + + + + + + {% FOREACH targets RENDER blocks/target-item.html %} + +
NameTypeOrbitLast observationObservations count
+
+
+
+
+
+
+ + + + + + + +
+ + \ No newline at end of file diff --git a/web/index.php b/web/index.php index 90e8f1a..124267a 100644 --- a/web/index.php +++ b/web/index.php @@ -15,9 +15,9 @@ $sites = [ "sites" => [ "observations" => ["controller" => __DIR__ . "/CONTROLLERS/observations.php", "name" => "Observations", "icon" => "/static/icons/telescope.svg", "menu" => true], + "targets" => ["controller" => __DIR__ . "/CONTROLLERS/targets.php", "name" => "Targets", "icon" => "/static/icons/focus-2.svg", "menu" => true], /* "stations" => ["controller" => __DIR__ . "/CONTROLLERS/stations.php", "name" => "Stations", "icon" => "/static/icons/radio.svg", "menu" => true], - "targets" => ["controller" => __DIR__ . "/CONTROLLERS/targets.php", "name" => "Targets", "icon" => "/static/icons/focus-2.svg", "menu" => true], "modulations" => ["controller" => __DIR__ . "/CONTROLLERS/modulations.php", "name" => "Modulations", "icon" => "/static/icons/wave-sine.svg", "menu" => true], "datatypes" => ["controller" => __DIR__ . "/CONTROLLERS/datatypes.php", "name" => "Data Types", "icon" => "/static/icons/file-analytics.svg", "menu" => true], */ diff --git a/web/seeds.php b/web/seeds.php index b28382b..641ca40 100644 --- a/web/seeds.php +++ b/web/seeds.php @@ -8,9 +8,9 @@ $admin->admin->set(true); $admin->commit(); /* commit changes to DB */ - $satType = new \DAL\targetType(); - $satType->name->set("sat"); - $satType->commit(); + $leoWSatTape = new \DAL\targetType(); + $leoWSatTape->name->set("Weather Satellite"); + $leoWSatTape->commit(); $avhrrType = new \DAL\dataType(); $avhrrType->name->set("AVHRR"); @@ -108,7 +108,7 @@ $aptPipe = new \DAL\processPipe(); $aptPipe->name->set("NOAA APT"); $aptPipe->pipe->set([ - "satdump noaa_apt baseband {baseband} {artefactDir} --samplerate {fs} --baseband_format s8", + "satdump noaa_apt baseband {baseband} {artefactDir} --samplerate {fs} --satellite_number {targetNum} --start_timestamp {start} --autocrop_wedges --baseband_format s8", "cp {baseband} {artefactDir}/{freq}_{fs}.s8" ]); @@ -129,7 +129,8 @@ */ $noaa19 = new \DAL\target(); $noaa19->name->set("NOAA 19"); - $noaa19->type->set($satType); + $noaa19->type->set($leoWSatTape); + $noaa19->orbit->set("leo"); $noaa19->description->set("NOAA 19 is the fifth in a series of five Polar-orbiting Operational Environmental Satellites (POES) with advanced microwave sounding instruments that provide imaging and sounding capabilities."); $noaa19->locator->set([ "tle" => [ @@ -173,7 +174,8 @@ */ $noaa18 = new \DAL\target(); $noaa18->name->set("NOAA 18"); - $noaa18->type->set($satType); + $noaa18->type->set($leoWSatTape); + $noaa18->orbit->set("leo"); $noaa18->description->set("NOAA 18, known before launch as NOAA-N, is a weather forecasting satellite run by NOAA. NOAA-N (18) was launched into a sun-synchronous orbit at an altitude of 854 km above the Earth, with an orbital period of 102 minutes. It hosts the AMSU-A, MHS, AVHRR, Space Environment Monitor SEM/2 instrument and High Resolution Infrared Radiation Sounder (HIRS) instruments, as well as the SBUV/2 ozone-monitoring instrument."); $noaa18->locator->set([ "tle" => [ @@ -217,7 +219,8 @@ */ $noaa15 = new \DAL\target(); $noaa15->name->set("NOAA 15"); - $noaa15->type->set($satType); + $noaa15->type->set($leoWSatTape); + $noaa15->orbit->set("leo"); $noaa15->description->set(""); $noaa15->locator->set([ "tle" => [ @@ -258,7 +261,8 @@ $meteor23 = new \DAL\target(); $meteor23->name->set("METEOR M2-3"); - $meteor23->type->set($satType); + $meteor23->type->set($leoWSatTape); + $meteor23->orbit->set("leo"); $meteor23->description->set(""); $meteor23->locator->set([ "tle" => [ diff --git a/web/static/js/dashboard.js b/web/static/js/dashboard.js index 701813d..a42db38 100644 --- a/web/static/js/dashboard.js +++ b/web/static/js/dashboard.js @@ -15,9 +15,9 @@ function addStation() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { - if (this.readyState == 4 && this.status == 200) { - alert(JSON.parse(this.responseText).id); - } + if (this.readyState == 4 && this.status == 200) { + window.location.href = "/station/" + JSON.parse(this.responseText).id; + } }; xhttp.open("POST", "/api/station/add", true); diff --git a/web/static/js/station.js b/web/static/js/station.js new file mode 100644 index 0000000..306935d --- /dev/null +++ b/web/static/js/station.js @@ -0,0 +1,58 @@ +function updateStation(id) { + var station = new FormData(); + + var name = document.getElementById("station-name").value; + var lat = document.getElementById("station-lat").value; + var lon = document.getElementById("station-lon").value; + var alt = document.getElementById("station-alt").value; + var description = document.getElementById("station-description").value; + + station.append('name', name); + station.append('lat', lat); + station.append('lon', lon); + station.append('alt', alt); + station.append('description', description); + station.append('id', id); + + var xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState == 4 && this.status == 200) { + location.reload(); + } + }; + + xhttp.open("POST", "/api/station/update", true); + xhttp.send(station); +} + +function deleteStation(id) { + var station = new FormData(); + + station.append('id', id); + + var xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState == 4 && this.status == 200) { + location.reload(); + } + }; + + xhttp.open("POST", "/api/station/delete", true); + xhttp.send(station); +} + +function apiRegenerate(id) { + var station = new FormData(); + + station.append('id', id); + + var xhttp = new XMLHttpRequest(); + xhttp.onreadystatechange = function() { + if (this.readyState == 4 && this.status == 200) { + location.reload(); + } + }; + + xhttp.open("POST", "/api/station/apiRegenerate", true); + xhttp.send(station); +} \ No newline at end of file