SimTX API/Transmitter session: Difference between revisions
Clanker moved page SimTX API/Transmitter session to SimTX API v24/Transmitter session: Archive the v24 protocol reference Tag: New redirect |
Protocol v25 reference Tag: Removed redirect |
||
| Line 1: | Line 1: | ||
# | {{SimTX API navigation}} | ||
A '''transmitter session''' puts a signal on the air. The client binds the transmitter to one of its persistent stations, waits for a transmitter slot, and then streams audio or IQ samples in real time while the server modulates them, models the power amplifier and antenna, and propagates the result to every receiver. Transmitter sessions use <code>ROLE_TX_AUDIO</code> or <code>ROLE_TX_GENERATED</code> and need an account with the <code>game.transmit</code> [[SimTX API/Permissions|permission]]. | |||
== Frames == | |||
{| class="wikitable" | |||
! Direction !! # !! Message !! When | |||
|- | |||
| C2S || 12 || [[SimTX API/Packets/TransmitterStart|TransmitterStart]] || Once, right after the hello. | |||
|- | |||
| S2C || 10 || [[SimTX API/Packets/SessionStatus|SessionStatus]] || <code>BOUND</code> or <code>REJECTED</code> after the start; later <code>UPDATED</code> and <code>ENDED</code>. | |||
|- | |||
| S2C || 13 || [[SimTX API/Packets/TxQueue|TxQueue]] || While waiting for a slot. | |||
|- | |||
| S2C || 14 || [[SimTX API/Packets/TxAccept|TxAccept]] || When the transmitter goes on the air. | |||
|- | |||
| C2S || 13 || [[SimTX API/Packets/SampleBlock|SampleBlock]] || Continuously after TxAccept (<code>ROLE_TX_AUDIO</code>). | |||
|- | |||
| C2S || 15 || [[SimTX API/Packets/TxModeInfo|TxModeInfo]] || Optional, after TxAccept. | |||
|- | |||
| C2S || 14 || [[SimTX API/Packets/TxUpdate|TxUpdate]] || Optional, to change settings on air. | |||
|- | |||
| S2C || 18 || [[SimTX API/Packets/TxUpdateAck|TxUpdateAck]] || In reply to each TxUpdate. | |||
|- | |||
| C2S || 16 || [[SimTX API/Packets/AntennaPointingUpdate|AntennaPointingUpdate]] || Optional, to steer the antenna or change tracking. | |||
|- | |||
| S2C || 17 || [[SimTX API/Packets/TxTelemetry|TxTelemetry]] || About every 50 ms while on air. | |||
|- | |||
| C2S / S2C || 2 || [[SimTX API/Packets/Ping|Ping]] / [[SimTX API/Packets/Pong|Pong]] || Any time. | |||
|- | |||
| S2C || 3 || [[SimTX API/Packets/Error|Error]] || When a pointing request fails, or on a protocol violation. | |||
|} | |||
== Sequence == | |||
<syntaxhighlight lang="text"> | |||
client server | |||
| POST /api/v1/game-tickets {role: "tx-audio", stationId} (HTTPS) | |||
| -- preface, [1] hello (ROLE_TX_AUDIO, ticket) --------> | | |||
| <----------------------------- [1] hello_result | | |||
| -- [12] transmitter_start (site.station) -------------> | | |||
| <----------------------------- [10] session_status | BOUND, station snapshot | |||
| <----------------------------- [13] tx_queue | (only if all slots are busy; | |||
| <----------------------------- [13] tx_queue | repeats about once a second) | |||
| <----------------------------- [14] tx_accept | | |||
| -- [13] samples --------------------------------------> | | |||
| <----------------------------- [17] tx_telemetry | | |||
| -- [13] samples --------------------------------------> | | |||
| -- [14] tx_update ------------------------------------> | | |||
| <----------------------------- [18] tx_update_ack | | |||
| ... | | |||
| -- close ---------------------------------------------> | off the air | |||
</syntaxhighlight> | |||
== Placing the transmitter == | |||
A transmitter normally runs on one of the account's own [[SimTX API/Stations|persistent stations]]: | |||
# Choose a station, an antenna and optionally a rig from <code>GET /api/v1/stations</code>. See [[SimTX API/Station endpoints]]. | |||
# Mint a <code>tx-audio</code> or <code>tx-generated</code> [[SimTX API/Game tickets|game ticket]] with the same <code>stationId</code>, <code>antennaId</code> and <code>rigId</code>. | |||
# Send the hello with the ticket, then a [[SimTX API/Packets/TransmitterStart|TransmitterStart]] whose <code>site.station</code> is a [[SimTX API/Data types#StationBinding|StationBinding]] with the same ids. Empty antenna and rig ids accept what the ticket bound. | |||
The station dictates the callsign, placement, antenna and pointing defaults; the bound rig dictates the PA cap and most imperfection knobs. The session chooses the modulation, frequency, power up to the cap, source, sample rate, gain, bandwidth, low cut, tone and duty cycle, plus drive, compression, frequency offset and AM index. See [[SimTX API/Stations#What the station dictates|What the station dictates]]. Only the owner may transmit through a station. | |||
On a satellite, the transmitter is a downlink transmitter at the satellite's position, and moves with it. | |||
=== Ad-hoc transmitters === | |||
A start whose <code>site</code> is an [[SimTX API/Data types#AdhocStation|AdhocStation]] is accepted only for principals that hold <code>tx.adhoc</code> (service integrations) or when the server's ad-hoc policy allows it. By default servers refuse it with <code>ERROR_CODE_STATION_REQUIRED</code>. Third-party clients should always bind a station. | |||
== Admission == | |||
After the start, the server answers with [[SimTX API/Packets/SessionStatus|SessionStatus]]: | |||
* '''<code>REJECTED</code>''': the start was refused. <code>code</code> and <code>reason</code> say why, and the connection closes. See [[SimTX API/Session status#REJECTED|REJECTED]]. | |||
* '''<code>BOUND</code>''': the start is accepted. For a station-bound session, <code>station</code> describes the station, antenna and rig and the effective PA cap. Then: | |||
** '''[[SimTX API/Packets/TxQueue|TxQueue]]''' if every transmitter slot on the server is busy. Further TxQueue frames report the position as it changes, at most about once a second. Keep reading and do not send samples yet. | |||
** '''[[SimTX API/Packets/TxAccept|TxAccept]]''' when the transmitter is on the air. Start streaming. | |||
== Sources == | |||
<code>source_type</code> decides what the client streams. | |||
{| class="wikitable" | |||
! Source type !! Role !! Client sends !! Server does | |||
|- | |||
| <code>AUDIO_STREAM</code>, <code>MICROPHONE</code>, <code>PIPEWIRE</code> || <code>ROLE_TX_AUDIO</code> || Mono audio, one float per sample at <code>sample_rate</code>, nominal range ±1, in <code>SampleBlock.audio</code> || Applies <code>audio_gain</code>, the audio low cut and compression, then modulates with the requested modulation. | |||
|- | |||
| <code>GNU_RADIO_IQ</code> || <code>ROLE_TX_AUDIO</code> || Complex baseband, I and Q interleaved, at <code>sample_rate</code>, centred on the carrier frequency, in <code>SampleBlock.iq</code> or <code>SampleBlock.compact_iq</code> || Applies <code>audio_gain</code>, normalises average power to at most 1.0 (equal to <code>power_watts</code>), and transmits it as it is. Use modulation <code>IQ</code>. | |||
|- | |||
| <code>WHITE_NOISE</code> || <code>ROLE_TX_GENERATED</code> || Nothing || Generates the signal itself. | |||
|} | |||
With an IQ source, the client is the modulator. Anything that can be expressed as complex baseband, including digital modes the server has never heard of, can be transmitted this way. [[SimTX API/Packets/TxModeInfo|TxModeInfo]] gives such a signal a name. | |||
=== Sample rates === | |||
The server processes each transmitter at a rate equal to the declared <code>sample_rate</code>, raised to at least 240,000 for <code>WFM</code> and limited to 10,000,000. Audio is resampled to that rate by a factor of at most 128; a lower audio rate is refused. Raw IQ above 10,000,000 samples per second is refused. | |||
== Streaming == | |||
Samples are sent in [[SimTX API/Packets/SampleBlock|SampleBlock]] frames of up to 65,536 values. IQ sources may use the compact 16-bit form, which halves the uplink. | |||
=== Pacing === | |||
The client must send samples '''in real time''', at the rate it declared. | |||
* The server keeps about 0.5 s of samples as a playout buffer. When its ring buffer is 90 % full, it stops reading from the socket, and TCP flow control slows the client down. Sending slightly ahead is therefore safe. | |||
* Input arriving faster than 1.05 times the declared rate, beyond a burst allowance of about two seconds of samples, is '''discarded''' block by block without notice. | |||
* <code>buffer_seconds</code> in [[SimTX API/Packets/TxTelemetry|TxTelemetry]] reports the server's buffer. It is the best pacing signal available: keep it above zero and below about two seconds. | |||
=== Keying === | |||
There is no push-to-talk frame. A transmitter is on the air from TxAccept until the connection closes. To go quiet without disconnecting, send silence, or set the power to 0 with [[SimTX API/Packets/TxUpdate|TxUpdate]]. | |||
An audio source that delivers no samples for 15 seconds is disconnected. An IQ source is not disconnected for being idle, but it is still on the air, transmitting nothing, and still occupies a transmitter slot. | |||
To leave cleanly, shut down the sending side of the socket (half-close) and then close it. | |||
== Live updates == | |||
[[SimTX API/Packets/TxUpdate|TxUpdate]] changes frequency, power, bandwidth, audio low cut, drive, headroom, compression and audio gain while on air. Every field is <code>optional</code>; send only those that change. The server answers each update with a [[SimTX API/Packets/TxUpdateAck|TxUpdateAck]] that reports, for every field set, whether it was applied and the value now in effect. At most one update is applied per 250 ms, and the frequency at most once per second; updates sent faster are refused in the ack, not queued. | |||
Other settings, such as the modulation, sample rate, source or station, cannot be changed on air. Close the session and open a new one. Antenna pointing and tracking change with [[SimTX API/Packets/AntennaPointingUpdate|AntennaPointingUpdate]]. | |||
== Tracking and Doppler == | |||
A transmitter can follow a target with its antenna and pre-correct its carrier for the target's Doppler shift, so that the signal arrives on frequency at a satellite: set <code>TransmitterStart.tracking</code>, or send an [[SimTX API/Packets/AntennaPointingUpdate|AntennaPointingUpdate]] later. See [[SimTX API/Tracking and pointing]]. | |||
== Telemetry == | |||
While on air the server sends [[SimTX API/Packets/TxTelemetry|TxTelemetry]] about every 50 ms. It reports forward, delivered and reflected power, SWR, amplifier compression and temperature, thermal foldback, and the playout buffer level, the same values the official transmitter shows on its meters. Telemetry is coalesced: a slow reader gets the newest values, not a backlog. | |||
The client must keep reading. A client that stops reading for 5 seconds is disconnected. | |||
== Taken off the air == | |||
The server ends a running session with [[SimTX API/Packets/SessionStatus|SessionStatus]] <code>ENDED</code>, a code and a reason, when a moderator or the operator removes the transmitter, the address is banned, the station is deleted or loses the bound antenna or rig, or a satellite reenters. The connection closes right after. When the account lease expires the connection is closed. See [[SimTX API/Session status]]. | |||
== Limits == | |||
* The power is capped by the PA cap: the bound rig's <code>paMaxWatts</code> and the account's <code>tx.pa_limit.N</code> capability, whichever is lower (<code>BoundStation.pa_cap_watts</code>). Requests above it are reduced to the cap; [[SimTX API/Packets/TxTelemetry|TxTelemetry]] shows the actual power. | |||
* The number of simultaneous transmitters per account and per station is limited. See [[SimTX API/Limits and errors]]. | |||
== Example == | |||
Building a station-bound [[SimTX API/Packets/TransmitterStart|TransmitterStart]] and an audio [[SimTX API/Packets/SampleBlock|SampleBlock]] with the helpers of [[SimTX API/Quick start|Quick start]]: | |||
<syntaxhighlight lang="python" line> | |||
import uuid | |||
# Ids from the game ticket response ("station": {"stationId", "antennaId", "rigId"}) | |||
station_id = uuid.UUID("3f2504e0-4f89-41d3-9a0c-0305e82c3301").bytes | |||
antenna_id = uuid.UUID("9b2c1e47-2f0a-4c55-8d1e-6a7b8c9d0e1f").bytes | |||
binding = f_bytes(1, station_id) + f_bytes(2, antenna_id) # rig_id empty: the rig the ticket bound | |||
start = ( | |||
f_bytes(1, f_bytes(1, binding)) # site { station { ... } } | |||
+ f_bytes(3, "USB") # modulation | |||
+ f_double(4, 14_230_000.0) # frequency_hz | |||
+ f_float(5, 100.0) # power_watts | |||
+ f_bytes(6, "AUDIO_STREAM") # source_type | |||
+ f_varint(7, 48_000) # sample_rate | |||
+ f_float(8, 1.0) # audio_gain | |||
+ f_float(9, 2_700.0) # bandwidth_hz | |||
+ f_float(10, 300.0) # audio_low_cut_hz | |||
+ f_float(12, 1.0) # duty_cycle; tone_hz (11) stays 0 | |||
) | |||
send_frame(sock, 12, start) # transmitter_start | |||
def sample_block(samples): # SampleBlock { audio: PackedFloats { values } } | |||
packed = struct.pack("<%df" % len(samples), *samples) | |||
return f_bytes(1, f_bytes(1, packed)) | |||
# after TxAccept, every 20 ms: | |||
send_frame(sock, 13, sample_block(block)) # samples | |||
</syntaxhighlight> | |||
== Checklist == | |||
# Obtain a bearer credential through [[SimTX API/Device login|device login]] (scope <code>game.transmit</code>) or a personal credential. | |||
# <code>GET /api/v1/stations</code>; pick an ACTIVE station (or a DEORBITING satellite before its reentry), an antenna and optionally a rig. | |||
# <code>POST /api/v1/game-tickets</code> with <code>{"serverId": ..., "role": "tx-audio", "stationId": ..., "antennaId": ..., "rigId": ...}</code>. | |||
# Connect with TLS. Send the preface and a <code>hello</code> with <code>role = ROLE_TX_AUDIO</code>, <code>auth = AUTH_KIND_GAME_TICKET</code> and the ticket. Require <code>HELLO_STATUS_ACCEPTED</code>. | |||
# Send <code>transmitter_start</code> with <code>site.station</code> and the signal parameters. | |||
# Read <code>session_status</code> (<code>BOUND</code>: show the station; <code>REJECTED</code>: show the code and reason), then <code>tx_queue</code> frames until <code>tx_accept</code>. | |||
# Stream <code>samples</code> in real time. Read telemetry on another thread. | |||
# Use <code>tx_update</code> for live changes. Close the socket to go off the air. On <code>ENDED</code>, show the reason. | |||
{{SimTX API navbox}} | |||
[[Category:SimTX API]] | |||
[[Category:SimTX API sessions]] | |||
Revision as of 16:38, 24 October 2026
A transmitter session puts a signal on the air. The client binds the transmitter to one of its persistent stations, waits for a transmitter slot, and then streams audio or IQ samples in real time while the server modulates them, models the power amplifier and antenna, and propagates the result to every receiver. Transmitter sessions use ROLE_TX_AUDIO or ROLE_TX_GENERATED and need an account with the game.transmit permission.
Frames
| Direction | # | Message | When |
|---|---|---|---|
| C2S | 12 | TransmitterStart | Once, right after the hello. |
| S2C | 10 | SessionStatus | BOUND or REJECTED after the start; later UPDATED and ENDED.
|
| S2C | 13 | TxQueue | While waiting for a slot. |
| S2C | 14 | TxAccept | When the transmitter goes on the air. |
| C2S | 13 | SampleBlock | Continuously after TxAccept (ROLE_TX_AUDIO).
|
| C2S | 15 | TxModeInfo | Optional, after TxAccept. |
| C2S | 14 | TxUpdate | Optional, to change settings on air. |
| S2C | 18 | TxUpdateAck | In reply to each TxUpdate. |
| C2S | 16 | AntennaPointingUpdate | Optional, to steer the antenna or change tracking. |
| S2C | 17 | TxTelemetry | About every 50 ms while on air. |
| C2S / S2C | 2 | Ping / Pong | Any time. |
| S2C | 3 | Error | When a pointing request fails, or on a protocol violation. |
Sequence
client server
| POST /api/v1/game-tickets {role: "tx-audio", stationId} (HTTPS)
| -- preface, [1] hello (ROLE_TX_AUDIO, ticket) --------> |
| <----------------------------- [1] hello_result |
| -- [12] transmitter_start (site.station) -------------> |
| <----------------------------- [10] session_status | BOUND, station snapshot
| <----------------------------- [13] tx_queue | (only if all slots are busy;
| <----------------------------- [13] tx_queue | repeats about once a second)
| <----------------------------- [14] tx_accept |
| -- [13] samples --------------------------------------> |
| <----------------------------- [17] tx_telemetry |
| -- [13] samples --------------------------------------> |
| -- [14] tx_update ------------------------------------> |
| <----------------------------- [18] tx_update_ack |
| ... |
| -- close ---------------------------------------------> | off the air
Placing the transmitter
A transmitter normally runs on one of the account's own persistent stations:
- Choose a station, an antenna and optionally a rig from
GET /api/v1/stations. See SimTX API/Station endpoints. - Mint a
tx-audioortx-generatedgame ticket with the samestationId,antennaIdandrigId. - Send the hello with the ticket, then a TransmitterStart whose
site.stationis a StationBinding with the same ids. Empty antenna and rig ids accept what the ticket bound.
The station dictates the callsign, placement, antenna and pointing defaults; the bound rig dictates the PA cap and most imperfection knobs. The session chooses the modulation, frequency, power up to the cap, source, sample rate, gain, bandwidth, low cut, tone and duty cycle, plus drive, compression, frequency offset and AM index. See What the station dictates. Only the owner may transmit through a station.
On a satellite, the transmitter is a downlink transmitter at the satellite's position, and moves with it.
Ad-hoc transmitters
A start whose site is an AdhocStation is accepted only for principals that hold tx.adhoc (service integrations) or when the server's ad-hoc policy allows it. By default servers refuse it with ERROR_CODE_STATION_REQUIRED. Third-party clients should always bind a station.
Admission
After the start, the server answers with SessionStatus:
REJECTED: the start was refused.codeandreasonsay why, and the connection closes. See REJECTED.BOUND: the start is accepted. For a station-bound session,stationdescribes the station, antenna and rig and the effective PA cap. Then:
Sources
source_type decides what the client streams.
| Source type | Role | Client sends | Server does |
|---|---|---|---|
AUDIO_STREAM, MICROPHONE, PIPEWIRE |
ROLE_TX_AUDIO |
Mono audio, one float per sample at sample_rate, nominal range ±1, in SampleBlock.audio |
Applies audio_gain, the audio low cut and compression, then modulates with the requested modulation.
|
GNU_RADIO_IQ |
ROLE_TX_AUDIO |
Complex baseband, I and Q interleaved, at sample_rate, centred on the carrier frequency, in SampleBlock.iq or SampleBlock.compact_iq |
Applies audio_gain, normalises average power to at most 1.0 (equal to power_watts), and transmits it as it is. Use modulation IQ.
|
WHITE_NOISE |
ROLE_TX_GENERATED |
Nothing | Generates the signal itself. |
With an IQ source, the client is the modulator. Anything that can be expressed as complex baseband, including digital modes the server has never heard of, can be transmitted this way. TxModeInfo gives such a signal a name.
Sample rates
The server processes each transmitter at a rate equal to the declared sample_rate, raised to at least 240,000 for WFM and limited to 10,000,000. Audio is resampled to that rate by a factor of at most 128; a lower audio rate is refused. Raw IQ above 10,000,000 samples per second is refused.
Streaming
Samples are sent in SampleBlock frames of up to 65,536 values. IQ sources may use the compact 16-bit form, which halves the uplink.
Pacing
The client must send samples in real time, at the rate it declared.
- The server keeps about 0.5 s of samples as a playout buffer. When its ring buffer is 90 % full, it stops reading from the socket, and TCP flow control slows the client down. Sending slightly ahead is therefore safe.
- Input arriving faster than 1.05 times the declared rate, beyond a burst allowance of about two seconds of samples, is discarded block by block without notice.
buffer_secondsin TxTelemetry reports the server's buffer. It is the best pacing signal available: keep it above zero and below about two seconds.
Keying
There is no push-to-talk frame. A transmitter is on the air from TxAccept until the connection closes. To go quiet without disconnecting, send silence, or set the power to 0 with TxUpdate.
An audio source that delivers no samples for 15 seconds is disconnected. An IQ source is not disconnected for being idle, but it is still on the air, transmitting nothing, and still occupies a transmitter slot.
To leave cleanly, shut down the sending side of the socket (half-close) and then close it.
Live updates
TxUpdate changes frequency, power, bandwidth, audio low cut, drive, headroom, compression and audio gain while on air. Every field is optional; send only those that change. The server answers each update with a TxUpdateAck that reports, for every field set, whether it was applied and the value now in effect. At most one update is applied per 250 ms, and the frequency at most once per second; updates sent faster are refused in the ack, not queued.
Other settings, such as the modulation, sample rate, source or station, cannot be changed on air. Close the session and open a new one. Antenna pointing and tracking change with AntennaPointingUpdate.
Tracking and Doppler
A transmitter can follow a target with its antenna and pre-correct its carrier for the target's Doppler shift, so that the signal arrives on frequency at a satellite: set TransmitterStart.tracking, or send an AntennaPointingUpdate later. See SimTX API/Tracking and pointing.
Telemetry
While on air the server sends TxTelemetry about every 50 ms. It reports forward, delivered and reflected power, SWR, amplifier compression and temperature, thermal foldback, and the playout buffer level, the same values the official transmitter shows on its meters. Telemetry is coalesced: a slow reader gets the newest values, not a backlog.
The client must keep reading. A client that stops reading for 5 seconds is disconnected.
Taken off the air
The server ends a running session with SessionStatus ENDED, a code and a reason, when a moderator or the operator removes the transmitter, the address is banned, the station is deleted or loses the bound antenna or rig, or a satellite reenters. The connection closes right after. When the account lease expires the connection is closed. See SimTX API/Session status.
Limits
- The power is capped by the PA cap: the bound rig's
paMaxWattsand the account'stx.pa_limit.Ncapability, whichever is lower (BoundStation.pa_cap_watts). Requests above it are reduced to the cap; TxTelemetry shows the actual power. - The number of simultaneous transmitters per account and per station is limited. See SimTX API/Limits and errors.
Example
Building a station-bound TransmitterStart and an audio SampleBlock with the helpers of Quick start:
import uuid
# Ids from the game ticket response ("station": {"stationId", "antennaId", "rigId"})
station_id = uuid.UUID("3f2504e0-4f89-41d3-9a0c-0305e82c3301").bytes
antenna_id = uuid.UUID("9b2c1e47-2f0a-4c55-8d1e-6a7b8c9d0e1f").bytes
binding = f_bytes(1, station_id) + f_bytes(2, antenna_id) # rig_id empty: the rig the ticket bound
start = (
f_bytes(1, f_bytes(1, binding)) # site { station { ... } }
+ f_bytes(3, "USB") # modulation
+ f_double(4, 14_230_000.0) # frequency_hz
+ f_float(5, 100.0) # power_watts
+ f_bytes(6, "AUDIO_STREAM") # source_type
+ f_varint(7, 48_000) # sample_rate
+ f_float(8, 1.0) # audio_gain
+ f_float(9, 2_700.0) # bandwidth_hz
+ f_float(10, 300.0) # audio_low_cut_hz
+ f_float(12, 1.0) # duty_cycle; tone_hz (11) stays 0
)
send_frame(sock, 12, start) # transmitter_start
def sample_block(samples): # SampleBlock { audio: PackedFloats { values } }
packed = struct.pack("<%df" % len(samples), *samples)
return f_bytes(1, f_bytes(1, packed))
# after TxAccept, every 20 ms:
send_frame(sock, 13, sample_block(block)) # samples
Checklist
- Obtain a bearer credential through device login (scope
game.transmit) or a personal credential. GET /api/v1/stations; pick an ACTIVE station (or a DEORBITING satellite before its reentry), an antenna and optionally a rig.POST /api/v1/game-ticketswith{"serverId": ..., "role": "tx-audio", "stationId": ..., "antennaId": ..., "rigId": ...}.- Connect with TLS. Send the preface and a
hellowithrole = ROLE_TX_AUDIO,auth = AUTH_KIND_GAME_TICKETand the ticket. RequireHELLO_STATUS_ACCEPTED. - Send
transmitter_startwithsite.stationand the signal parameters. - Read
session_status(BOUND: show the station;REJECTED: show the code and reason), thentx_queueframes untiltx_accept. - Stream
samplesin real time. Read telemetry on another thread. - Use
tx_updatefor live changes. Close the socket to go off the air. OnENDED, show the reason.