13 SondeHub Amateur Uploader Class Usage
Mark Jessop edytuje tę stronę 2023-06-02 10:29:19 +09:30

Getting pySondeHub

pySondeHub can be installed via the pip package manager as follows:

pip install sondehub

Initialising the Uploader

Import the Uploader class:

from sondehub.amateur import Uploader

Instantiate an Uploader object:

uploader = Uploader("MYCALL")

When instantiating, you can also provide uploader position and station information. This is added to the uploaded telemetry packets. If you are going to be uploading telemetry relayed from other sources (e.g. WSPR or APRS-IS), then it's best to not include the position/radio/antenna information.

uploader = Uploader(
    "MYCALL",
    uploader_position=[-34.0, 138.0, 100], # [latitude, longitude, altitude]
    uploader_radio="My Radio Information", # Radio information - Optional
    uploader_antenna="My antenna Information" # Antenna information - Optional
)

Other optional arguments available when instantiating the uploader are:

software_name (str) - Overrides the software name uploaded to Sondehub-Amateur (default: 'pysondehub')
software_version (str) - Overrides the software version uploaded to Sondehub-Amateur (default: Current pysondehub version)
upload_rate (int) - How many seconds between packet uploads. (default: 2),
upload_timeout (int) - Upload timeout, in seconds. (default: 20),
upload_retries (int) - How many times to retry uploading packets. (default: 5)
developer_mode (bool) - Enable Developer mode - If set to True, data uploaded to SondeHub-Amateur is discarded, though any upload errors are still returned.

Note that the software_name and software_version information will be displayed on the Sondehub-Amateur tracker on station icons.

Uploading a Station Location

For a station to appear on the Sondehub-Amateur tracker (as a green dot), 'listener' information needs to be uploaded. To stay on the map, this information should be re-uploaded every ~6 hours. Note that you don't need to upload a station position for payload telemetry to show up on the map. If you are uploading telemetry from another receiving network like APRS or WSPR, it's probably best to not upload station positions.

uploader.upload_station_position(
    "MYCALL",
    [-34.0, 138.0, 100], # [latitude, longitude, altitude]
    uploader_radio="My Radio Information", # Radio information - Optional
    uploader_antenna="My antenna Information" # Antenna information - Optional
)

Uploading a Chase-Car Position

Mobile stations can show up on the tracker as a chase-car using the same function, though adding a mobile=True argument. The station callsign will automatically have _chase appended when shown on the tracker.

uploader.upload_station_position(
    "MYCALL",
    [-34.0, 138.0, 100], # [latitude, longitude, altitude]
    mobile=True
)

Uploading Payload Telemetry

Telemetry can be queued for upload (the time between uploads set by the upload_rate argument of the Uploader constructor) using the add_telemetry function.

The callsign you specified in the Uploader constructor will be included with the telemetry, for display on the tracker. If you provided station information in the constructor then that will also be included.

Bare Minimum example

A basic example of uploading telemetry is as follows:

uploader.add_telemetry(
    "MYBALLOON", # Your payload callsign
    "2022-05-28T00:01:02Z", # Time
    -34.0, # Latitude
    138.0, # Longitude
    10000 # Altitude
)

The telemetry packet will be added to a queue for upload on the next upload cycle (every upload_rate seconds).

Note: If both latitude and longitude are set to 0, the packet will be discarded.

A note on Time

add_telemetry can accept time in the following formats:

  • A datetime object (e.g. datetime.datetime.utcnow() )
  • A string, in any format that python-dateutil's 'parse' function can parse.

If providing time as a string, and no date part is provided (e.g. "HH:MM:SS" format), it will be combined with the current local date. If the time is close to a UTC day boundary (00:00Z), the local time is checked to set the appropriate day (refer this function).

All times are assumed to be in UTC.

Uploading with additional fields.

The add_telemetry function also accepts a selection of common telemetry fields. These are all optional - only provide what you have! An example using these is as follows:

uploader.add_telemetry(
    "MYBALLOON", # Your payload callsign
    "2022-05-28T00:01:02Z", # Time - as either a datetime object or a string, e.g. "00:01:02"
    -34.0, # Latitude
    138.0, # Longitude
    10000, # Altitude
    frame=123, # Frame counter (e.g. packet number)
    sats=10, # Number of GNSS satellites in use 
    batt=3.14159, # Battery voltage (Volts)
    temp=-42.0, # Payload Temperature (˚C)
    pressure=1001.23, # Pressure (hPa)
    humidity=99, # Humidity (%)
    vel_v=-42.0, # Vertical Velocity (m/s)
    vel_h=100.0, # Horizontal Velocity (m/s)
    heading=359.0 # Heading (degrees True)
)

You can also add on completely custom fields by adding a extra_fields parameter, containing a dictionary of fields:

    extra_fields={"my_field_1":5, "my_field_2":"foo", "my_field_3":-123.456},

Note: If the 'sats' field has been provided and is 0, the packet will be discarded. (This is an attempt to drop bogus positions from getting through to the tracker).

Listener Metadata

You can also include listener metadata, indicating the modulation, frequency, Signal-to-noise ratio, and even receive signal strength of the received telemetry. Again, only provide these if you have them.

    snr=55.0, # Signal-to-Noise Ratio of the received telemetry, in dB.
    frequency=434.123, # Frequency of the received telemetry, in MHz.
    rssi=-123.0, # Received Signal Strength, in dBm
    modulation="Test", # Modulation type of the telemetry, e.g. RTTY, Horus Binary, LoRa, WSPR

Overriding Uploader Information

You can also set the uploader information (Callsign, position, etc) on a per-telemetry-packet basis by adding this to the add_telemetry call:

    uploader_callsign="SOME_OTHER_CALL",
    uploader_position=[0.15,0.15,0] # Latitude, Longitude, Altitude

This may be useful if uploading telemetry received via some other means, e.g. WSPRnet.

Note that you can only specify one callsign - if you want to indicate that a telemetry packet has been received by multiple stations, then you will need to call add_telemetry multiple times with different uploader_callsign values.

Shutting down the Uploader

When your uploading software is finished, you can close the uploader class by running:

uploader.close()

NOTE: Telemetry packets are not uploaded immediately, but instead are queued for upload at regular (default is every 2 seconds) intervals. You should not close the uploader immediately after adding a telemetry packet, but instead either wait before closing it, or just keep it open.

Examples of uploaded data

To see some examples of what is uploaded to the SondeHub-Amateur API, you can run a test script as follows:

python -m sondehub.amateur

This will output a large amount of debug information showing the packets that were generated, and what is uploaded:

2022-08-19 07:09:33,995 INFO:Sondehub Amateur Uploader - Started Sondehub Amateur Uploader Thread.
2022-08-19 07:09:33,995 DEBUG:Sondehub Amateur Uploader - Generated Station Position Packet: {'software_name': 'pysondehub', 'software_version': '0.3.0', 'uploader_callsign': 'N0CALL-DEV-TESTING', 'uploader_position': [0.1, 0.1, 0], 'uploader_radio': 'Testing pysondehub radio', 'uploader_antenna': 'Testing pysondehub antenna', 'uploader_contact_email': '', 'mobile': False, 'dev': True}
2022-08-19 07:09:34,046 DEBUG:Starting new HTTPS connection (1): api.v2.sondehub.org:443
2022-08-19 07:09:34,994 DEBUG:https://api.v2.sondehub.org:443 "PUT /amateur/listeners HTTP/1.1" 200 15
2022-08-19 07:09:35,000 INFO:Sondehub Amateur Uploader - Uploaded station information to Sondehub.
2022-08-19 07:09:35,000 DEBUG:Sondehub Amateur Uploader - Generated Station Position Packet: {'software_name': 'pysondehub', 'software_version': '0.3.0', 'uploader_callsign': 'N0CALL-DEV2-TESTING', 'uploader_position': [-0.1, -0.1, 0.0], 'uploader_radio': '', 'uploader_antenna': '', 'uploader_contact_email': '', 'mobile': True, 'dev': True}
2022-08-19 07:09:35,008 DEBUG:Starting new HTTPS connection (1): api.v2.sondehub.org:443
2022-08-19 07:09:36,071 DEBUG:https://api.v2.sondehub.org:443 "PUT /amateur/listeners HTTP/1.1" 200 15
2022-08-19 07:09:36,074 INFO:Sondehub Amateur Uploader - Uploaded station information to Sondehub.
2022-08-19 07:09:36,077 DEBUG:Sondehub Amateur Uploader - Generated Packet: {'dev': True, 'payload_callsign': 'VK5QI-DEV-TEST', 'datetime': '2022-08-18T21:39:36.000000Z', 'lat': -0.1, 'lon': 0.1, 'alt': 10000.0, 'time_received': '2022-08-18T21:39:36.077662Z', 'frame': 123, 'sats': 10, 'batt': 3.14159, 'temp': -42.0, 'humdity': 99.0, 'pressure': 1001.23, 'vel_v': -42.0, 'vel_h': 100.0, 'heading': 359.0, 'modulation': 'Test', 'snr': 55.0, 'frequency': 434.123, 'rssi': -123.0, 'uploader_callsign': 'N0CALL-DEV2-TESTING', 'uploader_position': [0.15, 0.15, 0], 'my_field_1': 5, 'my_field_2': 'foo', 'my_field_3': -123.456}
2022-08-19 07:09:38,014 DEBUG:Sondehub Amateur Uploader - Generated Packet: b'[{"dev": true, "payload_callsign": "VK5QI-DEV-TEST", "datetime": "2022-08-18T21:39:36.000000Z", "lat": -0.1, "lon": 0.1, "alt": 10000.0, "time_received": "2022-08-18T21:39:36.077662Z", "frame": 123, "sats": 10, "batt": 3.14159, "temp": -42.0, "humdity": 99.0, "pressure": 1001.23, "vel_v": -42.0, "vel_h": 100.0, "heading": 359.0, "modulation": "Test", "snr": 55.0, "frequency": 434.123, "rssi": -123.0, "uploader_callsign": "N0CALL-DEV2-TESTING", "uploader_position": [0.15, 0.15, 0], "my_field_1": 5, "my_field_2": "foo", "my_field_3": -123.456}]'
2022-08-19 07:09:38,014 DEBUG:Sondehub Amateur Uploader - Pre-compression: 548 bytes, post: 334 bytes. 60.9 % compression ratio, in 0.0 s
2022-08-19 07:09:38,015 DEBUG:Sondehub Amateur Uploader - Upload Headers: {'User-Agent': 'pysondehub-0.3.0', 'Content-Encoding': 'gzip', 'Content-Type': 'application/json', 'Date': 'Thu, 18 Aug 2022 21:39:38 GMT'}
2022-08-19 07:09:38,021 DEBUG:Starting new HTTPS connection (1): api.v2.sondehub.org:443
2022-08-19 07:09:38,829 DEBUG:https://api.v2.sondehub.org:443 "PUT /amateur/telemetry HTTP/1.1" 202 803
2022-08-19 07:09:38,834 ERROR:Sondehub Amateur Uploader - Error uploading to Sondehub Amateur. Status Code: 202 {"message": "some or all payloads could not be processed", "errors": [{"error_message": "All checks passed however payload contained dev flag so will not be uploaded to the database", "payload": {"dev": true, "payload_callsign": "VK5QI-DEV-TEST", "datetime": "2022-08-18T21:39:36.000000Z", "lat": -0.1, "lon": 0.1, "alt": 10000.0, "time_received": "2022-08-18T21:39:36.077662Z", "frame": 123, "sats": 10, "batt": 3.14159, "temp": -42.0, "humdity": 99.0, "pressure": 1001.23, "vel_v": -42.0, "vel_h": 100.0, "heading": 359.0, "modulation": "Test", "snr": 55.0, "frequency": 434.123, "rssi": -123.0, "uploader_callsign": "N0CALL-DEV2-TESTING", "uploader_position": [0.15, 0.15, 0], "my_field_1": 5, "my_field_2": "foo", "my_field_3": -123.456, "user-agent": "Amazon CloudFront", "position": "-0.1,0.1"}}]}.
2022-08-19 07:09:38,834 ERROR:Sondehub Amateur Uploader - Upload failed after 0 retries
2022-08-19 07:09:41,846 INFO:Sondehub Amateur Uploader - Stopped Sondehub Amateur Uploader Thread.

Note that the errors here are because we use the 'dev' flag for this example, which stops the packets from being stored into the database.