-
Notifications
You must be signed in to change notification settings - Fork 5
SondeHub Amateur Uploader Class Usage
pySondeHub can be installed via the pip package manager as follows:
pip install sondehub
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.
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
)
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
)
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.
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.
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.
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).
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
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.
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.
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.