Radio Control¶
OrbitDeck now includes a native Icom CI-V control path for direct rig validation and pass-driven control from the rotator screen.
This page documents the current controller scope, the session model, and the operating assumptions behind the radio API.
Current controller scope¶
Supported rig models in the persisted settings model:
ic705id5100
Current implementation status:
ic705has live-validated connect, poll, direct frequency write, and manual pair applicationid5100has controller and settings scaffolding, but not the same level of live validation
The radio stack lives under:
app/radio/civ.pyapp/radio/transport.pyapp/radio/service.pyapp/radio/controllers/ic705.pyapp/radio/controllers/id5100.py
Transport and connection model¶
OrbitDeck uses a native serial CI-V transport. Connection state is configured through RadioSettings and opened through the radio service.
The basic operator flow is:
- Save radio settings.
- Connect the rig.
- Poll the rig to confirm CI-V exchange.
- Apply a direct frequency, manual pair, or recommendation-driven target.
Important distinction:
- a serial port opening successfully only proves that OrbitDeck could open the device
- a successful poll proves that OrbitDeck exchanged CI-V commands and received usable state back from the rig
IC-705 VFO identity¶
OrbitDeck treats VFO A and VFO B on the IC-705 as absolute identities.
That matters because the radio's raw CI-V reads expose selected and unselected VFO state. OrbitDeck maps those reads back into absolute A/B slots instead of presenting selected and unselected values as if they were stable labels.
Behaviour:
- on connect, OrbitDeck explicitly selects
VFO A - poll logic maps selected and unselected readback into absolute
VFO AandVFO B - after a manual
VFO Bwrite, OrbitDeck restoresVFO Aas the selected working VFO
Direct actions¶
POST /api/v1/radio/frequency¶
This writes one frequency to one VFO.
Use it for:
- confirming a live write path
- checking that poll/readback matches a manual frequency change
- validating VFO identity behavior on a rig
POST /api/v1/radio/pair¶
This applies a manual uplink/downlink pair without relying on a live pass selection.
Current IC-705 pair behavior:
- disable split
- set
VFO Afrequency - set
VFO Amode - set
VFO Bfrequency - set
VFO Bmode - re-enable split
Default mode behavior:
uplink_modedefaults toFMif omitteddownlink_modedefaults toFMif omitted
The response includes:
- updated runtime
- the derived manual recommendation object
targetMapping
targetMapping describes which logical transmit and receive paths OrbitDeck used for the write.
Recommendation-driven actions¶
POST /api/v1/radio/apply¶
This applies the current recommendation for one satellite.
The request can include:
sat_idpass_aospass_losselected_column_indexlocation_sourceapply_mode_and_tone
OrbitDeck resolves the same backend recommendation model used by kiosk, rotator, lite, and GET /api/v1/frequency-guides/recommendation, then maps that recommendation into rig targets.
POST /api/v1/radio/auto-track/start¶
This starts periodic reapplication of the selected recommendation at the configured interval.
Use it when you want recommendation-driven retuning without using the rotator session model.
POST /api/v1/radio/auto-track/stop¶
This stops the background recommendation reapply loop and returns the runtime to idle.
Rotator radio-control session¶
The rotator uses a session model so that radio control can stay pinned to one selected pass.
Session state lives in:
GET /api/v1/radio/sessionGET /api/v1/radio/stateGET /api/v1/system/state
Selection starts with:
POST /api/v1/radio/session/select
The session stores:
- selected satellite identity
- selected pass AOS and LOS
- max elevation
- eligibility state
- default test-pair state
Screen states¶
idletestarmedactivereleasedcompleted
Control states¶
not_connectedconnected_idletest_appliedarmed_waiting_aostracking_activereleasedended
Session workflow¶
- Select a pass from the rotator view.
- OrbitDeck resolves the default test pair from the existing frequency-guide data.
POST /api/v1/radio/session/testapplies that pair and marks the sessiontest.POST /api/v1/radio/session/test/confirmreleases OrbitDeck control while keeping the session card active.POST /api/v1/radio/session/starteither:- arms the session if AOS is in the future
- or starts active tracking immediately if the pass is already above the horizon
POST /api/v1/radio/session/stopstops control and releases the session.- After LOS, OrbitDeck ends the session automatically and restores the previous rig snapshot when possible.
Eligibility rules¶
The rotator radio-control workflow currently enforces a VHF/UHF eligibility rule.
Supported ranges:
- VHF:
144.000 MHzto148.000 MHz - UHF:
420.000 MHzto450.000 MHz
Behaviour:
- a recommendation is eligible if either side lands in the supported VHF/UHF range
- receive-only downlink recommendations remain eligible when the downlink is in range
- out-of-range pairs are marked ineligible and expose
eligibility_reason
This rule is used for:
- rotator session selection
- default test-pair availability
- pass-driven start/arm actions
IC-705 operating defaults used by OrbitDeck¶
When OrbitDeck applies a satellite target on the IC-705, it also configures a few operating defaults used by the current controller:
- squelch is opened to
0 - scope display is enabled
- scope mode is set to center
- scope span is set to
1,000,000 Hz
Those values are part of the current controller behavior and are covered by API tests.
Restore behavior¶
Before a rotator test or session-controlled apply, OrbitDeck can capture a rig snapshot.
When the session is released, stopped, or ends after LOS, OrbitDeck attempts to restore:
- prior VFO frequencies
- prior VFO modes
- split state
- squelch level
- scope state
If the restore fails, OrbitDeck records the failure in runtime.last_error and leaves the session in a released state instead of failing the request outright.
Known operational notes¶
- Manual writes can be followed by an intermittent
timeout waiting for CI-V response to 0x25 - When that happens, the rig may still have applied the write successfully
- OrbitDeck keeps the last known good target values in runtime when a later readback is incomplete
- Poll again after the write if you need a fresh confirmed readback