Telemetry¶
Models¶
- class enhydris.telemetry.models.Telemetry¶
Information about how to automatically fetch data.
Telemetry
has a OneToOneField toStation
. Every minute Celery Beat runs a task that iterates through the records ofTelemetry
; for each record, if the time for fetching data has arrived, it fetches the data by calling thefetch()
method.Telemetry
objects have the following attributes, properties and methods:- type: CharField¶
The type of the API, such as
Adcon AddUPI
orMetrica MeteoView2
. See Telemetry API types for more information.
- data_timezone: CharField¶
The time zone of the data, like
Europe/Athens
orEtc/GMT
. Enhydris converts the timestamps from this time zone to UTC in order to store them.To avoid ambiguity, it is recommended that stations do not switch to DST. However, if
data_timezone
is a time zone that switches to DST, Enhydris will handle it accordingly. It assumes that the time change occurs exactly when it is supposed to occur, not a few hours earlier or later. For the switch towards DST, things are simple. For the switch from DST to winter time, things are more complicated, because there’s an hour that appears twice. If the ambiguous hour occurs twice, Enhydris will usually do the correct thing; it will consider that the second occurence is after the switch and the first is before the switch. If according to the system’s clock the switch hasn’t occurred yet, any references to the ambiguous hour are considered to have occurred before the switch.
- fetch_interval_minutes: PositiveSmallIntegerField¶
This can be, e.g., 60 to fetch data every 60 minutes, 1440 to fetch data once a day, etc.
- fetch_offset_minutes: PositiveSmallIntegerField¶
If
fetch_interval_minutes
is 10 andfetch_offset_minutes
is 2, then data will be fetched at :02, :12, :22, etc. Iffetch_interval_minutes
is 1440 andfetch_offset_minutes
is 125, then data will be fetched every day at 02:05 in the morning. Generallyfetch_offset_minutes
counts from midnight.
- fetch_offset_timezone: CharField¶
The time zone to which
fetch_offset_minutes
refers; a tz database name such asEurope/Athens
.
- device_locator: string¶
The address of the remote API. Depending on the API, this may be the IP address, host name, or URL of the data collection device. Some APIs don’t have it at all, as the API is served by a given location regardless of which station it is (e.g. TheThingsNetwork). In such cases the attribute is left blank.
- username: string¶
- password: string¶
The username and password with which Enhydris will log on to the remote API. The password might actually be an API key, and the username might be an email, or it could be absent.
- remote_station_id: string¶
If the API supports a single station (for that user), this should be blank. Some APIs provide access to many different stations; in that case, this is the id with which the station can be identified on the API (i.e. the
remote_station_id
on the API corresponds to thestation
of Enhydris).
- additional_config: JSONField¶
If the specific telemetry type needs any additional configuration (e.g. serial interface parameters), it is stored in this attribute.
- property is_due: Boolean¶
True
if according tofetch_interval_minutes
,fetch_offset_minutes
,fetch_offset_timezone
and the current system time it’s time to fetch data.
- fetch() None ¶
Connects to the API, fetches the data, and inserts them to
TimeseriesRecord
.
- class enhydris.telemetry.models.Sensor¶
Each record in that model represents a sensor in the API, and also holds the time series group to which the sensor corresponds, i.e. the time series group to which the data from the sensor are to be uploaded. If a sensor is to be ignored, then no row must exist in this table.
- sensor_id: string¶
An id with which the sensor can be identified in the API.
- timeseries_group_id: string¶
A foreign key to
TimeseriesGroup
.
Telemetry API types¶
Each API type is one Python file in the
enhydris/telemetry/types
directory. The Python file must
contain a TelemetryAPIClient
class with all required
functionality to retrieve data from the API.
When it starts, Enhydris scans the enhydris/telemetry/types
directory and imports all Python files it contains. The result of this
scanning goes to enhydris.telemetry.drivers
.
- enhydris.telemetry.drivers¶
A dictionary that contains all
TelemetryAPIClient
classes imported from theenhydris/telemetry/types
directory. Each dictionary item maps the telemetry type’s slug (the base name of the Python file) to theTelemetryAPIClient
class.
- class TelemetryAPIClient(telemetry)¶
Should inherit from
enhydris.telemetry.TelemetryAPIClientBase
. The base class__init__()
method initializes the object with aTelemetry
object, which becomes thetelemetry
attribute.TelemetryAPIClient
classes must define the following attributes, methods and properties:- name: string¶
The name of the API, such as
Adcon AddUPI
orMetrica MeteoView2
. This is what is stored inenhydris.telemetry.models.Telemetry.type
.
- device_locator_label: string¶
- device_locator_help_text: string¶
The label and help that appears in the wizard for
device_locator
when the user is configuring telemetry; if absent, “Device URL” is used for the label and nothing is shown as help.
- username_label: string¶
The label that appears in the wizard for
username
when the user is configuring telemetry; if absent, “Username” is used. For example, it can be “Email”.
- password_label: string¶
The string that appears in the wizard for
password
when the user is configuring telemetry; if absent, “Password” is used. For example, it can be “API key”.
- hide_device_locator: boolean¶
The default is
False
. Set it toTrue
if that particular driver shouldn’t show the device locator (i.e. the URL or hostname or IP address of the device) in the connection data form. This is useful for APIs that are served from a well-known location for all stations, such as Metrica MeteoView2 or TheThingsNetwork.
- connect() None ¶
Initiates connection to the API and logs on. Should raise
TelemetryError
if something goes wrong.
- get_stations() dict ¶
Retrieves and returns pairs of station ids and station names from the API. When the telemetry configuration wizard is shown to the user, at some point the user is asked which of the stations offered by the API corresponds to the Enhydris station; the stations offered by the API is what is returned by this method. If the API offers a single station, this method can be omitted (the base method returns
None
).The station id is what is stored in
remote_station_id
; the station name is what is shown to the user in the wizard.The method must raise
TelemetryError
if something goes wrong.
- get_sensors() dict ¶
Retrieves and returns pairs of sensor ids and sensor names from the API. When the telemetry configuration wizard is shown to the user, at some point the user is asked which Enhydris time series group corresponds to each sensor of the API; the sensors available on the API is what is returned by this method.
The sensor id is what is stored in
sensor_id
; the sensor name is what is shown to the user in the wizard.The method must raise
TelemetryError
if something goes wrong.
- get_measurements(sensor_id, enhydris_timeseries_end_date) StringIO ¶
Reads data records for the sensor specified, starting with the first record whose timestamp is greater than
enhydris_timeseries_end_date
, and returns them in text format.enhydris_timeseries_end_date
is either None (meaning get all measurements since the beginning) or a datetime.In order to avoid loading the server too much, this should not return more than a reasonable number of records, such as half a year or 20000 records. In the initial uploading of a backlog of records, it will thus take a few successive data fetches to bring the Enhydris time series up to date, but this is usually not a problem.
Enhydris can’t currently handle more than one records with timestamps within the same minute. However it’s OK for this method to return such records; the caller will ignore all except for the first one.
The method must raise
TelemetryError
if something goes wrong.
Exceptions¶
- class enhydris.telemetry.TelemetryError¶
Telemetry API clients raise this exception if something goes wrong when connecting to the API. It derives from
OSError
.