diff --git a/enhydris/telemetry/tests/test_types/test_addupi.py b/enhydris/telemetry/tests/test_types/test_addupi.py
index 2ce18500..1c5ebaf5 100644
--- a/enhydris/telemetry/tests/test_types/test_addupi.py
+++ b/enhydris/telemetry/tests/test_types/test_addupi.py
@@ -3,6 +3,7 @@
from unittest.mock import patch
from freezegun import freeze_time
+from parameterized import parameterized
from requests import Timeout
from enhydris.telemetry import TelemetryError
@@ -180,11 +181,6 @@ def test_request_when_no_start_date(self, mock_requests_get):
verify=False,
)
- def test_raises_when_s_attribute_is_nonzero(self, mock_requests_get):
- self._set_nonzero_s_request_result(mock_requests_get)
- with self.assertRaisesRegex(TelemetryError, "not supported"):
- self.telemetry_api_client.get_measurements(8231, None)
-
def _set_successful_request_result(self, mock_requests_get):
mock_requests_get.return_value.__enter__.return_value.content = (
""
@@ -195,11 +191,52 @@ def _set_successful_request_result(self, mock_requests_get):
""
).encode()
- def _set_nonzero_s_request_result(self, mock_requests_get):
+
+@patch("enhydris.telemetry.types.addupi.requests.get")
+@freeze_time("2022-06-14 08:35")
+class ReturnedStatusTestCase(LoggedOnTestCaseBase):
+ @parameterized.expand(
+ [
+ (3, 'invalid status value .s="3".'),
+ (-100, 'invalid status value .s="-100".'),
+ ("hello", 'invalid status value .s="hello".'),
+ ]
+ )
+ def test_error_handling(self, mock_requests_get, s, error_msg):
+ self._set_s_request_result(s, mock_requests_get)
+ with self.assertRaisesRegex(TelemetryError, error_msg):
+ self.telemetry_api_client.get_measurements(8231, None)
+
+ @parameterized.expand(
+ [
+ (0, ""),
+ (1, "INVALID"),
+ (2, "INVALID"),
+ (-99, "MISSING"),
+ (-1, "MISSING"),
+ ]
+ )
+ def test_flag(self, mock_requests_get, s, flag):
+ self._set_s_request_result(s, mock_requests_get)
+ result = self.telemetry_api_client.get_measurements(8231, None)
+ self.assertEqual(result.getvalue(), f"2022-06-14T08:10:00,1.42,{flag}\n")
+
+ def _set_s_request_result(self, s, mock_requests_get):
mock_requests_get.return_value.__enter__.return_value.content = (
""
" "
- " 1.42"
+ f" 1.42"
" "
""
).encode()
+
+ def test_s_attribute_missing(self, mock_requests_get):
+ mock_requests_get.return_value.__enter__.return_value.content = (
+ ""
+ " "
+ " 1.42"
+ " "
+ ""
+ ).encode()
+ with self.assertRaisesRegex(TelemetryError, 'invalid status value .s="None".'):
+ self.telemetry_api_client.get_measurements(8231, None)
diff --git a/enhydris/telemetry/types/addupi.py b/enhydris/telemetry/types/addupi.py
index 52c561ca..9437ec8e 100644
--- a/enhydris/telemetry/types/addupi.py
+++ b/enhydris/telemetry/types/addupi.py
@@ -41,8 +41,6 @@ def get_sensors(self):
return {x.attrib["id"]: x.attrib["name"] for x in sensors}
def get_measurements(self, sensor_id, timeseries_end_date):
- from enhydris.telemetry import TelemetryError
-
if timeseries_end_date is None:
timeseries_end_date = dt.datetime(1990, 1, 1)
xmlroot = self._make_request(
@@ -59,19 +57,36 @@ def get_measurements(self, sensor_id, timeseries_end_date):
timestamp = prev_timestamp + dt.timedelta(seconds=int(timestamp))
else:
timestamp = dt.datetime.strptime(timestamp, "%Y%m%dT%H:%M:%S")
- s = record.attrib["s"]
- if s != "0":
- raise TelemetryError(
- f"The record with timestamp {timestamp} has a non zero s "
- f'attribute (s="{s}"). This is probably normal, however it is '
- "currently not supported by the Enhydris addupi driver. Please "
- "ask for the driver to be fixed."
- )
- prev_timestamp = timestamp
value = float(record.text)
- result += f"{timestamp.isoformat()},{value},\n"
+ flags = self._get_flags(record, timestamp)
+ result += f"{timestamp.isoformat()},{value},{flags}\n"
+ prev_timestamp = timestamp
return StringIO(result)
+ def _get_flags(self, record, timestamp):
+ s = self._get_s_attribute(record, timestamp)
+ if s in (1, 2):
+ return "INVALID"
+ if s < 0:
+ return "MISSING"
+ return ""
+
+ def _get_s_attribute(self, record, timestamp):
+ try:
+ s = None
+ s = record.attrib["s"]
+ si = int(s)
+ if si < -99 or si > 2:
+ raise ValueError()
+ return si
+ except (KeyError, ValueError):
+ from enhydris.telemetry import TelemetryError
+
+ raise TelemetryError(
+ f"The record with timestamp {timestamp} has an invalid status "
+ f'value (s="{s}")'
+ )
+
def _make_request(self, query_string):
from enhydris.telemetry import TelemetryError
diff --git a/requirements-dev.txt b/requirements-dev.txt
index e86dd839..e4bf8d71 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -5,3 +5,4 @@ django-selenium-clean>=1,<2
beautifulsoup4>=4.4
celery>=4,<5
freezegun>=1.1,<2
+parameterized>=0.9.0,<1