Welcome to icom-lan Discussions! #558
Replies: 8 comments 1 reply
|
Stellar work Sergey. My use case involves LAN-based control of an Icom IC-9700 transceiver. The primary objective is to build a system that rapidly and reliably switches the rig between distinct operating profiles. Target configurations include:
Profile selection is initiated by pressing buttons on a Stream Deck, which publishes MQTT messages to the local network. A custom Python gateway subscribes to these topics and executes multiple radio.send_civ() commands. While the core functionality works, the Python gateway cannot currently run concurrently with the companion RigPlane web server. Additionally, the rigctl 'w' (send raw command) instruction fails to execute properly. To achieve a more streamlined, decoupled architecture, can raw CI-V commands be encapsulated and transmitted directly via curl POST to a RigPlane WEB API endpoint? If so, can you please show me an example? |
|
Hi,
Thanks for the detailed setup notes.
On raw CI-V over HTTP
The stable HTTP surface published at https://rigplane.dev/api/web/ does not include a raw-CI-V passthrough endpoint. Documented control endpoints are: POST /api/v1/radio/connect, POST /api/v1/radio/disconnect, POST /api/v1/radio/power, and POST /api/v1/band-plan/config. Nothing accepts arbitrary CI-V frames over HTTP.
The documented WebSocket route /api/v1/ws accepts JSON command envelopes of the form:
json
{"type":"cmd","id":"42","name":"set_freq","params":{"freq":144030000,"receiver":0}}
The envelope and one worked example (set_freq) plus the set_band workflow are in the docs. The full list of accepted namevalues is currently only in the source (src/rigplane/web/handlers/control.py), and the docs explicitly flag the non-contract surface as subject to change. If you depend on a specific command name today, plan for the possibility that it gets renamed before it's promoted into the stable contract.
Authentication on /api/v1/ws is conditional: when the server is started with --auth-token / --auth-token-file / RIGPLANE_AUTH_TOKEN, the WebSocket requires either an Authorization: Bearer <token> header or a ?token=<token> query parameter; when no auth token is configured, the WebSocket accepts connections without authentication.
On the rigctld w command
The w command is implemented in the codebase. src/rigplane/rigctld/contract.py defines it as short w / long send_raw, min_args=1, max_args=128. The handler in src/rigplane/rigctld/handler.py accepts two input formats:
w FE FE A2 E0 03 FD
w \xFE\xFE\xA2\xE0\x03\xFD
(0xA2 is the default CI-V address for the IC-9700.)
The handler calls _send_civ_raw on the underlying radio object. If that method is absent on the active backend, the handler returns Hamlib ENIMPL; on timeout it returns an empty response; on success it returns the response frame as space-separated uppercase hex.
Worth noting: the IC-9700 is listed on https://rigplane.dev/ as "Profile — not yet tested" — depending on which backend you're using for it, _send_civ_raw may not be wired up.
To narrow down your failure, could you send:
RigPlane version.
Which IC-9700 backend you're using (native LAN, USB serial, or external Hamlib rigctld provider — see https://rigplane.dev/guide/ic9700-usb-setup/).
The exact w … line you're sending, the rigctld port/host, and the client sending it.
The exact response you get back (including any RPRT code).
Any relevant lines from the RigPlane log around the call.
CI-V command reference (for sanity-checking byte sequences): https://rigplane.dev/guide/commands/.
73,
Sincerely,
Sergey Morozik
***@***.***
… On May 26, 2026, at 3:56 AM, AI7BQ ***@***.***> wrote:
Stellar work Sergey. My use case involves LAN-based control of an Icom IC-9700 transceiver. The primary objective is to build a system that rapidly and reliably switches the rig between distinct operating profiles. Target configurations include:
VARA FM (Data): Tuned to 144.030 MHz with dedicated audio levels routed via USB Audio.
FM VOICE: Configured for standard analog voice using the chassis microphone.
AllStarLink Voice: Utilizing the accessory (ACC) port for analog audio input/output.
Memory Recall: Direct selection of memory channels.
Profile selection is initiated by pressing buttons on a Stream Deck, which publishes MQTT messages to the local network. A custom Python gateway subscribes to these topics and executes multiple radio.send_civ() commands.
While the core functionality works, the Python gateway cannot currently run concurrently with the companion RigPlane web server. Additionally, the rigctl 'w' (send raw command) instruction fails to execute properly.
To achieve a more streamlined, decoupled architecture, can raw CI-V commands be encapsulated and transmitted directly via curl POST to a RigPlane WEB API endpoint? If so, can you please show me an example?
—
Reply to this email directly, view it on GitHub <#558?email_source=notifications&email_token=ABBQWA72CWOKNQLQGB7TWHD44VE2DA5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCNZQGU4TCMZRUZZGKYLTN5XKMYLVORUG64VFMV3GK3TUVRTG633UMVZF6Y3MNFRWW#discussioncomment-17059131>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/ABBQWA5NEELXUBFQQQFWQD344VE2DAVCNFSM6AAAAACXUNMZKWVHI2DSMVQWIX3LMV43URDJONRXK43TNFXW4Q3PNVWWK3TUHMYTOMBVHEYTGMI>.
You are receiving this because you authored the thread.
|
|
Sergey,
First off, thank you for the thorough diagnostic breakdown and, even more
so, for turning my use case into a formal feature specification so quickly.
That was well above and beyond.
The HTTP interface is exactly what I was hoping for. While I think most
users would be happy to handle the batching themselves by simply issuing
sequences of REST calls, the batch endpoint in particular maps perfectly
onto the profile-switching workflow: ordered execution, pacing through the
existing command queue, and deterministic partial-failure reporting are
precisely the semantics needed to reliably switch the IC-9700 between VARA
FM, FM Voice, AllStarLink, and memory configurations from a Stream
Deck/MQTT gateway. Though I'm not sure how the batch endpoint would work.
Perhaps a "batch builder" API would be used to define the sequence and
another "batch executor" API would trigger different batches by name.
Having RigPlane own the radio connection and act as the single control
authority is the right architecture. I was working around the absence of
this, and it shows.
I'll work against the WebSocket command channel in the meantime and keep
the gateway structure clean enough that migrating to the HTTP endpoints
will be straightforward once they land.
If it would be useful, I'm happy to serve as a test case for the IC-9700
backend during development, or to contribute to the curl/Python/MQTT
gateway examples flagged in the child issues. The MQTT > REST API >
RigPlane > IC-9700 flow feels like a natural reference implementation for
that documentation.
Looking forward to seeing this progress. Stellar work as always. I am a
huge fan.
*Failure Context*
- *RigPlane version:* 2.2.0
- *Which IC-9700 backend you're using:* Native LAN (provided by RigPlane)
- *The exact w … line you're sending:* w FE FE A2 E0 03 FD
- *The rigctld port/host:* 4532/localhost
- *The client sending it:* rigctl
- *The exact response you get back (including any RPRT code)*: Gibberish
(In Putty SSH session window).
[image: image.png]
- CI-V command reference (for sanity-checking byte sequences)
- [image: image.png]
[image: image.png]
- *Any relevant lines from the RigPlane log around the call.*
```
/root/rigplane-env/bin/rigplane \
--backend lan \
--model IC-9700 \
--host 192.168.1.19 \
--user AI7BQ \
--pass-file /root/rigplane-env/passfile.conf \
serve
Logging to /utils/logs/rigplane.log (rotate at 50000000 bytes, keep 5
backups)
21:48:25 DEBUG Loaded 7 rig profiles from
/root/rigplane-env/lib/python3.11/site-packages/rigplane/rigs: FTX-1,
IC-705, IC-7300, IC-7610, IC-9700, TX-500, X6100
21:48:25 INFO UDP open to 192.168.1.19:50001, my_id=0x0001ECBC
21:48:25 INFO I Am Here received, remote_id=0xD5CD9C88
21:48:25 INFO I Am Ready received
21:48:25 INFO Discovery complete, remote_id=0xD5CD9C88
21:48:25 INFO Authenticated with 192.168.1.19:50001, token=0xAF14D406
21:48:25 DEBUG Token ack sent (token=0xAF14D406)
21:48:26 DEBUG Got radio GUID: 000000000000001080000090c70d9161
21:48:26 DEBUG Reserved local ports on 192.168.1.55: civ=60394, audio=42440
21:48:26 DEBUG Conninfo sent (civ_local=60394, audio_local=42440)
21:48:26 INFO Status: civ_port=50002, audio_port=50003, error=0x00000000,
disconnected=False
21:48:26 INFO UDP open to 192.168.1.19:50002, my_id=0x0001EBEA
21:48:26 INFO I Am Here received, remote_id=0x7003637A
21:48:26 INFO I Am Ready received
21:48:26 INFO Discovery complete, remote_id=0x7003637A
21:48:26 DEBUG OpenClose(open) sent
21:48:26 DEBUG idle-keepalive: sent #1 (send_seq=2, rx_count=7)
21:48:27 INFO civ-data-watchdog: started
21:48:27 INFO Connected to 192.168.1.19 (control=50001, civ=50002)
21:48:27 DEBUG Skipping query 0x16/0x4E: capability 'digisel' not supported
by IC-9700
21:48:27 DEBUG Skipping query 0x16/0x4E: capability 'digisel' not supported
by IC-9700
21:48:27 INFO initial state fetch (63 queries, gap=12ms)...
21:48:27 DEBUG civ-rx: cmd=0x25 sub=0x00 to=0xE0 data=000050154501
21:48:27 DEBUG civ-rx: cmd=0x26 sub=0x00 to=0xE0 data=00050001
21:48:27 DEBUG civ-rx: cmd=0x11 sub=0x00 to=0xE0 data=00
21:48:27 DEBUG civ-rx: cmd=0x14 sub=0x01 to=0xE0 data=0074
21:48:27 DEBUG civ-rx: cmd=0x14 sub=0x02 to=0xE0 data=0255
21:48:27 DEBUG civ-rx: cmd=0x14 sub=0x03 to=0xE0 data=0092
21:48:27 DEBUG civ-rx: cmd=0x16 sub=0x02 to=0xE0 data=00
21:48:27 DEBUG civ-rx: cmd=0x16 sub=0x22 to=0xE0 data=00
21:48:27 DEBUG civ-rx: no callback for nb_changed
21:48:27 DEBUG civ-rx: cmd=0x16 sub=0x40 to=0xE0 data=00
21:48:27 DEBUG civ-rx: no callback for nr_changed
21:48:27 DEBUG civ-rx: cmd=0x16 sub=0x65 to=0xE0 data=00
21:48:27 DEBUG civ-rx: no callback for ipplus_changed
21:48:27 DEBUG civ-rx: no callback for ipplus_changed
21:48:27 DEBUG civ-rx: cmd=0x16 sub=0x42 to=0xE0 data=00
21:48:27 DEBUG civ-rx: no callback for repeater_tone_changed
21:48:27 DEBUG civ-rx: cmd=0x16 sub=0x43 to=0xE0 data=00
21:48:27 DEBUG civ-rx: no callback for repeater_tsql_changed
21:48:27 DEBUG civ-rx: cmd=0x1B sub=0x00 to=0xE0 data=001000
21:48:27 DEBUG civ-rx: cmd=0x1B sub=0x01 to=0xE0 data=001000
21:48:27 DEBUG civ-rx: cmd=0x14 sub=0x06 to=0xE0 data=0072
21:48:27 DEBUG civ-rx: cmd=0x14 sub=0x12 to=0xE0 data=0128
21:48:27 DEBUG civ-rx: cmd=0x14 sub=0x0D to=0xE0 data=0128
21:48:27 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:27 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:27 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:28 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:28 DEBUG civ-rx: cmd=0x15 sub=0x01 to=0xE0 data=00
21:48:28 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:28 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:28 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:28 DEBUG civ-rx: cmd=0x1C sub=0x00 to=0xE0 data=00
21:48:28 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:28 DEBUG civ-rx: cmd=0x1C sub=0x03 to=0xE0 data=0050154501
21:48:28 DEBUG civ-rx: cmd=0x14 sub=0x0A to=0xE0 data=0064
21:48:28 DEBUG civ-rx: cmd=0x14 sub=0x0B to=0xE0 data=0128
21:48:28 DEBUG civ-rx: cmd=0x14 sub=0x0E to=0xE0 data=0104
21:48:28 DEBUG civ-rx: cmd=0x14 sub=0x15 to=0xE0 data=0128
21:48:28 DEBUG civ-rx: cmd=0x14 sub=0x09 to=0xE0 data=0089
21:48:28 DEBUG civ-rx: cmd=0x14 sub=0x0C to=0xE0 data=0000
21:48:28 DEBUG civ-rx: cmd=0x0F sub=0x00 to=0xE0 data=00
21:48:28 DEBUG civ-rx: cmd=0x07 sub=0x00 to=0xE0 data=d200
21:48:28 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:28 DEBUG civ-rx: cmd=0x21 sub=0x00 to=0xE0 data=000000
21:48:28 DEBUG civ-rx: no callback for rit_freq_changed
21:48:28 DEBUG civ-rx: cmd=0x21 sub=0x01 to=0xE0 data=00
21:48:28 DEBUG civ-rx: no callback for rit_changed
21:48:28 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:28 DEBUG civ-rx: cmd=0x16 sub=0x12 to=0xE0 data=01
21:48:28 DEBUG civ-rx: no callback for agc_changed
21:48:28 DEBUG civ-rx: cmd=0x16 sub=0x44 to=0xE0 data=00
21:48:28 DEBUG civ-rx: no callback for compressor_changed
21:48:28 DEBUG civ-rx: cmd=0x16 sub=0x45 to=0xE0 data=00
21:48:28 DEBUG civ-rx: no callback for monitor_changed
21:48:28 DEBUG civ-rx: cmd=0x16 sub=0x46 to=0xE0 data=00
21:48:28 DEBUG civ-rx: no callback for vox_changed
21:48:28 DEBUG civ-rx: cmd=0x16 sub=0x47 to=0xE0 data=00
21:48:28 DEBUG civ-rx: no callback for break_in_changed
21:48:28 DEBUG civ-rx: cmd=0x16 sub=0x50 to=0xE0 data=00
21:48:28 DEBUG civ-rx: no callback for dial_lock_changed
21:48:28 DEBUG civ-rx: cmd=0x14 sub=0x16 to=0xE0 data=0128
21:48:29 DEBUG civ-rx: cmd=0x14 sub=0x17 to=0xE0 data=0153
21:48:29 DEBUG civ-rx: cmd=0x14 sub=0x0F to=0xE0 data=0128
21:48:29 DEBUG civ-rx: cmd=0x15 sub=0x07 to=0xE0 data=00
21:48:29 DEBUG civ-rx: cmd=0x16 sub=0x58 to=0xE0 data=01
21:48:29 DEBUG civ-rx: no callback for ssb_tx_bandwidth_changed
21:48:29 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:29 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:29 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:29 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:29 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:29 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:29 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:29 DEBUG civ-rx: cmd=0xFA sub=0x00 to=0xE0 data=
21:48:29 INFO initial state fetch done (63/63 ok)
--- rigplane v2.2.0 ---
Radio: IC-9700 at 192.168.1.19
rigctld: 0.0.0.0:4532
---
21:48:29 INFO rigctld listening on 0.0.0.0:4532
21:48:31 INFO client #1 connected from 127.0.0.1:57760
21:48:31 INFO AuditRecord(timestamp='2026-05-27T04:48:31.894020+00:00',
client_id=1, peername='127.0.0.1:57760', cmd='\\chk_vfo',
long_cmd='chk_vfo', args=(), duration_ms=0.075, rprt=0, is_set=False,
vfo=None)
21:48:31 INFO AuditRecord(timestamp='2026-05-27T04:48:31.894846+00:00',
client_id=1, peername='127.0.0.1:57760', cmd='\\dump_state',
long_cmd='dump_state', args=(), duration_ms=0.084, rprt=0, is_set=False,
vfo=None)
21:48:31 INFO AuditRecord(timestamp='2026-05-27T04:48:31.896472+00:00',
client_id=1, peername='127.0.0.1:57760', cmd='v', long_cmd='get_vfo',
args=(), duration_ms=0.075, rprt=0, is_set=False, vfo=None)
21:48:31 INFO AuditRecord(timestamp='2026-05-27T04:48:31.897384+00:00',
client_id=1, peername='127.0.0.1:57760', cmd='f', long_cmd='get_freq',
args=(), duration_ms=0.079, rprt=0, is_set=False, vfo='VFOA')
21:48:31 ERROR Internal error executing set_vfo
Traceback (most recent call last):
File
"/root/rigplane-env/lib/python3.11/site-packages/rigplane/rigctld/handler.py",
line 467, in execute
return cast(RigctldResponse, await handler_fn(self, cmd))
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File
"/root/rigplane-env/lib/python3.11/site-packages/rigplane/rigctld/handler.py",
line 856, in _cmd_set_vfo
await select_receiver(target)
File
"/root/rigplane-env/lib/python3.11/site-packages/rigplane/runtime/_dual_rx_runtime.py",
line 430, in select_receiver
await self._set_vfo_wire(target)
File
"/root/rigplane-env/lib/python3.11/site-packages/rigplane/runtime/radio.py",
line 2729, in _set_vfo_wire
raise CommandError(f"Radio rejected VFO select {vfo}")
rigplane.core.exceptions.CommandError: Radio rejected VFO select SUB
21:48:31 INFO AuditRecord(timestamp='2026-05-27T04:48:31.907606+00:00',
client_id=1, peername='127.0.0.1:57760', cmd='V', long_cmd='set_vfo',
args=('VFOB',), duration_ms=9.315, rprt=<HamlibError.EINTERNAL: -7>,
is_set=True, vfo=None)
21:48:31 INFO AuditRecord(timestamp='2026-05-27T04:48:31.908566+00:00',
client_id=1, peername='127.0.0.1:57760', cmd='s', long_cmd='get_split_vfo',
args=(), duration_ms=0.065, rprt=0, is_set=False, vfo='VFOA')
21:48:31 INFO AuditRecord(timestamp='2026-05-27T04:48:31.944023+00:00',
client_id=1, peername='127.0.0.1:57760', cmd='V', long_cmd='set_vfo',
args=('VFOA',), duration_ms=34.696, rprt=<HamlibError.OK: 0>, is_set=True,
vfo=None)
21:48:31 INFO AuditRecord(timestamp='2026-05-27T04:48:31.945194+00:00',
client_id=1, peername='127.0.0.1:57760', cmd='m', long_cmd='get_mode',
args=(), duration_ms=0.148, rprt=0, is_set=False, vfo='VFOA')
21:48:31 ERROR Internal error executing set_vfo
Traceback (most recent call last):
File
"/root/rigplane-env/lib/python3.11/site-packages/rigplane/rigctld/handler.py",
line 467, in execute
return cast(RigctldResponse, await handler_fn(self, cmd))
^^^^^^^^^^^^^^^^^^^^^^^^^^^
File
"/root/rigplane-env/lib/python3.11/site-packages/rigplane/rigctld/handler.py",
line 856, in _cmd_set_vfo
await select_receiver(target)
File
"/root/rigplane-env/lib/python3.11/site-packages/rigplane/runtime/_dual_rx_runtime.py",
line 430, in select_receiver
await self._set_vfo_wire(target)
File
"/root/rigplane-env/lib/python3.11/site-packages/rigplane/runtime/radio.py",
line 2729, in _set_vfo_wire
raise CommandError(f"Radio rejected VFO select {vfo}")
rigplane.core.exceptions.CommandError: Radio rejected VFO select SUB
21:48:31 INFO AuditRecord(timestamp='2026-05-27T04:48:31.989065+00:00',
client_id=1, peername='127.0.0.1:57760', cmd='V', long_cmd='set_vfo',
args=('VFOB',), duration_ms=43.028, rprt=<HamlibError.EINTERNAL: -7>,
is_set=True, vfo=None)
21:48:33 WARNING client #1 command '\\get_powerstat' timed out
21:48:34 WARNING Invalid value in send_raw
21:48:34 INFO AuditRecord(timestamp='2026-05-27T04:48:34.029973+00:00',
client_id=1, peername='127.0.0.1:57760', cmd='w', long_cmd='send_raw',
args=('FE',), duration_ms=36.608, rprt=<HamlibError.EINVAL: -1>,
is_set=False, vfo=None)
21:48:44 INFO client #1 quit
21:48:44 INFO client #1 disconnected
21:49:00 INFO rigctld stopped
21:49:00 INFO Disconnected
21:49:00 INFO Disconnected
21:49:00 INFO Disconnected from 192.168.1.19:50001
21:49:00 INFO UDP connection lost [peer=192.168.1.19:50002]: None
21:49:00 INFO UDP connection lost [peer=192.168.1.19:50001]: None
```
John,
73 de AI7BQ
|
|
Hi John,
Quick follow-up: the Core side of this is now implemented and documented.
The ordered HTTP batch implementation is merged on main here:
#1603
Merge commit:
31c4142
The docs examples were also corrected for the IC-9700 DATA-mode command
contract here:
#1609
That documentation deploy has completed, so the public docs are live now:
- Web API reference: https://rigplane.dev/api/web/
- Web UI / automation guide: https://rigplane.dev/guide/web-ui/
- CI-V / command background: https://rigplane.dev/guide/commands/
This is unreleased relative to the current public v2.4.0 package, but it is
on main and will be included in the next RigPlane release.
RigPlane now has structured HTTP command endpoints:
- POST /api/v1/commands
- POST /api/v1/commands/batch
The batch endpoint is intentionally stateless in Core: the caller sends the
full ordered sequence each time. RigPlane validates each step, translates
it through the same structured command surface used by the WebSocket
control channel, places each step onto the ordered command queue, and
reports a per-step result.
That means your Stream Deck / MQTT gateway can own the profile names
locally while RigPlane remains the single control authority for the radio
connection.
For an IC-9700-style VARA FM profile, the shape is roughly:
curl -X POST http://127.0.0.1:8080/api/v1/commands/batch \ -H
'Content-Type: application/json' \ -d '{ "id": "vara-fm",
"continue_on_error": false, "steps": [
{"name":"set_freq","params":{"freq":144030000,"receiver":0}},
{"name":"set_mode","params":{"mode":"FM","receiver":0}},
{"name":"set_data_mode","params":{"mode":1,"receiver":0}},
{"name":"set_data1_mod_input","params":{"source":3}},
{"name":"set_usb_mod_level","params":{"level":72}},
{"name":"set_af_level","params":{"level":72,"receiver":0}},
{"name":"set_squelch","params":{"level":0,"receiver":0}} ] }'
For the IC-9700 profile, DATA mode is currently 0 = OFF, 1 = DATA.
Modulation input source values are currently 0 = MIC, 1 = ACC, 2 = MIC+ACC, 3
= USB, 4 = MIC+USB. So an AllStarLink/ACC-oriented profile would likely use
set_data1_mod_input with source: 1, while a chassis-mic FM voice profile
would use set_data_mode with mode: 0 and the MIC input path.
A successful response looks like:
{ "id": "vara-fm", "ok": true, "results": [
{"index":0,"name":"set_freq","ok":true,"status":"executed","result":{"freq":144030000,"receiver":0}},
{"index":1,"name":"set_mode","ok":true,"status":"executed","result":{"mode":"FM","receiver":0}}
] }
If a step fails, later steps are skipped by default and reported
deterministically. You can opt into continuing with "continue_on_error":
true.
Python sketch:
import json import urllib.request batch = { "id": "vara-fm", "steps": [
{"name": "set_freq", "params": {"freq": 144030000, "receiver": 0}},
{"name": "set_mode", "params": {"mode": "FM", "receiver": 0}}, {"name":
"set_data_mode", "params": {"mode": 1, "receiver": 0}}, {"name":
"set_data1_mod_input", "params": {"source": 3}}, ], } req =
urllib.request.Request( "http://127.0.0.1:8080/api/v1/commands/batch",
data=json.dumps(batch).encode("utf-8"), headers={"Content-Type":
"application/json"}, method="POST", ) with urllib.request.urlopen(req,
timeout=30) as resp: result = json.load(resp) if not result["ok"]:
print("Batch failed:", result)
Memory recall is also in the same structured-command family where the
active backend supports it, for example:
{"name":"set_memory_mode","params":{"channel":42}}
One caveat: the full structured command catalog is not fully documented
yet. I opened a follow-up for that here:
#1604
For now, common commands such as set_freq, set_mode, set_data_mode,
set_af_level, set_squelch, and the modulation-input commands are the
intended path for profile-style automation. Raw CI-V remains better suited
for diagnostics or unsupported experiments.
If you are still willing to serve as an IC-9700 test case, your setup is
almost exactly the reference workflow I want to validate: MQTT -> HTTP
batch -> RigPlane ordered queue -> IC-9700 LAN backend.
73,
Sergey
|
|
I will test this new commit tonight. Thank you for your rapid response. I still need CI-V access via the HTTP REST scheme, unless you are willing to abstract 100% of the IC-9700 CI-V, which is something I don't think is a good use of your time.
For example, how would I change the screen background to blue using your new REST endpoint?
This is how I do it now:
```
import asyncio
import sys
from rigplane import create_radio, LanBackendConfig
async def main():
config = LanBackendConfig(
host="192.168.1.19",
radio_addr=0xA2,
username="AI7BQ",
password="shhhh",
)
async with create_radio(config) as radio:
async def run_step(message, coro, settle=0.05):
print(message)
await coro
# Give the radio a brief moment before the next command.
if settle > 0:
await asyncio.sleep(settle)
await run_step(
"SET > Display > Display Type = B",
radio.send_civ(command=0x1A, sub=0x05, data=b"\x01\x53\x01"),
)
sys.exit(0)
asyncio.run(main())
```
Of course, if RigPlane is in SERVE or WEB mode. I get an error:
```
rigplane.core.exceptions.ConnectionError: Radio rejected session allocation (civ_port=0, error=0xFFFFFFFF).
A previous session may still be active. Wait 30-60s and retry.
```
|
|
Hello Sergey This application looks awesome, is there network support yet for the IC-7300 Mk2? Regards |
|
Hello Colin,
Thank you.
Currently, there is no support for 7300 MK2, mostly because I don’t have one :)
But. Some people reported normal operations with IC-705 and IC-9300 with ethernet.
So, once RigPlane supports 7300 MK1 - it should be relatively easy to update it with MK2 support.
I assume, LAN protocol should be the same as 7610 has, and CAT commands system should be plus-minus the same as on 7300MK1. The thing is just to bind this and test on a real radio. Which I can not perform now.
At this point, development goes slowly, after I caught lightning to my antenna and fried ton of equipment, including IC-7610…
But there is definitely in plans to implement 7300 MK2 support.
If somebody could help me with testing on the real radio - would be faster, I hope :)
Sincerely,
Sergey Morozik
***@***.***
… On Aug 4, 2026, at 9:54 PM, Colin ***@***.***> wrote:
ZL2CB
|
|
Bummer about the lightning strike. You do strong work, and I look forward
to continued development of the rigplane/rigplane-core project.
With kind regards,
John Simpson, AI7BQ (In smoky Eugene Oregon)
…On Tue, Aug 4, 2026 at 7:24 PM Colin ***@***.***> wrote:
Thanks for the quick reply - and sorry to hear of the lightning strike!
I'm happy to test and provide feedback with this. My radio arrives in a few
days so I'll have a play and see what works, or doesn't.
Regards
Colin Larsen
—
Reply to this email directly, view it on GitHub
<#558?email_source=notifications&email_token=BKP7Z2WG7EJ52LVTBJIODQL5IKLFTA5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCNZZGAYDMNZUUZZGKYLTN5XKOY3PNVWWK3TUUVSXMZLOOSWGM33PORSXEX3DNRUWG2Y#discussioncomment-17900674>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BKP7Z2XZ5BJLHWG2SXSI7TT5IKLFTAVCNFSNUABIKJSXA33TNF2G64TZHMYTCNRWGM3TONBTGU5UI2LTMN2XG43JN5XDWOJYGYYTAMRZUF3AE>
.
Triage notifications, keep track of coding agent tasks and review pull
requests on the go with GitHub Mobile for iOS
<https://github.com/notifications/mobile/ios/BKP7Z2RNBHPH74L5UGRYED35IKLFTA5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCNZZGAYDMNZUUZZGKYLTN5XKOY3PNVWWK3TUUVSXMZLOOSVGM33PORSXEX3JN5ZQ>
and Android
<https://github.com/notifications/mobile/android/BKP7Z2V5YITA5CE6FDI6DM35IKLFTA5CNFSNUABIM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63SDN5WW2ZLOOQXTCNZZGAYDMNZUUZZGKYLTN5XKOY3PNVWWK3TUUVSXMZLOOSXGM33PORSXEX3BNZSHE33JMQ>.
Download it today!
You are receiving this because you commented.Message ID:
***@***.***>
|
Uh oh!
There was an error while loading. Please reload this page.
👋 Welcome!
We’re using Discussions as a place to connect with other members of our community. We hope that you:
build together 💪.
To get started, comment below with an introduction of yourself and tell us about what you do with this community.
All reactions