Jump to content

SimTX API/Receiver session: Difference between revisions

From SimTX Wiki
Clanker (talk | contribs)
Protocol v25 reference
Tag: Removed redirect
Clanker (talk | contribs)
Remove development history and server internals
 
Line 1: Line 1:
{{SimTX API navigation}}
{{SimTX API navigation}}
A '''receiver session''' delivers a continuous stream of complex baseband (IQ) samples, as received by a virtual antenna at a chosen place and frequency. It is what SDR software sees when it is connected to SimTX. Receiver sessions use <code>ROLE_RECEIVER</code>. An ad-hoc receiver works without an account; a receiver bound to a persistent station needs a game ticket for it.
A '''receiver session''' delivers a continuous stream of complex baseband (IQ) samples, as received by a virtual antenna at a chosen place and frequency. Receiver sessions use <code>ROLE_RECEIVER</code>. An ad-hoc receiver works without an account; a receiver bound to a persistent station needs a game ticket for it.


== Frames ==
== Frames ==
Line 46: Line 46:
== Placing the receiver ==
== Placing the receiver ==
<code>ReceiverStart.site</code> is a [[SimTX API/Data types#SessionSite|SessionSite]] with exactly one member:
<code>ReceiverStart.site</code> is a [[SimTX API/Data types#SessionSite|SessionSite]] with exactly one member:
* '''Ad hoc''' (<code>adhoc</code>): the client gives a callsign, a [[SimTX API/Data types#GeoPoint|position]] and an [[SimTX API/Data types#AntennaConfig|antenna]]. Works anonymously. This is the simplest way to receive.
* '''Ad hoc''' (<code>adhoc</code>): the client gives a callsign, a [[SimTX API/Data types#GeoPoint|position]] and an [[SimTX API/Data types#AntennaConfig|antenna]]. Works anonymously.
* '''Station-bound''' (<code>station</code>): the receiver uses one of the account's persistent stations, or any PUBLIC station of another account, including satellites. The station dictates the callsign, placement and antenna. The connection must present a <code>receiver</code> [[SimTX API/Game tickets|game ticket]] minted for that station, and the [[SimTX API/Data types#StationBinding|StationBinding]] must match it. See [[SimTX API/Stations]].
* '''Station-bound''' (<code>station</code>): the receiver uses one of the account's persistent stations, or any PUBLIC station of another account, including satellites. The station dictates the callsign, placement and antenna. The connection must present a <code>receiver</code> [[SimTX API/Game tickets|game ticket]] minted for that station, and the [[SimTX API/Data types#StationBinding|StationBinding]] must match it. See [[SimTX API/Stations]].


Line 59: Line 59:


=== Block size ===
=== Block size ===
Each IQ block carries exactly <code>chunk_samples</code> complex samples. The requested value is clamped to at least 1,024 and at most the smaller of 1,200,000 and the number of samples in a fixed duration at the negotiated rate. That duration is '''40 ms''' on the clustered public deployment and 0.5 s on a stand-alone server. At 48,000 samples per second on the public server, blocks are 1,920 samples long whatever the client asks for.
Each IQ block carries exactly <code>chunk_samples</code> complex samples. The requested value is clamped to at least 1,024 and at most the smaller of 1,200,000 and the number of samples in a fixed duration at the negotiated rate. That duration is a server setting: '''40 ms''' on <code>argon.simtx.net</code>, 0.5 s by default. At 48,000 samples per second on <code>argon.simtx.net</code>, blocks are 1,920 samples long whatever the client asks for.


=== Bandwidth ===
=== Bandwidth ===
Line 68: Line 68:


=== Noise figure ===
=== Noise figure ===
<code>noise_figure_db</code> is the receiver's front-end noise figure. Unset, it is the bound rig's noise figure, or 6 dB. Real HF receivers are typically 3 to 8 dB; HF reception is usually limited by external noise anyway.
<code>noise_figure_db</code> is the receiver's front-end noise figure. Unset, it is the bound rig's noise figure, or 6 dB. Typical values are 3 to 8 dB.


== Decoding samples ==
== Decoding samples ==
Line 75: Line 75:
<code>x = q × scale / 32767</code> (INT16) or <code>x = q × scale / 127</code> (INT8)
<code>x = q × scale / 32767</code> (INT16) or <code>x = q × scale / 127</code> (INT8)


The server chooses <code>scale</code> as the peak magnitude of the block, so the integers always use the full range and small signals keep their precision. Check that <code>samples</code> is exactly <code>chunk_samples × 2 × bytesPerComponent</code> bytes long and reject anything else.
The server chooses <code>scale</code> as the peak magnitude of the block. Check that <code>samples</code> is exactly <code>chunk_samples × 2 × bytesPerComponent</code> bytes long and reject anything else.


A sample with magnitude 1.0 corresponds to '''−12 dBm''' at the receiver input. The server clips each component to ±1.0 before quantising, so a receiver next to a strong transmitter overloads exactly like a real one. To convert a block's mean power to dBm:
A sample with magnitude 1.0 corresponds to '''−12 dBm''' at the receiver input. The server clips each component to ±1.0 before quantising, so a strong signal overloads the receiver. To convert a block's mean power to dBm:


<code>P(dBm) = −12 + 10 × log10( mean(I² + Q²) )</code>
<code>P(dBm) = −12 + 10 × log10( mean(I² + Q²) )</code>


=== What the samples contain ===
=== What the samples contain ===
The IQ stream is the signal at the output of the receiving antenna, after the antenna's pattern, the feed line loss and the noise figure. It includes everything a real receiver would hear: every transmitter in range with its propagation path, fading and Doppler shift, plus atmospheric, galactic and man-made noise. It does not include receiver hardware imperfections such as tuner roll-off, local-oscillator phase noise or image responses. Software that wants to imitate a particular radio adds those itself.
The IQ stream is the signal at the output of the receiving antenna, after the antenna's pattern, the feed line loss and the noise figure. It includes everything a real receiver would hear: every transmitter in range with its propagation path, fading and Doppler shift, plus atmospheric, galactic and man-made noise. It does not include receiver hardware imperfections such as tuner roll-off, local-oscillator phase noise or image responses.


== Timestamps ==
== Timestamps ==
With <code>timestamped</code> set in the start, every block carries the UTC instant of its first sample on the server's simulated RF timeline (<code>first_sample_epoch_seconds</code> and <code>first_sample_nanos</code>). Timestamps of different receivers are directly comparable, which makes them suitable for time-difference-of-arrival (TDOA) direction finding, aligning several receivers, or measuring end-to-end latency. Timestamps work with or without an account. The v24 role <code>TIMESTAMPED_RECEIVER</code> is gone.
With <code>timestamped</code> set in the start, every block carries the UTC instant of its first sample on the server's simulated RF timeline (<code>first_sample_epoch_seconds</code> and <code>first_sample_nanos</code>). Timestamps of different receivers are directly comparable. Timestamps work with or without an account.


== Sequence numbers ==
== Sequence numbers ==
<code>IqBlock.sequence</code> numbers the blocks of a stream: 1 for the first block, one more for each block after it, across retunes and moves between server nodes. A step larger than 1 means that the server dropped blocks for this stream, because of backpressure, a retune or a move. 0 means the sender does not number blocks.
<code>IqBlock.sequence</code> numbers the blocks of a stream: 1 for the first block, one more for each block after it, across retunes. A step larger than 1 means that the server dropped blocks for this stream. 0 means the sender does not number blocks.


== Retuning ==
== Retuning ==
Line 103: Line 103:
* The server queues up to 8 blocks per connection. When the queue is full, the '''oldest''' block is discarded, and the gap shows in <code>sequence</code>.
* The server queues up to 8 blocks per connection. When the queue is full, the '''oldest''' block is discarded, and the gap shows in <code>sequence</code>.
* If the client does not read for 5 seconds, the server closes the connection.
* If the client does not read for 5 seconds, the server closes the connection.
* Read the socket on a dedicated thread and hand blocks to processing through a queue of your own, so that slow processing does not stall reading.
* Read the socket on a dedicated thread and hand blocks to processing through a queue of your own.
 
Through the public gateway, a receiver may be moved from one server node to another. The client sees a short gap, but the connection and the stream continue.


== Failure ==
== Failure ==

Latest revision as of 17:14, 24 October 2026

A receiver session delivers a continuous stream of complex baseband (IQ) samples, as received by a virtual antenna at a chosen place and frequency. Receiver sessions use ROLE_RECEIVER. An ad-hoc receiver works without an account; a receiver bound to a persistent station needs a game ticket for it.

Frames[edit | edit source]

Direction # Message When
C2S 3 ForwardedClientAddress Optional, trusted proxies only, before the start.
C2S 10 ReceiverStart Once, right after the hello.
S2C 10 SessionStatus BOUND or REJECTED after the start; later UPDATED and ENDED.
S2C 11 IqStreamDescriptor Once, after BOUND.
S2C 12 IqBlock Continuously.
C2S 11 ReceiverRetune Any time, to change frequency.
C2S 16 AntennaPointingUpdate Station-bound sessions, to steer the antenna.
C2S / S2C 2 Ping / Pong Any time.
S2C 3 Error When a retune or pointing request fails, or on a protocol violation.

Sequence[edit | edit source]

 client                                                  server
   | -- preface, [1] hello (ROLE_RECEIVER) --------------> |
   | <---------------------------- [1] hello_result       |
   | -- [10] receiver_start -----------------------------> |
   | <---------------------------- [10] session_status    |   BOUND
   | <---------------------------- [11] iq_descriptor     |
   | <---------------------------- [12] iq                |   sequence 1
   | <---------------------------- [12] iq                |   sequence 2
   | -- [11] receiver_retune (request_id 7) -------------> |   (optional, any time)
   | <---------------------------- [12] iq                |
   | <---------------------------- [10] session_status    |   UPDATED, RETUNE, request_id 7
   | <---------------------------- [12] iq                |
   |                    ...                               |

After the start, a client may send only ReceiverRetune, AntennaPointingUpdate and Ping. Any other frame is answered with Error INVALID_REQUEST and the connection closes.

Placing the receiver[edit | edit source]

ReceiverStart.site is a SessionSite with exactly one member:

  • Ad hoc (adhoc): the client gives a callsign, a position and an antenna. Works anonymously.
  • Station-bound (station): the receiver uses one of the account's persistent stations, or any PUBLIC station of another account, including satellites. The station dictates the callsign, placement and antenna. The connection must present a receiver game ticket minted for that station, and the StationBinding must match it. See SimTX API/Stations.

A receiver on a satellite hears the uplink: the signals that reach the satellite's antenna in orbit.

Negotiation[edit | edit source]

The start states what the client would like; the IqStreamDescriptor states what it gets. Always use the values from the descriptor.

Sample rate[edit | edit source]

  • A requested rate up to 2,400,000 samples per second is narrowband. It is clamped to the range 24,000 to 2,400,000.
  • A requested rate above 2,400,000 is wideband. The rate becomes the smaller of the request and 32,000,000, and the block size is fixed at 16,384 samples. Wideband capacity is budgeted at 32 million samples per second per client address, plus a server-wide budget. A start over budget is refused with LIMIT_REACHED.

Block size[edit | edit source]

Each IQ block carries exactly chunk_samples complex samples. The requested value is clamped to at least 1,024 and at most the smaller of 1,200,000 and the number of samples in a fixed duration at the negotiated rate. That duration is a server setting: 40 ms on argon.simtx.net, 0.5 s by default. At 48,000 samples per second on argon.simtx.net, blocks are 1,920 samples long whatever the client asks for.

Bandwidth[edit | edit source]

The receiver's filter bandwidth is the requested bandwidth_hz, limited to at most the larger of 24,000 Hz and the sample rate, and to at least 50 Hz.

Sample format[edit | edit source]

sample_format selects 16-bit (SAMPLE_FORMAT_INT16, 0, the default) or 8-bit (SAMPLE_FORMAT_INT8, 1) samples. The descriptor confirms the format.

Noise figure[edit | edit source]

noise_figure_db is the receiver's front-end noise figure. Unset, it is the bound rig's noise figure, or 6 dB. Typical values are 3 to 8 dB.

Decoding samples[edit | edit source]

Each IqBlock has a per-block floating-point scale and a samples payload of interleaved I and Q integers, big-endian:

x = q × scale / 32767 (INT16) or x = q × scale / 127 (INT8)

The server chooses scale as the peak magnitude of the block. Check that samples is exactly chunk_samples × 2 × bytesPerComponent bytes long and reject anything else.

A sample with magnitude 1.0 corresponds to −12 dBm at the receiver input. The server clips each component to ±1.0 before quantising, so a strong signal overloads the receiver. To convert a block's mean power to dBm:

P(dBm) = −12 + 10 × log10( mean(I² + Q²) )

What the samples contain[edit | edit source]

The IQ stream is the signal at the output of the receiving antenna, after the antenna's pattern, the feed line loss and the noise figure. It includes everything a real receiver would hear: every transmitter in range with its propagation path, fading and Doppler shift, plus atmospheric, galactic and man-made noise. It does not include receiver hardware imperfections such as tuner roll-off, local-oscillator phase noise or image responses.

Timestamps[edit | edit source]

With timestamped set in the start, every block carries the UTC instant of its first sample on the server's simulated RF timeline (first_sample_epoch_seconds and first_sample_nanos). Timestamps of different receivers are directly comparable. Timestamps work with or without an account.

Sequence numbers[edit | edit source]

IqBlock.sequence numbers the blocks of a stream: 1 for the first block, one more for each block after it, across retunes. A step larger than 1 means that the server dropped blocks for this stream. 0 means the sender does not number blocks.

Retuning[edit | edit source]

A ReceiverRetune moves the centre frequency without reconnecting. The rate, block size, bandwidth and sample format stay the same, and no new descriptor is sent. The change takes effect after a settling time of about 120 ms; retunes received during that time are coalesced and only the latest is applied. Expect a short gap or transient.

With a nonzero request_id, the server confirms the retune with SessionStatus UPDATED, update_reason = UPDATE_REASON_RETUNE, the same request_id and the new frequency_hz, once the stream runs on the new frequency. A retune superseded by a later one before it took effect gets no confirmation of its own.

To change the sample rate or bandwidth, open a new connection.

Tracking and pointing[edit | edit source]

A station-bound receiver can follow a target, usually a satellite, from the start (ReceiverStart.tracking) or later (AntennaPointingUpdate). With doppler_correct, the receiver's tuning is shifted by the target's Doppler, so a satellite's signal stays at the same offset in the passband during a pass. See SimTX API/Tracking and pointing.

Flow control[edit | edit source]

  • The server queues up to 8 blocks per connection. When the queue is full, the oldest block is discarded, and the gap shows in sequence.
  • If the client does not read for 5 seconds, the server closes the connection.
  • Read the socket on a dedicated thread and hand blocks to processing through a queue of your own.

Failure[edit | edit source]

A start that cannot be accepted is answered with SessionStatus REJECTED, an error code and a reason: invalid values (INVALID_REQUEST), a binding that does not match the ticket (FORBIDDEN), a deleted station or a reentered satellite (STATION_INACTIVE), or a server, per-address, account or station limit or the wideband budget (LIMIT_REACHED). A running session that the server stops gets ENDED. See SimTX API/Session status and SimTX API/Limits and errors.

Checklist[edit | edit source]

  1. Connect with TLS to the host and port from the server directory. Set TCP_NODELAY.
  2. Send the preface 53 49 4D 54 00 00 00 19 and a hello frame: role = ROLE_RECEIVER; for a station-bound receiver also auth = AUTH_KIND_GAME_TICKET and the ticket.
  3. Read the hello_result; require HELLO_STATUS_ACCEPTED.
  4. Send receiver_start with a site, the centre frequency, bandwidth, sample rate and block size.
  5. Read session_status; stop on REJECTED and show its code and reason. Then read iq_descriptor.
  6. Loop on iq: decode samples (big-endian integer pairs) with scale, check sequence for gaps, and skip frames you do not handle.
  7. To retune, send receiver_retune.

A complete working program is on Quick start.

SimTX API reference (protocol v25)
Start OverviewQuick startFramingData typesPacket listSchemaLimits and errorsCompatibility and versioning
Account service OverviewDevice loginServer directoryStation endpointsGame ticketsPermissionsPublic endpoints
Game protocol Connection and handshakeSession statusReceiver sessionTransmitter sessionControl sessionCatalogModeration
Stations StationsSatellitesTracking and pointing
Connection ClientHelloPingServerHelloPongErrorBanner
Session AntennaPointingUpdateSessionStatus
Receiver ForwardedClientAddressReceiverStartReceiverRetuneIqStreamDescriptorIqBlock
Transmitter TransmitterStartSampleBlockTxUpdateTxModeInfoTxQueueTxAcceptTxTelemetryTxUpdateAck
Control ListStationsStartMonitorStopMonitorWeatherMapRequestServerHealthRequestCoverageMapRequestEphemerisRequestPassPredictionRequestStationListMonitorBlockMonitorEndWeatherMapResponseServerHealthReportCoverageMapResponseEphemerisResponsePassPredictionResponseMonitorAck
Catalog CatalogListRequestCatalogFetchCatalogUploadCatalogDeleteCatalogListCatalogEntryCatalogUploadResultCatalogDeleteResult
Moderation KickRequestIpModerationRequestBroadcastBannerKickResultIpModerationResultStationImpactList
Archive Protocol v24 reference