From 6a212e493a2383d5eab2ebd6a88884895e91c17b Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Fri, 1 Mar 2024 22:58:11 +0100 Subject: [PATCH 01/62] Adding extra help message to initbuckets.py --- src/transmission/management/commands/initbuckets.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/transmission/management/commands/initbuckets.py b/src/transmission/management/commands/initbuckets.py index 3e603ef7..7e0ef25b 100644 --- a/src/transmission/management/commands/initbuckets.py +++ b/src/transmission/management/commands/initbuckets.py @@ -26,3 +26,5 @@ def handle(self, *args, **options): if buckets_api.find_bucket_by_name(bucket) is None: buckets_api.create_bucket(bucket_name=bucket, retention_rules=retention_rules) print(f"Bucket: {bucket} created") + else: + print(f"Bucket: {bucket} already present") From fa9edd5625b56e54b255d754cff2740817c26168 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Fri, 1 Mar 2024 23:01:01 +0100 Subject: [PATCH 02/62] Set up the InfluxDB organization for grafana from environment variable --- docker-compose.yml | 3 ++- grafana/provisioning/grafana-datasources.yml | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) mode change 100644 => 100755 grafana/provisioning/grafana-datasources.yml diff --git a/docker-compose.yml b/docker-compose.yml index 2a672cd8..378da015 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -68,7 +68,7 @@ services: command: sh -c 'sleep 5; influx setup --bucket "${INFLUX_BUCKET:-default}" --token "${INFLUXDB_V2_TOKEN:-adminpwd}" - --org "${INFLUXDB_V2_ORG:-Delfi Space}" + --org "${INFLUXDB_V2_ORG:-DelfiSpace}" --username=${INFLUX_USERNAME:-"admin"} --password=${INFLUX_PASSWORD:-"adminpwd"} --host=http://influxdb:8086 @@ -88,6 +88,7 @@ services: environment: - GF_SERVER_DOMAIN=${GF_SERVER_DOMAIN:-localhost} - GF_INFLUXDB_V2_TOKEN=${INFLUXDB_V2_TOKEN:-adminpwd} + - INFLUXDB_V2_ORG=${INFLUXDB_V2_ORG:-DelfiSpace} restart: always logging: driver: "json-file" diff --git a/grafana/provisioning/grafana-datasources.yml b/grafana/provisioning/grafana-datasources.yml old mode 100644 new mode 100755 index 683c8be9..28c07979 --- a/grafana/provisioning/grafana-datasources.yml +++ b/grafana/provisioning/grafana-datasources.yml @@ -10,5 +10,4 @@ datasources: token: $GF_INFLUXDB_V2_TOKEN jsonData: version: Flux - organization: Delfi Space - defaultBucket: delfi_pq_downlink \ No newline at end of file + organization: $INFLUXDB_V2_ORG From 977c902065b2cd7585d369646ab555d76223060a Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Fri, 1 Mar 2024 23:02:07 +0100 Subject: [PATCH 03/62] Removing extra log messages --- src/transmission/processing/process_raw_bucket.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/transmission/processing/process_raw_bucket.py b/src/transmission/processing/process_raw_bucket.py index b2b263ae..ac007f51 100644 --- a/src/transmission/processing/process_raw_bucket.py +++ b/src/transmission/processing/process_raw_bucket.py @@ -60,14 +60,10 @@ def parse_and_store_frame(satellite: str, timestamp: str, frame: str, observer: except ValueError: pass - # print(field + " " + str(value) + " " + status) - logger.debug("%s: field: %s, val: %s, status: %s", satellite, field, str(value), status) - db_fields["fields"][field] = value db_fields["tags"]["status"] = status write_api.write(bucket, INFLUX_ORG, db_fields) - # print(db_fields) db_fields["fields"] = {} db_fields["tags"] = {} From 68d8d2e7d3ab9c547df2f21edfa9163588ad4379 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Fri, 1 Mar 2024 23:45:14 +0100 Subject: [PATCH 04/62] Setting display dates for Grafana dashboards --- grafana/dashboards/delfi_c3.json | 8 ++++---- grafana/dashboards/delfi_pq.json | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) mode change 100644 => 100755 grafana/dashboards/delfi_c3.json diff --git a/grafana/dashboards/delfi_c3.json b/grafana/dashboards/delfi_c3.json old mode 100644 new mode 100755 index 5d9f7923..cf875a22 --- a/grafana/dashboards/delfi_c3.json +++ b/grafana/dashboards/delfi_c3.json @@ -106,7 +106,7 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_c3_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"Housekeeping\")\n |> filter(fn: (r) => r[\"_field\"] == \"BootCounter\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_c3_downlink\")\n |> range(start: -20y)\n |> filter(fn: (r) => r[\"_measurement\"] == \"DelfiC3Housekeeping\")\n |> filter(fn: (r) => r[\"_field\"] == \"BootCounter\")", "refId": "A" } ], @@ -121,8 +121,8 @@ "list": [] }, "time": { - "from": "now-6h", - "to": "now" + "from": "2008-04-28T00:00:00.000Z", + "to": "2023-11-14T23:59:59.999Z" }, "timepicker": {}, "timezone": "", @@ -130,4 +130,4 @@ "uid": "ec0b906e-c704-41d9-a063-645b803db188", "version": 1, "weekStart": "" - } \ No newline at end of file + } diff --git a/grafana/dashboards/delfi_pq.json b/grafana/dashboards/delfi_pq.json index 5870f1bd..0fa59e9f 100644 --- a/grafana/dashboards/delfi_pq.json +++ b/grafana/dashboards/delfi_pq.json @@ -963,8 +963,8 @@ "list": [] }, "time": { - "from": "2022-01-14T15:00:00.000Z", - "to": "2022-02-06T14:59:59.000Z" + "from": "2022-01-13T00:00:00.000Z", + "to": "2024-01-08T23:59:59.999Z" }, "timepicker": {}, "timezone": "utc", @@ -972,4 +972,4 @@ "uid": "_j9ikmi4z", "version": 1, "weekStart": "" - } \ No newline at end of file + } From 3a6bd47a377e7f2d01ceb81c3127b5419a3d91ca Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sun, 3 Mar 2024 23:32:39 +0100 Subject: [PATCH 05/62] Reduce the crowdsec log file size --- docker-compose-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose-deploy.yml b/docker-compose-deploy.yml index de42811a..ac37d07a 100644 --- a/docker-compose-deploy.yml +++ b/docker-compose-deploy.yml @@ -22,7 +22,7 @@ services: driver: "json-file" options: max-file: "5" # file count - max-size: "10m" # file size + max-size: "1m" # file size proxy: From 1602483a1184e7d7d70bc47df09a1365e6f4ff54 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sun, 3 Mar 2024 23:37:12 +0100 Subject: [PATCH 06/62] Solving the Django 4 deprecation warnings --- requirements.txt | 8 ++------ src/delfitlm/settings.py | 2 -- src/transmission/processing/save_raw_data.py | 4 ++-- src/transmission/test/test_insert_tle.py | 6 +++--- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/requirements.txt b/requirements.txt index 86d9fe3f..85a81f4b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,8 +26,7 @@ djangorestframework-api-key==3.0.0 hyperlink==21.0.0 idna==3.6 incremental==22.10.0 -influxdb==5.3.1 -influxdb-client==1.40.0 +influxdb-client==1.41.0 isort==5.13.2 jplephem==2.21 lazy-object-proxy==1.10.0 @@ -47,12 +46,9 @@ pylint==3.0.3 pylint-django==2.5.5 pylint-plugin-utils==0.8.2 pyOpenSSL==24.0.0 -python-dateutil==2.8.2 -pytz==2021.3 -pytz-deprecation-shim==0.1.0.post0 requests==2.31.0 Rx==3.2.0 -satellitetle==0.14.0 +satellitetle==0.15.1 service-identity==24.1.0 sgp4==2.23 six==1.16.0 diff --git a/src/delfitlm/settings.py b/src/delfitlm/settings.py index a833f232..d16649f9 100644 --- a/src/delfitlm/settings.py +++ b/src/delfitlm/settings.py @@ -230,8 +230,6 @@ USE_I18N = True -USE_L10N = True - USE_TZ = True # Django Axes settings diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index 3e82d463..0035874f 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -11,7 +11,7 @@ from django.db.models.query import QuerySet from django.utils.dateparse import parse_datetime from skyfield.api import load, EarthSatellite -import pytz +from datetime import timezone from django_logger import logger from members.models import Member from transmission.models import Uplink, Downlink, TLE, Satellite @@ -102,7 +102,7 @@ def parse_submitted_frame(frame: dict, frame_entry: models.Model) -> models.Mode # assign the frame HEX values frame_entry.frame = frame['frame'] # assign the timestamp - frame_entry.timestamp = parse_datetime(frame["timestamp"]).astimezone(pytz.utc) + frame_entry.timestamp = parse_datetime(frame["timestamp"]).astimezone(timezone.utc) # assign frequency, if present if "frequency" in frame and frame["frequency"] is not None: frame_entry.frequency = frame["frequency"] diff --git a/src/transmission/test/test_insert_tle.py b/src/transmission/test/test_insert_tle.py index 01bb099b..cd36bac0 100644 --- a/src/transmission/test/test_insert_tle.py +++ b/src/transmission/test/test_insert_tle.py @@ -2,7 +2,7 @@ from transmission.models import TLE, Satellite from transmission.processing.save_raw_data import save_tle import datetime as dt -import pytz +from datetime import timezone # pylint: disable=all @@ -21,5 +21,5 @@ def test_insert_tle(self): tle_instance = TLE.objects.all()[0] self.assertEqual(tle_instance.sat, new_sat) self.assertEqual(tle_instance.tle, tle) - self.assertEqual(tle_instance.valid_from, dt.datetime(2008, 9, 20, 12, 25, 40, 104187, tzinfo=pytz.UTC)) - self.assertEqual(len(TLE.objects.all()), 1) \ No newline at end of file + self.assertEqual(tle_instance.valid_from, dt.datetime(2008, 9, 20, 12, 25, 40, 104187, tzinfo=timezone.utc)) + self.assertEqual(len(TLE.objects.all()), 1) From b41442214107e9755dc64a6d7b15597b98460d0d Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sun, 3 Mar 2024 23:40:20 +0100 Subject: [PATCH 07/62] Printing launch date and last received data in the main page --- src/delfitlm/settings.py | 1 + src/home/templates/home/index.html | 24 ++++++++----- src/home/views.py | 37 +++++++++++++++++++-- src/transmission/processing/influxdb_api.py | 29 ++++++++++++++-- src/transmission/processing/satellites.py | 6 +++- 5 files changed, 84 insertions(+), 13 deletions(-) diff --git a/src/delfitlm/settings.py b/src/delfitlm/settings.py index d16649f9..9b127a00 100644 --- a/src/delfitlm/settings.py +++ b/src/delfitlm/settings.py @@ -80,6 +80,7 @@ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'django.contrib.humanize', 'django_filters', 'axes', # Django Axes 'channels', diff --git a/src/home/templates/home/index.html b/src/home/templates/home/index.html index 9135b3e9..87275fbb 100644 --- a/src/home/templates/home/index.html +++ b/src/home/templates/home/index.html @@ -1,4 +1,5 @@ {% load static %} +{% load humanize %} {% block title %}DelfiSpace - Home{% endblock %} @@ -44,14 +45,13 @@ } -

Delfi Space - TU Delft SpaceOps

-
+
Delfi Space
Delfi-C3

Status: {{ delfi_c3_status }}

+

Launch:
   {% if delfi_c3_launch is not None %}{{ delfi_c3_launch|date:"M dS Y" }}{% else %}-{% endif %}

+

Last Reception:
   {% if delfi_c3_last_data is not None %}{{ delfi_c3_last_data|date:"M dS Y H:i:s" }} UTC{% else %}-{% endif %}

About Dashboard
@@ -80,7 +82,9 @@
Delfi-C3
Delfi-n3Xt
-

Status: {{delfi_next_status}}

+

Status: {{delfi_next_status}}

+

Launch:
   {% if delfi_next_launch is not None %}{{ delfi_next_launch|date:"M dS Y" }}{% else %}-{% endif %}

+

Last Reception:
   {% if delfi_next_last_data is not None %}{{ delfi_next_last_data|date:"M dS Y H:i:s" }} UTC{% else %}-{% endif %}

About @@ -93,7 +97,9 @@
Delfi-n3Xt
Delfi-PQ
-

Status: {{delfi_pq_status}}

+

Status: {{delfi_pq_status}}

+

Launch:
   {% if delfi_pq_launch is not None %}{{ delfi_pq_launch|date:"M dS Y" }}{% else %}-{% endif %}

+

Last Reception:
   {% if delfi_pq_last_data is not None %}{{ delfi_pq_last_data|date:"M dS Y H:i:s" }} UTC{% else %}-{% endif %}

About Dashboard
@@ -107,19 +113,21 @@
Delfi-PQ
Da Vinci Satellite
-

Status: {{da_vinci_status}}

+

Status: {{da_vinci_status}}

+

Launch:
   {% if da_vinci_launch is not None %}{{ da_vinci_launch|date:"M dS Y" }}{% else %}-{% endif %}

+

Last Reception:
   {% if da_vinci_last_data is not None %}{{ da_vinci_last_data|date:"M dS Y H:i:s" }} UTC{% else %}-{% endif %}

About
-
+ {% include 'home/map.html' %}
diff --git a/src/home/views.py b/src/home/views.py index 72cae4b2..8dc16d61 100644 --- a/src/home/views.py +++ b/src/home/views.py @@ -10,6 +10,9 @@ from skyfield.api import load, EarthSatellite, wgs84, Topos from satellite_tle import fetch_tle_from_celestrak from transmission.processing.satellites import SATELLITES, TIME_FORMAT +from transmission.processing.influxdb_api import get_last_received_frame +from django_logger import logger +import traceback #pylint: disable=W0718 def get_tle(norad_id: str): @@ -112,9 +115,30 @@ def get_satellite_location_now_api(request, norad_id): def _get_satellites_status(): """Method to find satellite status.""" sats_status = {} + logger.info("_get_satellites_status") for sat, info in SATELLITES.items(): + logger.info(sat) sats_status[str(sat + "_status")] = info["status"] - + last_rx_time = get_last_received_frame(sat) + logger.info(type(last_rx_time)) + logger.info(last_rx_time) + if last_rx_time is not None and type(last_rx_time) is datetime: + logger.info("XXX") + sats_status[str(sat + "_last_data")] = last_rx_time#.strftime('%m %d %Y %H:%M:%S UTC') + else: + logger.info("YYY") + sats_status[str(sat + "_last_data")] = None + logger.info(sats_status[str(sat + "_last_data")]) + + logger.info(type(info["launch"])) + + if info["launch"] is not None: + launch_time = datetime.strptime(info["launch"], '%Y-%m-%dT%H:%M:%S.%fZ')#.strftime('%M %d%S %Y') + logger.info(launch_time) + sats_status[str(sat + "_launch")] = launch_time + else: + sats_status[str(sat + "_launch")] = None + logger.info(sats_status) return sats_status @@ -126,7 +150,16 @@ def get_satellites_status(request): def home(request): """Render index.html page""" - context = _get_satellites_status() + #context = _get_satellites_status() + context = [] + logger.info("before Rendering home view") + try: + context = _get_satellites_status() + logger.info("after status") + #get_last_received_frame("delfi_pq") + return render(request, "home/index.html", context) + except Exception as e: + logger.error(traceback.format_exc()) return render(request, "home/index.html", context) diff --git a/src/transmission/processing/influxdb_api.py b/src/transmission/processing/influxdb_api.py index 154fd37f..e997b500 100644 --- a/src/transmission/processing/influxdb_api.py +++ b/src/transmission/processing/influxdb_api.py @@ -3,12 +3,13 @@ import os from influxdb_client import InfluxDBClient from influxdb_client.client.write_api import SYNCHRONOUS +import traceback from transmission.processing.satellites import TIME_FORMAT from django_logger import logger INFLUXDB_URL = "http://influxdb:8086" -INFLUX_ORG = os.environ.get('INFLUXDB_V2_ORG', 'Delfi Space') +INFLUX_ORG = os.environ.get('INFLUXDB_V2_ORG', 'DelfiSpace') def get_influxdb_client(): @@ -86,7 +87,6 @@ def commit_frame(write_api, query_api, satellite: str, link: str, tlm: dict) -> write_frame_to_raw_bucket(write_api, satellite, link, tlm["timestamp"], tlm) return True - def save_raw_frame_to_influxdb(satellite: str, link: str, telemetry) -> bool: """Connect to influxdb and save raw telemetry. Return True if telemetry was stored, False otherwise.""" @@ -102,3 +102,28 @@ def save_raw_frame_to_influxdb(satellite: str, link: str, telemetry) -> bool: stored = stored or commit_frame(write_api, query_api, satellite, link, telemetry) return stored + +def get_last_received_frame(satellite: str): + [write_api, query_api] = get_influx_db_read_and_query_api() + bucket = satellite + "_raw_data" + + query = f'''from(bucket: "{bucket}") + |> range(start: -15y) + |> filter(fn: (r) => r["_measurement"] == "{satellite + "_downlink_raw_data"}") + |> filter(fn: (r) => r["_field"] == "timestamp") + |> tail(n: 1) + ''' + + try: + ret = query_api.query(query=query) + + for table in ret: + logger.info(table.records[0]["_value"]) + #for record in table.records: + # #logger.info(record.values) + # logger.info(record["_value"]) + return datetime.strptime(table.records[0]["_value"], '%Y-%m-%dT%H:%M:%SZ') + + except: + e = traceback.format_exc() + logger.error(e) diff --git a/src/transmission/processing/satellites.py b/src/transmission/processing/satellites.py index 9cd2046c..89e5606d 100644 --- a/src/transmission/processing/satellites.py +++ b/src/transmission/processing/satellites.py @@ -6,17 +6,21 @@ "delfi_pq": { "norad_id": '51074', "status": "Decayed", + "launch": "2022-01-13T18:00:00.000Z", }, "delfi_next": { "norad_id": '39428', "status": "Non Operational", + "launch": "2013-11-21T18:00:00.000Z", }, "delfi_c3": { "norad_id": '32789', "status": "Decayed", + "launch": "2008-04-28T18:00:00.000Z", }, "da_vinci": { "norad_id": None, #update id - "status": "Under Development" + "status": "Under Development", + "launch": None, } } From 55037bd86cef2bcd2b01327a62eb59088e213507 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Mon, 4 Mar 2024 17:07:24 +0100 Subject: [PATCH 08/62] Increase the hasked_key size to 150 characters following djangorestframework-api-key version 2.2.0 --- ...alter_apikey_hashed_key_alter_apikey_id.py | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/members/migrations/0002_alter_apikey_hashed_key_alter_apikey_id.py diff --git a/src/members/migrations/0002_alter_apikey_hashed_key_alter_apikey_id.py b/src/members/migrations/0002_alter_apikey_hashed_key_alter_apikey_id.py new file mode 100644 index 00000000..8a380f0a --- /dev/null +++ b/src/members/migrations/0002_alter_apikey_hashed_key_alter_apikey_id.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.10 on 2024-03-04 16:03 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('members', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='apikey', + name='hashed_key', + field=models.CharField(editable=False, max_length=150), + ), + migrations.AlterField( + model_name='apikey', + name='id', + field=models.CharField(editable=False, max_length=150, primary_key=True, serialize=False, unique=True), + ), + ] From 55a68c9fa933648eed1a0aa9fc487c7f754e3be8 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Mon, 4 Mar 2024 21:55:28 +0100 Subject: [PATCH 09/62] Store the user name with frames, not the Django ID --- src/transmission/processing/save_raw_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index 0035874f..0a99f635 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -70,7 +70,7 @@ def build_frame_model_object(frame: dict, username: str, application: str = None if not user.has_perm("transmission.add_downlink"): raise PermissionDenied() frame_entry = Downlink() - frame_entry.observer = user.UUID + frame_entry.observer = user else: raise ValidationError("Invalid frame link.") From 1bd0bd01325dafa08e1accfdb0542020f144f25f Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Thu, 14 Mar 2024 10:38:35 +0100 Subject: [PATCH 10/62] Start processign job imediatly when frames is received --- src/transmission/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/transmission/views.py b/src/transmission/views.py index 9853fc38..68c0bae1 100644 --- a/src/transmission/views.py +++ b/src/transmission/views.py @@ -50,7 +50,7 @@ def submit_frame(request): # pylint:disable=R0911 api_key_name, number_of_saved_frames) try: - schedule_job("buffer_processing", date=datetime.now() + timedelta(seconds=30)) + schedule_job("buffer_processing", date=datetime.now()) except ValidationError as _: pass From 7a1507423bcaf14013a3caebef131abf5a9a2d39 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Fri, 22 Mar 2024 18:19:55 +0100 Subject: [PATCH 11/62] Map zoom adjusted --- src/static/map.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/static/map.js b/src/static/map.js index 446300dc..81d09f11 100644 --- a/src/static/map.js +++ b/src/static/map.js @@ -9,7 +9,14 @@ let SATELLITES = { // refresh rate in seconds const refreshRate = 2; -let map = L.map('map').setView([latitude, longitude], zoomLevel); +let map = L.map('map',{ + noWrap: true, + zoomSnap: 0.1, + maxBounds: [ + [-90.0, -180.0], + [90.0, 180.0]], + maxBoundsViscosity: 1.0 + }).setView([0, 0], 0); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' @@ -20,10 +27,19 @@ sunlightOverlay.addTo(map); setInterval(function(){updateTerminator(sunlightOverlay)}, refreshRate * 1000); +let minZoom = 1.0 / 10.0 * Math.ceil(10 * Math.log2(Math.max(map.getSize().x, map.getSize().y) / 256)) +map.setMinZoom(minZoom); + function updateTerminator(t) { t.setTime(); } +map.on('resize', function () + { + let minZoom = 1.0 / 10.0 * Math.ceil(10 * Math.log2(Math.max(map.getSize().x, map.getSize().y) / 256)) + map.setMinZoom(minZoom); + }); + let markers = {} function findSat() { @@ -31,10 +47,8 @@ function findSat() { .then(response => response.json()) .then(data => { let satellite_list = data.satellites; - console.log(satellite_list); for (const element of satellite_list){ - console.log(element); let sat = element.satellite let lat = element.latitude.toFixed(2); let long = element.longitude.toFixed(2); From c52d490f82b512a5259c50dd6855b1b836e9938e Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Fri, 22 Mar 2024 23:03:58 +0100 Subject: [PATCH 12/62] Cleanup debug messages --- src/home/views.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/home/views.py b/src/home/views.py index 8dc16d61..c63f5b09 100644 --- a/src/home/views.py +++ b/src/home/views.py @@ -115,30 +115,19 @@ def get_satellite_location_now_api(request, norad_id): def _get_satellites_status(): """Method to find satellite status.""" sats_status = {} - logger.info("_get_satellites_status") for sat, info in SATELLITES.items(): - logger.info(sat) sats_status[str(sat + "_status")] = info["status"] last_rx_time = get_last_received_frame(sat) - logger.info(type(last_rx_time)) - logger.info(last_rx_time) if last_rx_time is not None and type(last_rx_time) is datetime: - logger.info("XXX") sats_status[str(sat + "_last_data")] = last_rx_time#.strftime('%m %d %Y %H:%M:%S UTC') else: - logger.info("YYY") sats_status[str(sat + "_last_data")] = None - logger.info(sats_status[str(sat + "_last_data")]) - - logger.info(type(info["launch"])) if info["launch"] is not None: launch_time = datetime.strptime(info["launch"], '%Y-%m-%dT%H:%M:%S.%fZ')#.strftime('%M %d%S %Y') - logger.info(launch_time) sats_status[str(sat + "_launch")] = launch_time else: sats_status[str(sat + "_launch")] = None - logger.info(sats_status) return sats_status @@ -152,17 +141,14 @@ def home(request): """Render index.html page""" #context = _get_satellites_status() context = [] - logger.info("before Rendering home view") + try: context = _get_satellites_status() - logger.info("after status") - #get_last_received_frame("delfi_pq") return render(request, "home/index.html", context) except Exception as e: logger.error(traceback.format_exc()) return render(request, "home/index.html", context) - def ban_view(request): """Ban request""" raise PermissionDenied From 3955e4608228638793d682c59480c66e72bc0567 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Fri, 22 Mar 2024 23:15:38 +0100 Subject: [PATCH 13/62] Added norad id to satellite location api --- src/home/views.py | 9 ++++--- src/static/map.js | 69 ++++++++++++++++++++++++++++------------------- 2 files changed, 47 insertions(+), 31 deletions(-) diff --git a/src/home/views.py b/src/home/views.py index c63f5b09..95d1e331 100644 --- a/src/home/views.py +++ b/src/home/views.py @@ -43,7 +43,10 @@ def get_tle(norad_id: str): return tles[norad_id]['tle'] except Exception as _: - pass + # something went wrong retrieving TLEs + # use the old ones, even if outdated + logger.error("Error retrieving TLEs\n%s", traceback.format_exc()) + return tles[norad_id]['tle'] return None @@ -53,7 +56,7 @@ def get_satellite_location_now(norad_id: str) -> dict: tle = get_tle(norad_id) if tle is None: - return {"satellite": None, "latitude": None, "longitude": None, "sunlit": None} + return {"satellite": None, "norad_id": None, "latitude": None, "longitude": None, "sunlit": None} time_scale = load.timescale() time = time_scale.now() @@ -70,7 +73,7 @@ def get_satellite_location_now(norad_id: str) -> dict: eph = load('de421.bsp') sunlit = satellite.at(time).is_sunlit(eph) - return {"satellite": str(tle[0]), "latitude": lat_deg, "longitude": lon_deg, "sunlit": int(sunlit)} + return {"satellite": str(tle[0]), "norad_id": norad_id, "latitude": lat_deg, "longitude": lon_deg, "sunlit": int(sunlit)} def get_next_pass_over_delft(request, norad_id: str): diff --git a/src/static/map.js b/src/static/map.js index 81d09f11..c9a76a96 100644 --- a/src/static/map.js +++ b/src/static/map.js @@ -1,10 +1,6 @@ let zoomLevel = 3; let latitude = 52.0116; let longitude = 4.3571; -let SATELLITES = { - "DELFI-N3XT": '39428', - -} // refresh rate in seconds const refreshRate = 2; @@ -22,26 +18,37 @@ L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© OpenStreetMap contributors' }).addTo(map); +// use an icon to show the satellite position +var satellite = L.icon({ + iconUrl: 'static/satellite.webp', + + iconSize: [116, 87], // size of the icon + iconAnchor: [58, 43], // point of the icon which will correspond to marker's location + popupAnchor: [0, -21] // point from which the popup should open relative to the iconAnchor +}); + +// add the solar terminator let sunlightOverlay = L.terminator(); sunlightOverlay.addTo(map); +// update the solar terminator periodically +function updateTerminator(t) +{ + t.setTime(); +} setInterval(function(){updateTerminator(sunlightOverlay)}, refreshRate * 1000); -let minZoom = 1.0 / 10.0 * Math.ceil(10 * Math.log2(Math.max(map.getSize().x, map.getSize().y) / 256)) -map.setMinZoom(minZoom); - -function updateTerminator(t) { - t.setTime(); +// limit the zoom value to display the full Earth only once +function setMinimumZoom(map) +{ + let minZoom = 1.0 / 10.0 * Math.ceil(10 * Math.log2(Math.max(map.getSize().x, map.getSize().y) / 256)) + map.setMinZoom(minZoom); } - -map.on('resize', function () - { - let minZoom = 1.0 / 10.0 * Math.ceil(10 * Math.log2(Math.max(map.getSize().x, map.getSize().y) / 256)) - map.setMinZoom(minZoom); - }); +setMinimumZoom(map); let markers = {} +// display the satellites on the map function findSat() { fetch("/location/all/") .then(response => response.json()) @@ -49,23 +56,20 @@ function findSat() { let satellite_list = data.satellites; for (const element of satellite_list){ - let sat = element.satellite + let sat = element.satellite; let lat = element.latitude.toFixed(2); let long = element.longitude.toFixed(2); + let norad_id = element.norad_id; // let sunlit = element.sunlit; if (sat != null){ - updateSatMarker(sat, lat, long); + updateSatMarker(sat, norad_id, lat, long); } } }).catch(e => console.log(e)); } - - -function updateSatMarker(sat, lat, long,) { - - - fetch("/next-pass/"+ SATELLITES[sat]+"/") +function updateSatMarker(sat, norad_id, lat, long,) { + fetch("/next-pass/"+ norad_id + "/") .then(response => response.json()) .then(data => { let pass_events = data.passes; @@ -81,18 +85,27 @@ function updateSatMarker(sat, lat, long,) { if (markers.hasOwnProperty(sat)){ markers[sat].setLatLng([lat, long]); - markers[sat].bindPopup(sat + " Lat: " + lat + " Long: " + long +"
"+ next_pass); + //markers[sat].bindPopup(sat + " Lat: " + lat + " Long: " + long +"
"+ next_pass); + markers[sat].bindPopup(sat); } else{ - let marker = L.marker([lat, long]).addTo(map).bindPopup(sat + " Lat: " + lat + " Long: " + long +"
"+ next_pass).openPopup(); + //let marker = L.marker([lat, long], {icon: satellite}).addTo(map).bindPopup(sat + " Lat: " + lat + " Long: " + long +"
"+ next_pass); + let marker = L.marker([lat, long], {icon: satellite}).addTo(map).bindPopup(sat).openPopup(); markers[sat] = marker } }).catch(e => console.log(e)); - -// updates map view according to Marker's new position -// map.setView([lat, long]); } +findSat(); + +// automatically update the satellite positions setInterval(findSat, refreshRate * 1000); + +// automatically update the minimum zoom if the map is resized +map.on('resize', function () + { + setMinimumZoom(map); + }); + From 956a5b1bc01c059b588278682ff3704554a0b967 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Fri, 22 Mar 2024 23:17:07 +0100 Subject: [PATCH 14/62] Adding satellite icon to map --- src/static/satellite.webp | Bin 0 -> 32380 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/static/satellite.webp diff --git a/src/static/satellite.webp b/src/static/satellite.webp new file mode 100644 index 0000000000000000000000000000000000000000..4119632dd461081683a56e233a2706fc4569e3aa GIT binary patch literal 32380 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

%hZOa>O9iv*nZoz1v>2 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 DP@Nlt literal 0 HcmV?d00001 From 14718985877d3b6fe3b470f5d74b12bdb79df92b Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Fri, 22 Mar 2024 23:24:51 +0100 Subject: [PATCH 15/62] Changed homepage main picture --- src/home/templates/home/index.html | 12 +++++++++++- src/static/tud-lr.webp | Bin 400558 -> 243022 bytes 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/home/templates/home/index.html b/src/home/templates/home/index.html index 87275fbb..a17679c1 100644 --- a/src/home/templates/home/index.html +++ b/src/home/templates/home/index.html @@ -45,8 +45,14 @@ } -

Delfi Space - TU Delft SpaceOps

+

DelfiSpace

+ + +

Space Operations at the Delft University of Technology

+ +

Our Satellites

@@ -128,7 +134,11 @@
Da Vinci Satellite
+ +

Where are our satellites

+ {% include 'home/map.html' %} +

Only currently orbiting satellites are shown on the map. Decayed and not launched satellites ones are not visible.

{% endblock %} diff --git a/src/static/tud-lr.webp b/src/static/tud-lr.webp index 1ba7fad6b50796e3f43de38d12ddc86423e1ba4a..810d73ac0af3cd68119e86a0ee1590d6762eda33 100644 GIT binary patch literal 243022 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�tz?m^miS+!W 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
G}KCA8i5{pMQ-R8Dn8M=5^1kubVog7 zqp!_dn2-r`f6Z+XF!EaBywN5VatPn7DMi&W4zgd_2TqLly zW$GNGjxQ9!m5OJf59)YeUJwA-cCaaMRZBCmm$bCqO!t9`*>o`Zv{7v;yp7skE-hfm z@@#|H!u82kRdWc31?>z8hC5*acwl(^49p;UmC_qMbu=rayu$?9%aMK=7b22-we~2~ zn3kO5YTW|25(!EGuON;O$3g0T?NlyDwAY3N9;)ITLl ztW_uZ;J+-FeCEd|)0!B+pwb6w;L`wzufor>TqP}E1y^Vx=c(dzg>aE4^iIkLKGmt#hyVA?&jPnV zq+dY^Q|mx2Vhjm&1^`rY@T@jm7bjV6qlKhQLc!@^;9oJ^4Orz|JT|U|*cga57NRWN zDw#D@#bykKg%ZwktglLk;6CS1V|8apwt3*nuLEPj&oD3WZRy`L^yoXHT57qF6nVln zioHO0@Z~D)Z@?9kI^LuvaBAO(_07DP`tgbmFxCX2>@b41io_6E1#qRhO968o`>DuT zT#^8DbN^MWtILnu{>oX{?u7u1dnZq^_3*W3-*jYJk+AkB0ZUZfru)D0a^k)IXq$gRFJZM|Ff|$PVWH*-Zb{@1VnI0~wEy9Z#Mbj&i zc+6%lK`q@ZYoHs`Ku=4%4I*&zAzkG@`H8)cc7`ev8lfE5>*(Rmue-XWrEbiEC>z@y zWa3=kxQuEU{q}*iojyjF&Dz*H8PDXaw)wKygliQP^%wq2a33PO_~po_*!N?5AVo)c z7kpI)8iP4nPg)k!=lYSnLar&6O4hp^B9uM;c}Cr;LjpoOBUwbD*|~KreFNtBWpbjZ zo1;H57xIIIQd*YoHicUxSmtCGjZ=PzMHUidDhugAMy+%+z;l!ZhiS$AZurEwW~j?7 zUr#>!qIuvBuG8`ZfO$O7tpi(VR|p!rUOjVc~qSW`5CzbJJzgk{>Ogi0v8i}SjQkz7jbJi=0-p;U@wj|1S_jT9{Lqc=u^#IP-Cpiu6j7y z_Z2z|gdc0_OfC*_>&8yfj5Ongotca71n7)g0Gka@5gW-h`OHZ+@sze-=ZgFI=N0P) zUP1JA+1LhJt#>Lrbv`Iop&dEvqI}Q91$sTxEI1u81tocpkB|x*h>H$}Y_w4*p7<&j z?a_94#)e8Rm(5hTz|I!cU^+Bdg2=FmYXX=$Q=!%_JkxdO-MeMd}gUM=<~nI ziKmjjY}dLN!|_VrxhWJVWbxlQ!sr2vSz z0X;}L(!CvbL=pzW{!+A%819GHZ~3b9M>dr4!ZmrcF~|QAg`y*_hl6}8f;pK7?6da={+&FcW}eZeT{&`%4 zRWBx*eqv+|hk@zKedaWj-X&9L?+6k@&u1LO`DG!HcrzOfLr{ZMEgr`8FCbL8Z3@gU z-f-pqxW>|MIs$=Zq{Y69l5jSgk6xMWstQS2NN3;5)o3q9FCb42r#)m^_q+z0*8(=0 zq^2tCd;7k}hTml9yA^4l)!9W$flB#c2XB<}+$un++Xgc>NhTQeUPCkJ3^B+7kim-2 z6T>wss&YOSZwhZJBNKoJ3`GC{0013xnlS1-au3fM*@A@M6&WR?K1w%QQL`{6c-AvtQn{Voop|&=>PUDNGTOvrm8?uM9K5HC9i0rR2IN!4DWd;SW!@|YD!D=Rti3V{d zOtEi%p&jvdf&60oUhKVVvcY^fVBKCACe!f2=MVWY;ja~JAl8-^oaeU={du%9h-GDc z#kXP+Q>6uU(=1;H9>OStJG4peunmbcRg6rV6yS^rAs>6WklbrE<>Dr*laQEk%7@@F z2IJqMealx(yBgsvxukdy0fdT^cJTei)=m>p@R|v0cF8tnX`a!w2z3?$4C>T7AGR?& zS^GN@GM6c^5MtegMN8>6f!P4@tY0q}cwkMSjLhDq)%0D#z}PFwK4j6uX(qBSsQQVT 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 CGX`J) literal 400558 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

t)u(HrY)OVxs!heUdH`Ggc4!=6iySdSHQ+ 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%0AM}M5T!fwq7o>%N0i934zlt2|BjF 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 >tb2uA%re|29_;(=!+f6{^QQ{vs? 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 YXL731m@KtrAKn5ViCXBR From 70f8e5082bab16949924e60258b4421ef943a3cb Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Fri, 22 Mar 2024 23:28:13 +0100 Subject: [PATCH 16/62] Removing debug messages --- src/transmission/processing/influxdb_api.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/transmission/processing/influxdb_api.py b/src/transmission/processing/influxdb_api.py index e997b500..553cf418 100644 --- a/src/transmission/processing/influxdb_api.py +++ b/src/transmission/processing/influxdb_api.py @@ -118,10 +118,6 @@ def get_last_received_frame(satellite: str): ret = query_api.query(query=query) for table in ret: - logger.info(table.records[0]["_value"]) - #for record in table.records: - # #logger.info(record.values) - # logger.info(record["_value"]) return datetime.strptime(table.records[0]["_value"], '%Y-%m-%dT%H:%M:%SZ') except: From ad783e7219eb5000eee5a9933c7a871e4c3260b5 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 23 Mar 2024 23:13:08 +0100 Subject: [PATCH 17/62] Allow staff users to submit frames on behalf of other users --- src/transmission/processing/save_raw_data.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index 0a99f635..ac6197a5 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -64,13 +64,25 @@ def build_frame_model_object(frame: dict, username: str, application: str = None if not user.has_perm("transmission.add_uplink"): raise PermissionDenied() frame_entry = Uplink() - frame_entry.operator = user + if "username" not in frame: + frame_entry.operator = user + else: + if user.is_staff: + frame_entry.operator = frame["username"] + else: + raise PermissionDenied() elif frame["link"] == "downlink": if not user.has_perm("transmission.add_downlink"): raise PermissionDenied() frame_entry = Downlink() - frame_entry.observer = user + if "username" not in frame: + frame_entry.observer = user + else: + if user.is_staff: + frame_entry.observer = frame["username"] + else: + raise PermissionDenied() else: raise ValidationError("Invalid frame link.") From f067eba10ec231efb49ffb4dbd6d819366481f93 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 23 Mar 2024 23:41:07 +0100 Subject: [PATCH 18/62] Added buffer reprocessing task --- src/transmission/forms/forms.py | 1 + src/transmission/processing/save_raw_data.py | 30 ++++++++++++++++---- src/transmission/scheduler.py | 9 ++++-- 3 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/transmission/forms/forms.py b/src/transmission/forms/forms.py index 809f75eb..bb8a599f 100644 --- a/src/transmission/forms/forms.py +++ b/src/transmission/forms/forms.py @@ -12,6 +12,7 @@ jobs = [ (None, '-'), ('buffer_processing', 'Frame Buffer Processing'), + ('buffer_reprocessing', 'Frame Buffer Reprocessing'), ('scraper', 'Scrape'), ('raw_bucket_processing', 'Bucket Processing (new frames)'), ('reprocess_failed_raw_bucket', 'Bucket Reprocessing (failed frames)'), diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index ac6197a5..b7a88193 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -135,13 +135,30 @@ def process_uplink_and_downlink() -> tuple: """Process all unprocessed uplink and downlink frames, i.e. move them to the influxdb raw satellite data bucket.""" + logger.info("Process incoming frames") downlink_frames = Downlink.objects.all().filter(processed=False) - process_frames(downlink_frames, "downlink") + downlink_frames_count = process_frames(downlink_frames, "downlink") uplink_frames = Uplink.objects.all().filter(processed=False) - process_frames(uplink_frames, "uplink") + uplink_frames_count = process_frames(uplink_frames, "uplink") - return len(downlink_frames), len(uplink_frames) + logger.info("Incoming frames processed") + return downlink_frames_count, uplink_frames_count + + +def reprocess_uplink_and_downlink() -> tuple: + """Reprocess all invalid uplink and downlink frames, + i.e. move them to the influxdb raw satellite data bucket.""" + + logger.info("Reprocess incoming frames") + downlink_frames = Downlink.objects.all().filter(processed=True).filter(invalid=True) + downlink_frames_count = process_frames(downlink_frames, "downlink") + + uplink_frames = Uplink.objects.all().filter(processed=True).filter(invalid=True) + uplink_frames_count = process_frames(uplink_frames, "uplink") + + logger.info("Incoming frames reprocessed") + return downlink_frames_count, uplink_frames_count def process_frames(frames: QuerySet, link: str) -> int: @@ -154,10 +171,9 @@ def process_frames(frames: QuerySet, link: str) -> int: for frame_obj in frames: frame_dict = frame_obj.to_dictionary() stored, satellite = store_frame_to_influxdb(frame_dict, link) + frame_obj.processed = True if stored: - frame_obj.processed = True frame_obj.invalid = False - frame_obj.save() processed_frames += 1 if satellite not in processed_frames_timestamps: processed_frames_timestamps[satellite] = include_timestamp_in_time_range( @@ -171,6 +187,10 @@ def process_frames(frames: QuerySet, link: str) -> int: frame_obj.timestamp, existing_range=processed_frames_timestamps[satellite] ) + else: + frame_obj.invalid = True + frame_obj.save() + for satellite, time_range in processed_frames_timestamps.items(): path = get_new_data_buffer_temp_folder(satellite) path += satellite + "_" + link + "_" + str(len(os.listdir(path))) + ".json" diff --git a/src/transmission/scheduler.py b/src/transmission/scheduler.py index 198998e5..b3598301 100644 --- a/src/transmission/scheduler.py +++ b/src/transmission/scheduler.py @@ -21,7 +21,7 @@ from transmission.processing.satellites import SATELLITES from transmission.processing.process_raw_bucket import process_raw_bucket from transmission.processing.telemetry_scraper import scrape -from transmission.processing.save_raw_data import process_uplink_and_downlink +from transmission.processing.save_raw_data import process_uplink_and_downlink, reprocess_uplink_and_downlink def get_job_id(satellite: str, job_description: str) -> str: @@ -50,6 +50,11 @@ def schedule_job(job_type: str, satellite: str = None, link: str = None, job_id = job_type scheduler.add_job_to_schedule(process_uplink_and_downlink, args, job_id, date, interval) + elif job_type == "buffer_reprocessing": + args = [] + job_id = job_type + scheduler.add_job_to_schedule(reprocess_uplink_and_downlink, args, job_id, date, interval) + elif job_type == "raw_bucket_processing" and satellite in SATELLITES: args = [satellite, link] job_id = get_job_id(satellite, job_type) @@ -155,7 +160,7 @@ def executed_job_listener(self, event) -> None: # automated processing pipeline: # - when a buffer processing task completes that will trigger the raw bucket processing # - when a scraper task completes that will trigger the raw bucket processing - if "buffer_processing" in event.job_id: + if ("buffer_processing" in event.job_id) or ("buffer_reprocessing" in event.job_id): for sat in SATELLITES: schedule_job("raw_bucket_processing", sat) From 263d19b9f52dc01a3f494b8f0425582e36d9f6e6 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 23 Mar 2024 23:43:55 +0100 Subject: [PATCH 19/62] Skip already processed messages in the query --- .../processing/process_raw_bucket.py | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/transmission/processing/process_raw_bucket.py b/src/transmission/processing/process_raw_bucket.py index ac007f51..b0f9f951 100644 --- a/src/transmission/processing/process_raw_bucket.py +++ b/src/transmission/processing/process_raw_bucket.py @@ -97,10 +97,19 @@ def process_retrieved_frames(satellite: str, link: str, start_time: str, end_tim r["_field"] == "{radio_amateur}") |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") ''' + + if skip_processed == True: + get_unprocessed_frames_query = get_unprocessed_frames_query + f''' + |> filter(fn: (r) => r["processed"] == false) + ''' + # query result as dataframe dataframe = query_api.query_data_frame(query=get_unprocessed_frames_query) dataframe = dataframe.reset_index() + logger.info("Before query") + + failed_processing_count = 0 processed_frames_count = 0 total_frames_count = 0 @@ -109,7 +118,8 @@ def process_retrieved_frames(satellite: str, link: str, start_time: str, end_tim total_frames_count += 1 try: if row["processed"] and skip_processed: # skip frame if it's processed - logger.info("%s: frame skipped (already processed): %s ", satellite, row["frame"]) + logger.info("You should not see this message") + #logger.info("%s: frame skipped (already processed): %s ", satellite, row["frame"]) continue # store processed frame parse_and_store_frame(satellite, row["_time"], row["frame"], row[radio_amateur], link) @@ -135,6 +145,8 @@ def process_retrieved_frames(satellite: str, link: str, start_time: str, end_tim f"{skipped_frames_count} were skipped, and " + \ f"{failed_processing_count} failed." + logger.info("Query ended") + logger.info("%s: %s frames processed from %s - %s; %s", satellite, link, start_time, end_time, frames_status) if total_frames_count == 0: @@ -162,24 +174,32 @@ def _process_raw_bucket(satellite: str, link: str, all_frames: bool, failed: boo time_range.combine_time_ranges(satellite, link) + logger.info("_process_raw_bucket " + str(satellite) + " " + str(all_frames) + " " + str(failed)) # process the entire bucket if all_frames: + logger.info("_process_raw_bucket 1") return process_retrieved_frames(satellite, link, "0", "now()", skip_processed=False) # process frames in the failed frames time range if failed: + logger.info("_process_raw_bucket 2") file = time_range.get_failed_data_file_path(satellite, link) new_data_time_range = time_range.read_time_range_file(file) # process frames in the new data time range (newly ingested data) else: + logger.info("_process_raw_bucket 3") file = time_range.get_new_data_file_path(satellite, link) new_data_time_range = time_range.read_time_range_file(file) processed_frames_count = 0 total_frames_count = 0 + logger.info("_process_raw_bucket 4") + # if the time range is empty there are no frames to process if new_data_time_range[satellite][link] != []: + logger.info("_process_raw_bucket 5") + start_time = new_data_time_range[satellite][link][0] end_time = new_data_time_range[satellite][link][1] processed_frames_count, total_frames_count = process_retrieved_frames(satellite, link, start_time, end_time) @@ -188,5 +208,6 @@ def _process_raw_bucket(satellite: str, link: str, all_frames: bool, failed: boo if failed is False or processed_frames_count == total_frames_count: time_range.reset_new_data_timestamps(satellite, link, file) else: + logger.info("_process_raw_bucket 6") logger.info("%s: no frames to process", satellite) return processed_frames_count, total_frames_count From d61339e6d74ffa089755f6f0084083080f72037c Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 23 Mar 2024 23:45:24 +0100 Subject: [PATCH 20/62] Added debug messages in scraper --- .../processing/telemetry_scraper.py | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/transmission/processing/telemetry_scraper.py b/src/transmission/processing/telemetry_scraper.py index a921cfb1..69f80b00 100644 --- a/src/transmission/processing/telemetry_scraper.py +++ b/src/transmission/processing/telemetry_scraper.py @@ -34,7 +34,7 @@ def get_satnogs_params(satellite: str) -> dict: now = datetime.utcnow().strftime(TIME_FORMAT) logger.debug("Now: %s", now) # params = {'app_source':'network', 'end': now, 'format': 'json', 'satellite': '51074'} - params = {'end': now, 'format': 'json', 'satellite': SATELLITES[satellite]} + params = {'end': now, 'format': 'json', 'satellite': SATELLITES[satellite]['norad_id']} return params @@ -70,23 +70,30 @@ def scrape(satellite: str, save_to_db=True, save_to_file=False) -> None: logger.info("SatNOGS scraper started. Scraping %s telemetry.", satellite) time_range = {} while True: + logger.info(get_satnogs_params(satellite)) response = requests.get( SATNOGS_PATH, params=get_satnogs_params(satellite), headers=get_satnogs_headers(), - timeout=10 # seconds + timeout=100 # seconds ) + logger.info(response) telemetry_tmp = response.json() + logger.info(telemetry_tmp) try: + logger.info("1") last = telemetry_tmp[-1] + logger.info(last) first = telemetry_tmp[0] + logger.info(first) + logger.info(sate_to_db) # concatenate telemetry telemetry = telemetry + telemetry_tmp last_time = datetime.strptime(last['timestamp'], TIME_FORMAT) next_time = last_time - timedelta(seconds=1) - logger.debug("Next: %s", next_time.strftime(TIME_FORMAT)) + logger.info("Next: %s", next_time.strftime(TIME_FORMAT)) if save_to_db: fields_to_save = ["frame", "timestamp", "observer"] @@ -99,20 +106,20 @@ def scrape(satellite: str, save_to_db=True, save_to_file=False) -> None: # if the frame is not stored (due to it being stored in a past scrape) and # the next request retrieves data older than a week -> stop - elif (datetime.now() - next_time).days > 7: - logger.info("SatNOGS scraper stopped. Done scraping %s telemetry.", satellite) - break # stop scraping + #elif (datetime.now() - next_time).days > 7: + # logger.info("SatNOGS scraper stopped. Done scraping %s telemetry.", satellite) + # break # stop scraping except IndexError: logger.info("SatNOGS scraper stopped. Done scraping %s telemetry.", satellite) break except KeyError: - logger.debug(telemetry_tmp) + logger.info(telemetry_tmp) if 'detail' in telemetry_tmp: if "throttled" in telemetry_tmp["detail"]: delay = re.findall('[0-9]+', telemetry_tmp["detail"])[0] - logger.debug("Sleeping %s s (request throttled)", delay) + logger.info("Sleeping %s s (request throttled)", delay) time.sleep(int(delay)) path = get_new_data_scraper_temp_folder(satellite) path += satellite + "_downlink_" + str(len(os.listdir(path))) + ".json" @@ -124,3 +131,4 @@ def scrape(satellite: str, save_to_db=True, save_to_file=False) -> None: if save_to_file: dump_telemetry_to_file(satellite, telemetry) + logger.info("Scraper done") From 68d2b897525ae146346eb1ea87f1f3b561637711 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sun, 24 Mar 2024 17:27:27 +0100 Subject: [PATCH 21/62] Speeding up buffer processing by ~4x --- src/transmission/processing/XTCEParser.py | 21 +++++--- src/transmission/processing/save_raw_data.py | 57 ++++++++------------ 2 files changed, 37 insertions(+), 41 deletions(-) diff --git a/src/transmission/processing/XTCEParser.py b/src/transmission/processing/XTCEParser.py index 4b401b17..30d39153 100644 --- a/src/transmission/processing/XTCEParser.py +++ b/src/transmission/processing/XTCEParser.py @@ -11,11 +11,13 @@ class XTCEParser: def __init__(self, XTCEfile, stream): if XTCEParser.gateway_started == 0: + logger.info("Loading XTCETools") launch_gateway(classpath='transmission/processing/xtcetools-1.1.5.jar', port=25333, die_on_exit=True) XTCEParser.gateway_started = 1 + logger.info("Loading XTCEParser") gateway = JavaGateway() XTCEContainerContentModel = gateway.jvm.org.xtce.toolkit.XTCEContainerContentModel @@ -29,27 +31,32 @@ def __init__(self, XTCEfile, stream): XTCEEngineeringType = gateway.jvm.org.xtce.toolkit.XTCETypedObject.EngineeringType File = gateway.jvm.java.io.File + self.XTCEfile_ = XTCEfile self.db_ = XTCEDatabase(File(XTCEfile), True, False, True) self.stream_ = self.db_.getStream(stream) + # Deleting (Calling destructor) + def __del__(self): + logger.info('Destructor called, XTCEParser.gateway_started = ' + str(XTCEParser.gateway_started)) + + def getFile(self): + return self.XTCEfile + def processTMFrame(self, data): try: model = self.stream_.processStream(data) entries = model.getContentList() telemetry = {"frame": model.getName()} - logger.debug("TMFrame entries: %s", entries) - + #logger.debug("TMFrame entries: %s", entries) + # thriwn an error if the frame is found but empty for entry in entries: val = entry.getValue() name = entry.getName() - logger.debug("TMFrame val: %s", val) - logger.debug("TMFrame name: %s", name) if val: telemetry[name] = {"value": val.getCalibratedValue(), "status": self.isFieldValid(entry)} - logger.debug("TMFrame TLM: %s", telemetry) return telemetry except Py4JJavaError as ex: raise XTCEException(ex.java_exception) @@ -111,7 +118,7 @@ class SatParsers: def __init__(self): self.parsers = { "delfi_pq": XTCEParser("delfipq/Delfi-PQ.xml", "Radio"), - "delfi_next": None, + #"delfi_next": None, "delfi_c3": XTCEParser("delfic3/Delfi-C3.xml", "TLM"), - "da_vinci": None + #"da_vinci": None } diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index b7a88193..b684dc4d 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -20,6 +20,7 @@ include_timestamp_in_time_range, save_timestamps_to_file from transmission.processing.influxdb_api import save_raw_frame_to_influxdb from transmission.processing.telemetry_scraper import strip_tlm +import traceback def store_frames(frames, username: str, application: str = None) -> int: @@ -152,9 +153,11 @@ def reprocess_uplink_and_downlink() -> tuple: logger.info("Reprocess incoming frames") downlink_frames = Downlink.objects.all().filter(processed=True).filter(invalid=True) + logger.info("Downlink count " + str(len(downlink_frames))) downlink_frames_count = process_frames(downlink_frames, "downlink") uplink_frames = Uplink.objects.all().filter(processed=True).filter(invalid=True) + logger.info("Uplink count " + str(len(uplink_frames))) uplink_frames_count = process_frames(uplink_frames, "uplink") logger.info("Incoming frames reprocessed") @@ -166,73 +169,59 @@ def process_frames(frames: QuerySet, link: str) -> int: if a frame was successfully stored in influxdb. Returns the count of successfully processed_frames.""" + logger.info("process_frames started") + + parsers = SatParsers() + processed_frames = 0 processed_frames_timestamps = {} for frame_obj in frames: frame_dict = frame_obj.to_dictionary() - stored, satellite = store_frame_to_influxdb(frame_dict, link) + #logger.info(frame_dict) + stored, satellite = store_frame_to_influxdb(parsers, frame_dict, link) + #logger.info(str(stored) + " " + str(satellite)) frame_obj.processed = True if stored: frame_obj.invalid = False processed_frames += 1 - if satellite not in processed_frames_timestamps: - processed_frames_timestamps[satellite] = include_timestamp_in_time_range( - satellite, link, - frame_obj.timestamp, - existing_range={} - ) - else: - processed_frames_timestamps[satellite] = include_timestamp_in_time_range( - satellite, link, - frame_obj.timestamp, - existing_range=processed_frames_timestamps[satellite] - ) else: frame_obj.invalid = True frame_obj.save() - for satellite, time_range in processed_frames_timestamps.items(): - path = get_new_data_buffer_temp_folder(satellite) - path += satellite + "_" + link + "_" + str(len(os.listdir(path))) + ".json" - save_timestamps_to_file(time_range, path) - return processed_frames -def mark_frame_as_invalid(frame: str, link: str) -> None: - """Flag an invalid frame that doesn't correspond to any satellite.""" - if link == "downlink": - Downlink.objects.filter(frame=frame).update(invalid=True) - elif link == "uplink": - Uplink.objects.filter(frame=frame).update(invalid=True) - else: - return - - -def store_frame_to_influxdb(frame: dict, link: str) -> tuple: +def store_frame_to_influxdb(parsers: SatParsers, frame: dict, link: str) -> tuple: """Try to store frame to influxdb. Returns True if the frame was successfully stored, False otherwise.""" - satellite = get_satellite_from_frame(frame["frame"]) + #logger.info("store_frame_to_influxdb") + satellite = get_satellite_from_frame(parsers, frame["frame"]) + #logger.info("satellite " + str(satellite)) if satellite is None: - mark_frame_as_invalid(frame["frame"], link) - logger.warning("invalid %s frame, cannot match satellite: %s", link, frame["frame"]) + #logger.warning("invalid %s frame, cannot match satellite: %s", link, frame["frame"]) return False, satellite fields_to_save = ["frame", "timestamp", "observer", "frequency", "application", "metadata"] frame = strip_tlm(frame, fields_to_save) + #logger.info("saving " + str(frame)) stored = save_raw_frame_to_influxdb(satellite, link, frame) return stored, satellite -def get_satellite_from_frame(frame: str) -> Union[str, None]: +def get_satellite_from_frame(parsers: SatParsers, frame: str) -> Union[str, None]: """Find the corresponding satellite by attempting to parse the frame. If the parsing is successful, return the satellite name, else None.""" - for sat, parser in SatParsers().parsers.items(): + #logger.info("get_satellite_from_frame") + #logger.info(type(parsers)) + for sat, parser in parsers.parsers.items(): + #logger.info(str(sat) + " " + str(parser)) if parser is not None: + #logger.info(parser) + #logger.info(type(parser)) try: parser.processTMFrame(bytes.fromhex(frame)) return sat From f80cbb787d812a9a49951b03f7286a092fa48677 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Mon, 25 Mar 2024 09:59:14 +0100 Subject: [PATCH 22/62] Removing debug logger calls --- src/transmission/processing/save_raw_data.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index b684dc4d..aff87881 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -169,17 +169,13 @@ def process_frames(frames: QuerySet, link: str) -> int: if a frame was successfully stored in influxdb. Returns the count of successfully processed_frames.""" - logger.info("process_frames started") - parsers = SatParsers() processed_frames = 0 processed_frames_timestamps = {} for frame_obj in frames: frame_dict = frame_obj.to_dictionary() - #logger.info(frame_dict) stored, satellite = store_frame_to_influxdb(parsers, frame_dict, link) - #logger.info(str(stored) + " " + str(satellite)) frame_obj.processed = True if stored: frame_obj.invalid = False @@ -195,18 +191,14 @@ def store_frame_to_influxdb(parsers: SatParsers, frame: dict, link: str) -> tupl """Try to store frame to influxdb. Returns True if the frame was successfully stored, False otherwise.""" - #logger.info("store_frame_to_influxdb") satellite = get_satellite_from_frame(parsers, frame["frame"]) - #logger.info("satellite " + str(satellite)) if satellite is None: - #logger.warning("invalid %s frame, cannot match satellite: %s", link, frame["frame"]) return False, satellite fields_to_save = ["frame", "timestamp", "observer", "frequency", "application", "metadata"] frame = strip_tlm(frame, fields_to_save) - #logger.info("saving " + str(frame)) stored = save_raw_frame_to_influxdb(satellite, link, frame) return stored, satellite @@ -215,13 +207,8 @@ def store_frame_to_influxdb(parsers: SatParsers, frame: dict, link: str) -> tupl def get_satellite_from_frame(parsers: SatParsers, frame: str) -> Union[str, None]: """Find the corresponding satellite by attempting to parse the frame. If the parsing is successful, return the satellite name, else None.""" - #logger.info("get_satellite_from_frame") - #logger.info(type(parsers)) for sat, parser in parsers.parsers.items(): - #logger.info(str(sat) + " " + str(parser)) if parser is not None: - #logger.info(parser) - #logger.info(type(parser)) try: parser.processTMFrame(bytes.fromhex(frame)) return sat From a710be3d7f854f9ba8588518faaa910dae92f53e Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Mon, 25 Mar 2024 11:39:30 +0100 Subject: [PATCH 23/62] Start all tasks once frames are received to allow multi-threaded processing --- src/transmission/scheduler.py | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/transmission/scheduler.py b/src/transmission/scheduler.py index b3598301..a16c17c9 100644 --- a/src/transmission/scheduler.py +++ b/src/transmission/scheduler.py @@ -111,7 +111,7 @@ def __init__(self) -> None: logger.info("Scheduler already instantiated") else: executors = { - 'default': ThreadPoolExecutor(1), + 'default': ThreadPoolExecutor(10), # 'processpool': ProcessPoolExecutor(0) } job_defaults = { @@ -157,6 +157,24 @@ def executed_job_listener(self, event) -> None: logger.info("Scheduler executed job: %s", event.job_id) self.running_jobs.remove(event.job_id) + # automated processing pipeline: + # - when a buffer processing task completes that will trigger the raw bucket processing + # - when a scraper task completes that will trigger the raw bucket processing + #if ("buffer_processing" in event.job_id) or ("buffer_reprocessing" in event.job_id): + # for sat in SATELLITES: + # schedule_job("raw_bucket_processing", sat) + + #elif "scraper" in event.job_id: + # for sat in SATELLITES: + # if sat in event.job_id: + # schedule_job("raw_bucket_processing", sat, "downlink") + + def submitted_job_listener(self, event) -> None: + """Listens to submitted jobs""" + self.running_jobs.add(event.job_id) + logger.info("Scheduler submitted job: %s", event.job_id) + + # automated processing pipeline: # - when a buffer processing task completes that will trigger the raw bucket processing # - when a scraper task completes that will trigger the raw bucket processing @@ -169,11 +187,6 @@ def executed_job_listener(self, event) -> None: if sat in event.job_id: schedule_job("raw_bucket_processing", sat, "downlink") - def submitted_job_listener(self, event) -> None: - """Listens to submitted jobs""" - self.running_jobs.add(event.job_id) - logger.info("Scheduler submitted job: %s", event.job_id) - def get_pending_jobs(self) -> set: """Get the ids of the currently scheduled jobs.""" return self.pending_jobs From 9d4622903a351eb772f8169052cc1e7a444f655f Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Mon, 25 Mar 2024 11:41:36 +0100 Subject: [PATCH 24/62] Processing the raw bucket iteratively to allow multi-threaded processing --- .../processing/process_raw_bucket.py | 105 ++++++++++++------ 1 file changed, 71 insertions(+), 34 deletions(-) diff --git a/src/transmission/processing/process_raw_bucket.py b/src/transmission/processing/process_raw_bucket.py index b0f9f951..b767bea5 100644 --- a/src/transmission/processing/process_raw_bucket.py +++ b/src/transmission/processing/process_raw_bucket.py @@ -1,5 +1,7 @@ """Script to store satellite telemetry frames""" import string +import time +import traceback from transmission.processing import XTCEParser as xtce_parser from django_logger import logger import transmission.processing.bookkeep_new_data_time_range as time_range @@ -76,6 +78,11 @@ def mark_processed_flag(satellite: str, link: str, timestamp: str, value: bool) write_frame_to_raw_bucket(write_api, satellite, link, timestamp, {'processed': value}) +def mark_invalid_flag(satellite: str, link: str, timestamp: str, value: bool) -> None: + """Write the invalid flag to either True or False.""" + write_frame_to_raw_bucket(write_api, satellite, link, timestamp, {'invalid': value}) + + # pylint: disable=R0914 def process_retrieved_frames(satellite: str, link: str, start_time: str, end_time: str, skip_processed: bool = True) -> tuple: @@ -88,6 +95,8 @@ def process_retrieved_frames(satellite: str, link: str, start_time: str, end_tim if link == 'uplink': radio_amateur = 'operator' + # TODO: we need to still check the frames where processing failed + get_unprocessed_frames_query = f''' from(bucket: "{satellite + "_raw_data"}") |> range(start: {start_time}, stop: {end_time}) @@ -107,9 +116,6 @@ def process_retrieved_frames(satellite: str, link: str, start_time: str, end_tim dataframe = query_api.query_data_frame(query=get_unprocessed_frames_query) dataframe = dataframe.reset_index() - logger.info("Before query") - - failed_processing_count = 0 processed_frames_count = 0 total_frames_count = 0 @@ -121,10 +127,14 @@ def process_retrieved_frames(satellite: str, link: str, start_time: str, end_tim logger.info("You should not see this message") #logger.info("%s: frame skipped (already processed): %s ", satellite, row["frame"]) continue + # mark raw frame as processed + mark_processed_flag(satellite, link, row["_time"], True) # store processed frame parse_and_store_frame(satellite, row["_time"], row["frame"], row[radio_amateur], link) # mark raw frame as processed - mark_processed_flag(satellite, link, row["_time"], True) + # mark raw frame as valid + mark_invalid_flag(satellite, link, row["_time"], False) + #mark_processed_flag(satellite, link, row["_time"], True) processed_frames_count += 1 except xtce_parser.XTCEException as ex: @@ -134,8 +144,8 @@ def process_retrieved_frames(satellite: str, link: str, start_time: str, end_tim row["_time"], time_range.get_failed_data_file_path(satellite, link) ) - # mark frame as unprocessed - mark_processed_flag(satellite, link, row["_time"], False) + # mark frame as invalid + mark_invalid_flag(satellite, link, row["_time"], True) failed_processing_count += 1 skipped_frames_count = total_frames_count - processed_frames_count - failed_processing_count @@ -145,7 +155,6 @@ def process_retrieved_frames(satellite: str, link: str, start_time: str, end_tim f"{skipped_frames_count} were skipped, and " + \ f"{failed_processing_count} failed." - logger.info("Query ended") logger.info("%s: %s frames processed from %s - %s; %s", satellite, link, start_time, end_time, frames_status) @@ -158,14 +167,42 @@ def process_retrieved_frames(satellite: str, link: str, start_time: str, end_tim def process_raw_bucket(satellite: str, link: str = None, all_frames: bool = False, failed: bool = False): """Trigger bucket processing or reprocessing given satellite.""" # if link is None process both uplink and downlink, otherwise process only specified link - - if link in ["uplink", "downlink"]: - _process_raw_bucket(satellite, link, all_frames, failed) - else: - _process_raw_bucket(satellite, "uplink", all_frames, failed) - _process_raw_bucket(satellite, "downlink", all_frames, failed) - - + logger.info("process_raw_bucket") + logger.info("process_raw_bucket " + str(satellite) + " " + str(link)) + total_processed_frames = 0 + iterations = 0 + logger.info("pre while") + + while iterations < 5: + logger.info("sleep") + # debug code: delay bucket processing to ensure + try: + time.sleep(1) + except Exception as _: + logger.info(traceback.format_exc()) + total_processed_frames = 0 + + logger.info("sleep done") + + if link in ["uplink", "downlink"]: + processed_frames_count, total_frames_count = _process_raw_bucket(satellite, link, all_frames, failed) + total_processed_frames += processed_frames_count + else: + processed_frames_count, total_frames_count = _process_raw_bucket(satellite, "uplink", all_frames, failed) + total_processed_frames += processed_frames_count + processed_frames_count, total_frames_count = _process_raw_bucket(satellite, "downlink", all_frames, failed) + total_processed_frames += processed_frames_count + logger.info(str(satellite) + " processed " + str(total_processed_frames)) + # one more iteration + iterations += 1 + + if processed_frames_count != 0: + # frames were processed in this iteration, reset the iteration counter + iterations = 0 + + logger.info("Iterations " + str(iterations) + " Frames processed: " + str(total_processed_frames)) + + logger.info("process_raw_bucket " + str(satellite) + " " + str(link) + " completed") def _process_raw_bucket(satellite: str, link: str, all_frames: bool, failed: bool) -> tuple: """Trigger bucket processing given satellite and link. @@ -180,34 +217,34 @@ def _process_raw_bucket(satellite: str, link: str, all_frames: bool, failed: boo logger.info("_process_raw_bucket 1") return process_retrieved_frames(satellite, link, "0", "now()", skip_processed=False) # process frames in the failed frames time range - if failed: - logger.info("_process_raw_bucket 2") - file = time_range.get_failed_data_file_path(satellite, link) - new_data_time_range = time_range.read_time_range_file(file) + #if failed: + # logger.info("_process_raw_bucket 2") + # file = time_range.get_failed_data_file_path(satellite, link) + # new_data_time_range = time_range.read_time_range_file(file) # process frames in the new data time range (newly ingested data) else: logger.info("_process_raw_bucket 3") - file = time_range.get_new_data_file_path(satellite, link) - new_data_time_range = time_range.read_time_range_file(file) - + #file = time_range.get_new_data_file_path(satellite, link) + #new_data_time_range = time_range.read_time_range_file(file) + return process_retrieved_frames(satellite, link, "0", "now()", skip_processed=True) processed_frames_count = 0 total_frames_count = 0 logger.info("_process_raw_bucket 4") # if the time range is empty there are no frames to process - if new_data_time_range[satellite][link] != []: + #if new_data_time_range[satellite][link] != []: - logger.info("_process_raw_bucket 5") + # logger.info("_process_raw_bucket 5") - start_time = new_data_time_range[satellite][link][0] - end_time = new_data_time_range[satellite][link][1] - processed_frames_count, total_frames_count = process_retrieved_frames(satellite, link, start_time, end_time) - - # don't reset the interval of failed frames, unless reprocessing was successful - if failed is False or processed_frames_count == total_frames_count: - time_range.reset_new_data_timestamps(satellite, link, file) - else: - logger.info("_process_raw_bucket 6") - logger.info("%s: no frames to process", satellite) + # start_time = new_data_time_range[satellite][link][0] + # end_time = new_data_time_range[satellite][link][1] + # processed_frames_count, total_frames_count = process_retrieved_frames(satellite, link, start_time, end_time) + + # # don't reset the interval of failed frames, unless reprocessing was successful + # if failed is False or processed_frames_count == total_frames_count: + # time_range.reset_new_data_timestamps(satellite, link, file) + #else: + # logger.info("_process_raw_bucket 6") + # logger.info("%s: no frames to process", satellite) return processed_frames_count, total_frames_count From a289b6056e27eb7bc9a2ca9cfe037d66da474e3f Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 30 Mar 2024 00:35:56 +0100 Subject: [PATCH 25/62] Loading XTCETools only when starting the scheduler --- src/transmission/processing/XTCEParser.py | 22 +++++++------ src/transmission/scheduler.py | 40 ++++++++++------------- 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/transmission/processing/XTCEParser.py b/src/transmission/processing/XTCEParser.py index 30d39153..c0e64bdd 100644 --- a/src/transmission/processing/XTCEParser.py +++ b/src/transmission/processing/XTCEParser.py @@ -9,13 +9,13 @@ class XTCEParser: gateway_started = 0 def __init__(self, XTCEfile, stream): - - if XTCEParser.gateway_started == 0: - logger.info("Loading XTCETools") - launch_gateway(classpath='transmission/processing/xtcetools-1.1.5.jar', - port=25333, - die_on_exit=True) - XTCEParser.gateway_started = 1 + #logger.info("XTCETools " + str(XTCEfile) + " " + str(XTCEParser.gateway_started)) + #if XTCEParser.gateway_started == 0: + # XTCEParser.gateway_started = 1 + # logger.info("Loading XTCETools") + # launch_gateway(classpath='transmission/processing/xtcetools-1.1.5.jar', + # port=25333, + # die_on_exit=True) logger.info("Loading XTCEParser") gateway = JavaGateway() @@ -35,9 +35,11 @@ def __init__(self, XTCEfile, stream): self.db_ = XTCEDatabase(File(XTCEfile), True, False, True) self.stream_ = self.db_.getStream(stream) - # Deleting (Calling destructor) - def __del__(self): - logger.info('Destructor called, XTCEParser.gateway_started = ' + str(XTCEParser.gateway_started)) + def loadGateway(): + logger.info("Loading py4j and XTCETools") + launch_gateway(classpath='transmission/processing/xtcetools-1.1.5.jar', + port=25333, + die_on_exit=True) def getFile(self): return self.XTCEfile diff --git a/src/transmission/scheduler.py b/src/transmission/scheduler.py index a16c17c9..6a05e80a 100644 --- a/src/transmission/scheduler.py +++ b/src/transmission/scheduler.py @@ -9,20 +9,21 @@ - reprocess_failed_raw_bucket """ import datetime +import traceback from typing import Callable from apscheduler.schedulers.base import STATE_STOPPED, STATE_PAUSED, STATE_RUNNING from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.triggers.interval import IntervalTrigger from apscheduler.triggers.date import DateTrigger from apscheduler.executors.pool import ThreadPoolExecutor -from apscheduler.events import EVENT_JOB_ADDED, EVENT_JOB_REMOVED, EVENT_JOB_EXECUTED, EVENT_JOB_SUBMITTED +from apscheduler.events import EVENT_JOB_ADDED, EVENT_JOB_REMOVED, EVENT_JOB_EXECUTED, EVENT_JOB_SUBMITTED, EVENT_JOB_ERROR from django.forms import ValidationError from django_logger import logger from transmission.processing.satellites import SATELLITES from transmission.processing.process_raw_bucket import process_raw_bucket from transmission.processing.telemetry_scraper import scrape from transmission.processing.save_raw_data import process_uplink_and_downlink, reprocess_uplink_and_downlink - +from transmission.processing.XTCEParser import XTCEParser, XTCEException def get_job_id(satellite: str, job_description: str) -> str: """Create an id, job description""" @@ -128,9 +129,12 @@ def __init__(self) -> None: self.scheduler.add_listener(self.executed_job_listener, EVENT_JOB_EXECUTED) self.scheduler.add_listener(self.add_job_listener, EVENT_JOB_ADDED) self.scheduler.add_listener(self.remove_job_listener, EVENT_JOB_REMOVED) + self.scheduler.add_listener(self.exception_listener, EVENT_JOB_ERROR) Scheduler.__instance = self + XTCEParser.loadGateway(); + def get_state(self) -> str: """Returns the state of the scheduler: running, paused, shutdown.""" if self.scheduler.state == STATE_STOPPED: @@ -142,14 +146,19 @@ def get_state(self) -> str: return "" + def exception_listener(self, event) -> None: + """Listens to newly added jobs""" + self.running_jobs.remove(event.job_id) + logger.error(traceback.print_tb(event.exception.__traceback__)) + def add_job_listener(self, event) -> None: """Listens to newly added jobs""" - logger.info("Scheduler added job: %s", event.job_id) + #logger.info("Scheduler added job: %s", event.job_id) self.pending_jobs.add(event.job_id) def remove_job_listener(self, event) -> None: """Listens to removed jobs""" - logger.info("Scheduler removed job: %s", event.job_id) + #logger.info("Scheduler removed job: %s", event.job_id) self.pending_jobs.remove(event.job_id) def executed_job_listener(self, event) -> None: @@ -157,23 +166,10 @@ def executed_job_listener(self, event) -> None: logger.info("Scheduler executed job: %s", event.job_id) self.running_jobs.remove(event.job_id) - # automated processing pipeline: - # - when a buffer processing task completes that will trigger the raw bucket processing - # - when a scraper task completes that will trigger the raw bucket processing - #if ("buffer_processing" in event.job_id) or ("buffer_reprocessing" in event.job_id): - # for sat in SATELLITES: - # schedule_job("raw_bucket_processing", sat) - - #elif "scraper" in event.job_id: - # for sat in SATELLITES: - # if sat in event.job_id: - # schedule_job("raw_bucket_processing", sat, "downlink") - def submitted_job_listener(self, event) -> None: """Listens to submitted jobs""" - self.running_jobs.add(event.job_id) logger.info("Scheduler submitted job: %s", event.job_id) - + self.running_jobs.add(event.job_id) # automated processing pipeline: # - when a buffer processing task completes that will trigger the raw bucket processing @@ -182,10 +178,10 @@ def submitted_job_listener(self, event) -> None: for sat in SATELLITES: schedule_job("raw_bucket_processing", sat) - elif "scraper" in event.job_id: - for sat in SATELLITES: - if sat in event.job_id: - schedule_job("raw_bucket_processing", sat, "downlink") + #elif "scraper" in event.job_id: + # for sat in SATELLITES: + # if sat in event.job_id: + # schedule_job("raw_bucket_processing", sat, "downlink") def get_pending_jobs(self) -> set: """Get the ids of the currently scheduled jobs.""" From 581440c6315ca1292aa8f76b22396f1b6c5c2283 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 30 Mar 2024 00:36:32 +0100 Subject: [PATCH 26/62] Removing debug logger call --- src/transmission/processing/influxdb_api.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/transmission/processing/influxdb_api.py b/src/transmission/processing/influxdb_api.py index 553cf418..ce56624e 100644 --- a/src/transmission/processing/influxdb_api.py +++ b/src/transmission/processing/influxdb_api.py @@ -56,8 +56,8 @@ def write_frame_to_raw_bucket(write_api, satellite, link, timestamp, frame_field "fields": frame_fields } - logger.info("%s: raw frame stored or updated. Frame timestamp: %s, link: %s, bucket: %s", - satellite, timestamp, link, bucket) + #logger.info("%s: raw frame stored or updated. Frame timestamp: %s, link: %s, bucket: %s", + # satellite, timestamp, link, bucket) write_api.write(bucket, INFLUX_ORG, db_fields) From 02fe72c4884a0657f68742646b664127e7006cb4 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 30 Mar 2024 00:37:16 +0100 Subject: [PATCH 27/62] Processing frames in chunks to be more responsive --- .../processing/process_raw_bucket.py | 122 ++++++------------ src/transmission/processing/save_raw_data.py | 52 ++++++-- 2 files changed, 76 insertions(+), 98 deletions(-) diff --git a/src/transmission/processing/process_raw_bucket.py b/src/transmission/processing/process_raw_bucket.py index b767bea5..772dabfe 100644 --- a/src/transmission/processing/process_raw_bucket.py +++ b/src/transmission/processing/process_raw_bucket.py @@ -2,7 +2,7 @@ import string import time import traceback -from transmission.processing import XTCEParser as xtce_parser +from transmission.processing.XTCEParser import SatParsers, XTCEException from django_logger import logger import transmission.processing.bookkeep_new_data_time_range as time_range from transmission.processing.influxdb_api import INFLUX_ORG, commit_frame, \ @@ -27,11 +27,11 @@ def store_raw_frame(satellite: str, timestamp: str, frame: str, observer: str, l return stored -def parse_and_store_frame(satellite: str, timestamp: str, frame: str, observer: str, link: str) -> None: +def parse_and_store_frame(parsers: SatParsers, satellite: str, timestamp: str, frame: str, observer: str, link: str) -> None: """Store parsed frame in influxdb""" - parser = xtce_parser.SatParsers().parsers[satellite] - logger.debug("%s: frame: %s", satellite, frame) + parser = parsers.parsers[satellite] + #logger.debug("%s: frame: %s", satellite, frame) telemetry = parser.processTMFrame(bytes.fromhex(frame)) bucket = satellite + "_" + link @@ -69,8 +69,8 @@ def parse_and_store_frame(satellite: str, timestamp: str, frame: str, observer: db_fields["fields"] = {} db_fields["tags"] = {} - logger.info("%s: processed frame stored. Frame timestamp: %s, link: %s, bucket: %s", - satellite, timestamp, link, bucket) + #logger.info("%s: processed frame stored. Frame timestamp: %s, link: %s, bucket: %s", + # satellite, timestamp, link, bucket) def mark_processed_flag(satellite: str, link: str, timestamp: str, value: bool) -> None: @@ -84,7 +84,7 @@ def mark_invalid_flag(satellite: str, link: str, timestamp: str, value: bool) -> # pylint: disable=R0914 -def process_retrieved_frames(satellite: str, link: str, start_time: str, end_time: str, +def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, start_time: str, end_time: str, skip_processed: bool = True) -> tuple: """Parse frames, store the parsed form and mark the raw entry as processed. Return the total number of frames attempting to process and @@ -112,6 +112,11 @@ def process_retrieved_frames(satellite: str, link: str, start_time: str, end_tim |> filter(fn: (r) => r["processed"] == false) ''' + # limit the maximum numbr of frames processed per round + get_unprocessed_frames_query = get_unprocessed_frames_query + f''' + |> limit(n:100, offset: 0) + ''' + # query result as dataframe dataframe = query_api.query_data_frame(query=get_unprocessed_frames_query) dataframe = dataframe.reset_index() @@ -119,132 +124,77 @@ def process_retrieved_frames(satellite: str, link: str, start_time: str, end_tim failed_processing_count = 0 processed_frames_count = 0 total_frames_count = 0 + # process each frame for _, row in dataframe.iterrows(): total_frames_count += 1 try: - if row["processed"] and skip_processed: # skip frame if it's processed - logger.info("You should not see this message") - #logger.info("%s: frame skipped (already processed): %s ", satellite, row["frame"]) - continue - # mark raw frame as processed - mark_processed_flag(satellite, link, row["_time"], True) # store processed frame - parse_and_store_frame(satellite, row["_time"], row["frame"], row[radio_amateur], link) + parse_and_store_frame(parsers, satellite, row["_time"], row["frame"], row[radio_amateur], link) # mark raw frame as processed + mark_processed_flag(satellite, link, row["_time"], True) # mark raw frame as valid mark_invalid_flag(satellite, link, row["_time"], False) - #mark_processed_flag(satellite, link, row["_time"], True) processed_frames_count += 1 except xtce_parser.XTCEException as ex: logger.error("%s: frame processing error: %s (%s)", satellite, ex, row["frame"]) - time_range.include_timestamp_in_time_range(satellite, - link, - row["_time"], - time_range.get_failed_data_file_path(satellite, link) - ) + # mark raw frame as processed + mark_processed_flag(satellite, link, row["_time"], True) # mark frame as invalid mark_invalid_flag(satellite, link, row["_time"], True) failed_processing_count += 1 - skipped_frames_count = total_frames_count - processed_frames_count - failed_processing_count - - frames_status = f"out of {total_frames_count} frames: " + \ - f"{processed_frames_count} were successfully parsed, " + \ - f"{skipped_frames_count} were skipped, and " + \ - f"{failed_processing_count} failed." - - - logger.info("%s: %s frames processed from %s - %s; %s", satellite, link, start_time, end_time, frames_status) - - if total_frames_count == 0: - logger.info("%s: no frames to process", satellite) - return processed_frames_count, total_frames_count def process_raw_bucket(satellite: str, link: str = None, all_frames: bool = False, failed: bool = False): """Trigger bucket processing or reprocessing given satellite.""" # if link is None process both uplink and downlink, otherwise process only specified link - logger.info("process_raw_bucket") - logger.info("process_raw_bucket " + str(satellite) + " " + str(link)) + total_processed_frames = 0 iterations = 0 - logger.info("pre while") - while iterations < 5: - logger.info("sleep") - # debug code: delay bucket processing to ensure - try: - time.sleep(1) - except Exception as _: - logger.info(traceback.format_exc()) - total_processed_frames = 0 + parsers = SatParsers() - logger.info("sleep done") + # once the last frame has been processed, maintain the task active for + # at least 10 seconds while looking for more frames to process + while iterations < 50: + time.sleep(0.2) + + total_processed_frames = 0 if link in ["uplink", "downlink"]: - processed_frames_count, total_frames_count = _process_raw_bucket(satellite, link, all_frames, failed) + processed_frames_count, total_frames_count = _process_raw_bucket(parsers, satellite, link, all_frames, failed) total_processed_frames += processed_frames_count else: - processed_frames_count, total_frames_count = _process_raw_bucket(satellite, "uplink", all_frames, failed) + processed_frames_count, total_frames_count = _process_raw_bucket(parsers, satellite, "uplink", all_frames, failed) total_processed_frames += processed_frames_count - processed_frames_count, total_frames_count = _process_raw_bucket(satellite, "downlink", all_frames, failed) + processed_frames_count, total_frames_count = _process_raw_bucket(parsers, satellite, "downlink", all_frames, failed) total_processed_frames += processed_frames_count - logger.info(str(satellite) + " processed " + str(total_processed_frames)) + # one more iteration iterations += 1 + logger.info("Frames " + str(total_processed_frames) + " Iterations " + str(iterations)) - if processed_frames_count != 0: + if total_processed_frames != 0: # frames were processed in this iteration, reset the iteration counter iterations = 0 - logger.info("Iterations " + str(iterations) + " Frames processed: " + str(total_processed_frames)) - - logger.info("process_raw_bucket " + str(satellite) + " " + str(link) + " completed") -def _process_raw_bucket(satellite: str, link: str, all_frames: bool, failed: bool) -> tuple: +def _process_raw_bucket(parsers: SatParsers, satellite: str, link: str, all_frames: bool, failed: bool) -> tuple: """Trigger bucket processing given satellite and link. all_frames=True will process the entire bucket and failed=True will process only failed frames. When both flags are True all frames will be processed.""" - time_range.combine_time_ranges(satellite, link) - - logger.info("_process_raw_bucket " + str(satellite) + " " + str(all_frames) + " " + str(failed)) # process the entire bucket if all_frames: - logger.info("_process_raw_bucket 1") - return process_retrieved_frames(satellite, link, "0", "now()", skip_processed=False) - # process frames in the failed frames time range - #if failed: - # logger.info("_process_raw_bucket 2") - # file = time_range.get_failed_data_file_path(satellite, link) - # new_data_time_range = time_range.read_time_range_file(file) - # process frames in the new data time range (newly ingested data) + return process_retrieved_frames(parsers, satellite, link, "0", "now()", skip_processed=False) else: - logger.info("_process_raw_bucket 3") - #file = time_range.get_new_data_file_path(satellite, link) - #new_data_time_range = time_range.read_time_range_file(file) - return process_retrieved_frames(satellite, link, "0", "now()", skip_processed=True) + return process_retrieved_frames(parsers, satellite, link, "0", "now()", skip_processed=True) + processed_frames_count = 0 total_frames_count = 0 - logger.info("_process_raw_bucket 4") - - # if the time range is empty there are no frames to process - #if new_data_time_range[satellite][link] != []: - - # logger.info("_process_raw_bucket 5") - - # start_time = new_data_time_range[satellite][link][0] - # end_time = new_data_time_range[satellite][link][1] - # processed_frames_count, total_frames_count = process_retrieved_frames(satellite, link, start_time, end_time) - - # # don't reset the interval of failed frames, unless reprocessing was successful - # if failed is False or processed_frames_count == total_frames_count: - # time_range.reset_new_data_timestamps(satellite, link, file) - #else: - # logger.info("_process_raw_bucket 6") - # logger.info("%s: no frames to process", satellite) return processed_frames_count, total_frames_count + diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index aff87881..73eaeae1 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -4,6 +4,7 @@ import copy import json from typing import Union +import time from django.forms import ValidationError from django.core.exceptions import PermissionDenied @@ -137,40 +138,68 @@ def process_uplink_and_downlink() -> tuple: i.e. move them to the influxdb raw satellite data bucket.""" logger.info("Process incoming frames") - downlink_frames = Downlink.objects.all().filter(processed=False) - downlink_frames_count = process_frames(downlink_frames, "downlink") + iterations = 0 - uplink_frames = Uplink.objects.all().filter(processed=False) - uplink_frames_count = process_frames(uplink_frames, "uplink") + parsers = SatParsers() - logger.info("Incoming frames processed") - return downlink_frames_count, uplink_frames_count + # once the last frame has been processed, maintain the task active for + # at least 10 seconds while looking for more frames to process + while iterations < 50: + time.sleep(0.2) + + total_processed_frames = 0 + + # set a maximum length to the results to ensure responsive data processing + downlink_frames = Downlink.objects.all().filter(processed=False)[:100] + downlink_frames_count = process_frames(parsers, downlink_frames, "downlink") + total_processed_frames += downlink_frames_count + + # set a maximum length to the results to ensure responsive data processing + uplink_frames = Uplink.objects.all().filter(processed=False)[:100] + uplink_frames_count = process_frames(parsers, uplink_frames, "uplink") + total_processed_frames += uplink_frames_count + + logger.info("Incoming frames processed. Downlink: " + str(downlink_frames_count) + " Uplink: " + str(uplink_frames_count) ) + + # one more iteration + iterations += 1 + #logger.info("Frames " + str(total_processed_frames) + " Iterations " + str(iterations)) + if total_processed_frames != 0: + # frames were processed in this iteration, reset the iteration counter + iterations = 0 + + #return downlink_frames_count, uplink_frames_count + return 0, 0 def reprocess_uplink_and_downlink() -> tuple: """Reprocess all invalid uplink and downlink frames, i.e. move them to the influxdb raw satellite data bucket.""" logger.info("Reprocess incoming frames") + + parsers = SatParsers() + downlink_frames = Downlink.objects.all().filter(processed=True).filter(invalid=True) logger.info("Downlink count " + str(len(downlink_frames))) - downlink_frames_count = process_frames(downlink_frames, "downlink") + try: + downlink_frames_count = process_frames(parsers, downlink_frames, "downlink") + except Exception as _: + logger.info(traceback.format_exc()) uplink_frames = Uplink.objects.all().filter(processed=True).filter(invalid=True) logger.info("Uplink count " + str(len(uplink_frames))) - uplink_frames_count = process_frames(uplink_frames, "uplink") + uplink_frames_count = process_frames(parsers, uplink_frames, "uplink") logger.info("Incoming frames reprocessed") return downlink_frames_count, uplink_frames_count -def process_frames(frames: QuerySet, link: str) -> int: +def process_frames(parsers: SatParsers, frames: QuerySet, link: str) -> int: """Try to store frame to influxdb and set the processed flag to True if a frame was successfully stored in influxdb. Returns the count of successfully processed_frames.""" - parsers = SatParsers() - processed_frames = 0 processed_frames_timestamps = {} for frame_obj in frames: @@ -183,7 +212,6 @@ def process_frames(frames: QuerySet, link: str) -> int: else: frame_obj.invalid = True frame_obj.save() - return processed_frames From d4f74e5811c10acb09b0395ebd3b47ff1e577bcf Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 30 Mar 2024 19:59:55 +0100 Subject: [PATCH 28/62] Handle exceptions in the processign threads --- .../processing/process_raw_bucket.py | 22 +++++++++++++++---- src/transmission/scheduler.py | 7 +++--- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/transmission/processing/process_raw_bucket.py b/src/transmission/processing/process_raw_bucket.py index 772dabfe..349fea5b 100644 --- a/src/transmission/processing/process_raw_bucket.py +++ b/src/transmission/processing/process_raw_bucket.py @@ -62,10 +62,15 @@ def parse_and_store_frame(parsers: SatParsers, satellite: str, timestamp: str, f except ValueError: pass - db_fields["fields"][field] = value - db_fields["tags"]["status"] = status + try: + db_fields["fields"][field] = value + db_fields["tags"]["status"] = status + + write_api.write(bucket, INFLUX_ORG, db_fields) + except : + logger.info(db_fields) + raise - write_api.write(bucket, INFLUX_ORG, db_fields) db_fields["fields"] = {} db_fields["tags"] = {} @@ -137,7 +142,7 @@ def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, sta mark_invalid_flag(satellite, link, row["_time"], False) processed_frames_count += 1 - except xtce_parser.XTCEException as ex: + except XTCEException as ex: logger.error("%s: frame processing error: %s (%s)", satellite, ex, row["frame"]) # mark raw frame as processed mark_processed_flag(satellite, link, row["_time"], True) @@ -145,6 +150,15 @@ def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, sta mark_invalid_flag(satellite, link, row["_time"], True) failed_processing_count += 1 + except Exception as ex: + logger.error("%s: frame storage error: %s (%s)", satellite, ex, row["frame"]) + logger.error(traceback.format_exc()) + # mark raw frame as processed + mark_processed_flag(satellite, link, row["_time"], True) + # mark frame as invalid + mark_invalid_flag(satellite, link, row["_time"], True) + failed_processing_count += 1 + return processed_frames_count, total_frames_count diff --git a/src/transmission/scheduler.py b/src/transmission/scheduler.py index 6a05e80a..04c9263a 100644 --- a/src/transmission/scheduler.py +++ b/src/transmission/scheduler.py @@ -149,7 +149,8 @@ def get_state(self) -> str: def exception_listener(self, event) -> None: """Listens to newly added jobs""" self.running_jobs.remove(event.job_id) - logger.error(traceback.print_tb(event.exception.__traceback__)) + logger.info("Terminated job: %s", event.job_id) + logger.error(event.traceback) def add_job_listener(self, event) -> None: """Listens to newly added jobs""" @@ -163,12 +164,12 @@ def remove_job_listener(self, event) -> None: def executed_job_listener(self, event) -> None: """Listens to executed jobs""" - logger.info("Scheduler executed job: %s", event.job_id) + logger.info("Executed job: %s", event.job_id) self.running_jobs.remove(event.job_id) def submitted_job_listener(self, event) -> None: """Listens to submitted jobs""" - logger.info("Scheduler submitted job: %s", event.job_id) + logger.info("Started job: %s", event.job_id) self.running_jobs.add(event.job_id) # automated processing pipeline: From 9cbd5a6925d0e217f0bb4c5a3fb927daf939f9a5 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 30 Mar 2024 22:38:54 +0100 Subject: [PATCH 29/62] Removing bookkeeping files, frames to process fully handled via the database --- Dockerfile | 2 - docker-compose.yml | 1 - .../bookkeep_new_data_time_range.py | 133 ------------------ .../processing/process_raw_bucket.py | 4 - src/transmission/processing/save_raw_data.py | 2 - .../processing/telemetry_scraper.py | 2 - .../processing/temp/da_vinci/buffer/.gitkeep | 0 .../temp/da_vinci/da_vinci_downlink.json | 5 - .../temp/da_vinci/da_vinci_uplink.json | 5 - .../temp/da_vinci/failed_downlink.json | 5 - .../temp/da_vinci/failed_uplink.json | 5 - .../processing/temp/da_vinci/scraper/.gitkeep | 0 .../processing/temp/delfi_c3/buffer/.gitkeep | 0 .../temp/delfi_c3/delfi_c3_downlink.json | 5 - .../temp/delfi_c3/delfi_c3_uplink.json | 5 - .../temp/delfi_c3/failed_downlink.json | 5 - .../temp/delfi_c3/failed_uplink.json | 5 - .../processing/temp/delfi_c3/scraper/.gitkeep | 0 .../temp/delfi_next/buffer/.gitkeep | 0 .../temp/delfi_next/delfi_next_downlink.json | 5 - .../temp/delfi_next/delfi_next_uplink.json | 5 - .../temp/delfi_next/failed_downlink.json | 5 - .../temp/delfi_next/failed_uplink.json | 5 - .../temp/delfi_next/scraper/.gitkeep | 0 .../processing/temp/delfi_pq/buffer/.gitkeep | 0 .../temp/delfi_pq/delfi_pq_downlink.json | 5 - .../temp/delfi_pq/delfi_pq_uplink.json | 5 - .../temp/delfi_pq/failed_downlink.json | 5 - .../temp/delfi_pq/failed_uplink.json | 5 - .../processing/temp/delfi_pq/scraper/.gitkeep | 0 .../time_range_files/delfi_pq_uplink.json | 8 -- .../test/test_frame_processing.py | 10 -- src/transmission/test/test_views_templates.py | 8 -- 33 files changed, 250 deletions(-) delete mode 100644 src/transmission/processing/bookkeep_new_data_time_range.py delete mode 100644 src/transmission/processing/temp/da_vinci/buffer/.gitkeep delete mode 100644 src/transmission/processing/temp/da_vinci/da_vinci_downlink.json delete mode 100644 src/transmission/processing/temp/da_vinci/da_vinci_uplink.json delete mode 100644 src/transmission/processing/temp/da_vinci/failed_downlink.json delete mode 100644 src/transmission/processing/temp/da_vinci/failed_uplink.json delete mode 100644 src/transmission/processing/temp/da_vinci/scraper/.gitkeep delete mode 100644 src/transmission/processing/temp/delfi_c3/buffer/.gitkeep delete mode 100644 src/transmission/processing/temp/delfi_c3/delfi_c3_downlink.json delete mode 100644 src/transmission/processing/temp/delfi_c3/delfi_c3_uplink.json delete mode 100644 src/transmission/processing/temp/delfi_c3/failed_downlink.json delete mode 100644 src/transmission/processing/temp/delfi_c3/failed_uplink.json delete mode 100644 src/transmission/processing/temp/delfi_c3/scraper/.gitkeep delete mode 100644 src/transmission/processing/temp/delfi_next/buffer/.gitkeep delete mode 100644 src/transmission/processing/temp/delfi_next/delfi_next_downlink.json delete mode 100644 src/transmission/processing/temp/delfi_next/delfi_next_uplink.json delete mode 100644 src/transmission/processing/temp/delfi_next/failed_downlink.json delete mode 100644 src/transmission/processing/temp/delfi_next/failed_uplink.json delete mode 100644 src/transmission/processing/temp/delfi_next/scraper/.gitkeep delete mode 100644 src/transmission/processing/temp/delfi_pq/buffer/.gitkeep delete mode 100644 src/transmission/processing/temp/delfi_pq/delfi_pq_downlink.json delete mode 100644 src/transmission/processing/temp/delfi_pq/delfi_pq_uplink.json delete mode 100644 src/transmission/processing/temp/delfi_pq/failed_downlink.json delete mode 100644 src/transmission/processing/temp/delfi_pq/failed_uplink.json delete mode 100644 src/transmission/processing/temp/delfi_pq/scraper/.gitkeep delete mode 100644 src/transmission/processing/time_range_files/delfi_pq_uplink.json diff --git a/Dockerfile b/Dockerfile index ad5df686..c8ad522a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,8 +40,6 @@ RUN mkdir /var/log/django RUN chown -R user:user /app RUN chmod -R 755 /var/log/django -RUN chown -R user:user /app/transmission/processing/temp -RUN chmod -R 755 /app/transmission/processing/temp RUN chown -R user:user /app/home/temp RUN chmod -R 755 /app/home/temp diff --git a/docker-compose.yml b/docker-compose.yml index 378da015..1bfe5afb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,7 +23,6 @@ services: build: context: . volumes: - - ./src/transmission/processing/temp/:/app/transmission/processing/temp/ - ./src/home/temp/:/app/home/temp/ environment: - ALLOWED_HOSTS=${ALLOWED_HOSTS:-localhost,127.0.0.1} diff --git a/src/transmission/processing/bookkeep_new_data_time_range.py b/src/transmission/processing/bookkeep_new_data_time_range.py deleted file mode 100644 index 514070f4..00000000 --- a/src/transmission/processing/bookkeep_new_data_time_range.py +++ /dev/null @@ -1,133 +0,0 @@ -"""Methods recording timestamps of newly added data, used for more targeted processing.""" -import os -from datetime import datetime, timedelta -import json -from transmission.processing.satellites import TIME_FORMAT - -TIME_RANGE_FILES_DIR = "transmission/processing/temp/" - - -def get_new_data_file_path(satellite: str, link: str) -> str: - """Return filepath of the new data time range file.""" - return TIME_RANGE_FILES_DIR + satellite + "/" + satellite + "_" + link + ".json" - - -def get_failed_data_file_path(satellite: str, link: str) -> str: - """Return filepath of the time range file storing the interval .""" - return TIME_RANGE_FILES_DIR + satellite + "/" + "failed" + "_" + link + ".json" - - -def get_new_data_scraper_temp_folder(satellite: str) -> str: - """Return filepath of the scraper process temp time range files.""" - return TIME_RANGE_FILES_DIR + satellite + "/scraper/" - - -def get_new_data_buffer_temp_folder(satellite: str) -> str: - """Return filepath of the buffer process temp time range files.""" - return TIME_RANGE_FILES_DIR + satellite + "/buffer/" - - -def read_time_range_file(input_file: str) -> dict: - """Read time range file and return contents as dictionary.""" - new_data_time_range = {} - with open(input_file, "r", encoding="utf-8") as file: - new_data_time_range = json.load(file) - - return new_data_time_range - - -def save_timestamps_to_file(timestamps: dict, input_file: str) -> None: - """Dump timestamps to the input file in json format.""" - with open(input_file, "w", encoding="utf-8") as file: - file.write(json.dumps(timestamps, indent=4)) - - -def reset_new_data_timestamps(satellite: str, link: str, input_file: str) -> None: - """Replace timestamps form the json given by the input file with [].""" - new_data_time_range = read_time_range_file(input_file) - new_data_time_range[satellite][link] = [] - - with open(input_file, "w", encoding="utf-8") as file: - file.write(json.dumps(new_data_time_range, indent=4)) - - -def include_timestamp_in_time_range(satellite: str, link: str, timestamp, - input_file: str = None, existing_range: dict = None) -> dict: - """This function ensures that a given timestamp will be included in the - time range such that it can then be processed and parsed from raw form. - The range can be maintained in memory given an existing_range or in file given an input_file.""" - - if isinstance(timestamp, str): - time = datetime.strptime(timestamp, TIME_FORMAT) - else: - time = timestamp - - start_time = (time - timedelta(seconds=1)).strftime(TIME_FORMAT) - end_time = (time + timedelta(seconds=1)).strftime(TIME_FORMAT) - - time_range = (start_time, end_time) - - return update_new_data_timestamps(satellite, link, time_range, input_file, existing_range) - - -def update_new_data_timestamps(satellite: str, link: str, new_time_range: tuple, - input_file: str = None, existing_range: dict = None) -> dict: - """Bookkeep time range of unprocessed telemetry. - If an input_file is specified, the timestamps from the file, will be updated and dumped. - If the existing_range is specified, it will be updated and returned as a dictionary. - If both input_file and existing_range are specified, an exception is raised.""" - - if input_file is not None and existing_range is not None: - raise RuntimeError("Specify either input_file or existing_range, not both.") - - start_time = new_time_range[0] - end_time = new_time_range[1] - - if input_file is not None: - new_data_time_range = read_time_range_file(input_file) - - elif existing_range in [{}, None]: - new_data_time_range = {} - new_data_time_range[satellite] = {} - new_data_time_range[satellite][link] = [] - else: - new_data_time_range = existing_range - - # No time range saved - if new_data_time_range[satellite][link] == []: - new_data_time_range[satellite][link] = [start_time, end_time] - # Update time range - else: - new_data_time_range[satellite][link][0] = min( - new_data_time_range[satellite][link][0], - start_time - ) - new_data_time_range[satellite][link][1] = max( - new_data_time_range[satellite][link][1], - end_time - ) - if input_file is not None: - with open(input_file, "w", encoding="utf-8") as file: - json.dump(new_data_time_range, file, indent=4) - - return new_data_time_range - - -def combine_time_ranges(satellite: str, link: str) -> None: - """Combine time ranges of new data from all processes (buffer processing and scraper).""" - scraper_folder = get_new_data_scraper_temp_folder(satellite) - buffer_folder = get_new_data_buffer_temp_folder(satellite) - - for folder in [scraper_folder, buffer_folder]: - - for temp_file in os.listdir(folder): - if link in temp_file: - new_data_time_range = read_time_range_file(folder + temp_file) - new_data_overview_file = get_new_data_file_path(satellite, link) - include_timestamp_in_time_range(satellite, link, - new_data_time_range[satellite][link][0], - input_file=new_data_overview_file) - include_timestamp_in_time_range(satellite, link, - new_data_time_range[satellite][link][1], - input_file=new_data_overview_file) - os.remove(folder + temp_file) diff --git a/src/transmission/processing/process_raw_bucket.py b/src/transmission/processing/process_raw_bucket.py index 349fea5b..ed60e0f1 100644 --- a/src/transmission/processing/process_raw_bucket.py +++ b/src/transmission/processing/process_raw_bucket.py @@ -4,7 +4,6 @@ import traceback from transmission.processing.XTCEParser import SatParsers, XTCEException from django_logger import logger -import transmission.processing.bookkeep_new_data_time_range as time_range from transmission.processing.influxdb_api import INFLUX_ORG, commit_frame, \ get_influx_db_read_and_query_api, write_frame_to_raw_bucket @@ -21,9 +20,6 @@ def store_raw_frame(satellite: str, timestamp: str, frame: str, observer: str, l } stored = commit_frame(write_api, query_api, satellite, link, frame_fields) - if stored: - file = time_range.get_new_data_file_path(satellite, link) - time_range.include_timestamp_in_time_range(satellite, link, timestamp, file) return stored diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index 73eaeae1..3f0ab26a 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -17,8 +17,6 @@ from members.models import Member from transmission.models import Uplink, Downlink, TLE, Satellite from transmission.processing.XTCEParser import SatParsers, XTCEException -from transmission.processing.bookkeep_new_data_time_range import get_new_data_buffer_temp_folder, \ - include_timestamp_in_time_range, save_timestamps_to_file from transmission.processing.influxdb_api import save_raw_frame_to_influxdb from transmission.processing.telemetry_scraper import strip_tlm import traceback diff --git a/src/transmission/processing/telemetry_scraper.py b/src/transmission/processing/telemetry_scraper.py index 69f80b00..2508f357 100644 --- a/src/transmission/processing/telemetry_scraper.py +++ b/src/transmission/processing/telemetry_scraper.py @@ -8,8 +8,6 @@ from django_logger import logger from transmission.processing.satellites import SATELLITES, TIME_FORMAT -from transmission.processing.bookkeep_new_data_time_range import get_new_data_scraper_temp_folder, \ - include_timestamp_in_time_range, save_timestamps_to_file from transmission.processing.influxdb_api import save_raw_frame_to_influxdb SATNOGS_PATH = "https://db.satnogs.org/api/telemetry/" diff --git a/src/transmission/processing/temp/da_vinci/buffer/.gitkeep b/src/transmission/processing/temp/da_vinci/buffer/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/transmission/processing/temp/da_vinci/da_vinci_downlink.json b/src/transmission/processing/temp/da_vinci/da_vinci_downlink.json deleted file mode 100644 index 8afbb6e5..00000000 --- a/src/transmission/processing/temp/da_vinci/da_vinci_downlink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "da_vinci": { - "downlink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/da_vinci/da_vinci_uplink.json b/src/transmission/processing/temp/da_vinci/da_vinci_uplink.json deleted file mode 100644 index e2fae0b6..00000000 --- a/src/transmission/processing/temp/da_vinci/da_vinci_uplink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "da_vinci": { - "uplink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/da_vinci/failed_downlink.json b/src/transmission/processing/temp/da_vinci/failed_downlink.json deleted file mode 100644 index 8afbb6e5..00000000 --- a/src/transmission/processing/temp/da_vinci/failed_downlink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "da_vinci": { - "downlink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/da_vinci/failed_uplink.json b/src/transmission/processing/temp/da_vinci/failed_uplink.json deleted file mode 100644 index e2fae0b6..00000000 --- a/src/transmission/processing/temp/da_vinci/failed_uplink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "da_vinci": { - "uplink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/da_vinci/scraper/.gitkeep b/src/transmission/processing/temp/da_vinci/scraper/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/transmission/processing/temp/delfi_c3/buffer/.gitkeep b/src/transmission/processing/temp/delfi_c3/buffer/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/transmission/processing/temp/delfi_c3/delfi_c3_downlink.json b/src/transmission/processing/temp/delfi_c3/delfi_c3_downlink.json deleted file mode 100644 index b8d7085b..00000000 --- a/src/transmission/processing/temp/delfi_c3/delfi_c3_downlink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "delfi_c3": { - "downlink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/delfi_c3/delfi_c3_uplink.json b/src/transmission/processing/temp/delfi_c3/delfi_c3_uplink.json deleted file mode 100644 index 46f9c4d6..00000000 --- a/src/transmission/processing/temp/delfi_c3/delfi_c3_uplink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "delfi_c3": { - "uplink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/delfi_c3/failed_downlink.json b/src/transmission/processing/temp/delfi_c3/failed_downlink.json deleted file mode 100644 index b8d7085b..00000000 --- a/src/transmission/processing/temp/delfi_c3/failed_downlink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "delfi_c3": { - "downlink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/delfi_c3/failed_uplink.json b/src/transmission/processing/temp/delfi_c3/failed_uplink.json deleted file mode 100644 index 46f9c4d6..00000000 --- a/src/transmission/processing/temp/delfi_c3/failed_uplink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "delfi_c3": { - "uplink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/delfi_c3/scraper/.gitkeep b/src/transmission/processing/temp/delfi_c3/scraper/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/transmission/processing/temp/delfi_next/buffer/.gitkeep b/src/transmission/processing/temp/delfi_next/buffer/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/transmission/processing/temp/delfi_next/delfi_next_downlink.json b/src/transmission/processing/temp/delfi_next/delfi_next_downlink.json deleted file mode 100644 index 1c2ff850..00000000 --- a/src/transmission/processing/temp/delfi_next/delfi_next_downlink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "delfi_next": { - "downlink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/delfi_next/delfi_next_uplink.json b/src/transmission/processing/temp/delfi_next/delfi_next_uplink.json deleted file mode 100644 index 1b082f83..00000000 --- a/src/transmission/processing/temp/delfi_next/delfi_next_uplink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "delfi_next": { - "uplink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/delfi_next/failed_downlink.json b/src/transmission/processing/temp/delfi_next/failed_downlink.json deleted file mode 100644 index 1c2ff850..00000000 --- a/src/transmission/processing/temp/delfi_next/failed_downlink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "delfi_next": { - "downlink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/delfi_next/failed_uplink.json b/src/transmission/processing/temp/delfi_next/failed_uplink.json deleted file mode 100644 index 1b082f83..00000000 --- a/src/transmission/processing/temp/delfi_next/failed_uplink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "delfi_next": { - "uplink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/delfi_next/scraper/.gitkeep b/src/transmission/processing/temp/delfi_next/scraper/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/transmission/processing/temp/delfi_pq/buffer/.gitkeep b/src/transmission/processing/temp/delfi_pq/buffer/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/transmission/processing/temp/delfi_pq/delfi_pq_downlink.json b/src/transmission/processing/temp/delfi_pq/delfi_pq_downlink.json deleted file mode 100644 index 50133fd9..00000000 --- a/src/transmission/processing/temp/delfi_pq/delfi_pq_downlink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "delfi_pq": { - "downlink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/delfi_pq/delfi_pq_uplink.json b/src/transmission/processing/temp/delfi_pq/delfi_pq_uplink.json deleted file mode 100644 index 006a3d31..00000000 --- a/src/transmission/processing/temp/delfi_pq/delfi_pq_uplink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "delfi_pq": { - "uplink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/delfi_pq/failed_downlink.json b/src/transmission/processing/temp/delfi_pq/failed_downlink.json deleted file mode 100644 index 50133fd9..00000000 --- a/src/transmission/processing/temp/delfi_pq/failed_downlink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "delfi_pq": { - "downlink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/delfi_pq/failed_uplink.json b/src/transmission/processing/temp/delfi_pq/failed_uplink.json deleted file mode 100644 index 006a3d31..00000000 --- a/src/transmission/processing/temp/delfi_pq/failed_uplink.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "delfi_pq": { - "uplink": [] - } -} \ No newline at end of file diff --git a/src/transmission/processing/temp/delfi_pq/scraper/.gitkeep b/src/transmission/processing/temp/delfi_pq/scraper/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/transmission/processing/time_range_files/delfi_pq_uplink.json b/src/transmission/processing/time_range_files/delfi_pq_uplink.json deleted file mode 100644 index 0084296f..00000000 --- a/src/transmission/processing/time_range_files/delfi_pq_uplink.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "delfi_pq": { - "uplink": [ - "2021-12-19T02:20:13Z", - "2021-12-19T02:20:15Z" - ] - } -} \ No newline at end of file diff --git a/src/transmission/test/test_frame_processing.py b/src/transmission/test/test_frame_processing.py index 130a34df..ef1d79d3 100644 --- a/src/transmission/test/test_frame_processing.py +++ b/src/transmission/test/test_frame_processing.py @@ -4,7 +4,6 @@ from django.contrib.messages.storage.fallback import FallbackStorage from transmission.models import Downlink, Satellite, Uplink -from transmission.processing.bookkeep_new_data_time_range import combine_time_ranges from transmission.processing.satellites import SATELLITES from transmission.processing.save_raw_data import process_uplink_and_downlink, store_frames from transmission.views import delete_processed_frames, process @@ -25,11 +24,6 @@ def setUp(self): self.user.save() Satellite.objects.create(sat='delfipq', norad_id=1).save() - def tearDown(self) -> None: - for sat in SATELLITES: - combine_time_ranges(sat, 'uplink') - combine_time_ranges(sat, 'downlink') - def testSubmitFramesBatch(self): # add 3 valid frames from delfi_pq f1 = { "qos": 98.6, "sat": "delfipq", "timestamp": "2021-12-19T02:20:14.959630Z", "frequency": 2455.66, @@ -91,10 +85,6 @@ def setUp(self): store_frames(f, "user") def tearDown(self): - for sat in SATELLITES: - combine_time_ranges(sat, 'uplink') - combine_time_ranges(sat, 'downlink') - self.client.logout() diff --git a/src/transmission/test/test_views_templates.py b/src/transmission/test/test_views_templates.py index 0a4aed10..155f8936 100644 --- a/src/transmission/test/test_views_templates.py +++ b/src/transmission/test/test_views_templates.py @@ -7,7 +7,6 @@ from django.http import HttpRequest, SimpleCookie from django.urls import reverse from transmission.models import Downlink, Satellite, Uplink -from transmission.processing.bookkeep_new_data_time_range import combine_time_ranges from transmission.processing.satellites import SATELLITES from transmission.processing.save_raw_data import store_frames from transmission.views import submit_frame, submit_job, modify_scheduler @@ -338,9 +337,6 @@ def setUp(self): Satellite.objects.create(sat='delfic3', norad_id=1).save() def tearDown(self): - for sat in SATELLITES: - combine_time_ranges(sat, 'uplink') - combine_time_ranges(sat, 'downlink') self.client.logout() def test_requested_tables(self): @@ -398,10 +394,6 @@ def setUp(self): Satellite.objects.create(sat='delfic3', norad_id=1).save() def tearDown(self): - for sat in SATELLITES: - combine_time_ranges(sat, 'uplink') - combine_time_ranges(sat, 'downlink') - self.client.logout() def test_submit_get_request_not_allowed(self): From eba82d7ee7fa71ed2f2f80c3bbc8af36ccb436cf Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 30 Mar 2024 22:46:11 +0100 Subject: [PATCH 30/62] Removing debug logger messages --- src/transmission/processing/process_raw_bucket.py | 6 +----- src/transmission/processing/save_raw_data.py | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/transmission/processing/process_raw_bucket.py b/src/transmission/processing/process_raw_bucket.py index ed60e0f1..7f540007 100644 --- a/src/transmission/processing/process_raw_bucket.py +++ b/src/transmission/processing/process_raw_bucket.py @@ -27,7 +27,7 @@ def parse_and_store_frame(parsers: SatParsers, satellite: str, timestamp: str, f """Store parsed frame in influxdb""" parser = parsers.parsers[satellite] - #logger.debug("%s: frame: %s", satellite, frame) + telemetry = parser.processTMFrame(bytes.fromhex(frame)) bucket = satellite + "_" + link @@ -70,9 +70,6 @@ def parse_and_store_frame(parsers: SatParsers, satellite: str, timestamp: str, f db_fields["fields"] = {} db_fields["tags"] = {} - #logger.info("%s: processed frame stored. Frame timestamp: %s, link: %s, bucket: %s", - # satellite, timestamp, link, bucket) - def mark_processed_flag(satellite: str, link: str, timestamp: str, value: bool) -> None: """Write the processed flag to either True or False.""" @@ -185,7 +182,6 @@ def process_raw_bucket(satellite: str, link: str = None, all_frames: bool = Fals # one more iteration iterations += 1 - logger.info("Frames " + str(total_processed_frames) + " Iterations " + str(iterations)) if total_processed_frames != 0: # frames were processed in this iteration, reset the iteration counter diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index 3f0ab26a..4a7449b6 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -135,7 +135,6 @@ def process_uplink_and_downlink() -> tuple: """Process all unprocessed uplink and downlink frames, i.e. move them to the influxdb raw satellite data bucket.""" - logger.info("Process incoming frames") iterations = 0 parsers = SatParsers() @@ -157,11 +156,8 @@ def process_uplink_and_downlink() -> tuple: uplink_frames_count = process_frames(parsers, uplink_frames, "uplink") total_processed_frames += uplink_frames_count - logger.info("Incoming frames processed. Downlink: " + str(downlink_frames_count) + " Uplink: " + str(uplink_frames_count) ) - # one more iteration iterations += 1 - #logger.info("Frames " + str(total_processed_frames) + " Iterations " + str(iterations)) if total_processed_frames != 0: # frames were processed in this iteration, reset the iteration counter From 303bdc0ab0de20f2e53b5053ff1047e2078f9bde Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 30 Mar 2024 22:53:54 +0100 Subject: [PATCH 31/62] Fix pylint warnings --- src/home/views.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/home/views.py b/src/home/views.py index 95d1e331..772b7fd9 100644 --- a/src/home/views.py +++ b/src/home/views.py @@ -2,6 +2,7 @@ from datetime import datetime, timedelta import json import os +import traceback from django.core.exceptions import PermissionDenied from django.core.serializers.json import DjangoJSONEncoder from django.http.response import JsonResponse @@ -10,9 +11,8 @@ from skyfield.api import load, EarthSatellite, wgs84, Topos from satellite_tle import fetch_tle_from_celestrak from transmission.processing.satellites import SATELLITES, TIME_FORMAT -from transmission.processing.influxdb_api import get_last_received_frame +from transmission.processing.influxdb_api import get_last_received_frame from django_logger import logger -import traceback #pylint: disable=W0718 def get_tle(norad_id: str): @@ -73,7 +73,8 @@ def get_satellite_location_now(norad_id: str) -> dict: eph = load('de421.bsp') sunlit = satellite.at(time).is_sunlit(eph) - return {"satellite": str(tle[0]), "norad_id": norad_id, "latitude": lat_deg, "longitude": lon_deg, "sunlit": int(sunlit)} + return {"satellite": str(tle[0]), "norad_id": norad_id, "latitude": lat_deg, "longitude": lon_deg, + "sunlit": int(sunlit)} def get_next_pass_over_delft(request, norad_id: str): @@ -121,13 +122,13 @@ def _get_satellites_status(): for sat, info in SATELLITES.items(): sats_status[str(sat + "_status")] = info["status"] last_rx_time = get_last_received_frame(sat) - if last_rx_time is not None and type(last_rx_time) is datetime: - sats_status[str(sat + "_last_data")] = last_rx_time#.strftime('%m %d %Y %H:%M:%S UTC') + if last_rx_time is not None and isinstance(last_rx_time, datetime): + sats_status[str(sat + "_last_data")] = last_rx_time else: sats_status[str(sat + "_last_data")] = None - if info["launch"] is not None: - launch_time = datetime.strptime(info["launch"], '%Y-%m-%dT%H:%M:%S.%fZ')#.strftime('%M %d%S %Y') + if info["launch"] is not None: + launch_time = datetime.strptime(info["launch"], '%Y-%m-%dT%H:%M:%S.%fZ') sats_status[str(sat + "_launch")] = launch_time else: sats_status[str(sat + "_launch")] = None @@ -148,7 +149,7 @@ def home(request): try: context = _get_satellites_status() return render(request, "home/index.html", context) - except Exception as e: + except Exception as _: logger.error(traceback.format_exc()) return render(request, "home/index.html", context) From 721ce49c28b3c56c38e70f2786420c4314dc059c Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sun, 31 Mar 2024 00:39:18 +0100 Subject: [PATCH 32/62] Fixing pylint warnings --- src/transmission/processing/influxdb_api.py | 16 +++--- src/transmission/processing/save_raw_data.py | 51 +++++++------------ .../processing/telemetry_scraper.py | 10 +--- src/transmission/scheduler.py | 8 +-- 4 files changed, 29 insertions(+), 56 deletions(-) diff --git a/src/transmission/processing/influxdb_api.py b/src/transmission/processing/influxdb_api.py index ce56624e..03860253 100644 --- a/src/transmission/processing/influxdb_api.py +++ b/src/transmission/processing/influxdb_api.py @@ -3,7 +3,6 @@ import os from influxdb_client import InfluxDBClient from influxdb_client.client.write_api import SYNCHRONOUS -import traceback from transmission.processing.satellites import TIME_FORMAT from django_logger import logger @@ -108,18 +107,17 @@ def get_last_received_frame(satellite: str): bucket = satellite + "_raw_data" query = f'''from(bucket: "{bucket}") - |> range(start: -15y) + |> range(start: 0) |> filter(fn: (r) => r["_measurement"] == "{satellite + "_downlink_raw_data"}") |> filter(fn: (r) => r["_field"] == "timestamp") |> tail(n: 1) ''' - try: - ret = query_api.query(query=query) + ret = query_api.query(query=query) - for table in ret: - return datetime.strptime(table.records[0]["_value"], '%Y-%m-%dT%H:%M:%SZ') + if len(ret) > 0: + return datetime.strptime(ret[0].records[0]["_value"], '%Y-%m-%dT%H:%M:%SZ') + else: + # no result + return None - except: - e = traceback.format_exc() - logger.error(e) diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index 4a7449b6..4e74f3ef 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -5,6 +5,7 @@ import json from typing import Union import time +from datetime import timezone from django.forms import ValidationError from django.core.exceptions import PermissionDenied @@ -12,7 +13,6 @@ from django.db.models.query import QuerySet from django.utils.dateparse import parse_datetime from skyfield.api import load, EarthSatellite -from datetime import timezone from django_logger import logger from members.models import Member from transmission.models import Uplink, Downlink, TLE, Satellite @@ -131,9 +131,12 @@ def parse_submitted_frame(frame: dict, frame_entry: models.Model) -> models.Mode return frame_entry -def process_uplink_and_downlink() -> tuple: - """Process all unprocessed uplink and downlink frames, - i.e. move them to the influxdb raw satellite data bucket.""" +def process_uplink_and_downlink(invalid_frames: bool = False) -> tuple: + """Process all processed uplink and downlink frames, + i.e. move them to the influxdb raw satellite data bucket. + if invalid_frames is false, only new frames are processed. If + invalid_frames is true, only frames already marked as invalid + will be processed.""" iterations = 0 @@ -146,15 +149,18 @@ def process_uplink_and_downlink() -> tuple: total_processed_frames = 0 - # set a maximum length to the results to ensure responsive data processing - downlink_frames = Downlink.objects.all().filter(processed=False)[:100] - downlink_frames_count = process_frames(parsers, downlink_frames, "downlink") - total_processed_frames += downlink_frames_count + if not invalid_frames: + # set a maximum length to the results to ensure responsive data processing + downlink_frames = Downlink.objects.all().filter(processed=False)[:100] + uplink_frames = Uplink.objects.all().filter(processed=False)[:100] + else: + # set a maximum length to the results to ensure responsive data processing + downlink_frames = Downlink.objects.all().filter(processed=True).filter(invalid=True)[:100] + uplink_frames = Uplink.objects.all().filter(processed=True).filter(invalid=True)[:100] - # set a maximum length to the results to ensure responsive data processing - uplink_frames = Uplink.objects.all().filter(processed=False)[:100] + downlink_frames_count = process_frames(parsers, downlink_frames, "downlink") uplink_frames_count = process_frames(parsers, uplink_frames, "uplink") - total_processed_frames += uplink_frames_count + total_processed_frames += downlink_frames_count + uplink_frames_count # one more iteration iterations += 1 @@ -166,28 +172,6 @@ def process_uplink_and_downlink() -> tuple: #return downlink_frames_count, uplink_frames_count return 0, 0 -def reprocess_uplink_and_downlink() -> tuple: - """Reprocess all invalid uplink and downlink frames, - i.e. move them to the influxdb raw satellite data bucket.""" - - logger.info("Reprocess incoming frames") - - parsers = SatParsers() - - downlink_frames = Downlink.objects.all().filter(processed=True).filter(invalid=True) - logger.info("Downlink count " + str(len(downlink_frames))) - try: - downlink_frames_count = process_frames(parsers, downlink_frames, "downlink") - except Exception as _: - logger.info(traceback.format_exc()) - - uplink_frames = Uplink.objects.all().filter(processed=True).filter(invalid=True) - logger.info("Uplink count " + str(len(uplink_frames))) - uplink_frames_count = process_frames(parsers, uplink_frames, "uplink") - - logger.info("Incoming frames reprocessed") - return downlink_frames_count, uplink_frames_count - def process_frames(parsers: SatParsers, frames: QuerySet, link: str) -> int: """Try to store frame to influxdb and set the processed flag to True @@ -195,7 +179,6 @@ def process_frames(parsers: SatParsers, frames: QuerySet, link: str) -> int: Returns the count of successfully processed_frames.""" processed_frames = 0 - processed_frames_timestamps = {} for frame_obj in frames: frame_dict = frame_obj.to_dictionary() stored, satellite = store_frame_to_influxdb(parsers, frame_dict, link) diff --git a/src/transmission/processing/telemetry_scraper.py b/src/transmission/processing/telemetry_scraper.py index 2508f357..6e46d5d1 100644 --- a/src/transmission/processing/telemetry_scraper.py +++ b/src/transmission/processing/telemetry_scraper.py @@ -84,7 +84,6 @@ def scrape(satellite: str, save_to_db=True, save_to_file=False) -> None: logger.info(last) first = telemetry_tmp[0] logger.info(first) - logger.info(sate_to_db) # concatenate telemetry telemetry = telemetry + telemetry_tmp @@ -96,11 +95,7 @@ def scrape(satellite: str, save_to_db=True, save_to_file=False) -> None: if save_to_db: fields_to_save = ["frame", "timestamp", "observer"] stripped_tlm = strip_tlm_list(telemetry_tmp, fields_to_save) - if save_raw_frame_to_influxdb(satellite, "downlink", stripped_tlm): - time_range = include_timestamp_in_time_range(satellite, 'downlink', - first["timestamp"], existing_range=time_range) - time_range = include_timestamp_in_time_range(satellite, 'downlink', - last["timestamp"], existing_range=time_range) + save_raw_frame_to_influxdb(satellite, "downlink", stripped_tlm) # if the frame is not stored (due to it being stored in a past scrape) and # the next request retrieves data older than a week -> stop @@ -119,9 +114,6 @@ def scrape(satellite: str, save_to_db=True, save_to_file=False) -> None: delay = re.findall('[0-9]+', telemetry_tmp["detail"])[0] logger.info("Sleeping %s s (request throttled)", delay) time.sleep(int(delay)) - path = get_new_data_scraper_temp_folder(satellite) - path += satellite + "_downlink_" + str(len(os.listdir(path))) + ".json" - save_timestamps_to_file(time_range, path) else: break else: diff --git a/src/transmission/scheduler.py b/src/transmission/scheduler.py index 04c9263a..65b2fa47 100644 --- a/src/transmission/scheduler.py +++ b/src/transmission/scheduler.py @@ -22,7 +22,7 @@ from transmission.processing.satellites import SATELLITES from transmission.processing.process_raw_bucket import process_raw_bucket from transmission.processing.telemetry_scraper import scrape -from transmission.processing.save_raw_data import process_uplink_and_downlink, reprocess_uplink_and_downlink +from transmission.processing.save_raw_data import process_uplink_and_downlink from transmission.processing.XTCEParser import XTCEParser, XTCEException def get_job_id(satellite: str, job_description: str) -> str: @@ -47,14 +47,14 @@ def schedule_job(job_type: str, satellite: str = None, link: str = None, scheduler.add_job_to_schedule(scrape, args, job_id, date, interval) elif job_type == "buffer_processing": - args = [] + args = [False] job_id = job_type scheduler.add_job_to_schedule(process_uplink_and_downlink, args, job_id, date, interval) elif job_type == "buffer_reprocessing": - args = [] + args = [True] job_id = job_type - scheduler.add_job_to_schedule(reprocess_uplink_and_downlink, args, job_id, date, interval) + scheduler.add_job_to_schedule(process_uplink_and_downlink, args, job_id, date, interval) elif job_type == "raw_bucket_processing" and satellite in SATELLITES: args = [satellite, link] From 56846d5222d62db3f2a944084f2af8747e80437a Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sun, 31 Mar 2024 17:20:09 +0200 Subject: [PATCH 33/62] Fixing pyling warnings --- src/transmission/processing/influxdb_api.py | 7 ++-- .../processing/process_raw_bucket.py | 36 +++++++++---------- .../processing/telemetry_scraper.py | 1 - src/transmission/scheduler.py | 10 +++--- src/transmission/views.py | 2 +- 5 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/transmission/processing/influxdb_api.py b/src/transmission/processing/influxdb_api.py index 03860253..21ea9a08 100644 --- a/src/transmission/processing/influxdb_api.py +++ b/src/transmission/processing/influxdb_api.py @@ -5,7 +5,6 @@ from influxdb_client.client.write_api import SYNCHRONOUS from transmission.processing.satellites import TIME_FORMAT -from django_logger import logger INFLUXDB_URL = "http://influxdb:8086" INFLUX_ORG = os.environ.get('INFLUXDB_V2_ORG', 'DelfiSpace') @@ -103,6 +102,9 @@ def save_raw_frame_to_influxdb(satellite: str, link: str, telemetry) -> bool: return stored def get_last_received_frame(satellite: str): + """Retrieve the last received frame for the specified satellite from the raw + data bucket.""" + [write_api, query_api] = get_influx_db_read_and_query_api() bucket = satellite + "_raw_data" @@ -112,7 +114,7 @@ def get_last_received_frame(satellite: str): |> filter(fn: (r) => r["_field"] == "timestamp") |> tail(n: 1) ''' - + ret = query_api.query(query=query) if len(ret) > 0: @@ -120,4 +122,3 @@ def get_last_received_frame(satellite: str): else: # no result return None - diff --git a/src/transmission/processing/process_raw_bucket.py b/src/transmission/processing/process_raw_bucket.py index 7f540007..f0eb566f 100644 --- a/src/transmission/processing/process_raw_bucket.py +++ b/src/transmission/processing/process_raw_bucket.py @@ -23,7 +23,8 @@ def store_raw_frame(satellite: str, timestamp: str, frame: str, observer: str, l return stored -def parse_and_store_frame(parsers: SatParsers, satellite: str, timestamp: str, frame: str, observer: str, link: str) -> None: +def parse_and_store_frame(parsers: SatParsers, satellite: str, timestamp: str, frame: str, + observer: str, link: str) -> None: """Store parsed frame in influxdb""" parser = parsers.parsers[satellite] @@ -105,15 +106,13 @@ def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, sta |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") ''' - if skip_processed == True: - get_unprocessed_frames_query = get_unprocessed_frames_query + f''' - |> filter(fn: (r) => r["processed"] == false) - ''' + if skip_processed: + get_unprocessed_frames_query = get_unprocessed_frames_query + \ + "|> filter(fn: (r) => r[\"processed\"] == false)" # limit the maximum numbr of frames processed per round - get_unprocessed_frames_query = get_unprocessed_frames_query + f''' - |> limit(n:100, offset: 0) - ''' + get_unprocessed_frames_query = get_unprocessed_frames_query + \ + "|> limit(n:100, offset: 0)" # query result as dataframe dataframe = query_api.query_data_frame(query=get_unprocessed_frames_query) @@ -158,7 +157,7 @@ def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, sta def process_raw_bucket(satellite: str, link: str = None, all_frames: bool = False, failed: bool = False): """Trigger bucket processing or reprocessing given satellite.""" # if link is None process both uplink and downlink, otherwise process only specified link - + total_processed_frames = 0 iterations = 0 @@ -168,16 +167,19 @@ def process_raw_bucket(satellite: str, link: str = None, all_frames: bool = Fals # at least 10 seconds while looking for more frames to process while iterations < 50: time.sleep(0.2) - + total_processed_frames = 0 if link in ["uplink", "downlink"]: - processed_frames_count, total_frames_count = _process_raw_bucket(parsers, satellite, link, all_frames, failed) + processed_frames_count = _process_raw_bucket(parsers, satellite, + link, all_frames, failed) total_processed_frames += processed_frames_count else: - processed_frames_count, total_frames_count = _process_raw_bucket(parsers, satellite, "uplink", all_frames, failed) + processed_frames_count = _process_raw_bucket(parsers, satellite, + "uplink", all_frames, failed) total_processed_frames += processed_frames_count - processed_frames_count, total_frames_count = _process_raw_bucket(parsers, satellite, "downlink", all_frames, failed) + processed_frames_count = _process_raw_bucket(parsers, satellite, + "downlink", all_frames, failed) total_processed_frames += processed_frames_count # one more iteration @@ -196,11 +198,5 @@ def _process_raw_bucket(parsers: SatParsers, satellite: str, link: str, all_fram # process the entire bucket if all_frames: return process_retrieved_frames(parsers, satellite, link, "0", "now()", skip_processed=False) - else: - return process_retrieved_frames(parsers, satellite, link, "0", "now()", skip_processed=True) - - processed_frames_count = 0 - total_frames_count = 0 - - return processed_frames_count, total_frames_count + return process_retrieved_frames(parsers, satellite, link, "0", "now()", skip_processed=True) diff --git a/src/transmission/processing/telemetry_scraper.py b/src/transmission/processing/telemetry_scraper.py index 6e46d5d1..4fd43543 100644 --- a/src/transmission/processing/telemetry_scraper.py +++ b/src/transmission/processing/telemetry_scraper.py @@ -66,7 +66,6 @@ def scrape(satellite: str, save_to_db=True, save_to_file=False) -> None: telemetry = [] telemetry_tmp = [] logger.info("SatNOGS scraper started. Scraping %s telemetry.", satellite) - time_range = {} while True: logger.info(get_satnogs_params(satellite)) response = requests.get( diff --git a/src/transmission/scheduler.py b/src/transmission/scheduler.py index 65b2fa47..a1b208f8 100644 --- a/src/transmission/scheduler.py +++ b/src/transmission/scheduler.py @@ -9,21 +9,21 @@ - reprocess_failed_raw_bucket """ import datetime -import traceback from typing import Callable from apscheduler.schedulers.base import STATE_STOPPED, STATE_PAUSED, STATE_RUNNING from apscheduler.schedulers.background import BackgroundScheduler from apscheduler.triggers.interval import IntervalTrigger from apscheduler.triggers.date import DateTrigger from apscheduler.executors.pool import ThreadPoolExecutor -from apscheduler.events import EVENT_JOB_ADDED, EVENT_JOB_REMOVED, EVENT_JOB_EXECUTED, EVENT_JOB_SUBMITTED, EVENT_JOB_ERROR +from apscheduler.events import EVENT_JOB_ADDED, EVENT_JOB_REMOVED, EVENT_JOB_EXECUTED, + EVENT_JOB_SUBMITTED, EVENT_JOB_ERROR from django.forms import ValidationError from django_logger import logger from transmission.processing.satellites import SATELLITES from transmission.processing.process_raw_bucket import process_raw_bucket from transmission.processing.telemetry_scraper import scrape from transmission.processing.save_raw_data import process_uplink_and_downlink -from transmission.processing.XTCEParser import XTCEParser, XTCEException +from transmission.processing.XTCEParser import XTCEParser def get_job_id(satellite: str, job_description: str) -> str: """Create an id, job description""" @@ -133,7 +133,9 @@ def __init__(self) -> None: Scheduler.__instance = self - XTCEParser.loadGateway(); + # TODO not very nice to start it here, but this class is a singleton and + # in ensures the gateway is loaded only once + XTCEParser.loadGateway() def get_state(self) -> str: """Returns the state of the scheduler: running, paused, shutdown.""" diff --git a/src/transmission/views.py b/src/transmission/views.py index 68c0bae1..51583b80 100644 --- a/src/transmission/views.py +++ b/src/transmission/views.py @@ -1,5 +1,5 @@ """API request handling. Map requests to the corresponding HTMLs.""" -from datetime import timedelta, datetime +from datetime import datetime from http import HTTPStatus import json from json.decoder import JSONDecodeError From 767035b15b7c754bb8e6b1339c63cc0cf77ced29 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sun, 31 Mar 2024 17:37:08 +0200 Subject: [PATCH 34/62] Fixing remaining pylint warnings --- src/home/views.py | 2 +- src/transmission/processing/influxdb_api.py | 11 +++++++---- src/transmission/processing/process_raw_bucket.py | 8 +++----- src/transmission/processing/save_raw_data.py | 3 --- src/transmission/scheduler.py | 2 +- 5 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/home/views.py b/src/home/views.py index 772b7fd9..ae5ba542 100644 --- a/src/home/views.py +++ b/src/home/views.py @@ -73,7 +73,7 @@ def get_satellite_location_now(norad_id: str) -> dict: eph = load('de421.bsp') sunlit = satellite.at(time).is_sunlit(eph) - return {"satellite": str(tle[0]), "norad_id": norad_id, "latitude": lat_deg, "longitude": lon_deg, + return {"satellite": str(tle[0]), "norad_id": norad_id, "latitude": lat_deg, "longitude": lon_deg, "sunlit": int(sunlit)} diff --git a/src/transmission/processing/influxdb_api.py b/src/transmission/processing/influxdb_api.py index 21ea9a08..063dc682 100644 --- a/src/transmission/processing/influxdb_api.py +++ b/src/transmission/processing/influxdb_api.py @@ -105,7 +105,9 @@ def get_last_received_frame(satellite: str): """Retrieve the last received frame for the specified satellite from the raw data bucket.""" - [write_api, query_api] = get_influx_db_read_and_query_api() + client = get_influxdb_client() + query_api = client.query_api() + bucket = satellite + "_raw_data" query = f'''from(bucket: "{bucket}") @@ -118,7 +120,8 @@ def get_last_received_frame(satellite: str): ret = query_api.query(query=query) if len(ret) > 0: + # data received found in bucket return datetime.strptime(ret[0].records[0]["_value"], '%Y-%m-%dT%H:%M:%SZ') - else: - # no result - return None + + # no result + return None diff --git a/src/transmission/processing/process_raw_bucket.py b/src/transmission/processing/process_raw_bucket.py index f0eb566f..2464fde8 100644 --- a/src/transmission/processing/process_raw_bucket.py +++ b/src/transmission/processing/process_raw_bucket.py @@ -3,11 +3,9 @@ import time import traceback from transmission.processing.XTCEParser import SatParsers, XTCEException -from django_logger import logger from transmission.processing.influxdb_api import INFLUX_ORG, commit_frame, \ get_influx_db_read_and_query_api, write_frame_to_raw_bucket - -write_api, query_api = get_influx_db_read_and_query_api() +from django_logger import logger def store_raw_frame(satellite: str, timestamp: str, frame: str, observer: str, link: str) -> bool: @@ -173,12 +171,12 @@ def process_raw_bucket(satellite: str, link: str = None, all_frames: bool = Fals if link in ["uplink", "downlink"]: processed_frames_count = _process_raw_bucket(parsers, satellite, link, all_frames, failed) - total_processed_frames += processed_frames_count + total_processed_frames += processed_frames_count else: processed_frames_count = _process_raw_bucket(parsers, satellite, "uplink", all_frames, failed) total_processed_frames += processed_frames_count - processed_frames_count = _process_raw_bucket(parsers, satellite, + processed_frames_count = _process_raw_bucket(parsers, satellite, "downlink", all_frames, failed) total_processed_frames += processed_frames_count diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index 4e74f3ef..4f8bad4f 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -1,5 +1,4 @@ """Scripts for saving the frames into the database""" -import os import re import copy import json @@ -13,13 +12,11 @@ from django.db.models.query import QuerySet from django.utils.dateparse import parse_datetime from skyfield.api import load, EarthSatellite -from django_logger import logger from members.models import Member from transmission.models import Uplink, Downlink, TLE, Satellite from transmission.processing.XTCEParser import SatParsers, XTCEException from transmission.processing.influxdb_api import save_raw_frame_to_influxdb from transmission.processing.telemetry_scraper import strip_tlm -import traceback def store_frames(frames, username: str, application: str = None) -> int: diff --git a/src/transmission/scheduler.py b/src/transmission/scheduler.py index a1b208f8..cf96ed3f 100644 --- a/src/transmission/scheduler.py +++ b/src/transmission/scheduler.py @@ -15,7 +15,7 @@ from apscheduler.triggers.interval import IntervalTrigger from apscheduler.triggers.date import DateTrigger from apscheduler.executors.pool import ThreadPoolExecutor -from apscheduler.events import EVENT_JOB_ADDED, EVENT_JOB_REMOVED, EVENT_JOB_EXECUTED, +from apscheduler.events import EVENT_JOB_ADDED, EVENT_JOB_REMOVED, EVENT_JOB_EXECUTED, \ EVENT_JOB_SUBMITTED, EVENT_JOB_ERROR from django.forms import ValidationError from django_logger import logger From e24cbc6dea95c7013bf515217891f325599e4cd3 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Mon, 1 Apr 2024 21:47:43 +0200 Subject: [PATCH 35/62] Addid callback after raw bucket processing --- src/transmission/processing/save_raw_data.py | 25 ++++++++++++--- src/transmission/scheduler.py | 32 ++++++++++++-------- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index 4f8bad4f..09887ac5 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -5,6 +5,7 @@ from typing import Union import time from datetime import timezone +from django_logger import logger from django.forms import ValidationError from django.core.exceptions import PermissionDenied @@ -128,7 +129,7 @@ def parse_submitted_frame(frame: dict, frame_entry: models.Model) -> models.Mode return frame_entry -def process_uplink_and_downlink(invalid_frames: bool = False) -> tuple: +def process_uplink_and_downlink(invalid_frames: bool = False, callback = None) -> tuple: """Process all processed uplink and downlink frames, i.e. move them to the influxdb raw satellite data bucket. if invalid_frames is false, only new frames are processed. If @@ -139,6 +140,10 @@ def process_uplink_and_downlink(invalid_frames: bool = False) -> tuple: parsers = SatParsers() + # list the satellites whose frames have been processed: + # ths allows to later start their processing task + satellites_list = list() + # once the last frame has been processed, maintain the task active for # at least 10 seconds while looking for more frames to process while iterations < 50: @@ -155,9 +160,16 @@ def process_uplink_and_downlink(invalid_frames: bool = False) -> tuple: downlink_frames = Downlink.objects.all().filter(processed=True).filter(invalid=True)[:100] uplink_frames = Uplink.objects.all().filter(processed=True).filter(invalid=True)[:100] - downlink_frames_count = process_frames(parsers, downlink_frames, "downlink") - uplink_frames_count = process_frames(parsers, uplink_frames, "uplink") - total_processed_frames += downlink_frames_count + uplink_frames_count + downlink_frames_count = process_frames(parsers, downlink_frames, "downlink", satellites_list) + uplink_frames_count = process_frames(parsers, uplink_frames, "uplink", satellites_list) + total_processed_frames = downlink_frames_count + uplink_frames_count + + #satellites_list = list(set(downlink_sat_list + uplink_sat_list)) + #logger.info("Satellites: " + ' '.join(satellites_list)) + if callback is not None: + callback(satellites_list) + # empty the list + satellites_list = list() # one more iteration iterations += 1 @@ -170,7 +182,7 @@ def process_uplink_and_downlink(invalid_frames: bool = False) -> tuple: return 0, 0 -def process_frames(parsers: SatParsers, frames: QuerySet, link: str) -> int: +def process_frames(parsers: SatParsers, frames: QuerySet, link: str, satellites_list: list) -> int: """Try to store frame to influxdb and set the processed flag to True if a frame was successfully stored in influxdb. Returns the count of successfully processed_frames.""" @@ -186,6 +198,9 @@ def process_frames(parsers: SatParsers, frames: QuerySet, link: str) -> int: else: frame_obj.invalid = True frame_obj.save() + if satellite not in satellites_list: + satellites_list.append(satellite) + return processed_frames diff --git a/src/transmission/scheduler.py b/src/transmission/scheduler.py index cf96ed3f..66c35187 100644 --- a/src/transmission/scheduler.py +++ b/src/transmission/scheduler.py @@ -33,6 +33,21 @@ def get_job_id(satellite: str, job_description: str) -> str: return satellite + "_" + job_description + +def raw_bucket_processing_trigger_callback(satellites_list): + """Trigger raw bucket processing tasks. This callback is called when the buffer + processor finishes processing one block of frames.""" + + # retrieve the current scheduler instance + scheduler = Scheduler() + + for satellite in satellites_list: + args = [satellite] + job_id = get_job_id(satellite, "raw_bucket_processing") + # add a new job to the execution list + scheduler.add_job_to_schedule(process_raw_bucket, args, job_id) + + def schedule_job(job_type: str, satellite: str = None, link: str = None, date: datetime = None, interval: int = None) -> None: """Schedule job for a specified satellite and/or link. @@ -47,12 +62,14 @@ def schedule_job(job_type: str, satellite: str = None, link: str = None, scheduler.add_job_to_schedule(scrape, args, job_id, date, interval) elif job_type == "buffer_processing": - args = [False] + # process new frames. Add the trigger callback for start the raw bucket processing tasks + args = [False, raw_bucket_processing_trigger_callback] job_id = job_type scheduler.add_job_to_schedule(process_uplink_and_downlink, args, job_id, date, interval) elif job_type == "buffer_reprocessing": - args = [True] + # re-process failed frames. Add the trigger callback for start the raw bucket processing tasks + args = [True, raw_bucket_processing_trigger_callback] job_id = job_type scheduler.add_job_to_schedule(process_uplink_and_downlink, args, job_id, date, interval) @@ -113,7 +130,6 @@ def __init__(self) -> None: else: executors = { 'default': ThreadPoolExecutor(10), - # 'processpool': ProcessPoolExecutor(0) } job_defaults = { 'coalesce': True, @@ -156,12 +172,10 @@ def exception_listener(self, event) -> None: def add_job_listener(self, event) -> None: """Listens to newly added jobs""" - #logger.info("Scheduler added job: %s", event.job_id) self.pending_jobs.add(event.job_id) def remove_job_listener(self, event) -> None: """Listens to removed jobs""" - #logger.info("Scheduler removed job: %s", event.job_id) self.pending_jobs.remove(event.job_id) def executed_job_listener(self, event) -> None: @@ -174,13 +188,7 @@ def submitted_job_listener(self, event) -> None: logger.info("Started job: %s", event.job_id) self.running_jobs.add(event.job_id) - # automated processing pipeline: - # - when a buffer processing task completes that will trigger the raw bucket processing - # - when a scraper task completes that will trigger the raw bucket processing - if ("buffer_processing" in event.job_id) or ("buffer_reprocessing" in event.job_id): - for sat in SATELLITES: - schedule_job("raw_bucket_processing", sat) - + # TODO: add callback to force buffer processing when scraper is done #elif "scraper" in event.job_id: # for sat in SATELLITES: # if sat in event.job_id: From aec8bd8e4ed9d7caa5053b7a9e4f1cebef44679c Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Mon, 1 Apr 2024 21:48:31 +0200 Subject: [PATCH 36/62] Re-adding first row deleted by mistake and adding more comments --- .../processing/process_raw_bucket.py | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/transmission/processing/process_raw_bucket.py b/src/transmission/processing/process_raw_bucket.py index 2464fde8..e8d373f4 100644 --- a/src/transmission/processing/process_raw_bucket.py +++ b/src/transmission/processing/process_raw_bucket.py @@ -7,6 +7,7 @@ get_influx_db_read_and_query_api, write_frame_to_raw_bucket from django_logger import logger +write_api, query_api = get_influx_db_read_and_query_api() def store_raw_frame(satellite: str, timestamp: str, frame: str, observer: str, link: str) -> bool: """Store raw unprocessed frame in influxdb""" @@ -82,7 +83,7 @@ def mark_invalid_flag(satellite: str, link: str, timestamp: str, value: bool) -> # pylint: disable=R0914 def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, start_time: str, end_time: str, - skip_processed: bool = True) -> tuple: + skip_processed: bool = True) -> int: """Parse frames, store the parsed form and mark the raw entry as processed. Return the total number of frames attempting to process and how many frames were successfully processed. @@ -116,13 +117,10 @@ def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, sta dataframe = query_api.query_data_frame(query=get_unprocessed_frames_query) dataframe = dataframe.reset_index() - failed_processing_count = 0 processed_frames_count = 0 - total_frames_count = 0 # process each frame for _, row in dataframe.iterrows(): - total_frames_count += 1 try: # store processed frame parse_and_store_frame(parsers, satellite, row["_time"], row["frame"], row[radio_amateur], link) @@ -138,18 +136,20 @@ def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, sta mark_processed_flag(satellite, link, row["_time"], True) # mark frame as invalid mark_invalid_flag(satellite, link, row["_time"], True) - failed_processing_count += 1 - except Exception as ex: + # indeed a very broad exception, but it keeps the processor running in case of rogue frames + except Exception as ex: # pylint: disable=broad-except logger.error("%s: frame storage error: %s (%s)", satellite, ex, row["frame"]) logger.error(traceback.format_exc()) + logger.info("Problematic frame: " + str(row["_time"]) + " " + str(row["frame"]) + + " " + str(row[radio_amateur]) + " " + str(link)) + logger.info(row) # mark raw frame as processed mark_processed_flag(satellite, link, row["_time"], True) # mark frame as invalid mark_invalid_flag(satellite, link, row["_time"], True) - failed_processing_count += 1 - return processed_frames_count, total_frames_count + return processed_frames_count def process_raw_bucket(satellite: str, link: str = None, all_frames: bool = False, failed: bool = False): @@ -173,10 +173,10 @@ def process_raw_bucket(satellite: str, link: str = None, all_frames: bool = Fals link, all_frames, failed) total_processed_frames += processed_frames_count else: - processed_frames_count = _process_raw_bucket(parsers, satellite, + processed_frames_count = _process_raw_bucket(parsers, satellite, \ "uplink", all_frames, failed) total_processed_frames += processed_frames_count - processed_frames_count = _process_raw_bucket(parsers, satellite, + processed_frames_count = _process_raw_bucket(parsers, satellite, \ "downlink", all_frames, failed) total_processed_frames += processed_frames_count @@ -188,7 +188,7 @@ def process_raw_bucket(satellite: str, link: str = None, all_frames: bool = Fals iterations = 0 -def _process_raw_bucket(parsers: SatParsers, satellite: str, link: str, all_frames: bool, failed: bool) -> tuple: +def _process_raw_bucket(parsers: SatParsers, satellite: str, link: str, all_frames: bool, failed: bool) -> int: """Trigger bucket processing given satellite and link. all_frames=True will process the entire bucket and failed=True will process only failed frames. When both flags are True all frames will be processed.""" From 3b346b63501cd0bab6f3458922a884bb6366a56d Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Tue, 2 Apr 2024 22:59:37 +0200 Subject: [PATCH 37/62] Fixing the map wrap around --- src/home/templates/home/map.html | 2 +- src/static/map.js | 14 +-- src/static/terminator.js | 149 +++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 7 deletions(-) create mode 100644 src/static/terminator.js diff --git a/src/home/templates/home/map.html b/src/home/templates/home/map.html index c53937e1..a06f7b42 100644 --- a/src/home/templates/home/map.html +++ b/src/home/templates/home/map.html @@ -9,5 +9,5 @@ - + diff --git a/src/static/map.js b/src/static/map.js index c9a76a96..8c260428 100644 --- a/src/static/map.js +++ b/src/static/map.js @@ -7,6 +7,7 @@ const refreshRate = 2; let map = L.map('map',{ noWrap: true, + autoPan: false, zoomSnap: 0.1, maxBounds: [ [-90.0, -180.0], @@ -15,20 +16,21 @@ let map = L.map('map',{ }).setView([0, 0], 0); L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { - attribution: '© OpenStreetMap contributors' + attribution: '© OpenStreetMap contributors', + noWrap: true, + autoPan: false }).addTo(map); // use an icon to show the satellite position var satellite = L.icon({ iconUrl: 'static/satellite.webp', - iconSize: [116, 87], // size of the icon iconAnchor: [58, 43], // point of the icon which will correspond to marker's location popupAnchor: [0, -21] // point from which the popup should open relative to the iconAnchor }); // add the solar terminator -let sunlightOverlay = L.terminator(); +let sunlightOverlay = L.terminator({resolution: 5, longitudeRange:360}); sunlightOverlay.addTo(map); // update the solar terminator periodically @@ -41,7 +43,7 @@ setInterval(function(){updateTerminator(sunlightOverlay)}, refreshRate * 1000); // limit the zoom value to display the full Earth only once function setMinimumZoom(map) { - let minZoom = 1.0 / 10.0 * Math.ceil(10 * Math.log2(Math.max(map.getSize().x, map.getSize().y) / 256)) + let minZoom = 1.0 / 10.0 * Math.ceil(10 * Math.log2(Math.min(map.getSize().x, map.getSize().y) / 256)) map.setMinZoom(minZoom); } setMinimumZoom(map); @@ -86,11 +88,11 @@ function updateSatMarker(sat, norad_id, lat, long,) { if (markers.hasOwnProperty(sat)){ markers[sat].setLatLng([lat, long]); //markers[sat].bindPopup(sat + " Lat: " + lat + " Long: " + long +"
"+ next_pass); - markers[sat].bindPopup(sat); + markers[sat].bindPopup(sat, {autoPan: false}); } else{ //let marker = L.marker([lat, long], {icon: satellite}).addTo(map).bindPopup(sat + " Lat: " + lat + " Long: " + long +"
"+ next_pass); - let marker = L.marker([lat, long], {icon: satellite}).addTo(map).bindPopup(sat).openPopup(); + let marker = L.marker([lat, long], {icon: satellite, autoPan: false}).addTo(map).bindPopup(sat).openPopup(); markers[sat] = marker } diff --git a/src/static/terminator.js b/src/static/terminator.js new file mode 100644 index 00000000..e7a610f2 --- /dev/null +++ b/src/static/terminator.js @@ -0,0 +1,149 @@ +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('leaflet')) : + typeof define === 'function' && define.amd ? define(['leaflet'], factory) : + (global.L = global.L || {}, global.L.terminator = factory(global.L)); +}(this, (function (L) { 'use strict'; + + L = L && L.hasOwnProperty('default') ? L['default'] : L; + + /* Terminator.js -- Overlay day/night region on a Leaflet map */ + + function julian(date) { + /* Calculate the present UTC Julian Date. Function is valid after + * the beginning of the UNIX epoch 1970-01-01 and ignores leap + * seconds. */ + return (date / 86400000) + 2440587.5; + } + + function GMST(julianDay) { + /* Calculate Greenwich Mean Sidereal Time according to + http://aa.usno.navy.mil/faq/docs/GAST.php */ + var d = julianDay - 2451545.0; + // Low precision equation is good enough for our purposes. + return (18.697374558 + 24.06570982441908 * d) % 24; + } + + var Terminator = L.Polygon.extend({ + options: { + color: '#00', + opacity: 0.5, + fillColor: '#00', + fillOpacity: 0.5, + resolution: 2, + longitudeRange: 720 + }, + + initialize: function (options) { + this.version = '0.1.0'; + this._R2D = 180 / Math.PI; + this._D2R = Math.PI / 180; + L.Util.setOptions(this, options); + var latLng = this._compute(this.options.time); + this.setLatLngs(latLng); + }, + + setTime: function (date) { + this.options.time = date; + var latLng = this._compute(date); + this.setLatLngs(latLng); + }, + + _sunEclipticPosition: function (julianDay) { + /* Compute the position of the Sun in ecliptic coordinates at + julianDay. Following + http://en.wikipedia.org/wiki/Position_of_the_Sun */ + // Days since start of J2000.0 + var n = julianDay - 2451545.0; + // mean longitude of the Sun + var L$$1 = 280.460 + 0.9856474 * n; + L$$1 %= 360; + // mean anomaly of the Sun + var g = 357.528 + 0.9856003 * n; + g %= 360; + // ecliptic longitude of Sun + var lambda = L$$1 + 1.915 * Math.sin(g * this._D2R) + + 0.02 * Math.sin(2 * g * this._D2R); + // distance from Sun in AU + var R = 1.00014 - 0.01671 * Math.cos(g * this._D2R) - + 0.0014 * Math.cos(2 * g * this._D2R); + return {lambda: lambda, R: R}; + }, + + _eclipticObliquity: function (julianDay) { + // Following the short term expression in + // http://en.wikipedia.org/wiki/Axial_tilt#Obliquity_of_the_ecliptic_.28Earth.27s_axial_tilt.29 + var n = julianDay - 2451545.0; + // Julian centuries since J2000.0 + var T = n / 36525; + var epsilon = 23.43929111 - + T * (46.836769 / 3600 + - T * (0.0001831 / 3600 + + T * (0.00200340 / 3600 + - T * (0.576e-6 / 3600 + - T * 4.34e-8 / 3600)))); + return epsilon; + }, + + _sunEquatorialPosition: function (sunEclLng, eclObliq) { + /* Compute the Sun's equatorial position from its ecliptic + * position. Inputs are expected in degrees. Outputs are in + * degrees as well. */ + var alpha = Math.atan(Math.cos(eclObliq * this._D2R) + * Math.tan(sunEclLng * this._D2R)) * this._R2D; + var delta = Math.asin(Math.sin(eclObliq * this._D2R) + * Math.sin(sunEclLng * this._D2R)) * this._R2D; + + var lQuadrant = Math.floor(sunEclLng / 90) * 90; + var raQuadrant = Math.floor(alpha / 90) * 90; + alpha = alpha + (lQuadrant - raQuadrant); + + return {alpha: alpha, delta: delta}; + }, + + _hourAngle: function (lng, sunPos, gst) { + /* Compute the hour angle of the sun for a longitude on + * Earth. Return the hour angle in degrees. */ + var lst = gst + lng / 15; + return lst * 15 - sunPos.alpha; + }, + + _latitude: function (ha, sunPos) { + /* For a given hour angle and sun position, compute the + * latitude of the terminator in degrees. */ + var lat = Math.atan(-Math.cos(ha * this._D2R) / + Math.tan(sunPos.delta * this._D2R)) * this._R2D; + return lat; + }, + + _compute: function (time) { + var today = time ? new Date(time) : new Date(); + var julianDay = julian(today); + var gst = GMST(julianDay); + var latLng = []; + + var sunEclPos = this._sunEclipticPosition(julianDay); + var eclObliq = this._eclipticObliquity(julianDay); + var sunEqPos = this._sunEquatorialPosition(sunEclPos.lambda, eclObliq); + for (var i = 0; i <= this.options.longitudeRange * this.options.resolution; i++) { + var lng = -this.options.longitudeRange/2 + i / this.options.resolution; + var ha = this._hourAngle(lng, sunEqPos, gst); + latLng[i + 1] = [this._latitude(ha, sunEqPos), lng]; + } + if (sunEqPos.delta < 0) { + latLng[0] = [90, -this.options.longitudeRange/2]; + latLng[latLng.length] = [90, this.options.longitudeRange/2]; + } else { + latLng[0] = [-90, -this.options.longitudeRange/2]; + latLng[latLng.length] = [-90, this.options.longitudeRange/2]; + } + return latLng; + } + }); + + function terminator(options) { + return new Terminator(options); + } + + return terminator; + +}))); From 074403f39d245ed889a7fa5d5835fd1b6a538ddb Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Wed, 3 Apr 2024 17:13:00 +0200 Subject: [PATCH 38/62] Only add a satellite to the list if the frame was processd succesfully --- src/transmission/processing/save_raw_data.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index 09887ac5..b12e129f 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -142,7 +142,7 @@ def process_uplink_and_downlink(invalid_frames: bool = False, callback = None) - # list the satellites whose frames have been processed: # ths allows to later start their processing task - satellites_list = list() + satellites_list = [] # once the last frame has been processed, maintain the task active for # at least 10 seconds while looking for more frames to process @@ -166,10 +166,12 @@ def process_uplink_and_downlink(invalid_frames: bool = False, callback = None) - #satellites_list = list(set(downlink_sat_list + uplink_sat_list)) #logger.info("Satellites: " + ' '.join(satellites_list)) - if callback is not None: + # if the satellites list is not empty and the scheduler callback is not None + if satellites_list and callback is not None: + # report the satellites that have been sending frames callback(satellites_list) # empty the list - satellites_list = list() + satellites_list = [] # one more iteration iterations += 1 @@ -195,11 +197,12 @@ def process_frames(parsers: SatParsers, frames: QuerySet, link: str, satellites_ if stored: frame_obj.invalid = False processed_frames += 1 + # satellite found, add it to the processing list + if satellite not in satellites_list: + satellites_list.append(satellite) else: frame_obj.invalid = True frame_obj.save() - if satellite not in satellites_list: - satellites_list.append(satellite) return processed_frames From 173932929105c1c40a044012be4991bcf5273610 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 6 Apr 2024 15:57:50 +0200 Subject: [PATCH 39/62] Restructuring telemetry stored in influxdb --- grafana/dashboards/delfi_c3.json | 420 +++++++++++++----- grafana/dashboards/delfi_pq.json | 20 +- src/transmission/models.py | 8 +- src/transmission/processing/influxdb_api.py | 40 +- src/transmission/processing/influxdb_api2.py | 121 +++++ .../processing/process_raw_bucket.py | 30 +- src/transmission/processing/save_raw_data.py | 40 +- 7 files changed, 485 insertions(+), 194 deletions(-) mode change 100755 => 100644 grafana/dashboards/delfi_c3.json create mode 100644 src/transmission/processing/influxdb_api2.py diff --git a/grafana/dashboards/delfi_c3.json b/grafana/dashboards/delfi_c3.json old mode 100755 new mode 100644 index cf875a22..71b87875 --- a/grafana/dashboards/delfi_c3.json +++ b/grafana/dashboards/delfi_c3.json @@ -1,133 +1,317 @@ { - "annotations": { - "list": [ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ { - "builtIn": 1, "datasource": { - "type": "grafana", - "uid": "-- Grafana --" + "type": "influxdb", + "uid": "3ap6QYRVz" }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "type": "dashboard" + "query": "from(bucket: \"delfi_c3_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"Housekeeping\")\n |> filter(fn: (r) => r[\"_field\"] == \"RAP1_Rx_I\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" } - ] + ], + "title": "RAP Rx Current", + "type": "timeseries" }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 3, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_c3_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"Housekeeping\")\n |> filter(fn: (r) => r[\"_field\"] == \"OBC_T\"\n) |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "OBC Temperature", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 0 + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 16 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "id": 1, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"delfi_c3_downlink\")\n |> range(start: -20y)\n |> filter(fn: (r) => r[\"_measurement\"] == \"DelfiC3Housekeeping\")\n |> filter(fn: (r) => r[\"_field\"] == \"BootCounter\")", - "refId": "A" - } - ], - "title": "Boot Counter", - "type": "timeseries" - } - ], - "refresh": "", - "schemaVersion": 39, - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "2008-04-28T00:00:00.000Z", - "to": "2023-11-14T23:59:59.999Z" - }, - "timepicker": {}, - "timezone": "", - "title": "Delfi-C3", - "uid": "ec0b906e-c704-41d9-a063-645b803db188", - "version": 1, - "weekStart": "" - } + "query": "from(bucket: \"delfi_c3_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"Housekeeping\")\n |> filter(fn: (r) => r[\"_field\"] == \"BootCounter\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Boot Counter", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "2008-04-28T00:00:00.000Z", + "to": "2023-11-14T23:59:59.999Z" + }, + "timepicker": {}, + "timezone": "", + "title": "Delfi-C3", + "uid": "ec0b906e-c704-41d9-a063-645b803db188", + "version": 10, + "weekStart": "" +} diff --git a/grafana/dashboards/delfi_pq.json b/grafana/dashboards/delfi_pq.json index 0fa59e9f..8d91c8c7 100644 --- a/grafana/dashboards/delfi_pq.json +++ b/grafana/dashboards/delfi_pq.json @@ -131,7 +131,7 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"DelfiPqRadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpCurrent\" or r[\"_field\"] == \"PanelYmCurrent\" or r[\"_field\"] == \"PanelXpCurrent\" or r[\"_field\"] == \"PanelXmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpCurrent\" or r[\"_field\"] == \"PanelYmCurrent\" or r[\"_field\"] == \"PanelXpCurrent\" or r[\"_field\"] == \"PanelXmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], @@ -217,7 +217,7 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"DelfiPqRadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpCurrent\" or r[\"_field\"] == \"PanelYmCurrent\" or r[\"_field\"] == \"PanelXpCurrent\" or r[\"_field\"] == \"PanelXmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpCurrent\" or r[\"_field\"] == \"PanelYmCurrent\" or r[\"_field\"] == \"PanelXpCurrent\" or r[\"_field\"] == \"PanelXmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], @@ -302,7 +302,7 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"DelfiPqRadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpVoltage\" or r[\"_field\"] == \"PanelYmVoltage\" or r[\"_field\"] == \"PanelXpVoltage\" or r[\"_field\"] == \"PanelXmVoltage\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpVoltage\" or r[\"_field\"] == \"PanelYmVoltage\" or r[\"_field\"] == \"PanelXpVoltage\" or r[\"_field\"] == \"PanelXmVoltage\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], @@ -387,7 +387,7 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"DelfiPqRadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpVoltage\" or r[\"_field\"] == \"PanelYmVoltage\" or r[\"_field\"] == \"PanelXpVoltage\" or r[\"_field\"] == \"PanelXmVoltage\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> group(columns:[\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpVoltage\" or r[\"_field\"] == \"PanelYmVoltage\" or r[\"_field\"] == \"PanelXpVoltage\" or r[\"_field\"] == \"PanelXmVoltage\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> group(columns:[\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], @@ -497,7 +497,7 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"DelfiPqRadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpTemperature\" or r[\"_field\"] == \"PanelXmTemperature\" or r[\"_field\"] == \"PanelXpTemperature\" or r[\"_field\"] == \"PanelYmTemperature\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpTemperature\" or r[\"_field\"] == \"PanelXmTemperature\" or r[\"_field\"] == \"PanelXpTemperature\" or r[\"_field\"] == \"PanelYmTemperature\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], @@ -607,7 +607,7 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"DelfiPqRadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpTemperature\" or r[\"_field\"] == \"PanelXmTemperature\" or r[\"_field\"] == \"PanelXpTemperature\" or r[\"_field\"] == \"PanelYmTemperature\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpTemperature\" or r[\"_field\"] == \"PanelXmTemperature\" or r[\"_field\"] == \"PanelXpTemperature\" or r[\"_field\"] == \"PanelYmTemperature\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], @@ -692,7 +692,7 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"DelfiPqRadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpTemperature\" or r[\"_field\"] == \"PanelYpVoltage\" or r[\"_field\"] == \"PanelYpCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpTemperature\" or r[\"_field\"] == \"PanelYpVoltage\" or r[\"_field\"] == \"PanelYpCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], @@ -777,7 +777,7 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"DelfiPqRadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpTemperature\" or r[\"_field\"] == \"PanelYpVoltage\" or r[\"_field\"] == \"PanelYpCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpTemperature\" or r[\"_field\"] == \"PanelYpVoltage\" or r[\"_field\"] == \"PanelYpCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], @@ -862,7 +862,7 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"DelfiPqRadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Valid\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Valid\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], @@ -947,7 +947,7 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"DelfiPqRadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Valid\")\n |> group()\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Valid\")\n |> group()\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], diff --git a/src/transmission/models.py b/src/transmission/models.py index c18bee61..228f2301 100644 --- a/src/transmission/models.py +++ b/src/transmission/models.py @@ -36,10 +36,10 @@ class Downlink(models.Model): def to_dictionary(self) -> dict: """Convert Downlink object to dict""" frame_dict = {} - frame_dict["timestamp"] = self.timestamp.strftime(TIME_FORMAT) - frame_dict["observer"] = self.observer + frame_dict["user"] = self.observer frame_dict["application"] = self.application frame_dict["processed"] = self.processed + frame_dict["invalid"] = self.invalid frame_dict["frequency"] = self.frequency frame_dict["frame"] = self.frame frame_dict["metadata"] = self.metadata @@ -61,10 +61,10 @@ class Uplink(models.Model): def to_dictionary(self) -> dict: """Convert Uplink object to dict""" frame_dict = {} - frame_dict["timestamp"] = self.timestamp.strftime(TIME_FORMAT) - frame_dict["operator"] = self.operator + frame_dict["user"] = self.operator frame_dict["application"] = self.application frame_dict["processed"] = self.processed + frame_dict["invalid"] = self.invalid frame_dict["frequency"] = self.frequency frame_dict["frame"] = self.frame frame_dict["metadata"] = self.metadata diff --git a/src/transmission/processing/influxdb_api.py b/src/transmission/processing/influxdb_api.py index 063dc682..3b3e0604 100644 --- a/src/transmission/processing/influxdb_api.py +++ b/src/transmission/processing/influxdb_api.py @@ -3,6 +3,7 @@ import os from influxdb_client import InfluxDBClient from influxdb_client.client.write_api import SYNCHRONOUS +from django_logger import logger from transmission.processing.satellites import TIME_FORMAT @@ -48,58 +49,51 @@ def write_frame_to_raw_bucket(write_api, satellite, link, timestamp, frame_field bucket = satellite + "_raw_data" db_fields = { - "measurement": satellite + "_" + link + "_raw_data", + "measurement": "raw", "time": timestamp, "tags": tags, "fields": frame_fields } - #logger.info("%s: raw frame stored or updated. Frame timestamp: %s, link: %s, bucket: %s", - # satellite, timestamp, link, bucket) - write_api.write(bucket, INFLUX_ORG, db_fields) -def commit_frame(write_api, query_api, satellite: str, link: str, tlm: dict) -> bool: +def commit_frame(write_api, query_api, satellite: str, link: str, timestamp: datetime, tlm: dict) -> bool: """Write frame to corresponding satellite table (if not already stored). Returns True if the frame was stored and False otherwise (if the frame is already stored). Also store the frame with processed = False.""" bucket = satellite + "_raw_data" - tlm_time = datetime.strptime(tlm['timestamp'], TIME_FORMAT) + #tlm_time = datetime.strptime(tlm['timestamp'], TIME_FORMAT) + #logger.info("Timestamp type " + str(type(tlm_time))) - time_range_lower_bound = (tlm_time - timedelta(seconds=1)).strftime(TIME_FORMAT) - time_range_upper_bound = (tlm_time + timedelta(seconds=1)).strftime(TIME_FORMAT) + time_range_lower_bound = (timestamp - timedelta(seconds=1)).strftime(TIME_FORMAT) + time_range_upper_bound = (timestamp + timedelta(seconds=1)).strftime(TIME_FORMAT) # check if frame already exists query = f'''from(bucket: "{bucket}") |> range(start: {time_range_lower_bound}, stop: {time_range_upper_bound}) - |> filter(fn: (r) => r._measurement == "{satellite + "_" + link + "_raw_data"}") + |> filter(fn: (r) => r._measurement == "raw") |> filter(fn: (r) => r["_field"] == "frame" and r["_value"] == "{tlm["frame"]}") ''' # store frame only if not stored already if len(query_api.query(query=query)) != 0: + logger.info("Found!") return False tlm["processed"] = False - write_frame_to_raw_bucket(write_api, satellite, link, tlm["timestamp"], tlm) + tlm["invalid"] = False + write_frame_to_raw_bucket(write_api, satellite, link, timestamp, tlm) + return True -def save_raw_frame_to_influxdb(satellite: str, link: str, telemetry) -> bool: +def save_raw_frame_to_influxdb(satellite: str, link: str, timestamp: datetime, telemetry) -> bool: """Connect to influxdb and save raw telemetry. Return True if telemetry was stored, False otherwise.""" write_api, query_api = get_influx_db_read_and_query_api() - stored = False - - if isinstance(telemetry, list): - for tlm in telemetry: - stored = stored or commit_frame(write_api, query_api, satellite, link, tlm) - elif isinstance(telemetry, dict): - stored = stored or commit_frame(write_api, query_api, satellite, link, telemetry) - - return stored + return commit_frame(write_api, query_api, satellite, link, timestamp, telemetry) def get_last_received_frame(satellite: str): """Retrieve the last received frame for the specified satellite from the raw @@ -112,8 +106,8 @@ def get_last_received_frame(satellite: str): query = f'''from(bucket: "{bucket}") |> range(start: 0) - |> filter(fn: (r) => r["_measurement"] == "{satellite + "_downlink_raw_data"}") - |> filter(fn: (r) => r["_field"] == "timestamp") + |> filter(fn: (r) => r["_measurement"] == "raw") + |> keep(columns: ["_time"]) |> tail(n: 1) ''' @@ -121,7 +115,7 @@ def get_last_received_frame(satellite: str): if len(ret) > 0: # data received found in bucket - return datetime.strptime(ret[0].records[0]["_value"], '%Y-%m-%dT%H:%M:%SZ') + return ret[0].records[0]["_time"] # no result return None diff --git a/src/transmission/processing/influxdb_api2.py b/src/transmission/processing/influxdb_api2.py new file mode 100644 index 00000000..3b3e0604 --- /dev/null +++ b/src/transmission/processing/influxdb_api2.py @@ -0,0 +1,121 @@ +"""Methods for saving raw data frames and retrieving the influxdb API.""" +from datetime import datetime, timedelta +import os +from influxdb_client import InfluxDBClient +from influxdb_client.client.write_api import SYNCHRONOUS +from django_logger import logger + +from transmission.processing.satellites import TIME_FORMAT + +INFLUXDB_URL = "http://influxdb:8086" +INFLUX_ORG = os.environ.get('INFLUXDB_V2_ORG', 'DelfiSpace') + + +def get_influxdb_client(): + """Connect to influxdb and return the influxdb client.""" + + client = InfluxDBClient(url=INFLUXDB_URL, token=os.environ.get('INFLUXDB_V2_TOKEN', 'adminpwd'), org=INFLUX_ORG) + + return client + + +def get_influxdb_bucket_api(): + """Connect to influxdb and return bucket_api.""" + + client = get_influxdb_client() + + buckets_api = client.buckets_api() + + return buckets_api + + +def get_influx_db_read_and_query_api() -> tuple: + """Connect to influxdb and return write_api and query_api.""" + + client = get_influxdb_client() + + write_api = client.write_api(write_options=SYNCHRONOUS) + query_api = client.query_api() + + return (write_api, query_api) + + +def write_frame_to_raw_bucket(write_api, satellite, link, timestamp, frame_fields) -> None: + """Save frame given its fields. Note: to update/overwrite a field write the frame again + with the changed fields and the same timestamp as before.""" + + tags = {} + + bucket = satellite + "_raw_data" + + db_fields = { + "measurement": "raw", + "time": timestamp, + "tags": tags, + "fields": frame_fields + } + + write_api.write(bucket, INFLUX_ORG, db_fields) + + +def commit_frame(write_api, query_api, satellite: str, link: str, timestamp: datetime, tlm: dict) -> bool: + """Write frame to corresponding satellite table (if not already stored). + Returns True if the frame was stored and False otherwise (if the frame is already stored). + Also store the frame with processed = False.""" + + bucket = satellite + "_raw_data" + #tlm_time = datetime.strptime(tlm['timestamp'], TIME_FORMAT) + #logger.info("Timestamp type " + str(type(tlm_time))) + + time_range_lower_bound = (timestamp - timedelta(seconds=1)).strftime(TIME_FORMAT) + time_range_upper_bound = (timestamp + timedelta(seconds=1)).strftime(TIME_FORMAT) + + # check if frame already exists + query = f'''from(bucket: "{bucket}") + |> range(start: {time_range_lower_bound}, stop: {time_range_upper_bound}) + |> filter(fn: (r) => r._measurement == "raw") + |> filter(fn: (r) => r["_field"] == "frame" and r["_value"] == "{tlm["frame"]}") + ''' + # store frame only if not stored already + if len(query_api.query(query=query)) != 0: + logger.info("Found!") + return False + + tlm["processed"] = False + tlm["invalid"] = False + write_frame_to_raw_bucket(write_api, satellite, link, timestamp, tlm) + + return True + +def save_raw_frame_to_influxdb(satellite: str, link: str, timestamp: datetime, telemetry) -> bool: + """Connect to influxdb and save raw telemetry. + Return True if telemetry was stored, False otherwise.""" + + write_api, query_api = get_influx_db_read_and_query_api() + + return commit_frame(write_api, query_api, satellite, link, timestamp, telemetry) + +def get_last_received_frame(satellite: str): + """Retrieve the last received frame for the specified satellite from the raw + data bucket.""" + + client = get_influxdb_client() + query_api = client.query_api() + + bucket = satellite + "_raw_data" + + query = f'''from(bucket: "{bucket}") + |> range(start: 0) + |> filter(fn: (r) => r["_measurement"] == "raw") + |> keep(columns: ["_time"]) + |> tail(n: 1) + ''' + + ret = query_api.query(query=query) + + if len(ret) > 0: + # data received found in bucket + return ret[0].records[0]["_time"] + + # no result + return None diff --git a/src/transmission/processing/process_raw_bucket.py b/src/transmission/processing/process_raw_bucket.py index e8d373f4..e8196a89 100644 --- a/src/transmission/processing/process_raw_bucket.py +++ b/src/transmission/processing/process_raw_bucket.py @@ -32,17 +32,11 @@ def parse_and_store_frame(parsers: SatParsers, satellite: str, timestamp: str, f bucket = satellite + "_" + link if "frame" in telemetry: - sat_name_pascal_case = string.capwords(satellite.replace("_", " ")).replace(" ", "") - tags = {} - db_fields = { - - "measurement": sat_name_pascal_case + telemetry["frame"], + "measurement": telemetry["frame"], "time": timestamp, - "tags": tags, - "fields": { - "observer": observer, - } + "tags": {}, + "fields": {} } for field, value_and_status in telemetry.items(): @@ -89,19 +83,15 @@ def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, sta how many frames were successfully processed. Skip_processed=True will skip over the already processed frames.""" - radio_amateur = 'observer' - if link == 'uplink': - radio_amateur = 'operator' - # TODO: we need to still check the frames where processing failed get_unprocessed_frames_query = f''' from(bucket: "{satellite + "_raw_data"}") |> range(start: {start_time}, stop: {end_time}) - |> filter(fn: (r) => r._measurement == "{satellite + "_" + link + "_raw_data"}") + |> filter(fn: (r) => r._measurement == "raw") |> filter(fn: (r) => r["_field"] == "processed" or r["_field"] == "frame" or - r["_field"] == "{radio_amateur}") + r["_field"] == "user") |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") ''' @@ -111,7 +101,9 @@ def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, sta # limit the maximum numbr of frames processed per round get_unprocessed_frames_query = get_unprocessed_frames_query + \ - "|> limit(n:100, offset: 0)" + """ + |> sort(columns: ["_time"], desc: false) + |> limit(n:100, offset: 0)""" # query result as dataframe dataframe = query_api.query_data_frame(query=get_unprocessed_frames_query) @@ -123,7 +115,7 @@ def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, sta for _, row in dataframe.iterrows(): try: # store processed frame - parse_and_store_frame(parsers, satellite, row["_time"], row["frame"], row[radio_amateur], link) + parse_and_store_frame(parsers, satellite, row["_time"], row["frame"], row["user"], link) # mark raw frame as processed mark_processed_flag(satellite, link, row["_time"], True) # mark raw frame as valid @@ -132,6 +124,7 @@ def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, sta except XTCEException as ex: logger.error("%s: frame processing error: %s (%s)", satellite, ex, row["frame"]) + logger.error(traceback.format_exc()) # mark raw frame as processed mark_processed_flag(satellite, link, row["_time"], True) # mark frame as invalid @@ -141,8 +134,7 @@ def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, sta except Exception as ex: # pylint: disable=broad-except logger.error("%s: frame storage error: %s (%s)", satellite, ex, row["frame"]) logger.error(traceback.format_exc()) - logger.info("Problematic frame: " + str(row["_time"]) + " " + str(row["frame"]) + - " " + str(row[radio_amateur]) + " " + str(link)) + logger.info("Problematic frame: " + str(row)) logger.info(row) # mark raw frame as processed mark_processed_flag(satellite, link, row["_time"], True) diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index b12e129f..f867f2c3 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -4,7 +4,7 @@ import json from typing import Union import time -from datetime import timezone +from datetime import datetime, timezone from django_logger import logger from django.forms import ValidationError @@ -120,7 +120,7 @@ def parse_submitted_frame(frame: dict, frame_entry: models.Model) -> models.Mode # add metadata metadata = copy.deepcopy(frame) # remove previously parsed fields - for field in ["frame", "timestamp", "frequency"]: + for field in ["frame", "timestamp", "frequency", "link", "username"]: if field in metadata: del metadata[field] @@ -129,7 +129,7 @@ def parse_submitted_frame(frame: dict, frame_entry: models.Model) -> models.Mode return frame_entry -def process_uplink_and_downlink(invalid_frames: bool = False, callback = None) -> tuple: +def process_uplink_and_downlink(invalid_frames: bool = False, callback = None): """Process all processed uplink and downlink frames, i.e. move them to the influxdb raw satellite data bucket. if invalid_frames is false, only new frames are processed. If @@ -147,25 +147,23 @@ def process_uplink_and_downlink(invalid_frames: bool = False, callback = None) - # once the last frame has been processed, maintain the task active for # at least 10 seconds while looking for more frames to process while iterations < 50: - time.sleep(0.2) - total_processed_frames = 0 + logger.info("Iteration " + str(iterations)) if not invalid_frames: # set a maximum length to the results to ensure responsive data processing - downlink_frames = Downlink.objects.all().filter(processed=False)[:100] - uplink_frames = Uplink.objects.all().filter(processed=False)[:100] + downlink_frames = Downlink.objects.all().filter(processed=False).order_by("timestamp")[:100] + uplink_frames = Uplink.objects.all().filter(processed=False).order_by("timestamp")[:100] else: # set a maximum length to the results to ensure responsive data processing - downlink_frames = Downlink.objects.all().filter(processed=True).filter(invalid=True)[:100] - uplink_frames = Uplink.objects.all().filter(processed=True).filter(invalid=True)[:100] + downlink_frames = Downlink.objects.all().filter(processed=True).filter(invalid=True).order_by("timestamp")[:100] + uplink_frames = Uplink.objects.all().filter(processed=True).filter(invalid=True).order_by("timestamp")[:100] + logger.info("Frames listed: " + str(len(downlink_frames))) downlink_frames_count = process_frames(parsers, downlink_frames, "downlink", satellites_list) uplink_frames_count = process_frames(parsers, uplink_frames, "uplink", satellites_list) total_processed_frames = downlink_frames_count + uplink_frames_count - - #satellites_list = list(set(downlink_sat_list + uplink_sat_list)) - #logger.info("Satellites: " + ' '.join(satellites_list)) + logger.info("Frames " + str(total_processed_frames)) # if the satellites list is not empty and the scheduler callback is not None if satellites_list and callback is not None: # report the satellites that have been sending frames @@ -180,8 +178,8 @@ def process_uplink_and_downlink(invalid_frames: bool = False, callback = None) - # frames were processed in this iteration, reset the iteration counter iterations = 0 - #return downlink_frames_count, uplink_frames_count - return 0, 0 + # maintain the thread alive and re-check if new frames have been received + time.sleep(0.2) def process_frames(parsers: SatParsers, frames: QuerySet, link: str, satellites_list: list) -> int: @@ -190,24 +188,29 @@ def process_frames(parsers: SatParsers, frames: QuerySet, link: str, satellites_ Returns the count of successfully processed_frames.""" processed_frames = 0 + for frame_obj in frames: frame_dict = frame_obj.to_dictionary() - stored, satellite = store_frame_to_influxdb(parsers, frame_dict, link) + stored, satellite = store_frame_to_influxdb(parsers, frame_obj.timestamp, frame_dict, link) frame_obj.processed = True + if stored: + # valid frame frame_obj.invalid = False processed_frames += 1 + # satellite found, add it to the processing list if satellite not in satellites_list: satellites_list.append(satellite) else: frame_obj.invalid = True + frame_obj.save() return processed_frames -def store_frame_to_influxdb(parsers: SatParsers, frame: dict, link: str) -> tuple: +def store_frame_to_influxdb(parsers: SatParsers, timestamp: datetime, frame: dict, link: str) -> tuple: """Try to store frame to influxdb. Returns True if the frame was successfully stored, False otherwise.""" @@ -216,10 +219,7 @@ def store_frame_to_influxdb(parsers: SatParsers, frame: dict, link: str) -> tupl if satellite is None: return False, satellite - fields_to_save = ["frame", "timestamp", "observer", "frequency", "application", "metadata"] - - frame = strip_tlm(frame, fields_to_save) - stored = save_raw_frame_to_influxdb(satellite, link, frame) + stored = save_raw_frame_to_influxdb(satellite, link, timestamp, frame) return stored, satellite From 703f4cb2d4a74a41e0dd005d9df5112319f88ae5 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 6 Apr 2024 15:58:37 +0200 Subject: [PATCH 40/62] Removing dashboard no more used --- grafana/dashboards/reception_times.json | 309 ------------------------ 1 file changed, 309 deletions(-) delete mode 100644 grafana/dashboards/reception_times.json diff --git a/grafana/dashboards/reception_times.json b/grafana/dashboards/reception_times.json deleted file mode 100644 index 9e56f7a7..00000000 --- a/grafana/dashboards/reception_times.json +++ /dev/null @@ -1,309 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 2, - "links": [], - "liveNow": false, - "panels": [ - { - "collapsed": false, - "gridPos": { - "h": 1, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 7, - "panels": [], - "title": "Receptions", - "type": "row" - }, - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 1 - }, - "id": 2, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "/^timestamp$/", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.1.2", - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"delfi_pq_raw_data\")\n |> range(start: 0, stop: now())\n |> filter(fn: (r) => r._measurement == \"delfi_pq_downlink_raw_data\")\n |> filter(fn: (r) => r[\"_field\"] == \"timestamp\") \n |> last()\n", - "refId": "A" - } - ], - "title": "Delfi-PQ Last Reception", - "type": "stat" - }, - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 1 - }, - "id": 5, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "/^timestamp$/", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.1.2", - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"delfi_c3_raw_data\")\n |> range(start: 0, stop: now())\n |> filter(fn: (r) => r._measurement == \"delfi_c3_downlink_raw_data\")\n |> filter(fn: (r) => r[\"_field\"] == \"timestamp\") \n |> last()\n", - "refId": "A" - } - ], - "title": "Delfi-C3 Last Reception", - "type": "stat" - }, - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 0, - "y": 9 - }, - "id": 3, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "/^timestamp$/", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.1.2", - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"delfi_next_raw_data\")\n |> range(start: 0, stop: now())\n |> filter(fn: (r) => r._measurement == \"delfi_next_downlink_raw_data\")\n |> filter(fn: (r) => r[\"_field\"] == \"timestamp\") \n |> last()\n", - "refId": "A" - } - ], - "title": "Delfi-Next Last Reception", - "type": "stat" - }, - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 9 - }, - "id": 4, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": [ - "lastNotNull" - ], - "fields": "/^timestamp$/", - "values": false - }, - "textMode": "auto" - }, - "pluginVersion": "9.1.2", - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"da_vinci_raw_data\")\n |> range(start: 0, stop: now())\n |> filter(fn: (r) => r._measurement == \"da_vinci_downlink_raw_data\")\n |> filter(fn: (r) => r[\"_field\"] == \"timestamp\") \n |> last()\n", - "refId": "A" - } - ], - "title": "Da-Vinci-Satellite Last Reception", - "type": "stat" - } - ], - "schemaVersion": 37, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "now-6h", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Latest Reception Times", - "uid": "sknvMScVz", - "version": 1, - "weekStart": "" -} \ No newline at end of file From ea58d36c9b102458550a613aceb6157567461bd2 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sun, 14 Apr 2024 01:05:02 +0200 Subject: [PATCH 41/62] Changing influxdb_api to class to simplify code --- src/delfitlm/settings.py | 7 + src/home/views.py | 5 +- src/transmission/models.py | 7 + .../processing/.influxdb_api.py.swp | Bin 0 -> 16384 bytes src/transmission/processing/influxdb_api.py | 230 ++++++++++++------ src/transmission/processing/influxdb_api2.py | 121 --------- .../processing/process_raw_bucket.py | 123 ++-------- src/transmission/processing/save_raw_data.py | 21 +- .../processing/telemetry_scraper.py | 4 +- src/transmission/urls.py | 8 +- src/transmission/views.py | 16 +- 11 files changed, 217 insertions(+), 325 deletions(-) create mode 100644 src/transmission/processing/.influxdb_api.py.swp delete mode 100644 src/transmission/processing/influxdb_api2.py diff --git a/src/delfitlm/settings.py b/src/delfitlm/settings.py index 9b127a00..bf1dfcf0 100644 --- a/src/delfitlm/settings.py +++ b/src/delfitlm/settings.py @@ -193,6 +193,13 @@ if 'test' in sys.argv or 'test_coverage' in sys.argv: # Covers regular testing and django-coverage DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite3' +INFLUXDB = { + 'HOST' : "http://influxdb", + 'PORT' : 8086, + 'TOKEN' : os.environ.get('INFLUXDB_V2_TOKEN'), + 'ORGANIZATION' : os.environ.get('INFLUXDB_V2_ORG') +} + # Password validation # https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators diff --git a/src/home/views.py b/src/home/views.py index ae5ba542..7b781748 100644 --- a/src/home/views.py +++ b/src/home/views.py @@ -11,7 +11,7 @@ from skyfield.api import load, EarthSatellite, wgs84, Topos from satellite_tle import fetch_tle_from_celestrak from transmission.processing.satellites import SATELLITES, TIME_FORMAT -from transmission.processing.influxdb_api import get_last_received_frame +from transmission.processing.influxdb_api import influxdb_api from django_logger import logger #pylint: disable=W0718 @@ -118,10 +118,11 @@ def get_satellite_location_now_api(request, norad_id): def _get_satellites_status(): """Method to find satellite status.""" + db_connection = influxdb_api() sats_status = {} for sat, info in SATELLITES.items(): sats_status[str(sat + "_status")] = info["status"] - last_rx_time = get_last_received_frame(sat) + last_rx_time = db_connection.get_last_received_frame(sat) if last_rx_time is not None and isinstance(last_rx_time, datetime): sats_status[str(sat + "_last_data")] = last_rx_time else: diff --git a/src/transmission/models.py b/src/transmission/models.py index 228f2301..425fe593 100644 --- a/src/transmission/models.py +++ b/src/transmission/models.py @@ -70,3 +70,10 @@ def to_dictionary(self) -> dict: frame_dict["metadata"] = self.metadata return frame_dict + +class DateTimeMicrosecondsField(models.DateTimeField): + def db_type(self, connection): + return "timestamp(6) with time zone" + + #def rel_db_type(self, connection): + # return "integer UNSIGNED" diff --git a/src/transmission/processing/.influxdb_api.py.swp b/src/transmission/processing/.influxdb_api.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..e1148816711fd704ad00855d5cb6b02fd4a6acf4 GIT binary patch literal 16384 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 g{WD3Fb tuple: - """Connect to influxdb and return write_api and query_api.""" + query = f'''from(bucket: "{bucket}") + |> range(start: 0) + |> filter(fn: (r) => r["_measurement"] == "raw") + |> keep(columns: ["_time"]) + |> tail(n: 1) + ''' - client = get_influxdb_client() + ret = self._get_query_api().query(query=query) - write_api = client.write_api(write_options=SYNCHRONOUS) - query_api = client.query_api() + if len(ret) > 0: + # data received found in bucket + return ret[0].records[0]["_time"] - return (write_api, query_api) + # no result found + return None -def write_frame_to_raw_bucket(write_api, satellite, link, timestamp, frame_fields) -> None: - """Save frame given its fields. Note: to update/overwrite a field write the frame again - with the changed fields and the same timestamp as before.""" + def get_raw_frames_to_process(self, satellite: str, link: str, frames: int = 100): + """Retrieve the first raw frames to process""" - tags = {} + bucket = satellite + "_raw_data" - bucket = satellite + "_raw_data" + get_frames_to_process = f''' + from(bucket: "{bucket}") + |> range(start: 0, stop: now()) + |> filter(fn: (r) => r._measurement == "raw") + |> filter(fn: (r) => r["_field"] == "processed" or + r["_field"] == "frame" or + r["_field"] == "user") + |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") + |> filter(fn: (r) => r[\"processed\"] == false) + |> sort(columns: ["_time"], desc: false) + |> limit(n:{frames}, offset: 0)''' - db_fields = { - "measurement": "raw", - "time": timestamp, - "tags": tags, - "fields": frame_fields - } + # query result as dataframe + dataframe = self._get_query_api().query_data_frame(query=get_frames_to_process) + return dataframe - write_api.write(bucket, INFLUX_ORG, db_fields) + def save_raw_frame(self, satellite: str, link: str, timestamp: datetime, tlm: dict) -> bool: + """Write frame to corresponding satellite table (if not already stored). + Returns True if the frame was stored and False otherwise (if the frame is already stored). + Also store the frame with processed = False.""" -def commit_frame(write_api, query_api, satellite: str, link: str, timestamp: datetime, tlm: dict) -> bool: - """Write frame to corresponding satellite table (if not already stored). - Returns True if the frame was stored and False otherwise (if the frame is already stored). - Also store the frame with processed = False.""" + bucket = satellite + "_raw_data" + #tlm_time = datetime.strptime(tlm['timestamp'], TIME_FORMAT) + #logger.info("Timestamp type " + str(type(tlm_time))) - bucket = satellite + "_raw_data" - #tlm_time = datetime.strptime(tlm['timestamp'], TIME_FORMAT) - #logger.info("Timestamp type " + str(type(tlm_time))) + time_range_lower_bound = (timestamp - timedelta(seconds=1)).strftime(TIME_FORMAT) + time_range_upper_bound = (timestamp + timedelta(seconds=1)).strftime(TIME_FORMAT) - time_range_lower_bound = (timestamp - timedelta(seconds=1)).strftime(TIME_FORMAT) - time_range_upper_bound = (timestamp + timedelta(seconds=1)).strftime(TIME_FORMAT) + # check if frame already exists + query = f'''from(bucket: "{bucket}") + |> range(start: {time_range_lower_bound}, stop: {time_range_upper_bound}) + |> filter(fn: (r) => r._measurement == "raw") + |> filter(fn: (r) => r["_field"] == "frame" and r["_value"] == "{tlm["frame"]}") + ''' + # store frame only if not stored already + if len(self._get_query_api().query(query=query)) != 0: + logger.info("Found!") + return False - # check if frame already exists - query = f'''from(bucket: "{bucket}") - |> range(start: {time_range_lower_bound}, stop: {time_range_upper_bound}) - |> filter(fn: (r) => r._measurement == "raw") - |> filter(fn: (r) => r["_field"] == "frame" and r["_value"] == "{tlm["frame"]}") - ''' - # store frame only if not stored already - if len(query_api.query(query=query)) != 0: - logger.info("Found!") - return False + tlm["processed"] = False + tlm["invalid"] = False + + tags = {} + + bucket = satellite + "_raw_data" + + db_fields = { + "measurement": "raw", + "time": timestamp, + "tags": {}, + "fields": tlm + } + + self._get_write_api().write(bucket, self.organization, db_fields) + + return True - tlm["processed"] = False - tlm["invalid"] = False - write_frame_to_raw_bucket(write_api, satellite, link, timestamp, tlm) - return True + def save_processed_frame(self, bucket: str, measurement: str, timestamp, tags, fields): + """Write frame to corresponding satellite table (if not already stored). + Returns True if the frame was stored and False otherwise (if the frame is already stored). + Also store the frame with processed = False.""" -def save_raw_frame_to_influxdb(satellite: str, link: str, timestamp: datetime, telemetry) -> bool: - """Connect to influxdb and save raw telemetry. - Return True if telemetry was stored, False otherwise.""" + #bucket = satellite + "_" + link - write_api, query_api = get_influx_db_read_and_query_api() + #time_range_lower_bound = (timestamp - timedelta(seconds=1)).strftime(TIME_FORMAT) + #time_range_upper_bound = (timestamp + timedelta(seconds=1)).strftime(TIME_FORMAT) - return commit_frame(write_api, query_api, satellite, link, timestamp, telemetry) + # check if frame already exists + #query = f'''from(bucket: "{bucket}") + # |> range(start: {time_range_lower_bound}, stop: {time_range_upper_bound}) + # |> filter(fn: (r) => r._measurement == "raw") + # |> filter(fn: (r) => r["_field"] == "frame" and r["_value"] == "{tlm["frame"]}") + # ''' + # store frame only if not stored already + #if len(self._get_query_api().query(query=query)) != 0: + # logger.info("Found!") + # return False -def get_last_received_frame(satellite: str): - """Retrieve the last received frame for the specified satellite from the raw - data bucket.""" + #tlm["processed"] = False + #tlm["invalid"] = False - client = get_influxdb_client() - query_api = client.query_api() + tags = {} - bucket = satellite + "_raw_data" + db_fields = { + "measurement": measurement, + "time": timestamp, + "tags": tags, + "fields": fields + } - query = f'''from(bucket: "{bucket}") - |> range(start: 0) - |> filter(fn: (r) => r["_measurement"] == "raw") - |> keep(columns: ["_time"]) - |> tail(n: 1) - ''' + self._get_write_api().write(bucket, self.organization, db_fields) - ret = query_api.query(query=query) - if len(ret) > 0: - # data received found in bucket - return ret[0].records[0]["_time"] - - # no result - return None + def update_raw_frame(self, satellite: str, link: str, timestamp: datetime, tlm: dict) -> bool: + """Updates frame in corresponding satellite table (if not already stored). + Returns True if the frame was updated and False otherwise (if the frame was not found). + """ + + bucket = satellite + "_raw_data" + #tlm_time = datetime.strptime(tlm['timestamp'], TIME_FORMAT) + #logger.info("Timestamp type " + str(type(tlm_time))) + + time_range_lower_bound = (timestamp - timedelta(seconds=1)).strftime(TIME_FORMAT) + time_range_upper_bound = (timestamp + timedelta(seconds=1)).strftime(TIME_FORMAT) + + # check if frame already exists + query = f'''from(bucket: "{bucket}") + |> range(start: {time_range_lower_bound}, stop: {time_range_upper_bound}) + |> filter(fn: (r) => r._measurement == "raw") + ''' + + # update frame only if already present + if len(self._get_query_api().query(query=query)) != 0: + logger.info("Update found!") + bucket = satellite + "_raw_data" + + db_fields = { + "measurement": "raw", + "time": timestamp, + "tags": {}, + "fields": tlm + } + + self._get_write_api().write(bucket, self.organization, db_fields) + logger.info("Updated " + str(tlm)) + return True + + return False diff --git a/src/transmission/processing/influxdb_api2.py b/src/transmission/processing/influxdb_api2.py deleted file mode 100644 index 3b3e0604..00000000 --- a/src/transmission/processing/influxdb_api2.py +++ /dev/null @@ -1,121 +0,0 @@ -"""Methods for saving raw data frames and retrieving the influxdb API.""" -from datetime import datetime, timedelta -import os -from influxdb_client import InfluxDBClient -from influxdb_client.client.write_api import SYNCHRONOUS -from django_logger import logger - -from transmission.processing.satellites import TIME_FORMAT - -INFLUXDB_URL = "http://influxdb:8086" -INFLUX_ORG = os.environ.get('INFLUXDB_V2_ORG', 'DelfiSpace') - - -def get_influxdb_client(): - """Connect to influxdb and return the influxdb client.""" - - client = InfluxDBClient(url=INFLUXDB_URL, token=os.environ.get('INFLUXDB_V2_TOKEN', 'adminpwd'), org=INFLUX_ORG) - - return client - - -def get_influxdb_bucket_api(): - """Connect to influxdb and return bucket_api.""" - - client = get_influxdb_client() - - buckets_api = client.buckets_api() - - return buckets_api - - -def get_influx_db_read_and_query_api() -> tuple: - """Connect to influxdb and return write_api and query_api.""" - - client = get_influxdb_client() - - write_api = client.write_api(write_options=SYNCHRONOUS) - query_api = client.query_api() - - return (write_api, query_api) - - -def write_frame_to_raw_bucket(write_api, satellite, link, timestamp, frame_fields) -> None: - """Save frame given its fields. Note: to update/overwrite a field write the frame again - with the changed fields and the same timestamp as before.""" - - tags = {} - - bucket = satellite + "_raw_data" - - db_fields = { - "measurement": "raw", - "time": timestamp, - "tags": tags, - "fields": frame_fields - } - - write_api.write(bucket, INFLUX_ORG, db_fields) - - -def commit_frame(write_api, query_api, satellite: str, link: str, timestamp: datetime, tlm: dict) -> bool: - """Write frame to corresponding satellite table (if not already stored). - Returns True if the frame was stored and False otherwise (if the frame is already stored). - Also store the frame with processed = False.""" - - bucket = satellite + "_raw_data" - #tlm_time = datetime.strptime(tlm['timestamp'], TIME_FORMAT) - #logger.info("Timestamp type " + str(type(tlm_time))) - - time_range_lower_bound = (timestamp - timedelta(seconds=1)).strftime(TIME_FORMAT) - time_range_upper_bound = (timestamp + timedelta(seconds=1)).strftime(TIME_FORMAT) - - # check if frame already exists - query = f'''from(bucket: "{bucket}") - |> range(start: {time_range_lower_bound}, stop: {time_range_upper_bound}) - |> filter(fn: (r) => r._measurement == "raw") - |> filter(fn: (r) => r["_field"] == "frame" and r["_value"] == "{tlm["frame"]}") - ''' - # store frame only if not stored already - if len(query_api.query(query=query)) != 0: - logger.info("Found!") - return False - - tlm["processed"] = False - tlm["invalid"] = False - write_frame_to_raw_bucket(write_api, satellite, link, timestamp, tlm) - - return True - -def save_raw_frame_to_influxdb(satellite: str, link: str, timestamp: datetime, telemetry) -> bool: - """Connect to influxdb and save raw telemetry. - Return True if telemetry was stored, False otherwise.""" - - write_api, query_api = get_influx_db_read_and_query_api() - - return commit_frame(write_api, query_api, satellite, link, timestamp, telemetry) - -def get_last_received_frame(satellite: str): - """Retrieve the last received frame for the specified satellite from the raw - data bucket.""" - - client = get_influxdb_client() - query_api = client.query_api() - - bucket = satellite + "_raw_data" - - query = f'''from(bucket: "{bucket}") - |> range(start: 0) - |> filter(fn: (r) => r["_measurement"] == "raw") - |> keep(columns: ["_time"]) - |> tail(n: 1) - ''' - - ret = query_api.query(query=query) - - if len(ret) > 0: - # data received found in bucket - return ret[0].records[0]["_time"] - - # no result - return None diff --git a/src/transmission/processing/process_raw_bucket.py b/src/transmission/processing/process_raw_bucket.py index e8196a89..34363a05 100644 --- a/src/transmission/processing/process_raw_bucket.py +++ b/src/transmission/processing/process_raw_bucket.py @@ -3,27 +3,12 @@ import time import traceback from transmission.processing.XTCEParser import SatParsers, XTCEException -from transmission.processing.influxdb_api import INFLUX_ORG, commit_frame, \ - get_influx_db_read_and_query_api, write_frame_to_raw_bucket +from transmission.processing.influxdb_api import influxdb_api from django_logger import logger -write_api, query_api = get_influx_db_read_and_query_api() -def store_raw_frame(satellite: str, timestamp: str, frame: str, observer: str, link: str) -> bool: - """Store raw unprocessed frame in influxdb""" - frame_fields = { - "frame": frame, - "observer": observer, - "timestamp": timestamp, - "processed": False - } - - stored = commit_frame(write_api, query_api, satellite, link, frame_fields) - return stored - - -def parse_and_store_frame(parsers: SatParsers, satellite: str, timestamp: str, frame: str, - observer: str, link: str) -> None: +def parse_and_store_frame(parsers: SatParsers, db: influxdb_api, satellite: str, timestamp: str, frame: str, + link: str) -> None: """Store parsed frame in influxdb""" parser = parsers.parsers[satellite] @@ -52,83 +37,36 @@ def parse_and_store_frame(parsers: SatParsers, satellite: str, timestamp: str, f except ValueError: pass - try: - db_fields["fields"][field] = value - db_fields["tags"]["status"] = status - - write_api.write(bucket, INFLUX_ORG, db_fields) - except : - logger.info(db_fields) - raise + db.save_processed_frame(bucket, telemetry["frame"], timestamp, {"Status": status}, {field: value}) db_fields["fields"] = {} db_fields["tags"] = {} -def mark_processed_flag(satellite: str, link: str, timestamp: str, value: bool) -> None: - """Write the processed flag to either True or False.""" - write_frame_to_raw_bucket(write_api, satellite, link, timestamp, {'processed': value}) - - -def mark_invalid_flag(satellite: str, link: str, timestamp: str, value: bool) -> None: - """Write the invalid flag to either True or False.""" - write_frame_to_raw_bucket(write_api, satellite, link, timestamp, {'invalid': value}) - - -# pylint: disable=R0914 -def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, start_time: str, end_time: str, - skip_processed: bool = True) -> int: +def process_retrieved_frames(parsers: SatParsers, db: influxdb_api, satellite: str, link: str) -> int: """Parse frames, store the parsed form and mark the raw entry as processed. Return the total number of frames attempting to process and how many frames were successfully processed. Skip_processed=True will skip over the already processed frames.""" - # TODO: we need to still check the frames where processing failed - - get_unprocessed_frames_query = f''' - from(bucket: "{satellite + "_raw_data"}") - |> range(start: {start_time}, stop: {end_time}) - |> filter(fn: (r) => r._measurement == "raw") - |> filter(fn: (r) => r["_field"] == "processed" or - r["_field"] == "frame" or - r["_field"] == "user") - |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") - ''' - - if skip_processed: - get_unprocessed_frames_query = get_unprocessed_frames_query + \ - "|> filter(fn: (r) => r[\"processed\"] == false)" - - # limit the maximum numbr of frames processed per round - get_unprocessed_frames_query = get_unprocessed_frames_query + \ - """ - |> sort(columns: ["_time"], desc: false) - |> limit(n:100, offset: 0)""" - - # query result as dataframe - dataframe = query_api.query_data_frame(query=get_unprocessed_frames_query) - dataframe = dataframe.reset_index() + frames_list = db.get_raw_frames_to_process(satellite, link) processed_frames_count = 0 # process each frame - for _, row in dataframe.iterrows(): + for _, row in frames_list.iterrows(): try: # store processed frame - parse_and_store_frame(parsers, satellite, row["_time"], row["frame"], row["user"], link) - # mark raw frame as processed - mark_processed_flag(satellite, link, row["_time"], True) - # mark raw frame as valid - mark_invalid_flag(satellite, link, row["_time"], False) + parse_and_store_frame(parsers, db, satellite, row["_time"], row["frame"], link) + # mark raw frame as processed and valid + db.update_raw_frame(satellite, link, row["_time"], {'processed': True, 'invalid': False}) processed_frames_count += 1 except XTCEException as ex: logger.error("%s: frame processing error: %s (%s)", satellite, ex, row["frame"]) logger.error(traceback.format_exc()) - # mark raw frame as processed - mark_processed_flag(satellite, link, row["_time"], True) - # mark frame as invalid - mark_invalid_flag(satellite, link, row["_time"], True) + # mark raw frame as processed and invalid + db.update_raw_frame(satellite, link, row["_time"], {'processed': True, 'invalid': True}) # indeed a very broad exception, but it keeps the processor running in case of rogue frames except Exception as ex: # pylint: disable=broad-except @@ -136,40 +74,36 @@ def process_retrieved_frames(parsers: SatParsers, satellite: str, link: str, sta logger.error(traceback.format_exc()) logger.info("Problematic frame: " + str(row)) logger.info(row) - # mark raw frame as processed - mark_processed_flag(satellite, link, row["_time"], True) - # mark frame as invalid - mark_invalid_flag(satellite, link, row["_time"], True) + # mark raw frame as processed and invalid + db.update_raw_frame(satellite, link, row["_time"], {'processed': True, 'invalid': True}) return processed_frames_count def process_raw_bucket(satellite: str, link: str = None, all_frames: bool = False, failed: bool = False): - """Trigger bucket processing or reprocessing given satellite.""" + """Bucket processing or reprocessing task.""" # if link is None process both uplink and downlink, otherwise process only specified link total_processed_frames = 0 iterations = 0 parsers = SatParsers() + db = influxdb_api() + + # TODO handle reprocessing failed frames # once the last frame has been processed, maintain the task active for # at least 10 seconds while looking for more frames to process while iterations < 50: - time.sleep(0.2) - total_processed_frames = 0 if link in ["uplink", "downlink"]: - processed_frames_count = _process_raw_bucket(parsers, satellite, - link, all_frames, failed) + processed_frames_count = process_retrieved_frames(parsers, db, satellite, link) total_processed_frames += processed_frames_count else: - processed_frames_count = _process_raw_bucket(parsers, satellite, \ - "uplink", all_frames, failed) - total_processed_frames += processed_frames_count - processed_frames_count = _process_raw_bucket(parsers, satellite, \ - "downlink", all_frames, failed) + #processed_frames_count = process_retrieved_frames(parsers, db, satellite, "uplink") + #total_processed_frames += processed_frames_count + processed_frames_count = process_retrieved_frames(parsers, db, satellite, "downlink") total_processed_frames += processed_frames_count # one more iteration @@ -179,14 +113,5 @@ def process_raw_bucket(satellite: str, link: str = None, all_frames: bool = Fals # frames were processed in this iteration, reset the iteration counter iterations = 0 - -def _process_raw_bucket(parsers: SatParsers, satellite: str, link: str, all_frames: bool, failed: bool) -> int: - """Trigger bucket processing given satellite and link. - all_frames=True will process the entire bucket and failed=True will process only failed frames. - When both flags are True all frames will be processed.""" - - # process the entire bucket - if all_frames: - return process_retrieved_frames(parsers, satellite, link, "0", "now()", skip_processed=False) - - return process_retrieved_frames(parsers, satellite, link, "0", "now()", skip_processed=True) + # maintain the thread alive and re-check if new frames have been received + time.sleep(0.2) diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index f867f2c3..a8cefe06 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -16,9 +16,7 @@ from members.models import Member from transmission.models import Uplink, Downlink, TLE, Satellite from transmission.processing.XTCEParser import SatParsers, XTCEException -from transmission.processing.influxdb_api import save_raw_frame_to_influxdb -from transmission.processing.telemetry_scraper import strip_tlm - +from transmission.processing.influxdb_api import influxdb_api def store_frames(frames, username: str, application: str = None) -> int: """Store frames in batches if the input is a list. @@ -139,6 +137,7 @@ def process_uplink_and_downlink(invalid_frames: bool = False, callback = None): iterations = 0 parsers = SatParsers() + db = influxdb_api() # list the satellites whose frames have been processed: # ths allows to later start their processing task @@ -149,7 +148,6 @@ def process_uplink_and_downlink(invalid_frames: bool = False, callback = None): while iterations < 50: total_processed_frames = 0 - logger.info("Iteration " + str(iterations)) if not invalid_frames: # set a maximum length to the results to ensure responsive data processing downlink_frames = Downlink.objects.all().filter(processed=False).order_by("timestamp")[:100] @@ -159,11 +157,10 @@ def process_uplink_and_downlink(invalid_frames: bool = False, callback = None): downlink_frames = Downlink.objects.all().filter(processed=True).filter(invalid=True).order_by("timestamp")[:100] uplink_frames = Uplink.objects.all().filter(processed=True).filter(invalid=True).order_by("timestamp")[:100] - logger.info("Frames listed: " + str(len(downlink_frames))) - downlink_frames_count = process_frames(parsers, downlink_frames, "downlink", satellites_list) - uplink_frames_count = process_frames(parsers, uplink_frames, "uplink", satellites_list) + downlink_frames_count = process_frames(parsers, db, downlink_frames, "downlink", satellites_list) + uplink_frames_count = process_frames(parsers, db, uplink_frames, "uplink", satellites_list) total_processed_frames = downlink_frames_count + uplink_frames_count - logger.info("Frames " + str(total_processed_frames)) + # if the satellites list is not empty and the scheduler callback is not None if satellites_list and callback is not None: # report the satellites that have been sending frames @@ -182,7 +179,7 @@ def process_uplink_and_downlink(invalid_frames: bool = False, callback = None): time.sleep(0.2) -def process_frames(parsers: SatParsers, frames: QuerySet, link: str, satellites_list: list) -> int: +def process_frames(parsers: SatParsers, db: influxdb_api, frames: QuerySet, link: str, satellites_list: list) -> int: """Try to store frame to influxdb and set the processed flag to True if a frame was successfully stored in influxdb. Returns the count of successfully processed_frames.""" @@ -191,7 +188,7 @@ def process_frames(parsers: SatParsers, frames: QuerySet, link: str, satellites_ for frame_obj in frames: frame_dict = frame_obj.to_dictionary() - stored, satellite = store_frame_to_influxdb(parsers, frame_obj.timestamp, frame_dict, link) + stored, satellite = store_frame_to_influxdb(parsers, db, frame_obj.timestamp, frame_dict, link) frame_obj.processed = True if stored: @@ -210,7 +207,7 @@ def process_frames(parsers: SatParsers, frames: QuerySet, link: str, satellites_ return processed_frames -def store_frame_to_influxdb(parsers: SatParsers, timestamp: datetime, frame: dict, link: str) -> tuple: +def store_frame_to_influxdb(parsers: SatParsers, db: influxdb_api, timestamp: datetime, frame: dict, link: str) -> tuple: """Try to store frame to influxdb. Returns True if the frame was successfully stored, False otherwise.""" @@ -219,7 +216,7 @@ def store_frame_to_influxdb(parsers: SatParsers, timestamp: datetime, frame: dic if satellite is None: return False, satellite - stored = save_raw_frame_to_influxdb(satellite, link, timestamp, frame) + stored = db.save_raw_frame(satellite, link, timestamp, frame) return stored, satellite diff --git a/src/transmission/processing/telemetry_scraper.py b/src/transmission/processing/telemetry_scraper.py index 4fd43543..850c3c32 100644 --- a/src/transmission/processing/telemetry_scraper.py +++ b/src/transmission/processing/telemetry_scraper.py @@ -8,7 +8,7 @@ from django_logger import logger from transmission.processing.satellites import SATELLITES, TIME_FORMAT -from transmission.processing.influxdb_api import save_raw_frame_to_influxdb +#from transmission.processing.influxdb_api import save_raw_frame_to_influxdb SATNOGS_PATH = "https://db.satnogs.org/api/telemetry/" SATNOGS_TOKEN_PATH = "tokens/satnogs_token.txt" @@ -94,7 +94,7 @@ def scrape(satellite: str, save_to_db=True, save_to_file=False) -> None: if save_to_db: fields_to_save = ["frame", "timestamp", "observer"] stripped_tlm = strip_tlm_list(telemetry_tmp, fields_to_save) - save_raw_frame_to_influxdb(satellite, "downlink", stripped_tlm) + #save_raw_frame_to_influxdb(satellite, "downlink", stripped_tlm) # if the frame is not stored (due to it being stored in a past scrape) and # the next request retrieves data older than a week -> stop diff --git a/src/transmission/urls.py b/src/transmission/urls.py index 13dbdac5..223978be 100644 --- a/src/transmission/urls.py +++ b/src/transmission/urls.py @@ -16,8 +16,8 @@ ] # add path only in debug mode -dummy_data_path = path('add/', views.add_dummy_downlink_frames, name='add_dummy_downlink_frames') -DEBUG = bool(int(os.environ.get('DEBUG', 1))) +#dummy_data_path = path('add/', views.add_dummy_downlink_frames, name='add_dummy_downlink_frames') +#DEBUG = bool(int(os.environ.get('DEBUG', 1))) -if DEBUG: - urlpatterns.append(dummy_data_path) +#if DEBUG: +# urlpatterns.append(dummy_data_path) diff --git a/src/transmission/views.py b/src/transmission/views.py index 51583b80..c980d40b 100644 --- a/src/transmission/views.py +++ b/src/transmission/views.py @@ -16,7 +16,7 @@ from django_logger import logger from members.models import APIKey from transmission.forms.forms import SubmitJob -from transmission.processing.add_dummy_data import add_dummy_downlink_frames +#from transmission.processing.add_dummy_data import add_dummy_downlink_frames from transmission.scheduler import Scheduler, schedule_job from .models import Uplink, Downlink, TLE from .filters import TelemetryDownlinkFilter, TelemetryUplinkFilter, TLEFilter @@ -101,13 +101,13 @@ def submit_frame(request): # pylint:disable=R0911 # POST is the only supported method, return error return JsonResponse({"result": "failure", "message": "Method not allowed"}, status=HTTPStatus.METHOD_NOT_ALLOWED) - -def add_dummy_downlink(request): - """Add dummy frames to Downlink table as admin user.""" - - add_dummy_downlink_frames() - - return JsonResponse({"len": len(Downlink.objects.all())}) +# TODO fix this +#def add_dummy_downlink(request): +# """Add dummy frames to Downlink table as admin user.""" +# +# add_dummy_downlink_frames() +# +# return JsonResponse({"len": len(Downlink.objects.all())}) @login_required(login_url='/login') From 0a8a055a787bfcbfa5389afbb800175c4bd0838b Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sun, 14 Apr 2024 01:05:28 +0200 Subject: [PATCH 42/62] Fixing popup not moving with satellite --- src/static/map.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/static/map.js b/src/static/map.js index 8c260428..bf117039 100644 --- a/src/static/map.js +++ b/src/static/map.js @@ -88,7 +88,7 @@ function updateSatMarker(sat, norad_id, lat, long,) { if (markers.hasOwnProperty(sat)){ markers[sat].setLatLng([lat, long]); //markers[sat].bindPopup(sat + " Lat: " + lat + " Long: " + long +"
"+ next_pass); - markers[sat].bindPopup(sat, {autoPan: false}); + //markers[sat].bindPopup(sat, {autoPan: false}); } else{ //let marker = L.marker([lat, long], {icon: satellite}).addTo(map).bindPopup(sat + " Lat: " + lat + " Long: " + long +"
"+ next_pass); From ef911229fd4592858ce543429713d56d7bf5c790 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sun, 14 Apr 2024 01:06:12 +0200 Subject: [PATCH 43/62] Bumping pgAdmin to version 8.5 --- docker-compose-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose-deploy.yml b/docker-compose-deploy.yml index ac37d07a..10182100 100644 --- a/docker-compose-deploy.yml +++ b/docker-compose-deploy.yml @@ -51,7 +51,7 @@ services: pgadmin: container_name: pgadmin4_container - image: dpage/pgadmin4:8.3 + image: dpage/pgadmin4:8.5 restart: always environment: - PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL:-admin@admin.com} From a65ee80741c94a125de1cd7a12306db81fec6ada Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Mon, 22 Apr 2024 23:35:56 +0200 Subject: [PATCH 44/62] Changing thwe influxDB api to contain all database related code --- docker-compose.yml | 1 - grafana/dashboards/delfi_pq.json | 2601 +++++++++++------ src/delfitlm/settings.py | 1 - src/home/views.py | 15 +- .../management/commands/initbuckets.py | 24 +- src/transmission/models.py | 13 +- .../processing/.influxdb_api.py.swp | Bin 16384 -> 0 bytes src/transmission/processing/influxdb_api.py | 139 +- .../processing/process_raw_bucket.py | 17 +- .../processing/telemetry_scraper.py | 6 +- src/transmission/scheduler.py | 9 +- src/transmission/urls.py | 10 - src/transmission/views.py | 76 +- 13 files changed, 1867 insertions(+), 1045 deletions(-) delete mode 100644 src/transmission/processing/.influxdb_api.py.swp diff --git a/docker-compose.yml b/docker-compose.yml index 1bfe5afb..73357daa 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -67,7 +67,6 @@ services: command: sh -c 'sleep 5; influx setup --bucket "${INFLUX_BUCKET:-default}" --token "${INFLUXDB_V2_TOKEN:-adminpwd}" - --org "${INFLUXDB_V2_ORG:-DelfiSpace}" --username=${INFLUX_USERNAME:-"admin"} --password=${INFLUX_PASSWORD:-"adminpwd"} --host=http://influxdb:8086 diff --git a/grafana/dashboards/delfi_pq.json b/grafana/dashboards/delfi_pq.json index 8d91c8c7..32de9e14 100644 --- a/grafana/dashboards/delfi_pq.json +++ b/grafana/dashboards/delfi_pq.json @@ -1,975 +1,1802 @@ { - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "grafana", - "uid": "-- Grafana --" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "links": [], - "liveNow": false, - "panels": [ + "annotations": { + "list": [ { + "builtIn": 1, "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "target": { + "limit": 100, + "matchAny": false, + "tags": [], + "type": "dashboard" + }, + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 16, + "panels": [], + "title": "Solar Panels", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [ - { - "__systemRef": "hideSeriesFrom", - "matcher": { - "id": "byNames", - "options": { - "mode": "exclude", - "names": [ - "PanelXmCurrent Valid" - ], - "prefix": "All except:", - "readOnly": true - } + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": false, - "tooltip": false, - "viz": true - } - } - ] - } - ] - }, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 0 - }, - "id": 14, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" - }, - "tooltip": { - "mode": "single", - "sort": "none" - } + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "amp", + "unitScale": true }, - "targets": [ + "overrides": [ { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" + "__systemRef": "hideSeriesFrom", + "matcher": { + "id": "byNames", + "options": { + "mode": "exclude", + "names": [ + "PanelYpCurrent Valid", + "PanelXmCurrent Valid", + "PanelXpCurrent Valid", + "PanelYmCurrent Valid" + ], + "prefix": "All except:", + "readOnly": true + } }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpCurrent\" or r[\"_field\"] == \"PanelYmCurrent\" or r[\"_field\"] == \"PanelXpCurrent\" or r[\"_field\"] == \"PanelXmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", - "refId": "A" + "properties": [ + { + "id": "custom.hideFrom", + "value": { + "legend": false, + "tooltip": false, + "viz": true + } + } + ] } - ], - "title": "Solar Panels Currents + Status", - "type": "timeseries" + ] }, - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 1 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpCurrent\" or r[\"_field\"] == \"PanelYmCurrent\" or r[\"_field\"] == \"PanelXpCurrent\" or r[\"_field\"] == \"PanelXmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Solar Panels Current", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "volt", + "unitScale": true }, - "gridPos": { - "h": 9, - "w": 24, - "x": 0, - "y": 9 + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 9, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "id": 15, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpCurrent\" or r[\"_field\"] == \"PanelYmCurrent\" or r[\"_field\"] == \"PanelXpCurrent\" or r[\"_field\"] == \"PanelXmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", - "refId": "A" - } - ], - "title": "Solar Panels Currents", - "type": "timeseries" + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpVoltage\" or r[\"_field\"] == \"PanelYmVoltage\" or r[\"_field\"] == \"PanelXpVoltage\" or r[\"_field\"] == \"PanelXmVoltage\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns:[\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Solar Panels Voltage", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } + ] + }, + "unit": "celsius", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 18 + }, + "id": 10, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpTemperature\" or r[\"_field\"] == \"PanelXmTemperature\" or r[\"_field\"] == \"PanelXpTemperature\" or r[\"_field\"] == \"PanelYmTemperature\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Solar Panels Temperature", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "volt", + "unitScale": true }, - "gridPos": { - "h": 8, - "w": 24, - "x": 0, - "y": 18 + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 26 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "id": 12, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpVoltage\" or r[\"_field\"] == \"PanelYmVoltage\" or r[\"_field\"] == \"PanelXpVoltage\" or r[\"_field\"] == \"PanelXmVoltage\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", - "refId": "A" - } - ], - "title": "Solar Panels Voltages + Status", - "type": "timeseries" + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"CellXpVoltage\" or r[\"_field\"] == \"CellXmVoltage\" or r[\"_field\"] == \"CellYpVoltage\" or r[\"_field\"] == \"CellYmVoltage\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Solar Cells Voltage", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } + ] + }, + "unit": "amp", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 26 + }, + "id": 7, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"CellXpCurrent\" or r[\"_field\"] == \"CellXmCurrent\" or r[\"_field\"] == \"CellYpCurrent\" or r[\"_field\"] == \"CellYmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Solar Cells Current", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "volt", + "unitScale": true }, - "gridPos": { - "h": 8, - "w": 24, - "x": 0, - "y": 26 + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 0, + "y": 35 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "id": 9, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpVoltage\" or r[\"_field\"] == \"PanelYmVoltage\" or r[\"_field\"] == \"PanelXpVoltage\" or r[\"_field\"] == \"PanelXmVoltage\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> group(columns:[\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", - "refId": "A" - } - ], - "title": "Solar Panels Voltages ", - "type": "timeseries" + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"MpptXpVoltage\" or r[\"_field\"] == \"MpptXmVoltage\" or r[\"_field\"] == \"MpptYpVoltage\" or r[\"_field\"] == \"MpptYmVoltage\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "MPPT Voltage", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } + ] + }, + "unit": "amp", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 12, + "x": 12, + "y": 35 + }, + "id": 3, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"MpptXpCurrent\" or r[\"_field\"] == \"MpptXmCurrent\" or r[\"_field\"] == \"MpptYpCurrent\" or r[\"_field\"] == \"MpptYmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "MPPT Current", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 44 + }, + "id": 17, + "panels": [], + "title": "Battery", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "description": "Battery Current", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [ - { - "__systemRef": "hideSeriesFrom", - "matcher": { - "id": "byNames", - "options": { - "mode": "exclude", - "names": [ - "PanelYpTemperature Valid" - ], - "prefix": "All except:", - "readOnly": true - } + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": false, - "tooltip": false, - "viz": true - } - } - ] - } - ] - }, - "gridPos": { - "h": 8, - "w": 24, - "x": 0, - "y": 34 - }, - "id": 10, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" - }, - "tooltip": { - "mode": "single", - "sort": "none" - } + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "amp", + "unitScale": true }, - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpTemperature\" or r[\"_field\"] == \"PanelXmTemperature\" or r[\"_field\"] == \"PanelXpTemperature\" or r[\"_field\"] == \"PanelYmTemperature\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", - "refId": "A" - } - ], - "title": "Solar Panels Temp + Status", - "type": "timeseries" + "overrides": [] }, - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 45 + }, + "id": 20, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"BatteryINACurrent\" )\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Battery Current ", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } + ] + }, + "unit": "volt", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 54 + }, + "id": 21, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"BatteryINAVoltage\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Battery Voltage ", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [ - { - "__systemRef": "hideSeriesFrom", - "matcher": { - "id": "byNames", - "options": { - "mode": "exclude", - "names": [ - "PanelXmTemperature" - ], - "prefix": "All except:", - "readOnly": true - } + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "properties": [ - { - "id": "custom.hideFrom", - "value": { - "legend": false, - "tooltip": false, - "viz": true - } - } - ] - } - ] - }, - "gridPos": { - "h": 8, - "w": 24, - "x": 0, - "y": 42 - }, - "id": 11, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" - }, - "tooltip": { - "mode": "single", - "sort": "none" - } + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "celsius", + "unitScale": true }, - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpTemperature\" or r[\"_field\"] == \"PanelXmTemperature\" or r[\"_field\"] == \"PanelXpTemperature\" or r[\"_field\"] == \"PanelYmTemperature\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", - "refId": "A" - } - ], - "title": "Solar Panels Temp", - "type": "timeseries" + "overrides": [] }, - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 63 + }, + "id": 22, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"BatteryGGTemperature\" or r[\"_field\"] == \"BatteryTMP20Temperature\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Battery Temperture", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } + ] + }, + "unit": "mamph", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 72 + }, + "id": 23, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"BatteryGGCapacity\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Battery Capacity", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 80 + }, + "id": 18, + "panels": [], + "title": "Main Board", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "amp", + "unitScale": true }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 50 + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 81 + }, + "id": 24, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "id": 6, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpTemperature\" or r[\"_field\"] == \"PanelYpVoltage\" or r[\"_field\"] == \"PanelYpCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", - "refId": "A" - } - ], - "title": "PanelYp + Status", - "type": "timeseries" + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"UnregulatedINACurrent\" or r[\"_field\"] == \"InternalINACurrent\" or r[\"_field\"] == \"Bus1Current\" or r[\"_field\"] == \"Bus2Current\" or r[\"_field\"] == \"Bus3Current\" or r[\"_field\"] == \"Bus4Current\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "EPS Currents", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } + ] + }, + "unit": "volt", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 89 + }, + "id": 25, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"Bus1Voltage\" or r[\"_field\"] == \"Bus2Voltage\" or r[\"_field\"] == \"Bus3Voltage\" or r[\"_field\"] == \"Bus4Voltage\" or r[\"_field\"] == \"InternalINAVoltage\" or r[\"_field\"] == \"UnregulatedINAVoltage\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "EPS Voltage", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "celsius", + "unitScale": true }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 50 + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 97 + }, + "id": 26, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "id": 7, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpTemperature\" or r[\"_field\"] == \"PanelYpVoltage\" or r[\"_field\"] == \"PanelYpCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\" or r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Too High\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", - "refId": "A" - } - ], - "title": "PanelYp", - "type": "timeseries" + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"MCUTemp\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "EPS Temperature", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "log": 2, + "type": "log" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } + ] + }, + "unit": "s", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 105 + }, + "id": 27, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"Uptime\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "EPS Uptime", + "type": "timeseries" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 114 + }, + "id": 19, + "panels": [], + "title": "Anomalies", + "type": "row" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "amp", + "unitScale": true }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 59 + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 115 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "id": 2, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Valid\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", - "refId": "A" - } - ], - "title": "PanelYmCurrent + status", - "type": "timeseries" + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYpCurrent\" or r[\"_field\"] == \"PanelYmCurrent\" or r[\"_field\"] == \"PanelXpCurrent\" or r[\"_field\"] == \"PanelXmCurrent\")\n |> filter(fn: (r) => r[\"status\"] != \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Solar Panels Current Anomalies", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null }, - "thresholdsStyle": { - "mode": "off" + { + "color": "red", + "value": 80 } + ] + }, + "unit": "amp", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 124 + }, + "id": 12, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"BatteryINACurrent\")\n |> filter(fn: (r) => r[\"status\"] != \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Battery Current Anomaly", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green" - }, - { - "color": "red", - "value": 80 - } - ] + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" } }, - "overrides": [] + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 59 + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 132 + }, + "id": 11, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true }, - "id": 3, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom" + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "targets": [ - { - "datasource": { - "type": "influxdb", - "uid": "3ap6QYRVz" - }, - "query": "from(bucket: \"delfi_pq_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"PanelYmCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Too Low\" or r[\"status\"] == \"Valid\")\n |> group()\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", - "refId": "A" - } - ], - "title": "PanelYmCurrent", - "type": "timeseries" - } - ], - "refresh": "5s", - "schemaVersion": 36, - "style": "dark", - "tags": [], - "templating": { - "list": [] - }, - "time": { - "from": "2022-01-13T00:00:00.000Z", - "to": "2024-01-08T23:59:59.999Z" - }, - "timepicker": {}, - "timezone": "utc", - "title": "DelfiPQ", - "uid": "_j9ikmi4z", - "version": 1, - "weekStart": "" - } + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioEPSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"Bus1Voltage\" or r[\"_field\"] == \"Bus2Voltage\" or r[\"_field\"] == \"Bus3Voltage\" or r[\"_field\"] == \"Bus4Voltage\" or r[\"_field\"] == \"BatteryGGVoltage\" or r[\"_field\"] == \"UnregulatedINAVoltage\" or r[\"_field\"] == \"InternalINAVoltage\")\n |> filter(fn: (r) => r[\"status\"] != \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "EPS Voltage Anomalies ", + "type": "timeseries" + } + ], + "refresh": "5s", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "2022-01-13T00:00:00.000Z", + "to": "2024-01-08T23:59:59.999Z" + }, + "timepicker": {}, + "timezone": "utc", + "title": "DelfiPQ", + "uid": "_j9ikmi4z", + "version": 8, + "weekStart": "" +} diff --git a/src/delfitlm/settings.py b/src/delfitlm/settings.py index bf1dfcf0..ffd22fc5 100644 --- a/src/delfitlm/settings.py +++ b/src/delfitlm/settings.py @@ -197,7 +197,6 @@ 'HOST' : "http://influxdb", 'PORT' : 8086, 'TOKEN' : os.environ.get('INFLUXDB_V2_TOKEN'), - 'ORGANIZATION' : os.environ.get('INFLUXDB_V2_ORG') } # Password validation diff --git a/src/home/views.py b/src/home/views.py index 7b781748..b8710400 100644 --- a/src/home/views.py +++ b/src/home/views.py @@ -2,6 +2,7 @@ from datetime import datetime, timedelta import json import os +import sys import traceback from django.core.exceptions import PermissionDenied from django.core.serializers.json import DjangoJSONEncoder @@ -118,11 +119,21 @@ def get_satellite_location_now_api(request, norad_id): def _get_satellites_status(): """Method to find satellite status.""" - db_connection = influxdb_api() + try: + db = influxdb_api() + except : + db = None + logger.info("before list " + str(db)) sats_status = {} for sat, info in SATELLITES.items(): sats_status[str(sat + "_status")] = info["status"] - last_rx_time = db_connection.get_last_received_frame(sat) + if db is None: + last_rx_time = None + else: + try: + last_rx_time = db.get_last_received_frame(sat) + except: + last_rx_time = None if last_rx_time is not None and isinstance(last_rx_time, datetime): sats_status[str(sat + "_last_data")] = last_rx_time else: diff --git a/src/transmission/management/commands/initbuckets.py b/src/transmission/management/commands/initbuckets.py index 7e0ef25b..fbe4159f 100644 --- a/src/transmission/management/commands/initbuckets.py +++ b/src/transmission/management/commands/initbuckets.py @@ -3,28 +3,18 @@ from django.core.management.base import BaseCommand from influxdb_client import BucketRetentionRules from transmission.processing.satellites import SATELLITES -from transmission.processing.influxdb_api import get_influxdb_bucket_api +from transmission.processing.influxdb_api import influxdb_api class Command(BaseCommand): """Django command class""" def handle(self, *args, **options): - """Create influxdb buckets for each satellite: - - 1 raw data bucket - - 1 bucket for uplink data - - 1 bucket for downlink data""" + """Initialize the database for each satellite, uplink and downlink""" - buckets_api = get_influxdb_bucket_api() - buckets = [] + db = influxdb_api() + + satellites = [] for sat in SATELLITES: - buckets.append(sat + "_raw_data") - buckets.append(sat + "_downlink") - buckets.append(sat + "_uplink") + satellites.append(sat) - for bucket in buckets: - retention_rules = BucketRetentionRules(type="expire", every_seconds=0) - if buckets_api.find_bucket_by_name(bucket) is None: - buckets_api.create_bucket(bucket_name=bucket, retention_rules=retention_rules) - print(f"Bucket: {bucket} created") - else: - print(f"Bucket: {bucket} already present") + db.init_database(satellites) diff --git a/src/transmission/models.py b/src/transmission/models.py index 425fe593..a4f8d010 100644 --- a/src/transmission/models.py +++ b/src/transmission/models.py @@ -2,7 +2,6 @@ from django.db import models from django.db.models.deletion import DO_NOTHING from django.utils import timezone -from transmission.processing.telemetry_scraper import TIME_FORMAT class Satellite(models.Model): @@ -71,9 +70,9 @@ def to_dictionary(self) -> dict: return frame_dict -class DateTimeMicrosecondsField(models.DateTimeField): - def db_type(self, connection): - return "timestamp(6) with time zone" - - #def rel_db_type(self, connection): - # return "integer UNSIGNED" +#class DateTimeMicrosecondsField(models.DateTimeField): +# def db_type(self, connection): +# return "timestamp(6) with time zone" +# +# #def rel_db_type(self, connection): +# # return "integer UNSIGNED" diff --git a/src/transmission/processing/.influxdb_api.py.swp b/src/transmission/processing/.influxdb_api.py.swp deleted file mode 100644 index e1148816711fd704ad00855d5cb6b02fd4a6acf4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16384 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 g{WD3Fb range(start: 0) - |> filter(fn: (r) => r["_measurement"] == "raw") + |> filter(fn: (r) => r["_measurement"] == "{RAW_MEASUREMENT}") |> keep(columns: ["_time"]) |> tail(n: 1) ''' - ret = self._get_query_api().query(query=query) + ret = self._get_query_api().query(query=query, org="downlink") if len(ret) > 0: # data received found in bucket @@ -63,12 +111,10 @@ def get_last_received_frame(self, satellite: str): def get_raw_frames_to_process(self, satellite: str, link: str, frames: int = 100): """Retrieve the first raw frames to process""" - bucket = satellite + "_raw_data" - get_frames_to_process = f''' - from(bucket: "{bucket}") + from(bucket: "{satellite}") |> range(start: 0, stop: now()) - |> filter(fn: (r) => r._measurement == "raw") + |> filter(fn: (r) => r._measurement == "{RAW_MEASUREMENT}") |> filter(fn: (r) => r["_field"] == "processed" or r["_field"] == "frame" or r["_field"] == "user") @@ -78,7 +124,7 @@ def get_raw_frames_to_process(self, satellite: str, link: str, frames: int = 100 |> limit(n:{frames}, offset: 0)''' # query result as dataframe - dataframe = self._get_query_api().query_data_frame(query=get_frames_to_process) + dataframe = self._get_query_api().query_data_frame(query=get_frames_to_process, org=link) return dataframe @@ -87,55 +133,45 @@ def save_raw_frame(self, satellite: str, link: str, timestamp: datetime, tlm: di Returns True if the frame was stored and False otherwise (if the frame is already stored). Also store the frame with processed = False.""" - bucket = satellite + "_raw_data" - #tlm_time = datetime.strptime(tlm['timestamp'], TIME_FORMAT) - #logger.info("Timestamp type " + str(type(tlm_time))) - - time_range_lower_bound = (timestamp - timedelta(seconds=1)).strftime(TIME_FORMAT) - time_range_upper_bound = (timestamp + timedelta(seconds=1)).strftime(TIME_FORMAT) + time_range_start = (timestamp - timedelta(seconds=0.1)).strftime(DATETIME_FORMAT_STRING) + time_range_stop = (timestamp + timedelta(seconds=0.1)).strftime(DATETIME_FORMAT_STRING) # check if frame already exists - query = f'''from(bucket: "{bucket}") - |> range(start: {time_range_lower_bound}, stop: {time_range_upper_bound}) - |> filter(fn: (r) => r._measurement == "raw") + query = f'''from(bucket: "{satellite}") + |> range(start: {time_range_start}, stop: {time_range_stop}) + |> filter(fn: (r) => r._measurement == "{RAW_MEASUREMENT}") |> filter(fn: (r) => r["_field"] == "frame" and r["_value"] == "{tlm["frame"]}") ''' + # store frame only if not stored already - if len(self._get_query_api().query(query=query)) != 0: - logger.info("Found!") + if len(self._get_query_api().query(query=query, org=link)) != 0: return False tlm["processed"] = False tlm["invalid"] = False - tags = {} - - bucket = satellite + "_raw_data" - db_fields = { - "measurement": "raw", + "measurement": RAW_MEASUREMENT, "time": timestamp, "tags": {}, "fields": tlm } - self._get_write_api().write(bucket, self.organization, db_fields) + self._get_write_api().write(satellite, link, db_fields) return True - def save_processed_frame(self, bucket: str, measurement: str, timestamp, tags, fields): + def save_processed_frame(self, satellite: str, link: str, measurement: str, timestamp, tags, fields): """Write frame to corresponding satellite table (if not already stored). Returns True if the frame was stored and False otherwise (if the frame is already stored). Also store the frame with processed = False.""" - #bucket = satellite + "_" + link - - #time_range_lower_bound = (timestamp - timedelta(seconds=1)).strftime(TIME_FORMAT) - #time_range_upper_bound = (timestamp + timedelta(seconds=1)).strftime(TIME_FORMAT) + #time_range_lower_bound = (timestamp - timedelta(seconds=1)).strftime(DATETIME_FORMAT_STRING) + #time_range_upper_bound = (timestamp + timedelta(seconds=1)).strftime(DATETIME_FORMAT_STRING) # check if frame already exists - #query = f'''from(bucket: "{bucket}") + #query = f'''from(bucket: "{satellite}") # |> range(start: {time_range_lower_bound}, stop: {time_range_upper_bound}) # |> filter(fn: (r) => r._measurement == "raw") # |> filter(fn: (r) => r["_field"] == "frame" and r["_value"] == "{tlm["frame"]}") @@ -148,8 +184,6 @@ def save_processed_frame(self, bucket: str, measurement: str, timestamp, tags, f #tlm["processed"] = False #tlm["invalid"] = False - tags = {} - db_fields = { "measurement": measurement, "time": timestamp, @@ -157,41 +191,34 @@ def save_processed_frame(self, bucket: str, measurement: str, timestamp, tags, f "fields": fields } - self._get_write_api().write(bucket, self.organization, db_fields) + self._get_write_api().write(satellite, link, db_fields) def update_raw_frame(self, satellite: str, link: str, timestamp: datetime, tlm: dict) -> bool: """Updates frame in corresponding satellite table (if not already stored). Returns True if the frame was updated and False otherwise (if the frame was not found). """ - - bucket = satellite + "_raw_data" - #tlm_time = datetime.strptime(tlm['timestamp'], TIME_FORMAT) - #logger.info("Timestamp type " + str(type(tlm_time))) - - time_range_lower_bound = (timestamp - timedelta(seconds=1)).strftime(TIME_FORMAT) - time_range_upper_bound = (timestamp + timedelta(seconds=1)).strftime(TIME_FORMAT) + time_range_start = (timestamp - timedelta(seconds=0.1)).strftime(DATETIME_FORMAT_STRING) + time_range_stop = (timestamp + timedelta(seconds=0.1)).strftime(DATETIME_FORMAT_STRING) # check if frame already exists - query = f'''from(bucket: "{bucket}") - |> range(start: {time_range_lower_bound}, stop: {time_range_upper_bound}) - |> filter(fn: (r) => r._measurement == "raw") + query = f'''from(bucket: "{satellite}") + |> range(start: {time_range_start}, stop: {time_range_stop}) + |> filter(fn: (r) => r._measurement == "{RAW_MEASUREMENT}") ''' # update frame only if already present - if len(self._get_query_api().query(query=query)) != 0: - logger.info("Update found!") - bucket = satellite + "_raw_data" + if len(self._get_query_api().query(query=query, org=link)) != 0: + bucket = satellite db_fields = { - "measurement": "raw", + "measurement": RAW_MEASUREMENT, "time": timestamp, "tags": {}, "fields": tlm } - self._get_write_api().write(bucket, self.organization, db_fields) - logger.info("Updated " + str(tlm)) + self._get_write_api().write(bucket, link, db_fields) return True return False diff --git a/src/transmission/processing/process_raw_bucket.py b/src/transmission/processing/process_raw_bucket.py index 34363a05..1f78c1ed 100644 --- a/src/transmission/processing/process_raw_bucket.py +++ b/src/transmission/processing/process_raw_bucket.py @@ -17,13 +17,6 @@ def parse_and_store_frame(parsers: SatParsers, db: influxdb_api, satellite: str, bucket = satellite + "_" + link if "frame" in telemetry: - db_fields = { - "measurement": telemetry["frame"], - "time": timestamp, - "tags": {}, - "fields": {} - } - for field, value_and_status in telemetry.items(): # skip frame field if field == "frame": @@ -37,10 +30,7 @@ def parse_and_store_frame(parsers: SatParsers, db: influxdb_api, satellite: str, except ValueError: pass - db.save_processed_frame(bucket, telemetry["frame"], timestamp, {"Status": status}, {field: value}) - - db_fields["fields"] = {} - db_fields["tags"] = {} + db.save_processed_frame(satellite, link, telemetry["frame"], timestamp, {"status": status}, {field: value}) def process_retrieved_frames(parsers: SatParsers, db: influxdb_api, satellite: str, link: str) -> int: @@ -101,8 +91,8 @@ def process_raw_bucket(satellite: str, link: str = None, all_frames: bool = Fals processed_frames_count = process_retrieved_frames(parsers, db, satellite, link) total_processed_frames += processed_frames_count else: - #processed_frames_count = process_retrieved_frames(parsers, db, satellite, "uplink") - #total_processed_frames += processed_frames_count + processed_frames_count = process_retrieved_frames(parsers, db, satellite, "uplink") + total_processed_frames += processed_frames_count processed_frames_count = process_retrieved_frames(parsers, db, satellite, "downlink") total_processed_frames += processed_frames_count @@ -112,6 +102,7 @@ def process_raw_bucket(satellite: str, link: str = None, all_frames: bool = Fals if total_processed_frames != 0: # frames were processed in this iteration, reset the iteration counter iterations = 0 + logger.info("Processed " + str(total_processed_frames) + " frames") # maintain the thread alive and re-check if new frames have been received time.sleep(0.2) diff --git a/src/transmission/processing/telemetry_scraper.py b/src/transmission/processing/telemetry_scraper.py index 850c3c32..44cb19ae 100644 --- a/src/transmission/processing/telemetry_scraper.py +++ b/src/transmission/processing/telemetry_scraper.py @@ -91,9 +91,9 @@ def scrape(satellite: str, save_to_db=True, save_to_file=False) -> None: next_time = last_time - timedelta(seconds=1) logger.info("Next: %s", next_time.strftime(TIME_FORMAT)) - if save_to_db: - fields_to_save = ["frame", "timestamp", "observer"] - stripped_tlm = strip_tlm_list(telemetry_tmp, fields_to_save) + #if save_to_db: + #fields_to_save = ["frame", "timestamp", "observer"] + #stripped_tlm = strip_tlm_list(telemetry_tmp, fields_to_save) #save_raw_frame_to_influxdb(satellite, "downlink", stripped_tlm) # if the frame is not stored (due to it being stored in a past scrape) and diff --git a/src/transmission/scheduler.py b/src/transmission/scheduler.py index 66c35187..130dd073 100644 --- a/src/transmission/scheduler.py +++ b/src/transmission/scheduler.py @@ -149,7 +149,7 @@ def __init__(self) -> None: Scheduler.__instance = self - # TODO not very nice to start it here, but this class is a singleton and + # TODO not very nice to start it here, but this class is a singleton and # in ensures the gateway is loaded only once XTCEParser.loadGateway() @@ -188,11 +188,8 @@ def submitted_job_listener(self, event) -> None: logger.info("Started job: %s", event.job_id) self.running_jobs.add(event.job_id) - # TODO: add callback to force buffer processing when scraper is done - #elif "scraper" in event.job_id: - # for sat in SATELLITES: - # if sat in event.job_id: - # schedule_job("raw_bucket_processing", sat, "downlink") + if "scraper" in event.job_id: + schedule_job("buffer_processing") def get_pending_jobs(self) -> set: """Get the ids of the currently scheduled jobs.""" diff --git a/src/transmission/urls.py b/src/transmission/urls.py index 223978be..12f9c21e 100644 --- a/src/transmission/urls.py +++ b/src/transmission/urls.py @@ -1,23 +1,13 @@ """API urls""" -import os from django.urls import path from django.views.decorators.csrf import csrf_exempt from . import views urlpatterns = [ path('transmission//', views.get_frames_table, name='get_frames_table'), - path('transmission/process-frames//', views.process, name='process'), path('transmission/delete-processed-frames//', views.delete_processed_frames, name='delete_processed_frames'), # path('TLEs/', views.get_tle_table, name='get_tle_table'), path('submit/', csrf_exempt(views.submit_frame), name='submit_frame'), path('schedule-job/', views.submit_job, name='submit_job'), path('modify-scheduler//', views.modify_scheduler, name='modify_scheduler'), - ] - -# add path only in debug mode -#dummy_data_path = path('add/', views.add_dummy_downlink_frames, name='add_dummy_downlink_frames') -#DEBUG = bool(int(os.environ.get('DEBUG', 1))) - -#if DEBUG: -# urlpatterns.append(dummy_data_path) diff --git a/src/transmission/views.py b/src/transmission/views.py index c980d40b..a6a07b10 100644 --- a/src/transmission/views.py +++ b/src/transmission/views.py @@ -16,11 +16,11 @@ from django_logger import logger from members.models import APIKey from transmission.forms.forms import SubmitJob -#from transmission.processing.add_dummy_data import add_dummy_downlink_frames from transmission.scheduler import Scheduler, schedule_job from .models import Uplink, Downlink, TLE from .filters import TelemetryDownlinkFilter, TelemetryUplinkFilter, TLEFilter -from .processing.save_raw_data import process_frames, store_frames +#from .processing.save_raw_data import process_frames, store_frames +from .processing.save_raw_data import store_frames QUERY_ROW_LIMIT = 100 @@ -101,14 +101,6 @@ def submit_frame(request): # pylint:disable=R0911 # POST is the only supported method, return error return JsonResponse({"result": "failure", "message": "Method not allowed"}, status=HTTPStatus.METHOD_NOT_ALLOWED) -# TODO fix this -#def add_dummy_downlink(request): -# """Add dummy frames to Downlink table as admin user.""" -# -# add_dummy_downlink_frames() -# -# return JsonResponse({"len": len(Downlink.objects.all())}) - @login_required(login_url='/login') def delete_processed_frames(request, link): @@ -137,38 +129,38 @@ def delete_processed_frames(request, link): return redirect('get_frames_table', link) -@login_required(login_url='/login') -def process(request, link): - """Process frames that are not already stored in influxdb""" - - user = request.user - - if link not in ['uplink', 'downlink']: - return HttpResponseBadRequest() - - if link == "uplink" and user.has_perm("transmission.view_uplink"): - frames = Uplink.objects.all().filter(processed=False) - logger.info("%s frames processing triggered: %s frames to process", link, len(frames)) - - processed_frame_count = process_frames(frames, link) - logger.info("%s %s frames were successfully processed", processed_frame_count, link) - - messages.info(request, f"{processed_frame_count} {link} frames were processed.") - - elif link == "downlink" and user.has_perm("transmission.view_downlink"): - frames = Downlink.objects.all().filter(processed=False) - logger.info("%s frames processing triggered: %s frames to process", link, len(frames)) - - processed_frame_count = process_frames(frames, link) - logger.info("%s %s frames were successfully processed", processed_frame_count, link) - - messages.info(request, f"{processed_frame_count} {link} frames were processed.") - - else: - logger.warning("%s was denied permission to access uplink or downlink tables", request.user) - return HttpResponseForbidden() - - return redirect('get_frames_table', link) +#@login_required(login_url='/login') +#def process(request, link): +# """Process frames that are not already stored in influxdb""" +# +# user = request.user +# +# if link not in ['uplink', 'downlink']: +# return HttpResponseBadRequest() +# +# if link == "uplink" and user.has_perm("transmission.view_uplink"): +# frames = Uplink.objects.all().filter(processed=False) +# logger.info("%s frames processing triggered: %s frames to process", link, len(frames)) +# +# processed_frame_count = process_frames(frames, link) +# logger.info("%s %s frames were successfully processed", processed_frame_count, link) +# +# messages.info(request, f"{processed_frame_count} {link} frames were processed.") +# +# elif link == "downlink" and user.has_perm("transmission.view_downlink"): +# frames = Downlink.objects.all().filter(processed=False) +# logger.info("%s frames processing triggered: %s frames to process", link, len(frames)) +# +# processed_frame_count = process_frames(frames, link) +# logger.info("%s %s frames were successfully processed", processed_frame_count, link) +# +# messages.info(request, f"{processed_frame_count} {link} frames were processed.") +# +# else: +# logger.warning("%s was denied permission to access uplink or downlink tables", request.user) +# return HttpResponseForbidden() +# +# return redirect('get_frames_table', link) def paginate_telemetry_table(request, telemetry_filter, table_name): From 27ac4e7024bfd65c41fa7bcbcc34f50272ca48c2 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Mon, 22 Apr 2024 23:38:34 +0200 Subject: [PATCH 45/62] Improving the Delfi-PQ dashboard --- grafana/dashboards/Delfi-PQ/comms.json | 611 ++++++++++++++++++ .../{delfi_pq.json => Delfi-PQ/eps.json} | 102 +-- grafana/dashboards/Delfi-PQ/obc.json | 519 +++++++++++++++ grafana/dashboards/Delfi-PQ/overview.json | 176 +++++ grafana/dashboards/grafana-dashboard.yml | 3 +- grafana/provisioning/grafana-datasources.yml | 2 +- src/home/templates/home/index.html | 2 +- 7 files changed, 1368 insertions(+), 47 deletions(-) create mode 100644 grafana/dashboards/Delfi-PQ/comms.json rename grafana/dashboards/{delfi_pq.json => Delfi-PQ/eps.json} (97%) create mode 100644 grafana/dashboards/Delfi-PQ/obc.json create mode 100644 grafana/dashboards/Delfi-PQ/overview.json diff --git a/grafana/dashboards/Delfi-PQ/comms.json b/grafana/dashboards/Delfi-PQ/comms.json new file mode 100644 index 00000000..ec24a1d8 --- /dev/null +++ b/grafana/dashboards/Delfi-PQ/comms.json @@ -0,0 +1,611 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 11, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "amp", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [ + "logmin", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioCOMMSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"Current\" or r[\"_field\"] == \"AmplifierCurrent\" or r[\"_field\"] == \"TransmitCurrent\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Current", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "volt", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 12 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "logmin", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioCOMMSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"Voltage\" or r[\"_field\"] == \"AmplifierVoltage\" or r[\"_field\"] == \"TransmitVoltage\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Voltage", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "celsius", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 12, + "w": 24, + "x": 0, + "y": 23 + }, + "id": 3, + "options": { + "legend": { + "calcs": [ + "min", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioCOMMSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"MCUTemp\" or r[\"_field\"] == \"Temperature\" or r[\"_field\"] == \"AmplifierTemperature\" or r[\"_field\"] == \"PhasingTemperature\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Temperature", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "dBm", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 35 + }, + "id": 5, + "options": { + "legend": { + "calcs": [ + "min", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioCOMMSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"ReceiverRSSI\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Receiver Signal Strength Indicator", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "log": 2, + "type": "log" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 45 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "logmin", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioCOMMSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"Uptime\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Uptime", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 13, + "w": 24, + "x": 0, + "y": 56 + }, + "id": 6, + "options": { + "legend": { + "calcs": [], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioCOMMSTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"BootCounter\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Boot Counter", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "2022-01-13T00:00:00.000Z", + "to": "2024-01-08T23:59:59.999Z" + }, + "timepicker": {}, + "timezone": "", + "title": "COMMS", + "uid": "e47df615-40eb-40c6-9934-703458d84fae", + "version": 1, + "weekStart": "" +} diff --git a/grafana/dashboards/delfi_pq.json b/grafana/dashboards/Delfi-PQ/eps.json similarity index 97% rename from grafana/dashboards/delfi_pq.json rename to grafana/dashboards/Delfi-PQ/eps.json index 32de9e14..fe36f8cf 100644 --- a/grafana/dashboards/delfi_pq.json +++ b/grafana/dashboards/Delfi-PQ/eps.json @@ -24,6 +24,7 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, + "id": 1, "links": [], "liveNow": false, "panels": [ @@ -316,7 +317,7 @@ "overrides": [] }, "gridPos": { - "h": 8, + "h": 10, "w": 24, "x": 0, "y": 18 @@ -324,8 +325,11 @@ "id": 10, "options": { "legend": { - "calcs": [], - "displayMode": "list", + "calcs": [ + "min", + "max" + ], + "displayMode": "table", "placement": "bottom", "showLegend": true }, @@ -412,7 +416,7 @@ "h": 9, "w": 12, "x": 0, - "y": 26 + "y": 28 }, "id": 6, "options": { @@ -505,7 +509,7 @@ "h": 9, "w": 12, "x": 12, - "y": 26 + "y": 28 }, "id": 7, "options": { @@ -598,7 +602,7 @@ "h": 9, "w": 12, "x": 0, - "y": 35 + "y": 37 }, "id": 2, "options": { @@ -691,7 +695,7 @@ "h": 9, "w": 12, "x": 12, - "y": 35 + "y": 37 }, "id": 3, "options": { @@ -725,7 +729,7 @@ "h": 1, "w": 24, "x": 0, - "y": 44 + "y": 46 }, "id": 17, "panels": [], @@ -798,7 +802,7 @@ "h": 9, "w": 24, "x": 0, - "y": 45 + "y": 47 }, "id": 20, "options": { @@ -809,7 +813,7 @@ "showLegend": true }, "tooltip": { - "mode": "single", + "mode": "multi", "sort": "none" } }, @@ -891,7 +895,7 @@ "h": 9, "w": 24, "x": 0, - "y": 54 + "y": 56 }, "id": 21, "options": { @@ -902,7 +906,7 @@ "showLegend": true }, "tooltip": { - "mode": "single", + "mode": "multi", "sort": "none" } }, @@ -981,16 +985,19 @@ "overrides": [] }, "gridPos": { - "h": 9, + "h": 10, "w": 24, "x": 0, - "y": 63 + "y": 65 }, "id": 22, "options": { "legend": { - "calcs": [], - "displayMode": "list", + "calcs": [ + "min", + "max" + ], + "displayMode": "table", "placement": "bottom", "showLegend": true }, @@ -1074,16 +1081,19 @@ "overrides": [] }, "gridPos": { - "h": 8, + "h": 10, "w": 24, "x": 0, - "y": 72 + "y": 75 }, "id": 23, "options": { "legend": { - "calcs": [], - "displayMode": "list", + "calcs": [ + "min", + "max" + ], + "displayMode": "table", "placement": "bottom", "showLegend": true }, @@ -1111,7 +1121,7 @@ "h": 1, "w": 24, "x": 0, - "y": 80 + "y": 85 }, "id": 18, "panels": [], @@ -1183,7 +1193,7 @@ "h": 8, "w": 24, "x": 0, - "y": 81 + "y": 86 }, "id": 24, "options": { @@ -1276,7 +1286,7 @@ "h": 8, "w": 24, "x": 0, - "y": 89 + "y": 94 }, "id": 25, "options": { @@ -1369,18 +1379,21 @@ "h": 8, "w": 24, "x": 0, - "y": 97 + "y": 102 }, "id": 26, "options": { "legend": { - "calcs": [], - "displayMode": "list", + "calcs": [ + "min", + "max" + ], + "displayMode": "table", "placement": "bottom", "showLegend": true }, "tooltip": { - "mode": "single", + "mode": "multi", "sort": "none" } }, @@ -1463,18 +1476,21 @@ "h": 9, "w": 24, "x": 0, - "y": 105 + "y": 110 }, "id": 27, "options": { "legend": { - "calcs": [], - "displayMode": "list", + "calcs": [ + "logmin", + "max" + ], + "displayMode": "table", "placement": "bottom", "showLegend": true }, "tooltip": { - "mode": "single", + "mode": "multi", "sort": "none" } }, @@ -1497,7 +1513,7 @@ "h": 1, "w": 24, "x": 0, - "y": 114 + "y": 119 }, "id": 19, "panels": [], @@ -1569,7 +1585,7 @@ "h": 9, "w": 24, "x": 0, - "y": 115 + "y": 120 }, "id": 15, "options": { @@ -1580,7 +1596,7 @@ "showLegend": true }, "tooltip": { - "mode": "single", + "mode": "multi", "sort": "none" } }, @@ -1644,8 +1660,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1662,7 +1677,7 @@ "h": 8, "w": 24, "x": 0, - "y": 124 + "y": 129 }, "id": 12, "options": { @@ -1673,7 +1688,7 @@ "showLegend": true }, "tooltip": { - "mode": "single", + "mode": "multi", "sort": "none" } }, @@ -1737,8 +1752,7 @@ "mode": "absolute", "steps": [ { - "color": "green", - "value": null + "color": "green" }, { "color": "red", @@ -1754,7 +1768,7 @@ "h": 8, "w": 24, "x": 0, - "y": 132 + "y": 137 }, "id": 11, "options": { @@ -1765,7 +1779,7 @@ "showLegend": true }, "tooltip": { - "mode": "single", + "mode": "multi", "sort": "none" } }, @@ -1795,8 +1809,8 @@ }, "timepicker": {}, "timezone": "utc", - "title": "DelfiPQ", + "title": "EPS", "uid": "_j9ikmi4z", - "version": 8, + "version": 15, "weekStart": "" } diff --git a/grafana/dashboards/Delfi-PQ/obc.json b/grafana/dashboards/Delfi-PQ/obc.json new file mode 100644 index 00000000..df1bb2ca --- /dev/null +++ b/grafana/dashboards/Delfi-PQ/obc.json @@ -0,0 +1,519 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 8, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "amp", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [ + "min", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioOBCTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"Current\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Current", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "volt", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 10 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "logmin", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioOBCTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"Voltage\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Voltage", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "celsius", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 14, + "w": 24, + "x": 0, + "y": 21 + }, + "id": 3, + "options": { + "legend": { + "calcs": [ + "min", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioOBCTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"MCUTemp\" or r[\"_field\"] == \"Temperature\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Temperature", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "log": 2, + "type": "log" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "s", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 35 + }, + "id": 4, + "options": { + "legend": { + "calcs": [ + "logmin", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioOBCTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"Uptime\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Uptime", + "type": "timeseries" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 11, + "w": 24, + "x": 0, + "y": 46 + }, + "id": 5, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"RadioOBCTelemetry\")\n |> filter(fn: (r) => r[\"_field\"] == \"BootCounter\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns: [\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Boot Counter", + "type": "timeseries" + } + ], + "refresh": false, + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "2022-01-13T00:00:00.000Z", + "to": "2024-01-08T23:59:59.999Z" + }, + "timepicker": {}, + "timezone": "", + "title": "OBC", + "uid": "d343255b-4972-4ca7-bb80-b836aa3ae642", + "version": 1, + "weekStart": "" +} diff --git a/grafana/dashboards/Delfi-PQ/overview.json b/grafana/dashboards/Delfi-PQ/overview.json new file mode 100644 index 00000000..abd9760a --- /dev/null +++ b/grafana/dashboards/Delfi-PQ/overview.json @@ -0,0 +1,176 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [ + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": false, + "title": "EPS", + "tooltip": "EPS Dashboard", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/_j9ikmi4z/eps?orgId=1&refresh=5s" + }, + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": false, + "title": "COMMS", + "tooltip": "COMMS Dashboard", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/e47df615-40eb-40c6-9934-703458d84fae/comms?orgId=1" + }, + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": false, + "title": "OBC", + "tooltip": "OBC Dashboard", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/d343255b-4972-4ca7-bb80-b836aa3ae642/obc?orgId=1" + } + ], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "gridPos": { + "h": 10, + "w": 9, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "markdown" + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "", + "refId": "A" + } + ], + "type": "text" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "displayName": "${__field.labels.__values}" + "mappings": [], + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 10, + "w": 7, + "x": 9, + "y": 0 + }, + "id": 2, + "options": { + "displayLabels": [ + "percent", + "name" + ], + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": " from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"_raw\" and r[\"_field\"] == \"application\")\n |> duplicate(column: \"_value\", as: \"new_column\")\n |> group(columns: [\"new_column\"])\n |> count()\n ", + "refId": "A" + } + ], + "title": "Data Source", + "type": "piechart" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "2022-01-13T00:00:00.000Z", + "to": "2024-01-08T23:59:59.999Z" + }, + "timepicker": {}, + "timezone": "", + "title": "Overview", + "uid": "f4c5128b-0826-4503-9848-b59ddb4cae00", + "version": 3, + "weekStart": "" +} diff --git a/grafana/dashboards/grafana-dashboard.yml b/grafana/dashboards/grafana-dashboard.yml index e020c284..6099532d 100644 --- a/grafana/dashboards/grafana-dashboard.yml +++ b/grafana/dashboards/grafana-dashboard.yml @@ -6,8 +6,9 @@ providers: folder: '' type: 'file' editable: true + allowUiUpdates: false options: # path to dashboard files on disk. Required when using the 'file' type path: /etc/grafana/provisioning/dashboards/ # use folder names from filesystem to create folders in Grafana - foldersFromFilesStructure: true \ No newline at end of file + foldersFromFilesStructure: true diff --git a/grafana/provisioning/grafana-datasources.yml b/grafana/provisioning/grafana-datasources.yml index 28c07979..41c1e4df 100755 --- a/grafana/provisioning/grafana-datasources.yml +++ b/grafana/provisioning/grafana-datasources.yml @@ -10,4 +10,4 @@ datasources: token: $GF_INFLUXDB_V2_TOKEN jsonData: version: Flux - organization: $INFLUXDB_V2_ORG + organization: downlink diff --git a/src/home/templates/home/index.html b/src/home/templates/home/index.html index a17679c1..d023295a 100644 --- a/src/home/templates/home/index.html +++ b/src/home/templates/home/index.html @@ -107,7 +107,7 @@

Delfi-PQ

Launch:
   {% if delfi_pq_launch is not None %}{{ delfi_pq_launch|date:"M dS Y" }}{% else %}-{% endif %}

Last Reception:
   {% if delfi_pq_last_data is not None %}{{ delfi_pq_last_data|date:"M dS Y H:i:s" }} UTC{% else %}-{% endif %}

About - Dashboard + Dashboard

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êJ&gOCo-di|#U7os6_DK>{lP>Y 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

|iq^Ir(-63sVOjT(Csy77_d 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

From 8e7422ff872c94b853c6ca20d9ade1ca1acc59f9 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Wed, 24 Apr 2024 11:57:41 +0200 Subject: [PATCH 46/62] Removing legend from graphs with a single value --- grafana/dashboards/Delfi-PQ/obc.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/grafana/dashboards/Delfi-PQ/obc.json b/grafana/dashboards/Delfi-PQ/obc.json index df1bb2ca..ae0acb04 100644 --- a/grafana/dashboards/Delfi-PQ/obc.json +++ b/grafana/dashboards/Delfi-PQ/obc.json @@ -98,7 +98,7 @@ ], "displayMode": "table", "placement": "bottom", - "showLegend": true + "showLegend": false }, "tooltip": { "mode": "multi", @@ -194,7 +194,7 @@ ], "displayMode": "table", "placement": "bottom", - "showLegend": true + "showLegend": false }, "tooltip": { "mode": "multi", @@ -387,7 +387,7 @@ ], "displayMode": "table", "placement": "bottom", - "showLegend": true + "showLegend": false }, "tooltip": { "mode": "multi", @@ -479,7 +479,7 @@ "calcs": [], "displayMode": "list", "placement": "bottom", - "showLegend": true + "showLegend": false }, "tooltip": { "mode": "multi", @@ -500,7 +500,7 @@ "type": "timeseries" } ], - "refresh": false, + "refresh": "", "schemaVersion": 39, "tags": [], "templating": { @@ -514,6 +514,6 @@ "timezone": "", "title": "OBC", "uid": "d343255b-4972-4ca7-bb80-b836aa3ae642", - "version": 1, + "version": 4, "weekStart": "" } From 6ecf3b6c1dcec376f5afb87e689abf5e1f6ec813 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Wed, 24 Apr 2024 11:57:58 +0200 Subject: [PATCH 47/62] Added total number of received frames --- grafana/dashboards/Delfi-PQ/overview.json | 80 +++++++++++++++++++++-- 1 file changed, 73 insertions(+), 7 deletions(-) diff --git a/grafana/dashboards/Delfi-PQ/overview.json b/grafana/dashboards/Delfi-PQ/overview.json index abd9760a..f4fb3130 100644 --- a/grafana/dashboards/Delfi-PQ/overview.json +++ b/grafana/dashboards/Delfi-PQ/overview.json @@ -18,6 +18,7 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, + "id": 10, "links": [ { "asDropdown": false, @@ -64,8 +65,8 @@ "uid": "3ap6QYRVz" }, "gridPos": { - "h": 10, - "w": 9, + "h": 9, + "w": 8, "x": 0, "y": 0 }, @@ -109,16 +110,16 @@ "viz": false } }, - "displayName": "${__field.labels.__values}" + "displayName": "${__field.labels.__values}", "mappings": [], "unitScale": true }, "overrides": [] }, "gridPos": { - "h": 10, - "w": 7, - "x": 9, + "h": 9, + "w": 6, + "x": 8, "y": 0 }, "id": 2, @@ -155,6 +156,71 @@ ], "title": "Data Source", "type": "piechart" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 9, + "x": 14, + "y": 0 + }, + "id": 3, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"_raw\")\n |> filter(fn: (r) => r[\"_field\"] == \"user\")\n |> aggregateWindow(every: v.windowPeriod, fn: count)\n |> cumulativeSum(columns: [\"_value\"]) ", + "refId": "A" + } + ], + "title": "Frame Count", + "type": "stat" } ], "refresh": "", @@ -171,6 +237,6 @@ "timezone": "", "title": "Overview", "uid": "f4c5128b-0826-4503-9848-b59ddb4cae00", - "version": 3, + "version": 5, "weekStart": "" } From 8085a013067eb33f396866d1fadd27cebc6f30e2 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Mon, 29 Apr 2024 23:18:52 +0200 Subject: [PATCH 48/62] Restructured grafana dashboards --- grafana/dashboards/Delfi-C3/overview.json | 365 ++++++++++++++++++ grafana/dashboards/Delfi-C3/payload.json | 161 ++++++++ .../telemetry.json} | 76 ++-- grafana/dashboards/Delfi-PQ/comms.json | 45 ++- grafana/dashboards/Delfi-PQ/eps.json | 43 ++- grafana/dashboards/Delfi-PQ/obc.json | 45 ++- grafana/dashboards/Delfi-PQ/overview.json | 160 +++++++- src/home/templates/home/index.html | 4 +- 8 files changed, 850 insertions(+), 49 deletions(-) create mode 100644 grafana/dashboards/Delfi-C3/overview.json create mode 100644 grafana/dashboards/Delfi-C3/payload.json rename grafana/dashboards/{delfi_c3.json => Delfi-C3/telemetry.json} (74%) diff --git a/grafana/dashboards/Delfi-C3/overview.json b/grafana/dashboards/Delfi-C3/overview.json new file mode 100644 index 00000000..9f59f55e --- /dev/null +++ b/grafana/dashboards/Delfi-C3/overview.json @@ -0,0 +1,365 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [ + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": true, + "tags": [], + "targetBlank": false, + "title": "Telemetry", + "tooltip": "Delfi-C3 Telemetry", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-C3_Telemetry" + }, + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": true, + "tags": [], + "targetBlank": false, + "title": "Payload", + "tooltip": "Delfi-C3 Payload", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-C3_Payload" + } + ], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "gridPos": { + "h": 9, + "w": 8, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "code": { + "language": "plaintext", + "showLineNumbers": false, + "showMiniMap": false + }, + "content": "", + "mode": "markdown" + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "", + "refId": "A" + } + ], + "type": "text" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + } + }, + "displayName": "${__field.labels.__values}", + "mappings": [], + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 6, + "x": 8, + "y": 0 + }, + "id": 2, + "options": { + "displayLabels": [ + "percent", + "name" + ], + "legend": { + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "pieType": "pie", + "reduceOptions": { + "calcs": [], + "fields": "", + "values": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": " from(bucket: \"delfi_c3\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"_raw\" and r[\"_field\"] == \"application\")\n |> duplicate(column: \"_value\", as: \"new_column\")\n |> group(columns: [\"new_column\"])\n |> count()\n ", + "refId": "A" + } + ], + "title": "Data Source", + "type": "piechart" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "dark-green", + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 10, + "x": 14, + "y": 0 + }, + "id": 3, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_c3\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"_raw\")\n |> filter(fn: (r) => r[\"_field\"] == \"user\")\n |> aggregateWindow(every: v.windowPeriod, fn: count)\n |> cumulativeSum(columns: [\"_value\"]) ", + "refId": "A" + } + ], + "title": "Frame Count", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "dark-green", + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 9 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "/^user$/", + "limit": 1, + "values": true + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_c3\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"_raw\")\n |> filter(fn: (r) => r[\"_field\"] == \"user\")\n |> last()", + "refId": "A" + } + ], + "title": "Last Frame Received by", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "dark-green", + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "dateTimeAsIsoNoDateIfToday", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 11, + "x": 8, + "y": 9 + }, + "id": 5, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "/^Time$/", + "limit": 1, + "values": true + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_c3\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"_raw\")\n |> filter(fn: (r) => r[\"_field\"] == \"user\")\n |> last()", + "refId": "A" + } + ], + "title": "Last Frame Received on", + "type": "stat" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "2008-04-28T00:00:00.000Z", + "to": "2023-11-14T23:59:59.999Z" + }, + "timepicker": {}, + "timezone": "utc", + "title": "Overview", + "uid": "Delfi-C3_Overview", + "version": 2, + "weekStart": "" +} diff --git a/grafana/dashboards/Delfi-C3/payload.json b/grafana/dashboards/Delfi-C3/payload.json new file mode 100644 index 00000000..b2295d26 --- /dev/null +++ b/grafana/dashboards/Delfi-C3/payload.json @@ -0,0 +1,161 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "links": [ + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": true, + "tags": [], + "targetBlank": false, + "title": "Overview", + "tooltip": "Delfi-C3 Overview", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-C3_Overview" + }, + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": true, + "tags": [], + "targetBlank": false, + "title": "Telemetry", + "tooltip": "Delfi-C3 Telemetry", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-C3_Telemetry" + } + ], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "smooth", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 2, + "options": { + "legend": { + "calcs": [ + "min", + "max" + ], + "displayMode": "table", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "multi", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_c3\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"Payload\")\n |> filter(fn: (r) => r[\"_field\"] == \"TFSC_T_ZmYm\" or r[\"_field\"] == \"TFSC_T_ZmYp\" or r[\"_field\"] == \"TFSC_T_ZpXm\" or r[\"_field\"] == \"TFSC_T_ZpXp\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns:[\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "refId": "A" + } + ], + "title": "Thin-Film Solar Cells Temperature", + "type": "timeseries" + } + ], + "refresh": false, + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "2008-04-28T00:00:00.000Z", + "to": "2023-11-14T23:59:59.999Z" + }, + "timepicker": {}, + "timezone": "utc", + "title": "Payload", + "uid": "Delfi-C3_Payload", + "version": 2, + "weekStart": "" +} diff --git a/grafana/dashboards/delfi_c3.json b/grafana/dashboards/Delfi-C3/telemetry.json similarity index 74% rename from grafana/dashboards/delfi_c3.json rename to grafana/dashboards/Delfi-C3/telemetry.json index 71b87875..992a616f 100644 --- a/grafana/dashboards/delfi_c3.json +++ b/grafana/dashboards/Delfi-C3/telemetry.json @@ -18,7 +18,32 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "links": [], + "links": [ + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": true, + "tags": [], + "targetBlank": false, + "title": "Overview", + "tooltip": "Delfi-C3 Overview", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-C3_Overview" + }, + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": true, + "tags": [], + "targetBlank": false, + "title": "Payload", + "tooltip": "Delfi-C3 Payload", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-C3_Payload" + } + ], "liveNow": false, "panels": [ { @@ -82,8 +107,8 @@ "overrides": [] }, "gridPos": { - "h": 8, - "w": 12, + "h": 10, + "w": 24, "x": 0, "y": 0 }, @@ -106,7 +131,7 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_c3_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"Housekeeping\")\n |> filter(fn: (r) => r[\"_field\"] == \"RAP1_Rx_I\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_c3\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"Housekeeping\")\n |> filter(fn: (r) => r[\"_field\"] == \"RAP1_Rx_I\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], @@ -139,7 +164,7 @@ "viz": false }, "insertNulls": false, - "lineInterpolation": "linear", + "lineInterpolation": "smooth", "lineWidth": 1, "pointSize": 5, "scaleDistribution": { @@ -174,21 +199,24 @@ "overrides": [] }, "gridPos": { - "h": 8, - "w": 12, + "h": 9, + "w": 24, "x": 0, - "y": 8 + "y": 10 }, "id": 2, "options": { "legend": { - "calcs": [], - "displayMode": "list", + "calcs": [ + "min", + "max" + ], + "displayMode": "table", "placement": "bottom", "showLegend": true }, "tooltip": { - "mode": "single", + "mode": "multi", "sort": "none" } }, @@ -198,11 +226,11 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_c3_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"Housekeeping\")\n |> filter(fn: (r) => r[\"_field\"] == \"OBC_T\"\n) |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_c3\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"Housekeeping\")\n |> filter(fn: (r) => r[\"_field\"] == \"OBC_T\" or r[\"_field\"] == \"RAP1_T\" or r[\"_field\"] == \"RAP2_T\")\n |> filter(fn: (r) => r[\"status\"] == \"Valid\")\n |> group(columns:[\"_field\"])\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], - "title": "OBC Temperature", + "title": "Temperature", "type": "timeseries" }, { @@ -266,10 +294,10 @@ "overrides": [] }, "gridPos": { - "h": 8, - "w": 12, + "h": 9, + "w": 24, "x": 0, - "y": 16 + "y": 19 }, "id": 1, "options": { @@ -277,7 +305,7 @@ "calcs": [], "displayMode": "list", "placement": "bottom", - "showLegend": true + "showLegend": false }, "tooltip": { "mode": "single", @@ -290,7 +318,7 @@ "type": "influxdb", "uid": "3ap6QYRVz" }, - "query": "from(bucket: \"delfi_c3_downlink\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"Housekeeping\")\n |> filter(fn: (r) => r[\"_field\"] == \"BootCounter\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", + "query": "from(bucket: \"delfi_c3\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"Housekeeping\")\n |> filter(fn: (r) => r[\"_field\"] == \"BootCounter\")\n |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)\n |> yield(name: \"mean\")", "refId": "A" } ], @@ -298,7 +326,7 @@ "type": "timeseries" } ], - "refresh": "", + "refresh": false, "schemaVersion": 39, "tags": [], "templating": { @@ -306,12 +334,12 @@ }, "time": { "from": "2008-04-28T00:00:00.000Z", - "to": "2023-11-14T23:59:59.999Z" + "to": "2024-11-14T23:59:59.000Z" }, "timepicker": {}, - "timezone": "", - "title": "Delfi-C3", - "uid": "ec0b906e-c704-41d9-a063-645b803db188", - "version": 10, + "timezone": "utc", + "title": "Telemetry", + "uid": "Delfi-C3_Telemetry", + "version": 5, "weekStart": "" } diff --git a/grafana/dashboards/Delfi-PQ/comms.json b/grafana/dashboards/Delfi-PQ/comms.json index ec24a1d8..877d6e16 100644 --- a/grafana/dashboards/Delfi-PQ/comms.json +++ b/grafana/dashboards/Delfi-PQ/comms.json @@ -19,7 +19,44 @@ "fiscalYearStartMonth": 0, "graphTooltip": 0, "id": 11, - "links": [], + "links": [ + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": false, + "title": "Overview", + "tooltip": "Delfi-PQ Overview", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-PQ_Overview" + }, + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": false, + "title": "EPS", + "tooltip": "EPS Telemetry", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-PQ_EPS" + }, + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": false, + "title": "OBC", + "tooltip": "OBC Telemetry", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-PQ_OBC" + } + ], "liveNow": false, "panels": [ { @@ -603,9 +640,9 @@ "to": "2024-01-08T23:59:59.999Z" }, "timepicker": {}, - "timezone": "", + "timezone": "utc", "title": "COMMS", - "uid": "e47df615-40eb-40c6-9934-703458d84fae", - "version": 1, + "uid": "Delfi-PQ_COMMS", + "version": 2, "weekStart": "" } diff --git a/grafana/dashboards/Delfi-PQ/eps.json b/grafana/dashboards/Delfi-PQ/eps.json index fe36f8cf..53dc018f 100644 --- a/grafana/dashboards/Delfi-PQ/eps.json +++ b/grafana/dashboards/Delfi-PQ/eps.json @@ -25,7 +25,44 @@ "fiscalYearStartMonth": 0, "graphTooltip": 0, "id": 1, - "links": [], + "links": [ + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": false, + "title": "Overview", + "tooltip": "Delfi-PQ Overview", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-PQ_Overview" + }, + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": false, + "title": "COMMS", + "tooltip": "COMMS Telemetry", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-PQ_COMMS" + }, + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": false, + "title": "OBC", + "tooltip": "OBC Telemetry", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-PQ_OBC" + } + ], "liveNow": false, "panels": [ { @@ -1810,7 +1847,7 @@ "timepicker": {}, "timezone": "utc", "title": "EPS", - "uid": "_j9ikmi4z", - "version": 15, + "uid": "Delfi-PQ_EPS", + "version": 16, "weekStart": "" } diff --git a/grafana/dashboards/Delfi-PQ/obc.json b/grafana/dashboards/Delfi-PQ/obc.json index ae0acb04..e896d205 100644 --- a/grafana/dashboards/Delfi-PQ/obc.json +++ b/grafana/dashboards/Delfi-PQ/obc.json @@ -19,7 +19,44 @@ "fiscalYearStartMonth": 0, "graphTooltip": 0, "id": 8, - "links": [], + "links": [ + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": false, + "title": "Overview", + "tooltip": "Delfi-PQ Overview", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-PQ_Overview" + }, + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": false, + "title": "EPS", + "tooltip": "EPS Telemetry", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-PQ_EPS" + }, + { + "asDropdown": false, + "icon": "dashboard", + "includeVars": false, + "keepTime": false, + "tags": [], + "targetBlank": false, + "title": "COMMS", + "tooltip": "COMMS Telemetry", + "type": "link", + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-PQ_COMMS" + } + ], "liveNow": false, "panels": [ { @@ -511,9 +548,9 @@ "to": "2024-01-08T23:59:59.999Z" }, "timepicker": {}, - "timezone": "", + "timezone": "utc", "title": "OBC", - "uid": "d343255b-4972-4ca7-bb80-b836aa3ae642", - "version": 4, + "uid": "Delfi-PQ_OBC", + "version": 5, "weekStart": "" } diff --git a/grafana/dashboards/Delfi-PQ/overview.json b/grafana/dashboards/Delfi-PQ/overview.json index f4fb3130..adb1a61d 100644 --- a/grafana/dashboards/Delfi-PQ/overview.json +++ b/grafana/dashboards/Delfi-PQ/overview.json @@ -18,7 +18,7 @@ "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 10, + "id": 15, "links": [ { "asDropdown": false, @@ -28,9 +28,9 @@ "tags": [], "targetBlank": false, "title": "EPS", - "tooltip": "EPS Dashboard", + "tooltip": "EPS Telemetry", "type": "link", - "url": "https://delfispace.tudelft.nl/grafana/d/_j9ikmi4z/eps?orgId=1&refresh=5s" + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-PQ_EPS" }, { "asDropdown": false, @@ -40,9 +40,9 @@ "tags": [], "targetBlank": false, "title": "COMMS", - "tooltip": "COMMS Dashboard", + "tooltip": "COMMS Telemetry", "type": "link", - "url": "https://delfispace.tudelft.nl/grafana/d/e47df615-40eb-40c6-9934-703458d84fae/comms?orgId=1" + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-PQ_COMMS" }, { "asDropdown": false, @@ -52,9 +52,9 @@ "tags": [], "targetBlank": false, "title": "OBC", - "tooltip": "OBC Dashboard", + "tooltip": "OBC Telemetry", "type": "link", - "url": "https://delfispace.tudelft.nl/grafana/d/d343255b-4972-4ca7-bb80-b836aa3ae642/obc?orgId=1" + "url": "https://delfispace.tudelft.nl/grafana/d/Delfi-PQ_OBC" } ], "liveNow": false, @@ -165,7 +165,8 @@ "fieldConfig": { "defaults": { "color": { - "mode": "thresholds" + "fixedColor": "dark-green", + "mode": "fixed" }, "mappings": [], "thresholds": { @@ -187,7 +188,7 @@ }, "gridPos": { "h": 9, - "w": 9, + "w": 10, "x": 14, "y": 0 }, @@ -221,6 +222,141 @@ ], "title": "Frame Count", "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "dark-green", + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 8, + "x": 0, + "y": 9 + }, + "id": 4, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "/^user$/", + "limit": 1, + "values": true + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"_raw\")\n |> filter(fn: (r) => r[\"_field\"] == \"user\")\n |> last()", + "refId": "A" + } + ], + "title": "Last Frame Received by", + "type": "stat" + }, + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "fieldConfig": { + "defaults": { + "color": { + "fixedColor": "dark-green", + "mode": "fixed" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "dateTimeAsIsoNoDateIfToday", + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 11, + "x": 8, + "y": 9 + }, + "id": 5, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "/^Time$/", + "limit": 1, + "values": true + }, + "showPercentChange": false, + "textMode": "auto", + "wideLayout": true + }, + "pluginVersion": "10.3.1", + "targets": [ + { + "datasource": { + "type": "influxdb", + "uid": "3ap6QYRVz" + }, + "query": "from(bucket: \"delfi_pq\")\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n |> filter(fn: (r) => r[\"_measurement\"] == \"_raw\")\n |> filter(fn: (r) => r[\"_field\"] == \"user\")\n |> last()", + "refId": "A" + } + ], + "title": "Last Frame Received on", + "type": "stat" } ], "refresh": "", @@ -234,9 +370,9 @@ "to": "2024-01-08T23:59:59.999Z" }, "timepicker": {}, - "timezone": "", + "timezone": "utc", "title": "Overview", - "uid": "f4c5128b-0826-4503-9848-b59ddb4cae00", - "version": 5, + "uid": "Delfi-PQ_Overview", + "version": 2, "weekStart": "" } diff --git a/src/home/templates/home/index.html b/src/home/templates/home/index.html index d023295a..c7b36b73 100644 --- a/src/home/templates/home/index.html +++ b/src/home/templates/home/index.html @@ -78,7 +78,7 @@
Delfi-C3

Launch:
   {% if delfi_c3_launch is not None %}{{ delfi_c3_launch|date:"M dS Y" }}{% else %}-{% endif %}

Last Reception:
   {% if delfi_c3_last_data is not None %}{{ delfi_c3_last_data|date:"M dS Y H:i:s" }} UTC{% else %}-{% endif %}

About - Dashboard + Dashboard @@ -107,7 +107,7 @@
Delfi-PQ

Launch:
   {% if delfi_pq_launch is not None %}{{ delfi_pq_launch|date:"M dS Y" }}{% else %}-{% endif %}

Last Reception:
   {% if delfi_pq_last_data is not None %}{{ delfi_pq_last_data|date:"M dS Y H:i:s" }} UTC{% else %}-{% endif %}

About - Dashboard + Dashboard From e0a0fbe5782b06fd58b793c84c4d02b80b723827 Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 11 May 2024 22:15:28 +0200 Subject: [PATCH 49/62] Addind microseconds to the frames tables --- src/transmission/templates/transmission/table.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/transmission/templates/transmission/table.html b/src/transmission/templates/transmission/table.html index 26801bb7..f8ed6001 100644 --- a/src/transmission/templates/transmission/table.html +++ b/src/transmission/templates/transmission/table.html @@ -1,4 +1,5 @@ {% load static %} +{% load humanize %} {% block title %}DelfiSpace - Frames{% endblock %} @@ -58,7 +59,7 @@

{{ table_name }} Frames

{% for frame in page_obj %} {{ frame.id }} - {{ frame.timestamp }} + {{ frame.timestamp|date:"Y-m-d H:i:s.u" }} {% if table_name == "Downlink" %} {{ frame.observer }} {% endif %} From 0ec7f815d6181c47cb5ca5e20689deb55cd240fc Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 11 May 2024 22:16:19 +0200 Subject: [PATCH 50/62] Ignore fields marked as to be ignored --- src/transmission/processing/XTCEParser.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/transmission/processing/XTCEParser.py b/src/transmission/processing/XTCEParser.py index c0e64bdd..58795a47 100644 --- a/src/transmission/processing/XTCEParser.py +++ b/src/transmission/processing/XTCEParser.py @@ -50,13 +50,12 @@ def processTMFrame(self, data): entries = model.getContentList() telemetry = {"frame": model.getName()} - #logger.debug("TMFrame entries: %s", entries) - # thriwn an error if the frame is found but empty + # throw an error if the frame is found but empty for entry in entries: val = entry.getValue() name = entry.getName() - if val: + if val and entry.getParameter().getAncillaryData("Ignore").isEmpty(): telemetry[name] = {"value": val.getCalibratedValue(), "status": self.isFieldValid(entry)} return telemetry From c9d53efbb46e69426766074b9c0056284116005d Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 11 May 2024 22:17:19 +0200 Subject: [PATCH 51/62] Fix pylint warnings --- .../management/commands/initbuckets.py | 2 +- src/transmission/processing/influxdb_api.py | 24 ++++--------------- src/transmission/processing/save_raw_data.py | 2 -- 3 files changed, 5 insertions(+), 23 deletions(-) diff --git a/src/transmission/management/commands/initbuckets.py b/src/transmission/management/commands/initbuckets.py index fbe4159f..5a981646 100644 --- a/src/transmission/management/commands/initbuckets.py +++ b/src/transmission/management/commands/initbuckets.py @@ -9,7 +9,7 @@ class Command(BaseCommand): """Django command class""" def handle(self, *args, **options): - """Initialize the database for each satellite, uplink and downlink""" + """Initialize the database for each satellite, uplink and downlink""" db = influxdb_api() diff --git a/src/transmission/processing/influxdb_api.py b/src/transmission/processing/influxdb_api.py index 50eee394..28eb1e68 100644 --- a/src/transmission/processing/influxdb_api.py +++ b/src/transmission/processing/influxdb_api.py @@ -4,13 +4,15 @@ from influxdb_client.client.write_api import SYNCHRONOUS from influxdb_client.rest import ApiException from influxdb_client.domain.bucket import Bucket -from django_logger import logger from django.conf import settings +from django_logger import logger RAW_MEASUREMENT = "_raw" DATETIME_FORMAT_STRING = "%Y-%m-%dT%H:%M:%S.%fZ" class influxdb_api: + """Class interfcing with InfluxDB""" + def __init__(self): self.url = settings.INFLUXDB['HOST'] + ":" + str(settings.INFLUXDB['PORT']) self.token = settings.INFLUXDB['TOKEN'] @@ -51,40 +53,22 @@ def init_database(self, satellites): try: orgs = self._get_organizations_api().find_organizations(org="downlink") except ApiException: - logger.info("Adding downlink") self._get_organizations_api().create_organization('downlink') - logger.info("Downlink added") try: orgs = self._get_organizations_api().find_organizations(org="uplink") except ApiException: - logger.info("Adding uplink") self._get_organizations_api().create_organization('uplink') - logger.info("Uplink added") for sat in satellites: try: - logger.info("Looking for " + sat + " in downlibnk") self._get_buckets_api().find_buckets(name=sat, org="downlink") except ApiException: - logger.info(sat + " downlink not found") - new_bucket = Bucket( - name=sat, - retention_rules=[], - org_id="downlink" - ) self._get_buckets_api().create_bucket(bucket_name=sat, org="downlink") - logger.info("bucket added") try: self._get_buckets_api().find_buckets(name=sat, org="uplink") - except ApiException: - logger.info(sat + " uplink not found") - new_bucket = Bucket( - name=sat, - retention_rules=[], - org_id="uplink" - ) + except ApiException: self._get_buckets_api().create_bucket(bucket_name=sat, org="uplink") def get_last_received_frame(self, satellite: str): diff --git a/src/transmission/processing/save_raw_data.py b/src/transmission/processing/save_raw_data.py index a8cefe06..3bd93568 100644 --- a/src/transmission/processing/save_raw_data.py +++ b/src/transmission/processing/save_raw_data.py @@ -5,8 +5,6 @@ from typing import Union import time from datetime import datetime, timezone -from django_logger import logger - from django.forms import ValidationError from django.core.exceptions import PermissionDenied from django.db import models From e991da7acb26728f01d6bc53af7a10184ab9996f Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Sat, 11 May 2024 22:17:44 +0200 Subject: [PATCH 52/62] Remove debug log call --- src/home/views.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/home/views.py b/src/home/views.py index b8710400..e20e001d 100644 --- a/src/home/views.py +++ b/src/home/views.py @@ -123,7 +123,6 @@ def _get_satellites_status(): db = influxdb_api() except : db = None - logger.info("before list " + str(db)) sats_status = {} for sat, info in SATELLITES.items(): sats_status[str(sat + "_status")] = info["status"] From 3e5e2ce311ce960b84ac0ea60b8302e82c4f755e Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Mon, 20 May 2024 00:05:23 +0200 Subject: [PATCH 53/62] Update crowdsec and pgadmin --- docker-compose-deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose-deploy.yml b/docker-compose-deploy.yml index 10182100..a7897306 100644 --- a/docker-compose-deploy.yml +++ b/docker-compose-deploy.yml @@ -51,7 +51,7 @@ services: pgadmin: container_name: pgadmin4_container - image: dpage/pgadmin4:8.5 + image: dpage/pgadmin4:8.6 restart: always environment: - PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL:-admin@admin.com} @@ -68,7 +68,7 @@ services: crowdsec: - image: crowdsecurity/crowdsec:v1.6.0-1 + image: crowdsecurity/crowdsec:v1.6.1-2 restart: always ports: - "8080:8080" From 2efb7f5fb4c5a7f4be6061685e8c89fbad66e0aa Mon Sep 17 00:00:00 2001 From: StefanoSperetta Date: Mon, 20 May 2024 00:05:58 +0200 Subject: [PATCH 54/62] Set the user and application as tags in the raw frames table --- src/transmission/processing/influxdb_api.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/transmission/processing/influxdb_api.py b/src/transmission/processing/influxdb_api.py index 28eb1e68..0b6ea125 100644 --- a/src/transmission/processing/influxdb_api.py +++ b/src/transmission/processing/influxdb_api.py @@ -78,8 +78,9 @@ def get_last_received_frame(self, satellite: str): query = f'''from(bucket: "{satellite}") |> range(start: 0) |> filter(fn: (r) => r["_measurement"] == "{RAW_MEASUREMENT}") - |> keep(columns: ["_time"]) - |> tail(n: 1) + |> filter(fn: (r) => r["_field"] == "processed") + |> group() + |> last() ''' ret = self._get_query_api().query(query=query, org="downlink") @@ -137,7 +138,7 @@ def save_raw_frame(self, satellite: str, link: str, timestamp: datetime, tlm: di db_fields = { "measurement": RAW_MEASUREMENT, "time": timestamp, - "tags": {}, + "tags": {"user": tlm.pop("user"), "application": tlm.pop("application")}, "fields": tlm } @@ -189,16 +190,19 @@ def update_raw_frame(self, satellite: str, link: str, timestamp: datetime, tlm: query = f'''from(bucket: "{satellite}") |> range(start: {time_range_start}, stop: {time_range_stop}) |> filter(fn: (r) => r._measurement == "{RAW_MEASUREMENT}") + |> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value") ''' # update frame only if already present - if len(self._get_query_api().query(query=query, org=link)) != 0: + frames = self._get_query_api().query(query=query, org=link) + if len(frames) != 0: + frame = frames[0].records[0] bucket = satellite db_fields = { "measurement": RAW_MEASUREMENT, "time": timestamp, - "tags": {}, + "tags": {"user": frame["user"], "application": frame["application"]}, "fields": tlm } From 56feef12de7e6df8fbb441f0cba0e088484bedf0 Mon Sep 17 00:00:00 2001 From: Stefano Speretta Date: Sat, 29 Jun 2024 16:35:57 +0200 Subject: [PATCH 55/62] Fixex copy-paste error in documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cd694200..924080ee 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ CROWDSEC_LAPI= 8. Generate a django keys with `python manage.py djecrety` and copy it to the .env file. -9. Create the InfluxDB buckets: `python src/manage.py initbuckets` +9. Create the InfluxDB buckets: `python manage.py initbuckets` Note: remove `--build` to skip building the container, will use the cached one (last build) From aa7f624dc8257ecedce5e547e1f52a76e65f6dc8 Mon Sep 17 00:00:00 2001 From: Stefano Speretta Date: Sat, 29 Jun 2024 16:36:40 +0200 Subject: [PATCH 56/62] Fixed copy-paste error in documentation --- docs/deployment_intructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/deployment_intructions.md b/docs/deployment_intructions.md index 5d9c1b6a..da22b847 100644 --- a/docs/deployment_intructions.md +++ b/docs/deployment_intructions.md @@ -110,7 +110,7 @@ CROWDSEC_LAPI= 8. Generate a django keys with `python manage.py djecrety` and copy it to the .env file. -9. Create the InfluxDB buckets: `python src/manage.py initbuckets` +9. Create the InfluxDB buckets: `python manage.py initbuckets` Note: remove `--build` to skip building the container, will use the cached one (last build) From 3da3c9e6c7831e72cdfbab87d55106247b732b21 Mon Sep 17 00:00:00 2001 From: Stefano Speretta Date: Sat, 29 Jun 2024 17:45:41 +0200 Subject: [PATCH 57/62] Added missing step to local setup guide --- README.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 924080ee..0374a525 100644 --- a/README.md +++ b/README.md @@ -21,22 +21,25 @@ 3. Install the requirements (one time instruction): `pip install -r requirements.txt` -4. Set up the database via docker or connect your own Postgres instance +4. Set up the database via docker `docker compose up db` 5. Run the migrations from the root folder: `python src/manage.py migrate` -6. Create the InfluxDB buckets: +6. Set up InfluxDB via docker +`docker compose up influxdb` + +7. Create the InfluxDB buckets: `python src/manage.py initbuckets` -7. Run the server from the root folder: +8. Run the server from the root folder: `python src/manage.py runserver` The server runs on http://127.0.0.1:8000/ -8. To run the tests: +9. To run the tests: `python src/manage.py test` -9. To run pylint: +10. To run pylint: `find src -name "*.py" | xargs pylint` ## Setup (Run via docker) From f6c9fcae6954763f838e7604ad300113c47616fd Mon Sep 17 00:00:00 2001 From: Stefano Speretta Date: Sat, 29 Jun 2024 17:46:57 +0200 Subject: [PATCH 58/62] Added missing step to local setup guide --- docs/deployment_intructions.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/docs/deployment_intructions.md b/docs/deployment_intructions.md index da22b847..f0bc21ca 100644 --- a/docs/deployment_intructions.md +++ b/docs/deployment_intructions.md @@ -24,22 +24,25 @@ nav_order: 5 3. Install the requirements (one time instruction): `pip install -r requirements.txt` -4. Set up the database via docker or connect your own Postgres instance +4. Set up the database via docker `docker compose up db` 5. Run the migrations from the root folder: `python src/manage.py migrate` -6. Create the InfluxDB buckets: +6. Set up InfluxDB via docker +`docker compose up influxdb` + +7. Create the InfluxDB buckets: `python src/manage.py initbuckets` -7. Run the server from the root folder: +8. Run the server from the root folder: `python src/manage.py runserver` The server runs on http://127.0.0.1:8000/ -8. To run the tests: +9. To run the tests: `python src/manage.py test` -9. To run pylint: +10. To run pylint: `find src -name "*.py" | xargs pylint` ## Setup (Run via docker) From 8570ad9155b66448ac03b4dce15b7184376fee83 Mon Sep 17 00:00:00 2001 From: Stefano Speretta Date: Sun, 7 Jul 2024 15:02:54 +0000 Subject: [PATCH 59/62] Do not create a Delfispace bucket anymore --- docker-compose.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 0ed4cf53..16c02e9a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -31,7 +31,6 @@ services: - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:-postgres} - POSTGRES_HOST=${POSTGRES_HOST:-db} - POSTGRES_PORT=${POSTGRES_PORT:-5432} - - INFLUXDB_V2_ORG=${INFLUXDB_V2_ORG:-DelfiSpace} - INFLUXDB_V2_TOKEN=${INFLUXDB_V2_TOKEN:-adminpwd} restart: always depends_on: @@ -55,8 +54,8 @@ services: - DOCKER_INFLUXDB_INIT_MODE=setup - DOCKER_INFLUXDB_INIT_USERNAME=${INFLUX_USERNAME:-admin} - DOCKER_INFLUXDB_INIT_PASSWORD=${INFLUX_PASSWORD:-adminpwd} - - DOCKER_INFLUXDB_INIT_ORG=${INFLUXDB_V2_ORG:-DelfiSpace} - - DOCKER_INFLUXDB_INIT_BUCKET=${INFLUX_BUCKET:-default} + - DOCKER_INFLUXDB_INIT_ORG=default + - DOCKER_INFLUXDB_INIT_BUCKET=default - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=${INFLUXDB_V2_TOKEN:-adminpwd} restart: always logging: From 5388f9ffc7de0e7c5ab797283a21aecdf970f555 Mon Sep 17 00:00:00 2001 From: Stefano Speretta Date: Sun, 7 Jul 2024 15:03:22 +0000 Subject: [PATCH 60/62] Update crowdsec to latest version --- docker-compose-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose-deploy.yml b/docker-compose-deploy.yml index 04d213d6..7749fd6a 100644 --- a/docker-compose-deploy.yml +++ b/docker-compose-deploy.yml @@ -68,7 +68,7 @@ services: crowdsec: - image: crowdsecurity/crowdsec:v1.6.0-1 + image: crowdsecurity/crowdsec:v1.6.2 restart: always ports: - "8080:8080" From fc88604d97d42337170242e35395808ef722493e Mon Sep 17 00:00:00 2001 From: Stefano Speretta Date: Wed, 17 Jul 2024 14:55:38 +0000 Subject: [PATCH 61/62] Fixing unit test username / usi swap --- src/members/test/test_views_templates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/members/test/test_views_templates.py b/src/members/test/test_views_templates.py index 53cda73c..0455531d 100644 --- a/src/members/test/test_views_templates.py +++ b/src/members/test/test_views_templates.py @@ -759,7 +759,7 @@ def test_telemetry_persistence_after_account_deletion(self): self.assertEqual(len(Uplink.objects.all()), 3) for frame in Downlink.objects.all(): - self.assertEqual(frame.observer, str(self.user.UUID)) + self.assertEqual(frame.observer, str(self.user.username)) for frame in Uplink.objects.all(): self.assertEqual(frame.operator, 'user') From 07114a2fcf1a6f8334025f57a6a1b79fbf2805e3 Mon Sep 17 00:00:00 2001 From: Stefano Speretta Date: Wed, 17 Jul 2024 14:58:10 +0000 Subject: [PATCH 62/62] Fixing unit test username / usi swap --- src/members/test/test_views_templates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/members/test/test_views_templates.py b/src/members/test/test_views_templates.py index 0455531d..b4832825 100644 --- a/src/members/test/test_views_templates.py +++ b/src/members/test/test_views_templates.py @@ -781,7 +781,7 @@ def test_telemetry_persistence_after_account_deletion(self): self.assertEqual(len(Uplink.objects.all()), 3) for frame in Downlink.objects.all(): - self.assertEqual(frame.observer, str(self.user.UUID)) + self.assertEqual(frame.observer, str(self.user.username)) for frame in Uplink.objects.all(): self.assertEqual(frame.operator, 'user')