Skip to main content

DuCoBelt: Dual Conveyor Belt

What does it do, in a nutshell

This program, called "ducobelt", makes it more convenient to operate the mercury modem, in particular, its TNC network API.

  • You can type TNC commands that are to be sent to mercury's command port (TCP port 8300).
    • The line endings you type are normalized to \r (aka CR) as wanted by mercury.
    • The characters you type are normalized to upper case as required by mercury.
  • You can see what mercury answers via that command port.
    • These answers are typically given in lines terminated with \r. If those are displayed as is, each line fully or partially replaces the previous one. So ducobelt replaces \r line ends coming from mercury with \r\n (aka CR LF) line endings that will display nicely.

So this is a bit like netcat, ncat, or socat, but with some convenience conversations.

Why the name?

At the end of the day, ducobelt just transfers data. What mercury supplies via the ARQ socket is transferred to np and, simultaneously, what you provide via your keyboard is transferred to that socket, in a parallel dual conveyer belt.

Alternative

There is an alternative solution by the makers of mercury, namely mercury-client. That software can be used for first experiments quite as well as ducobelt.

The main differences (from my point of view as the ducobelt author):

  • You need to compile mercury-client, while ducobelt works out of the box with Python.
  • ducobelt presently will not work on Windows and may or may not work on Mac, while mercury-client serves all three platforms.
  • mercury-client gives you a GUI, while ducobelt can be run "headless", that is, only needs text terminals.
  • mercury-client tries to offer a unified GUI, while docubelt follows the time-honored approach "pull what you need out of a well-stocked toolbox".
  • Other than mercury-client, ducobelt leaves the data port (usually 8301) alone. This may change in later versions, but I plan to always provide an option to not touch that port. On the other hand, it is unclear what to do in mercury-client to free that port for use by other software.
  • The ducobelt approach means: You need the toolbox. E.g., for text chat, you'll need to use some network-enabled program to connect to the data port, e.g., nc (from one of the netcat packages).
  • On the other hand, it is more straightforward to rig up fun experiments with ducobelt. E.g., we played around with sz and rz (from the lrzsz package) to send files via the venerable ZMODEM protocol (see below). This is probably not the most efficient choice on top of Mercury, but totally can be made to work.

How to set this up

  • Install Linux (this will presently not run unter Windows, it might run on Mac)
  • Install Python (version 3.12 or later)
  • Create a virtual environment
    • either barefeet
    • or install uv (which also allows to install Python 3.12 if you are stuck with an older version) and use that.
  • Activate that virtual env and install ducobelt with pip (either plain pip install ducobelt or uv pip install ducobelt).
  • Install mercury (either plain headless mercury or GUI mercury-ui, both do)
  • Install some netcat version; if in doubt, the netcat-openbsd flavor is fine.

How to run: The four-terminal setup

I suggest using four different terminals.

(Personally, I like to use tmux to manage many terminals in the same terminal window.)

What is the plan? If you follow the instructions below, these are the terminals you'll end up with:

  • Terminal 1 runs the ducobelt binary. You type your TNC commands commands into this termina. They'll be slightly changed, to upper-cased and \r line endings, and sent to port 8300.
  • Terminal 2 echoes the replies that come back from the mercury or mercury-ui binary over the network (from port 8300).
  • Terminal 3 The mercury or mercury-ui binary itself runs here. You'll see the log lines scroll by.
  • Terminal 4 In this terminal, you can type chat messages to your QSO partner and see what they type back, and/or trigger sending or receipt of (text or binary) data.

The most complicated thing here is: How does the ducobelt programm get its output into terminal 2? Presently, that program is hard-wired to write this output into some file np in its current directory. So you need some way to display whatever is writen to np in terminal 2.

There is more than one way to do this.

My original way was:

  • I create a "named pipe" via mknod np p in the directory in which I intend to run the docubelt binary later.
  • In terminal 2, I start cat np .

Nowadays,

  • I run ps ax | grep 'ps ax' in terminal 2 to find out which terminal, in the sense of /dev/pts/N or similar, is connected with terminal 2.
  • In the directory in which I intend to run the ducobelt binary, I run ln -s /dev/pts/N np (while replacing N with the number I found).
  • In that same directory (possibly in terminal 1), I test this with echo hello > np which should cause "hello" to appear in terminal 2.

After that is accomplished, start either mercury or mercury-ui in terminal 3. It is your choice which of the two you use; if in doubt, the mercury-ui is recommended, it allows looking at the waterfall display and makes it easier to set audio volume.

Afterwards, start ducobelt in terminal 1. You'll have to activate the Python virtual environment into which you installed ducobeltin that terminal https://docs.python.org/3/library/venv.html#how-venvs-work in order to do that.

If all runs well, the text BUFFER 0 should appear in terminal 2, and, every so often, IAMALIVE.

You can now type things like mycall ab0xyz (replace with whatever your real amateur radio call is) into terminal 1 and should see an OK appear in terminal 2.

If you type something like connect ab0xyz xy0abc to (attempt to) connect with XY0ABC (or whatever callsign you actually type), ducobelt will cause mercury (or mercury-ui) to key your trx and send pertinent data.

For the things you can type, refer to mercury's TNC documentation. The manual page of mercury also contains this information.

The setup of the fourth terminal is only needed when a connection with another station has actually been established.

To chat with that station, I use nc (the binary from the netcat package) to connect to the data port 8301 of mercury or mercury-ui:

nc -v -v localhost 8301

If I want to transfer binary data, the QSO partner needs to be ready to receive such data. Any data piped into the tcp/ip socket 8301 on my machine will come out of the tcp/ip socket 8301 on the other machine, be it text or binary.

On my machine, I can pipe some file binary.data into the socket with

nc -v -v -N localhost 8301 < binary.data

But Mercury does not provide a way for the sending side to communicate to the other side "a batch of data has now come to an end". In tests, we have successfully used ZMODEM for that. This is probably overkill, but it works.

Details:

  • We used sz and rz from the lrzsz package on both Linux and Mac.
  • On Linux, --tcp-client 127.0.0.1 8301 connect either of the two with the data port.
  • On Mac, sz / rz didn't provide that switch. So we pulled socat with EXEC: out of our toolbox, which worked nicely.
  • --disable-timeouts was essential.
  • -b worked (needed on the sz side), quite as we expected.
  • We used -L 42 (on the sz side), but could probably have used much larger windows.
  • -v -v keeps you more entertained and informed.

Mercury hints

I have found the alsa sound access hard to use, but the pulse interface works nicely on my Debian Trixie machine (that actually uses pipewire audio).

For first experiments, I put a mercury.ini into the directory in which I intend to start the marcury-ui (or plain mercury) binary.

Those first experiments do not actually use my transceiver, but just listen to the noise that comes out of my laptop's speakers resp. feed such noise into my laptop's microphone. For this, this is my "acoustic couple" mercury.ini:

[main]
ui_enabled = true
ui_port = 10000
ui_protocol = ws
waterfall_enabled = true
radio_model = 6
radio_device = ""
input_device = "alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__Mic1__source"
output_device = "alsa_output.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__Speaker__sink"
capture_channel = stereo
sound_system = pulse
arq_tcp_base_port = 8300
broadcast_tcp_port = 8100
verbose = true
freedv_verbosity = 1
hamlib_log_level = 3
radio_serial_speed = 0

[arq]
no_progress_timeout_s = 180
disconnect_drain_timeout_s = 30
data_retry_slots = 10
mode_hold_after_downgrade_s = 6
ladder_up_successes = 2
retry_downgrade_threshold = 2
channel_guard_ms = 700
iss_post_ack_guard_ms = 900
keepalive_interval_s = 20
keepalive_miss_limit = 5
peer_payload_hold_s = 15
startup_max_s = 10

[channel]
busy_detect = false
busy_threshold_db = 10
busy_hysteresis_db = 3
busy_on_debounce_ms = 300
busy_hang_ms = 1500

[audio]
tx_gain_db = -8.50

[tnc]
keepalive_s = 60
buffer_report_ms = 1000

You will probably want to set your own values for input_device, output_device, and tx_gain_db.

An actual first experiment that does not require a QSO partner

My actual first experiment was: With no trx connected,

  • send MYCALL and then CONNECT commands, trying to connect to a fake call,
  • record the noise with my smarthopne,
  • switch to the fake call using MYCALL,
  • let the smartphone play back the sound to the laptop's microphone.

Sample cuts of the four terminals:

Terminal 1:

$ ducobelt 
> mycall dj3ei
> connect dj3ei dl1ejw
> mycall dl1ejw
> listen on
> 

Terminal 2, the head is missing, this starts when the smartphone sent the recording:

SN 1.6                                                                                             │andreas@uhu:~
BITRATE (3) 321 BPS                                                                                │$ nc -v -v localhost 8301
PENDING                                                                                            │nc: connect to localhost (::1) port 8301 (tcp) failed: Connection refused
PTT ON                                                                                             │Connection to localhost (127.0.0.1) 8301 port [tcp/*] succeeded!
PTT OFF                                                                                            │
SN 5.8                                                                                             │
BITRATE (15) 68 BPS                                                                                │
PTT ON                                                                                             │
PTT OFF                                                                                            │
SN 3.4                                                                                             │
BITRATE (15) 68 BPS                                                                                │
PTT ON                                                                                             │
PTT OFF                                                                                            │
PTT ON                                                                                             │
PTT OFF                                                                                            │
PTT ON                                                                                             │
IAMALIVE                                                                                           │
PTT OFF                                                                                            │
PTT ON                                                                                             │
PTT OFF                                                                                            │
CANCELPENDING                                                                                      │
IAMALIVE

And here is the last part of the log of mercury-ui, slightly earlier, starting with the moment when listen on was typed into terminal 1 (and converted to upper case LISTEN ON by ducobelt).

18:11:28.896 [+119.274s] [INF] [tcp-ctl] Command received: LISTEN ON
18:11:39.865 [+130.243s] [INF] [arq] Incoming connection from DJ3EI on DL1EJW (pending)
18:11:40.608 [+130.986s] [INF] [radio] TX enabled (PTT ON)
18:11:44.318 [+134.696s] [INF] [radio] TX disabled (PTT OFF)
18:11:53.352 [+143.730s] [INF] [radio] TX enabled (PTT ON)
18:11:57.063 [+147.441s] [INF] [radio] TX disabled (PTT OFF)
18:12:06.096 [+156.474s] [INF] [radio] TX enabled (PTT ON)
18:12:09.806 [+160.185s] [INF] [radio] TX disabled (PTT OFF)
18:12:18.837 [+169.216s] [INF] [radio] TX enabled (PTT ON)
18:12:22.548 [+172.926s] [INF] [radio] TX disabled (PTT OFF)
18:12:31.548 [+181.926s] [INF] [arq] Incoming connection cancelled

The mercury program sends out four times its affirmative answer to the offer that came in (by the smart phone audio) of an incoming connection originating from DJ3EI.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ducobelt-0.1.0.tar.gz (15.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ducobelt-0.1.0-py3-none-any.whl (10.4 kB view details)

Uploaded Python 3

File details

Details for the file ducobelt-0.1.0.tar.gz.

File metadata

  • Download URL: ducobelt-0.1.0.tar.gz
  • Upload date:
  • Size: 15.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.13

File hashes

Hashes for ducobelt-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9492725cdbbb8bdc05fabf9f2e7a1d8d81a84786aca7db9acc2325314ff99860
MD5 a4fcd80bd45a23a49381d3420df323a2
BLAKE2b-256 14566b750140ada7162a237602de6795de351573e7a433c7e8aa818226b84c61

See more details on using hashes here.

File details

Details for the file ducobelt-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: ducobelt-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.13

File hashes

Hashes for ducobelt-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 63f979b40c91e3f6bc809341d84d147b415d2b933f3bee13c31764dcab59f79c
MD5 be011341b20ce8a4600e6555636bff36
BLAKE2b-256 aba0c9350c6929390f7c5f262c1df9b55d7aefe803904891ddc01d69297dcbe3

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.1

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page