From d93f7c7b0d37ae6d9b3329a72d5bf3192cff6581 Mon Sep 17 00:00:00 2001 From: "Adam.Dybbroe" Date: Mon, 29 Aug 2022 13:24:30 +0200 Subject: [PATCH 1/5] Add alarms posting Signed-off-by: Adam.Dybbroe --- activefires_pp/api_posting.py | 32 ++++++++++-- .../spatiotemporal_alarm_filtering.py | 17 +++++- .../test_spatiotemporal_alarm_filtering.py | 52 +++++++++++++++++-- 3 files changed, 93 insertions(+), 8 deletions(-) diff --git a/activefires_pp/api_posting.py b/activefires_pp/api_posting.py index a51532f..485ded8 100644 --- a/activefires_pp/api_posting.py +++ b/activefires_pp/api_posting.py @@ -1,11 +1,11 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# Copyright (c) 2022 Adam.Dybbroe +# Copyright (c) 2022 Adam Dybbroe # Author(s): -# Adam.Dybbroe +# Adam Dybbroe # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -23,7 +23,31 @@ """Post geojson formatted Alarms to a ReST-API """ +import logging +import requests -def post_alarm(geojson_data, url): +# Exempel på post: +# {"type": "Feature", "geometry": {"type": "Point", "coordinates": [15.860621, 61.403141]}, +# "properties": {"power": 3.09576535, "tb": 328.81933594, "confidence": 8, +# "observation_time": "2022-08-02T03:27:43.850000", +# "platform_name": "NOAA-20", "related_detection": false}} + +LOG = logging.getLogger(__name__) + + +def post_alarm(geojson_data, api_url, xauth=None): """Post an Alarm to a rest-api stored as a geojson file.""" - pass + + if xauth is None: + headers = {"Content-Type": "application/json; charset=utf-8"} + else: + headers = {"Content-Type": "application/json; charset=utf-8", + "X-Auth-Token": xauth} + + response = requests.post(api_url, + headers=headers, + json=geojson_data) + + LOG.info("Alarm posted: Response = %s", str(response)) + LOG.debug("Status code = %d", response.status_code) + return response.ok diff --git a/activefires_pp/spatiotemporal_alarm_filtering.py b/activefires_pp/spatiotemporal_alarm_filtering.py index 3b4a46b..62c46fb 100644 --- a/activefires_pp/spatiotemporal_alarm_filtering.py +++ b/activefires_pp/spatiotemporal_alarm_filtering.py @@ -36,6 +36,7 @@ """ +import os import logging import signal from queue import Empty @@ -84,6 +85,10 @@ def __init__(self, configfile): self.sos_alarms_file_pattern = self.options['geojson_file_pattern_alarms'] self.restapi_url = self.options['restapi_url'] + self.restapi_xauth = get_xauth_environment_variable() + if self.restapi_xauth is None: + raise OSError("Environment variable XAUTH_SMHI_FIREALARMS_REST_API not set!") + self.fire_alarms_dir = Path(self.options['fire_alarms_dir']) self.listener = None @@ -180,7 +185,12 @@ def send_alarms(self, geojson_alarms, msg): # 1) Create the filename # 2) Wite to a file output_filename = store_geojson_alarm(self.fire_alarms_dir, p__, idx, alarm) - post_alarm(alarm, self.restapi_url) + status = post_alarm(alarm, self.restapi_url, self.restapi_xauth) + if status: + LOG.info('Alarm sent - status OK') + else: + LOG.error('Failed sending alarm!') + output_message = _create_output_message(msg, self.output_topic, alarm, output_filename) if output_message: LOG.debug("Sending message: %s", str(output_message)) @@ -203,6 +213,11 @@ def close(self): LOG.exception("Couldn't stop publisher.") +def get_xauth_environment_variable(): + """Get the environment variable for the X-Authentication-token needed for posting to the API.""" + return os.environ.get('XAUTH_SMHI_FIREALARMS_REST_API') + + def dump_collection(idx, features): """Dump the list of features as a Geojson Feature Collection.""" tmpdir = Path(DIR_SPATIAL_FILTER) diff --git a/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py b/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py index f4cdafb..39f6eeb 100644 --- a/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py +++ b/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py @@ -24,8 +24,10 @@ """ import pytest +import logging from unittest.mock import patch import pathlib +from geojson import FeatureCollection from geojson import dump import json from activefires_pp.geojson_utils import read_geojson_data @@ -35,6 +37,7 @@ from activefires_pp.spatiotemporal_alarm_filtering import create_one_detection_from_collection from activefires_pp.spatiotemporal_alarm_filtering import create_single_point_alarms_from_collections from activefires_pp.spatiotemporal_alarm_filtering import AlarmFilterRunner +from activefires_pp.api_posting import post_alarm TEST_GEOJSON_FILE_CONTENT = """{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [23.562864, 67.341919]}, "properties": {"power": 1.62920368, "tb": 325.2354126, "confidence": 8, "observation_time": "2022-06-29T14:01:08.850000", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [23.56245, 67.347328]}, "properties": {"power": 3.40044808, "tb": 329.46963501, "confidence": 8, "observation_time": "2022-06-29T14:01:08.850000", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [23.555086, 67.343231]}, "properties": {"power": 6.81757641, "tb": 334.62347412, "confidence": 8, "observation_time": "2022-06-29T14:01:08.850000", "platform_name": "NOAA-20"}}]}""" @@ -225,7 +228,6 @@ def test_create_alarms_from_fire_detections(fake_past_detections_dir): # Default distance threshold but disregarding past alarms: alarms = create_alarms_from_fire_detections(json_test_data, fake_past_detections_dir, pattern, 1.2, 0.0) - assert len(alarms) == 3 assert alarms[0]['features']['geometry']['coordinates'] == [16.247334, 57.172443] assert alarms[0]['features']['properties']['power'] == 5.85325146 @@ -282,7 +284,8 @@ def test_create_alarms_from_fire_detections(fake_past_detections_dir): alarms = create_alarms_from_fire_detections(json_test_data, fake_past_detections_dir, pattern, 1.2, 16.0) - assert len(alarms) == 1 + + assert len(alarms) == 0 assert alarms[0]['features']['geometry']['coordinates'] == [16.249069, 57.156235] assert alarms[0]['features']['properties']['power'] == 2.23312426 assert alarms[0]['features']['properties']['related_detection'] is False @@ -292,6 +295,7 @@ def test_create_alarms_from_fire_detections(fake_past_detections_dir): alarms = create_alarms_from_fire_detections(json_test_data, fake_past_detections_dir, pattern, 1.2) + assert len(alarms) == 1 assert alarms[0]['features']['geometry']['coordinates'] == [16.249069, 57.156235] assert alarms[0]['features']['properties']['power'] == 2.23312426 @@ -301,11 +305,13 @@ def test_create_alarms_from_fire_detections(fake_past_detections_dir): assert alarms[0]['features']['properties']['observation_time'] == '2021-06-19T02:58:45.700000+02:00' +@patch('activefires_pp.spatiotemporal_alarm_filtering.get_xauth_environment_variable') @patch('activefires_pp.spatiotemporal_alarm_filtering.read_config') @patch('activefires_pp.spatiotemporal_alarm_filtering.AlarmFilterRunner._setup_and_start_communication') -def test_alarm_filter_runner_init(setup_comm, get_config): +def test_alarm_filter_runner_init(setup_comm, get_config, get_xauth): """Test initialize the AlarmFilterRunner class.""" get_config.return_value = CONFIG_EXAMPLE + get_xauth.return_value = 'some-token' myconfigfile = "/my/config/file/path" @@ -328,6 +334,23 @@ def test_alarm_filter_runner_init(setup_comm, get_config): 'restapi_url': 'https://xxx.smhi.se:xxxx'} +@patch('activefires_pp.spatiotemporal_alarm_filtering.get_xauth_environment_variable') +@patch('activefires_pp.spatiotemporal_alarm_filtering.read_config') +@patch('activefires_pp.spatiotemporal_alarm_filtering.AlarmFilterRunner._setup_and_start_communication') +def test_alarm_filter_runner_init_no_env(setup_comm, get_config, get_xauth): + """Test initialize the AlarmFilterRunner class.""" + get_config.return_value = CONFIG_EXAMPLE + get_xauth.return_value = None + + myconfigfile = "/my/config/file/path" + + with pytest.raises(OSError) as exec_info: + _ = AlarmFilterRunner(myconfigfile) + + expected = "Environment variable XAUTH_SMHI_FIREALARMS_REST_API not set!" + assert str(exec_info.value) == expected + + @patch('activefires_pp.spatiotemporal_alarm_filtering.read_config') @patch('activefires_pp.spatiotemporal_alarm_filtering.AlarmFilterRunner._setup_and_start_communication') @patch('activefires_pp.spatiotemporal_alarm_filtering.get_filename_from_posttroll_message') @@ -400,3 +423,26 @@ def test_alarm_filter_runner_call_spatio_temporal_alarm_filtering_no_alarms(crea dummy_msg = None result = alarm_runner.spatio_temporal_alarm_filtering(dummy_msg) assert result is None + + +def test_send_alarm_post_ok(fake_past_detections_dir): + """Test send alarm.""" + + alarm = json.loads(PAST_ALARMS_MONSTERAS3) + restapi_url = "https://httpbin.org/post" + + retv = post_alarm(alarm, restapi_url) + assert retv is True + + +def test_send_alarm_post_log_messages(caplog, fake_past_detections_dir): + """Test send alarm.""" + + alarm = json.loads(PAST_ALARMS_MONSTERAS3) + restapi_url = "https://httpbin.org/post" + + with caplog.at_level(logging.INFO): + retv = post_alarm(alarm, restapi_url) + + log_output = "Alarm posted: Response = " + assert log_output in caplog.text From 1cbf3ee844bdcd941f2da77ca0d56cce26e43f35 Mon Sep 17 00:00:00 2001 From: "Adam.Dybbroe" Date: Mon, 29 Aug 2022 13:55:45 +0200 Subject: [PATCH 2/5] Fix tests after adding environment variable for X-authentication Signed-off-by: Adam.Dybbroe --- .../test_spatiotemporal_alarm_filtering.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py b/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py index 39f6eeb..3a56342 100644 --- a/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py +++ b/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py @@ -285,7 +285,7 @@ def test_create_alarms_from_fire_detections(fake_past_detections_dir): alarms = create_alarms_from_fire_detections(json_test_data, fake_past_detections_dir, pattern, 1.2, 16.0) - assert len(alarms) == 0 + assert len(alarms) == 1 assert alarms[0]['features']['geometry']['coordinates'] == [16.249069, 57.156235] assert alarms[0]['features']['properties']['power'] == 2.23312426 assert alarms[0]['features']['properties']['related_detection'] is False @@ -351,6 +351,7 @@ def test_alarm_filter_runner_init_no_env(setup_comm, get_config, get_xauth): assert str(exec_info.value) == expected +@patch('activefires_pp.spatiotemporal_alarm_filtering.get_xauth_environment_variable') @patch('activefires_pp.spatiotemporal_alarm_filtering.read_config') @patch('activefires_pp.spatiotemporal_alarm_filtering.AlarmFilterRunner._setup_and_start_communication') @patch('activefires_pp.spatiotemporal_alarm_filtering.get_filename_from_posttroll_message') @@ -358,8 +359,10 @@ def test_alarm_filter_runner_init_no_env(setup_comm, get_config, get_xauth): @patch('activefires_pp.spatiotemporal_alarm_filtering.create_alarms_from_fire_detections') @patch('activefires_pp.spatiotemporal_alarm_filtering.AlarmFilterRunner.send_alarms') def test_alarm_filter_runner_call_spatio_temporal_alarm_filtering_has_alarms(send_alarms, create_alarms, read_geojson, - get_filename_from_pmsg, setup_comm, get_config): + get_filename_from_pmsg, setup_comm, + get_config, get_xauth): """Test run the spatio_temporal_alarm_filtering method of the AlarmFilterRunner class.""" + get_xauth.return_value = 'some-token' get_config.return_value = CONFIG_EXAMPLE json_test_data = json.loads(TEST_MONSTERAS_FIRST_COLLECTION) read_geojson.return_value = json_test_data @@ -383,13 +386,16 @@ def test_alarm_filter_runner_call_spatio_temporal_alarm_filtering_has_alarms(sen assert result[0] == alarm +@patch('activefires_pp.spatiotemporal_alarm_filtering.get_xauth_environment_variable') @patch('activefires_pp.spatiotemporal_alarm_filtering.read_config') @patch('activefires_pp.spatiotemporal_alarm_filtering.AlarmFilterRunner._setup_and_start_communication') @patch('activefires_pp.spatiotemporal_alarm_filtering.get_filename_from_posttroll_message') @patch('activefires_pp.spatiotemporal_alarm_filtering.read_geojson_data') def test_alarm_filter_runner_call_spatio_temporal_alarm_filtering_no_firedata(read_geojson, - get_filename_from_pmsg, setup_comm, get_config): + get_filename_from_pmsg, setup_comm, + get_config, get_xauth): """Test run the spatio_temporal_alarm_filtering method of the AlarmFilterRunner class - no fires.""" + get_xauth.return_value = 'some-token' get_config.return_value = CONFIG_EXAMPLE read_geojson.return_value = None @@ -402,14 +408,17 @@ def test_alarm_filter_runner_call_spatio_temporal_alarm_filtering_no_firedata(re assert result is None +@patch('activefires_pp.spatiotemporal_alarm_filtering.get_xauth_environment_variable') @patch('activefires_pp.spatiotemporal_alarm_filtering.read_config') @patch('activefires_pp.spatiotemporal_alarm_filtering.AlarmFilterRunner._setup_and_start_communication') @patch('activefires_pp.spatiotemporal_alarm_filtering.get_filename_from_posttroll_message') @patch('activefires_pp.spatiotemporal_alarm_filtering.read_geojson_data') @patch('activefires_pp.spatiotemporal_alarm_filtering.create_alarms_from_fire_detections') def test_alarm_filter_runner_call_spatio_temporal_alarm_filtering_no_alarms(create_alarms, read_geojson, - get_filename_from_pmsg, setup_comm, get_config): + get_filename_from_pmsg, setup_comm, + get_config, get_xauth): """Test run the spatio_temporal_alarm_filtering method of the AlarmFilterRunner class - no alarms.""" + get_xauth.return_value = 'some-token' get_config.return_value = CONFIG_EXAMPLE json_test_data = json.loads(TEST_MONSTERAS_FIRST_COLLECTION) read_geojson.return_value = json_test_data From 9f34886cd82b77cffd06ce882ef32f5fc14f2453 Mon Sep 17 00:00:00 2001 From: "Adam.Dybbroe" Date: Mon, 29 Aug 2022 14:20:22 +0200 Subject: [PATCH 3/5] Fix cut'n'paste error Signed-off-by: Adam.Dybbroe --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 4c30037..d288490 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,6 +2,6 @@ - [ ] Closes #xxxx - [ ] Tests added - - [ ] Tests passed: Passes ``pytest pyspectral`` + - [ ] Tests passed: Passes ``pytest`` - [ ] Passes ``flake8`` - [ ] Fully documented From 5f0c51c5bb6ee301b295f4f2b7101bd3cf2cab06 Mon Sep 17 00:00:00 2001 From: "Adam.Dybbroe" Date: Mon, 29 Aug 2022 15:41:22 +0200 Subject: [PATCH 4/5] Bugfix payload data in alarm posting, and fix authentication header type Signed-off-by: Adam.Dybbroe --- activefires_pp/api_posting.py | 6 +- .../spatiotemporal_alarm_filtering.py | 9 +- .../test_spatiotemporal_alarm_filtering.py | 206 +++++++++++++++--- 3 files changed, 182 insertions(+), 39 deletions(-) diff --git a/activefires_pp/api_posting.py b/activefires_pp/api_posting.py index 485ded8..71cdc89 100644 --- a/activefires_pp/api_posting.py +++ b/activefires_pp/api_posting.py @@ -20,8 +20,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -"""Post geojson formatted Alarms to a ReST-API -""" +"""Post geojson formatted Alarms to a ReST-API.""" import logging import requests @@ -37,12 +36,11 @@ def post_alarm(geojson_data, api_url, xauth=None): """Post an Alarm to a rest-api stored as a geojson file.""" - if xauth is None: headers = {"Content-Type": "application/json; charset=utf-8"} else: headers = {"Content-Type": "application/json; charset=utf-8", - "X-Auth-Token": xauth} + "x-auth-satellite-alarm": xauth} response = requests.post(api_url, headers=headers, diff --git a/activefires_pp/spatiotemporal_alarm_filtering.py b/activefires_pp/spatiotemporal_alarm_filtering.py index 14831a0..89f0970 100644 --- a/activefires_pp/spatiotemporal_alarm_filtering.py +++ b/activefires_pp/spatiotemporal_alarm_filtering.py @@ -107,7 +107,6 @@ def _setup_and_start_communication(self): def _set_options_from_config(self, config): """From the configuration on disk set the option dictionary with all metadata for real-time processing.""" - for item in config: self.options[item] = config[item] @@ -185,11 +184,13 @@ def send_alarms(self, geojson_alarms, msg): # 1) Create the filename # 2) Wite to a file output_filename = store_geojson_alarm(self.fire_alarms_dir, p__, idx, alarm) - status = post_alarm(alarm, self.restapi_url, self.restapi_xauth) + status = post_alarm(alarm['features'], + self.restapi_url, self.restapi_xauth) if status: LOG.info('Alarm sent - status OK') else: LOG.error('Failed sending alarm!') + LOG.debug('Data: %s', str(alarm['features'])) output_message = _create_output_message(msg, self.output_topic, alarm, output_filename) LOG.debug("Sending message: %s", str(output_message)) @@ -234,7 +235,7 @@ def create_alarms_from_fire_detections(fire_data, past_detections_dir, sos_alarm # detections in smaller parts, and create potential alarms: alarms_list = [] - for idx, key in enumerate(gathered_fires): + for key in gathered_fires: LOG.debug("Key: %s" % key) fire_alarms = get_single_point_fires_as_collections(gathered_fires[key], long_fires_threshold) @@ -270,7 +271,6 @@ def find_neighbours(feature, other_features, thr_dist=0.8): def gather_neighbours_to_new_collection(start_id, features, feature_collections, thr_dist=None): """Go through all features and gather into groups of neighbouring detections.""" - first_point = features[start_id] features.pop(start_id) neighbour_ids = find_neighbours(first_point, features) @@ -321,7 +321,6 @@ def join_fire_detections(gdata): def split_large_fire_clusters(features, km_threshold): """Take a list of fire detection features and split in smaller clusters/chains.""" - num_features = len(features) LOG.debug("Split large fire clusters - Number of features: %d" % num_features) features = dict(zip(range(num_features), features)) diff --git a/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py b/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py index 3a56342..10549e2 100644 --- a/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py +++ b/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py @@ -20,15 +20,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -"""Testing the spatio-temporal alarm filtering -""" +"""Testing the spatio-temporal alarm filtering.""" import pytest import logging from unittest.mock import patch import pathlib -from geojson import FeatureCollection -from geojson import dump import json from activefires_pp.geojson_utils import read_geojson_data from activefires_pp.spatiotemporal_alarm_filtering import create_alarms_from_fire_detections @@ -40,42 +37,187 @@ from activefires_pp.api_posting import post_alarm -TEST_GEOJSON_FILE_CONTENT = """{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [23.562864, 67.341919]}, "properties": {"power": 1.62920368, "tb": 325.2354126, "confidence": 8, "observation_time": "2022-06-29T14:01:08.850000", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [23.56245, 67.347328]}, "properties": {"power": 3.40044808, "tb": 329.46963501, "confidence": 8, "observation_time": "2022-06-29T14:01:08.850000", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [23.555086, 67.343231]}, "properties": {"power": 6.81757641, "tb": 334.62347412, "confidence": 8, "observation_time": "2022-06-29T14:01:08.850000", "platform_name": "NOAA-20"}}]}""" +TEST_GEOJSON_FILE_CONTENT = """{"type": "FeatureCollection", "features": +[{"type": "Feature", "geometry": {"type": "Point", "coordinates": [23.562864, 67.341919]}, +"properties": {"power": 1.62920368, "tb": 325.2354126, "confidence": 8, +"observation_time": "2022-06-29T14:01:08.850000", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [23.56245, 67.347328]}, +"properties": {"power": 3.40044808, "tb": 329.46963501, "confidence": 8, +"observation_time": "2022-06-29T14:01:08.850000", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [23.555086, 67.343231]}, +"properties": {"power": 6.81757641, "tb": 334.62347412, "confidence": 8, +"observation_time": "2022-06-29T14:01:08.850000", "platform_name": "NOAA-20"}}]}""" # afimg_20220629_110913.geojson -TEST_GEOJSON_FILE_CONTENT2 = """{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [20.629259, 65.48558]}, "properties": {"power": 21.38915062, "tb": 343.66696167, "confidence": 8, "observation_time": "2022-06-29T13:09:55.350000", "platform_name": "Suomi-NPP"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [20.627005, 65.489014]}, "properties": {"power": 26.42259789, "tb": 346.634552, "confidence": 8, "observation_time": "2022-06-29T13:09:55.350000", "platform_name": "Suomi-NPP"}}]}""" +TEST_GEOJSON_FILE_CONTENT2 = """{"type": "FeatureCollection", "features": +[{"type": "Feature", "geometry": {"type": "Point", "coordinates": [20.629259, 65.48558]}, +"properties": {"power": 21.38915062, "tb": 343.66696167, "confidence": 8, +"observation_time": "2022-06-29T13:09:55.350000", "platform_name": "Suomi-NPP"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [20.627005, 65.489014]}, +"properties": {"power": 26.42259789, "tb": 346.634552, "confidence": 8, +"observation_time": "2022-06-29T13:09:55.350000", "platform_name": "Suomi-NPP"}}]}""" # afimg_20220629_110748.geojson -TEST_GEOJSON_FILE_CONTENT3 = """{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [15.262635, 59.30434]}, "properties": {"power": 4.96109343, "tb": 337.80944824, "confidence": 8, "observation_time": "2022-06-29T13:08:30.150000", "platform_name": "Suomi-NPP"}}]}""" +TEST_GEOJSON_FILE_CONTENT3 = """{"type": "FeatureCollection", "features": +[{"type": "Feature", "geometry": {"type": "Point", "coordinates": [15.262635, 59.30434]}, +"properties": {"power": 4.96109343, "tb": 337.80944824, "confidence": 8, +"observation_time": "2022-06-29T13:08:30.150000", "platform_name": "Suomi-NPP"}}]}""" # afimg_20220629_101926.geojson -TEST_GEOJSON_FILE_CONTENT4 = """{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [20.659672, 65.496849]}, "properties": {"power": 4.94186735, "tb": 334.15759277, "confidence": 8, "observation_time": "2022-06-29T12:20:08.800000", "platform_name": "NOAA-20"}}]}""" +TEST_GEOJSON_FILE_CONTENT4 = """{"type": "FeatureCollection", "features": +[{"type": "Feature", "geometry": {"type": "Point", "coordinates": [20.659672, 65.496849]}, +"properties": {"power": 4.94186735, "tb": 334.15759277, "confidence": 8, +"observation_time": "2022-06-29T12:20:08.800000", "platform_name": "NOAA-20"}}]}""" # afimg_20220629_092938.geojson -TEST_GEOJSON_FILE_CONTENT5 = """{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [20.657578, 65.493927]}, "properties": {"power": 9.46942616, "tb": 341.33267212, "confidence": 8, "observation_time": "2022-06-29T11:30:20.950000", "platform_name": "Suomi-NPP"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [20.650656, 65.497543]}, "properties": {"power": 9.46942616, "tb": 348.74557495, "confidence": 8, "observation_time": "2022-06-29T11:30:20.950000", "platform_name": "Suomi-NPP"}}]}""" +TEST_GEOJSON_FILE_CONTENT5 = """{"type": "FeatureCollection", "features": +[{"type": "Feature", "geometry": {"type": "Point", "coordinates": [20.657578, 65.493927]}, +"properties": {"power": 9.46942616, "tb": 341.33267212, "confidence": 8, +"observation_time": "2022-06-29T11:30:20.950000", "platform_name": "Suomi-NPP"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [20.650656, 65.497543]}, +"properties": {"power": 9.46942616, "tb": 348.74557495, "confidence": 8, +"observation_time": "2022-06-29T11:30:20.950000", "platform_name": "Suomi-NPP"}}]}""" # AFIMG_NOAA-20_20210619_005803_sweden.geojson -TEST_GEOJSON_FILE_CONTENT_MONSTERAS = """{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.240452, 57.17329]}, "properties": {"power": 4.19946575, "tb": 336.38024902, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.247334, 57.172443]}, "properties": {"power": 5.85325146, "tb": 339.84768677, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.242519, 57.17498]}, "properties": {"power": 3.34151864, "tb": 316.57772827, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.249384, 57.174122]}, "properties": {"power": 3.34151864, "tb": 310.37808228, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.241102, 57.171574]}, "properties": {"power": 3.34151864, "tb": 339.86465454, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.247967, 57.170712]}, "properties": {"power": 3.34151864, "tb": 335.95074463, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.246538, 57.167309]}, "properties": {"power": 3.10640526, "tb": 337.62503052, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.239674, 57.168167]}, "properties": {"power": 3.10640526, "tb": 305.36495972, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.245104, 57.163902]}, "properties": {"power": 3.10640526, "tb": 336.21279907, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.251965, 57.16304]}, "properties": {"power": 2.40693879, "tb": 306.66555786, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.250517, 57.159637]}, "properties": {"power": 2.23312426, "tb": 325.92211914, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.24366, 57.160496]}, "properties": {"power": 1.51176202, "tb": 317.16009521, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.242212, 57.157097]}, "properties": {"power": 1.51176202, "tb": 303.77804565, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.249069, 57.156235]}, "properties": {"power": 2.23312426, "tb": 310.37322998, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}]}""" - -TEST_MONSTERAS_FIRST_COLLECTION = """{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.240452, 57.17329]}, "properties": {"power": 4.19946575, "tb": 336.38024902, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.247334, 57.172443]}, "properties": {"power": 5.85325146, "tb": 339.84768677, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.242519, 57.17498]}, "properties": {"power": 3.34151864, "tb": 316.57772827, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.249384, 57.174122]}, "properties": {"power": 3.34151864, "tb": 310.37808228, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.241102, 57.171574]}, "properties": {"power": 3.34151864, "tb": 339.86465454, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.247967, 57.170712]}, "properties": {"power": 3.34151864, "tb": 335.95074463, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.246538, 57.167309]}, "properties": {"power": 3.10640526, "tb": 337.62503052, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.239674, 57.168167]}, "properties": {"power": 3.10640526, "tb": 305.36495972, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}]}""" - -TEST_MONSTERAS_SECOND_COLLECTION = """{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.245104, 57.163902]}, "properties": {"power": 3.10640526, "tb": 336.21279907, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.251965, 57.16304]}, "properties": {"power": 2.40693879, "tb": 306.66555786, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.250517, 57.159637]}, "properties": {"power": 2.23312426, "tb": 325.92211914, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.24366, 57.160496]}, "properties": {"power": 1.51176202, "tb": 317.16009521, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.242212, 57.157097]}, "properties": {"power": 1.51176202, "tb": 303.77804565, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}]}""" - -TEST_MONSTERAS_THIRD_COLLECTION = """{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.249069, 57.156235]}, "properties": {"power": 2.23312426, "tb": 310.37322998, "confidence": 8, "observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}]}""" +TEST_GEOJSON_FILE_CONTENT_MONSTERAS = """{"type": "FeatureCollection", "features": +[{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.240452, 57.17329]}, +"properties": {"power": 4.19946575, "tb": 336.38024902, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.247334, 57.172443]}, +"properties": {"power": 5.85325146, "tb": 339.84768677, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.242519, 57.17498]}, +"properties": {"power": 3.34151864, "tb": 316.57772827, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.249384, 57.174122]}, +"properties": {"power": 3.34151864, "tb": 310.37808228, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.241102, 57.171574]}, +"properties": {"power": 3.34151864, "tb": 339.86465454, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.247967, 57.170712]}, +"properties": {"power": 3.34151864, "tb": 335.95074463, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.246538, 57.167309]}, +"properties": {"power": 3.10640526, "tb": 337.62503052, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.239674, 57.168167]}, +"properties": {"power": 3.10640526, "tb": 305.36495972, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.245104, 57.163902]}, +"properties": {"power": 3.10640526, "tb": 336.21279907, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.251965, 57.16304]}, +"properties": {"power": 2.40693879, "tb": 306.66555786, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.250517, 57.159637]}, +"properties": {"power": 2.23312426, "tb": 325.92211914, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.24366, 57.160496]}, +"properties": {"power": 1.51176202, "tb": 317.16009521, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.242212, 57.157097]}, +"properties": {"power": 1.51176202, "tb": 303.77804565, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.249069, 57.156235]}, +"properties": {"power": 2.23312426, "tb": 310.37322998, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}]}""" + +TEST_MONSTERAS_FIRST_COLLECTION = """{"type": "FeatureCollection", "features": +[{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.240452, 57.17329]}, +"properties": {"power": 4.19946575, "tb": 336.38024902, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.247334, 57.172443]}, +"properties": {"power": 5.85325146, "tb": 339.84768677, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.242519, 57.17498]}, +"properties": {"power": 3.34151864, "tb": 316.57772827, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.249384, 57.174122]}, +"properties": {"power": 3.34151864, "tb": 310.37808228, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.241102, 57.171574]}, +"properties": {"power": 3.34151864, "tb": 339.86465454, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.247967, 57.170712]}, +"properties": {"power": 3.34151864, "tb": 335.95074463, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.246538, 57.167309]}, +"properties": {"power": 3.10640526, "tb": 337.62503052, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.239674, 57.168167]}, +"properties": {"power": 3.10640526, "tb": 305.36495972, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}]}""" + +TEST_MONSTERAS_SECOND_COLLECTION = """{"type": "FeatureCollection", "features": +[{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.245104, 57.163902]}, +"properties": {"power": 3.10640526, "tb": 336.21279907, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.251965, 57.16304]}, +"properties": {"power": 2.40693879, "tb": 306.66555786, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.250517, 57.159637]}, +"properties": {"power": 2.23312426, "tb": 325.92211914, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.24366, 57.160496]}, +"properties": {"power": 1.51176202, "tb": 317.16009521, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.242212, 57.157097]}, +"properties": {"power": 1.51176202, "tb": 303.77804565, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}]}""" + +TEST_MONSTERAS_THIRD_COLLECTION = """{"type": "FeatureCollection", "features": +[{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.249069, 57.156235]}, +"properties": {"power": 2.23312426, "tb": 310.37322998, "confidence": 8, +"observation_time": "2021-06-19T02:58:45.700000+02:00", "platform_name": "NOAA-20"}}]}""" # AFIMG_Suomi-NPP_20210619_000651_sweden.geojson -TEST_MONSTERAS_PREVIOUS1_COLLECTION = """{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.246222, 57.175987]}, "properties": {"power": 1.83814871, "tb": 302.3949585, "confidence": 8, "observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.245924, 57.17054]}, "properties": {"power": 1.83814871, "tb": 338.78729248, "confidence": 8, "observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.239649, 57.17067]}, "properties": {"power": 1.83814871, "tb": 301.75921631, "confidence": 8, "observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.245516, 57.1651]}, "properties": {"power": 2.94999027, "tb": 324.5098877, "confidence": 8, "observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.251759, 57.164974]}, "properties": {"power": 1.55109835, "tb": 308.91491699, "confidence": 8, "observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.245028, 57.15966]}, "properties": {"power": 2.94999027, "tb": 313.83581543, "confidence": 8, "observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}, {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.251282, 57.159531]}, "properties": {"power": 1.55109835, "tb": 310.77600098, "confidence": 8, "observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}]}""" +TEST_MONSTERAS_PREVIOUS1_COLLECTION = """{"type": "FeatureCollection", "features": +[{"type": "Feature", +"geometry": {"type": "Point", "coordinates": [16.246222, 57.175987]}, +"properties": {"power": 1.83814871, "tb": 302.3949585, "confidence": 8, +"observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.245924, 57.17054]}, +"properties": {"power": 1.83814871, "tb": 338.78729248, "confidence": 8, +"observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.239649, 57.17067]}, +"properties": {"power": 1.83814871, "tb": 301.75921631, "confidence": 8, +"observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.245516, 57.1651]}, +"properties": {"power": 2.94999027, "tb": 324.5098877, "confidence": 8, +"observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.251759, 57.164974]}, +"properties": {"power": 1.55109835, "tb": 308.91491699, "confidence": 8, +"observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.245028, 57.15966]}, +"properties": {"power": 2.94999027, "tb": 313.83581543, "confidence": 8, +"observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}, +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.251282, 57.159531]}, +"properties": {"power": 1.55109835, "tb": 310.77600098, "confidence": 8, +"observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP"}}]}""" # AFIMG_NOAA-20_20210618_124819_sweden.geojson -TEST_MONSTERAS_PREVIOUS2_COLLECTION = """{"type": "FeatureCollection", "features": [{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.252192, 57.15242]}, "properties": {"power": 2.87395763, "tb": 330.10293579, "confidence": 8, "observation_time": "2021-06-18T14:49:01.750000+02:00", "platform_name": "NOAA-20"}}]}""" +TEST_MONSTERAS_PREVIOUS2_COLLECTION = """{"type": "FeatureCollection", "features": +[{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.252192, 57.15242]}, +"properties": {"power": 2.87395763, "tb": 330.10293579, "confidence": 8, +"observation_time": "2021-06-18T14:49:01.750000+02:00", "platform_name": "NOAA-20"}}]}""" # Past alarms: -PAST_ALARMS_MONSTERAS1 = """{"type": "FeatureCollection", "features": {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.246222, 57.175987]}, "properties": {"power": 1.83814871, "tb": 302.3949585, "confidence": 8, "observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP", "related_detection": true}}}""" +PAST_ALARMS_MONSTERAS1 = """{"type": "FeatureCollection", "features": +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.246222, 57.175987]}, +"properties": {"power": 1.83814871, "tb": 302.3949585, "confidence": 8, +"observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP", "related_detection": true}}}""" -PAST_ALARMS_MONSTERAS2 = """{"type": "FeatureCollection", "features": {"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.245516, 57.1651]}, "properties": {"power": 2.94999027, "tb": 324.5098877, "confidence": 8, "observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP", "related_detection": true}}}""" +PAST_ALARMS_MONSTERAS2 = """{"type": "FeatureCollection", "features": +{"type": "Feature", "geometry": {"type": "Point", "coordinates": [16.245516, 57.1651]}, +"properties": {"power": 2.94999027, "tb": 324.5098877, "confidence": 8, +"observation_time": "2021-06-19T02:07:33.050000+02:00", "platform_name": "Suomi-NPP", "related_detection": true}}}""" -PAST_ALARMS_MONSTERAS3 = """{"features": {"geometry": {"coordinates": [16.252192, 57.15242], "type": "Point"}, "properties": {"confidence": 8, "observation_time": "2021-06-18T14:49:01.750000+02:00", "platform_name": "NOAA-20", "related_detection": false, "power": 2.87395763, "tb": 330.10293579}, "type": "Feature"}, "type": "FeatureCollection"}""" +PAST_ALARMS_MONSTERAS3 = """{"features": {"geometry": {"coordinates": [16.252192, 57.15242], "type": "Point"}, +"properties": {"confidence": 8, "observation_time": "2021-06-18T14:49:01.750000+02:00", +"platform_name": "NOAA-20", "related_detection": false, "power": 2.87395763, "tb": 330.10293579}, +"type": "Feature"}, "type": "FeatureCollection"}""" CONFIG_EXAMPLE = {'subscribe_topics': '/VIIRS/L2/Fires/PP/National', @@ -138,22 +280,26 @@ def test_join_fire_detections_large_fire(fake_geojson_file_many_detections): collection_id = '1624045_5717329' assert len(joined_detections[collection_id]) == 8 for idx in range(8): - assert joined_detections[collection_id][idx]['geometry']['coordinates'] == json_test_data['features'][idx]['geometry']['coordinates'] + expected = json_test_data['features'][idx]['geometry']['coordinates'] + assert joined_detections[collection_id][idx]['geometry']['coordinates'] == expected assert joined_detections[collection_id][idx]['properties'] == json_test_data['features'][idx]['properties'] json_test_data = json.loads(TEST_MONSTERAS_SECOND_COLLECTION) collection_id = '1624510_5716390' assert len(joined_detections[collection_id]) == 5 for idx in range(5): - assert joined_detections[collection_id][idx]['geometry']['coordinates'] == json_test_data['features'][idx]['geometry']['coordinates'] + expected = json_test_data['features'][idx]['geometry']['coordinates'] + assert joined_detections[collection_id][idx]['geometry']['coordinates'] == expected assert joined_detections[collection_id][idx]['properties'] == json_test_data['features'][idx]['properties'] json_test_data = json.loads(TEST_MONSTERAS_THIRD_COLLECTION) collection_id = '1624906_5715623' assert len(joined_detections[collection_id]) == 1 for idx in range(1): - assert joined_detections[collection_id][idx]['geometry']['coordinates'] == json_test_data['features'][idx]['geometry']['coordinates'] - assert joined_detections[collection_id][idx]['properties'] == json_test_data['features'][idx]['properties'] + expected = json_test_data['features'][idx]['geometry']['coordinates'] + assert joined_detections[collection_id][idx]['geometry']['coordinates'] == expected + expected = json_test_data['features'][idx]['properties'] + assert joined_detections[collection_id][idx]['properties'] == expected def test_split_large_fire_clusters(): @@ -436,8 +582,8 @@ def test_alarm_filter_runner_call_spatio_temporal_alarm_filtering_no_alarms(crea def test_send_alarm_post_ok(fake_past_detections_dir): """Test send alarm.""" - - alarm = json.loads(PAST_ALARMS_MONSTERAS3) + features = json.loads(PAST_ALARMS_MONSTERAS3) + alarm = features['features'] restapi_url = "https://httpbin.org/post" retv = post_alarm(alarm, restapi_url) @@ -446,12 +592,12 @@ def test_send_alarm_post_ok(fake_past_detections_dir): def test_send_alarm_post_log_messages(caplog, fake_past_detections_dir): """Test send alarm.""" - - alarm = json.loads(PAST_ALARMS_MONSTERAS3) + features = json.loads(PAST_ALARMS_MONSTERAS3) + alarm = features['features'] restapi_url = "https://httpbin.org/post" with caplog.at_level(logging.INFO): - retv = post_alarm(alarm, restapi_url) + _ = post_alarm(alarm, restapi_url) log_output = "Alarm posted: Response = " assert log_output in caplog.text From eefbd83165bdd076077a17fb4c6391d3a5ea27e1 Mon Sep 17 00:00:00 2001 From: "Adam.Dybbroe" Date: Mon, 29 Aug 2022 16:30:00 +0200 Subject: [PATCH 5/5] Minor refactoring Signed-off-by: Adam.Dybbroe --- activefires_pp/api_posting.py | 4 +- .../spatiotemporal_alarm_filtering.py | 20 ++++---- .../test_spatiotemporal_alarm_filtering.py | 46 ++++++++++++++----- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/activefires_pp/api_posting.py b/activefires_pp/api_posting.py index 71cdc89..1cfc9e4 100644 --- a/activefires_pp/api_posting.py +++ b/activefires_pp/api_posting.py @@ -25,7 +25,7 @@ import logging import requests -# Exempel på post: +# Data payload to be posted - Example: # {"type": "Feature", "geometry": {"type": "Point", "coordinates": [15.860621, 61.403141]}, # "properties": {"power": 3.09576535, "tb": 328.81933594, "confidence": 8, # "observation_time": "2022-08-02T03:27:43.850000", @@ -48,4 +48,4 @@ def post_alarm(geojson_data, api_url, xauth=None): LOG.info("Alarm posted: Response = %s", str(response)) LOG.debug("Status code = %d", response.status_code) - return response.ok + response.raise_for_status() diff --git a/activefires_pp/spatiotemporal_alarm_filtering.py b/activefires_pp/spatiotemporal_alarm_filtering.py index 89f0970..ded0fb9 100644 --- a/activefires_pp/spatiotemporal_alarm_filtering.py +++ b/activefires_pp/spatiotemporal_alarm_filtering.py @@ -41,6 +41,7 @@ import signal from queue import Empty from threading import Thread +from requests.exceptions import HTTPError from posttroll.listener import ListenerContainer from posttroll.message import Message from posttroll.publisher import NoisyPublisher @@ -86,8 +87,6 @@ def __init__(self, configfile): self.sos_alarms_file_pattern = self.options['geojson_file_pattern_alarms'] self.restapi_url = self.options['restapi_url'] self.restapi_xauth = get_xauth_environment_variable() - if self.restapi_xauth is None: - raise OSError("Environment variable XAUTH_SMHI_FIREALARMS_REST_API not set!") self.fire_alarms_dir = Path(self.options['fire_alarms_dir']) @@ -184,13 +183,12 @@ def send_alarms(self, geojson_alarms, msg): # 1) Create the filename # 2) Wite to a file output_filename = store_geojson_alarm(self.fire_alarms_dir, p__, idx, alarm) - status = post_alarm(alarm['features'], - self.restapi_url, self.restapi_xauth) - if status: + try: + post_alarm(alarm['features'], self.restapi_url, self.restapi_xauth) LOG.info('Alarm sent - status OK') - else: - LOG.error('Failed sending alarm!') - LOG.debug('Data: %s', str(alarm['features'])) + except HTTPError: + LOG.exception('Failed sending alarm!') + LOG.error('Data: %s', str(alarm['features'])) output_message = _create_output_message(msg, self.output_topic, alarm, output_filename) LOG.debug("Sending message: %s", str(output_message)) @@ -213,7 +211,11 @@ def close(self): def get_xauth_environment_variable(): """Get the environment variable for the X-Authentication-token needed for posting to the API.""" - return os.environ.get('XAUTH_SMHI_FIREALARMS_REST_API') + restapi_xauth = os.environ.get('XAUTH_FIREALARMS_REST_API') + if restapi_xauth is None: + raise OSError("Environment variable XAUTH_FIREALARMS_REST_API not set!") + + return restapi_xauth def dump_collection(idx, features): diff --git a/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py b/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py index 10549e2..e602c9f 100644 --- a/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py +++ b/activefires_pp/tests/test_spatiotemporal_alarm_filtering.py @@ -25,6 +25,7 @@ import pytest import logging from unittest.mock import patch +import requests import pathlib import json from activefires_pp.geojson_utils import read_geojson_data @@ -34,6 +35,7 @@ from activefires_pp.spatiotemporal_alarm_filtering import create_one_detection_from_collection from activefires_pp.spatiotemporal_alarm_filtering import create_single_point_alarms_from_collections from activefires_pp.spatiotemporal_alarm_filtering import AlarmFilterRunner +from activefires_pp.spatiotemporal_alarm_filtering import get_xauth_environment_variable from activefires_pp.api_posting import post_alarm @@ -480,20 +482,15 @@ def test_alarm_filter_runner_init(setup_comm, get_config, get_xauth): 'restapi_url': 'https://xxx.smhi.se:xxxx'} -@patch('activefires_pp.spatiotemporal_alarm_filtering.get_xauth_environment_variable') -@patch('activefires_pp.spatiotemporal_alarm_filtering.read_config') -@patch('activefires_pp.spatiotemporal_alarm_filtering.AlarmFilterRunner._setup_and_start_communication') -def test_alarm_filter_runner_init_no_env(setup_comm, get_config, get_xauth): +@patch('activefires_pp.spatiotemporal_alarm_filtering.os.environ.get') +def test_alarm_filter_runner_init_no_env(os_environ_get): """Test initialize the AlarmFilterRunner class.""" - get_config.return_value = CONFIG_EXAMPLE - get_xauth.return_value = None - - myconfigfile = "/my/config/file/path" + os_environ_get.return_value = None with pytest.raises(OSError) as exec_info: - _ = AlarmFilterRunner(myconfigfile) + _ = get_xauth_environment_variable() - expected = "Environment variable XAUTH_SMHI_FIREALARMS_REST_API not set!" + expected = "Environment variable XAUTH_FIREALARMS_REST_API not set!" assert str(exec_info.value) == expected @@ -586,8 +583,33 @@ def test_send_alarm_post_ok(fake_past_detections_dir): alarm = features['features'] restapi_url = "https://httpbin.org/post" - retv = post_alarm(alarm, restapi_url) - assert retv is True + post_alarm(alarm, restapi_url) + + +def test_send_alarm_post_raise_exception(fake_past_detections_dir): + """Test send alarm.""" + features = json.loads(PAST_ALARMS_MONSTERAS3) + alarm = features['features'] + restapi_url = "https://httpbin.org/status/:500" + + with pytest.raises(Exception) as exec_info: + post_alarm(alarm, restapi_url) + + assert exec_info.type == requests.exceptions.HTTPError + + restapi_url = "https://httpbin.org/status/:300" + + with pytest.raises(Exception) as exec_info: + post_alarm(alarm, restapi_url) + + assert exec_info.type == requests.exceptions.HTTPError + + restapi_url = "https://httpbin.org/status/:400" + + with pytest.raises(Exception) as exec_info: + post_alarm(alarm, restapi_url) + + assert exec_info.type == requests.exceptions.HTTPError def test_send_alarm_post_log_messages(caplog, fake_past_detections_dir):