Skip to content

Instantly share code, notes, and snippets.

@mgiugliano
Created May 10, 2023 20:21
Show Gist options
  • Save mgiugliano/bb3e24abc1e27527863236ee64344155 to your computer and use it in GitHub Desktop.
Save mgiugliano/bb3e24abc1e27527863236ee64344155 to your computer and use it in GitHub Desktop.
Quick and dirty (python and bash) sync script between a radio (CAT controlled) and SDR++
#!/usr/bin/env bash
#
# Demo of how to bidirectionally synchronize SDR++ (running with a hardware or
# remote SDR hardware) with a physical radio connected to the computer by
# CAT control.
# This requires to install the following software:
# - hamlib (https://hamlib.github.io/hamlib/), which is used to control the radio with CAT commands, by
# . rigctld (https://hamlib.github.io/hamlib/rigctld.1.html)
# . rigctl (https://hamlib.github.io/hamlib/rigctl.1.html)
# - SDRplay driver (API) for macOS (runs as a demon in the background) (https://www.sdrplay.com/downloads/)
# - SDR++ (https://github.com/AlexandreRouma/SDRPlusPlus/releases/tag/nightly)
# 10 May 2023 - Michele Giugliano, PhD (iv3ifz)
# The following variables need to be set by the user
# bash function to set the frequency of the radio
set_freq_radio() {
# $1 is the frequency in Hz
rigctl -m 2037 -r /dev/cu.usbserial-0567003F3120 -s 115200 F $1 > /dev/null
}
set_freq_sdr() {
# $1 is the frequency in Hz
echo "\set_freq $1" | nc -w 1 localhost 4534 > /dev/null
}
# bash function to read the frequency of the radio
get_freq_radio() {
rigctl -m 2037 -r /dev/cu.usbserial-0567003F3120 -s 115200 f
}
# bash function to read the frequency of the SDR
get_freq_sdr() {
echo "\get_freq" | nc -w 1 localhost 4534
}
# Test whether the process rigctld is running
if pgrep -x "rigctld" > /dev/null
then
echo "rigctld is running"
else
echo "rigctld is not running"
rigctld -m 2037 -r /dev/cu.usbserial-0567003F3120 -s 11520 &
fi
freq_radio=$(get_freq_radio)
set_freq_sdr $freq_radio
freq_radio_old=$freq_radio
freq_sdr_old=$freq_sdr
# Loop
while true
do
freq_radio=$(get_freq_radio)
if [ "$freq_radio" != "$freq_radio_old" ]
then
echo "Radio: $freq_radio Hz"
set_freq_sdr $freq_radio
freq_radio_old=$freq_radio
freq_sdr_old=$freq_radio
fi
freq_sdr=$(get_freq_sdr)
if [ "$freq_sdr" != "$freq_sdr_old" ]
then
echo "SDR: $freq_sdr Hz"
set_freq_radio $freq_sdr
freq_sdr_old=$freq_sdr
freq_radio_old=$freq_radio
fi
#sleep 0.1
done
#
# Demo of how to bidirectionally synchronize SDR++ (running with a hardware or remote SDR hardware)
# with a physical radio connected to the computer by CAT control.
# This requires to install
# - hamlib (https://hamlib.github.io/hamlib/), which is used to control the radio with CAT commands, by
# . rigctld (https://hamlib.github.io/hamlib/rigctld.1.html)
# . rigctl (https://hamlib.github.io/hamlib/rigctl.1.html)
# - Python (https://www.python.org/), which is used to run this script, and the following Python packages
# - SDRplay driver (API) for macOS (runs as a demon in the background) (https://www.sdrplay.com/downloads/)
# - SDR++ (https://github.com/AlexandreRouma/SDRPlusPlus/releases/tag/nightly)
# 10 May 2023 - Michele Giugliano, PhD (iv3ifz)
# This script is released under the MIT license
# https://opensource.org/licenses/MIT
#------------------------------------------------------------
# Import the required libraries
from ctypes import memmove
import os # for system calls
import subprocess # for system calls
import time # for sleep
import socket # for socket communication
# Let's define some constants...
serial_port = '/dev/cu.usbserial-0567003F3120' # The serial port of the radio, check it with ls /dev/cu.usbserial*
baud_rate = '115200' # The baud rate of the radio, set for CAT control in the radio's menu
model = '2037' # The model of the radio (KENWOOD TS-590SG)
port = '4534' # The port on which the rigctld server of SDR++ listens for incoming connections
#------------------------------------------------------------
# Let's define some useful functions
def netcat(host, port, content):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, int(port)))
s.sendall(content.encode())
#time.sleep(0.5)
s.shutdown(socket.SHUT_WR)
data = s.recv(4096) # 4096 is the buffer size
# repr() is used here for
# while True:
# data = s.recv(4096)
# print(data)
# if not data:
# break
# #print(repr(data))
s.close()
return repr(data) #data.decode('utf-8')
def launch_process(command): # Launch a process in the background...
p = subprocess.Popen(command, stdout=subprocess.PIPE)
try:
out, err = p.communicate(timeout=5)
except subprocess.TimeoutExpired:
#p.kill() # The child process is not killed if the timeout expire. I exploit it to launch rigctld.
#out, err = proc.communicate()
return None, '' # If the process is still running, return an empty string
out = out.decode('utf-8')
return err, out
def check_rigctld(): # Check that a process named 'rigctld' is running in the background...
err, out = launch_process(['ps', '-A'])
for line in out.splitlines():
if 'rigctld' in line:
print('The daemon rigctld was already running!')
return True # rigctld is already running: nothing to do, exiting!
# ...if not, start it
print('Starting the deamon rigctld...')
err, out = launch_process(['rigctld', '-m', model, '-r', serial_port, '-s', baud_rate])
if err is not None:
print('Error starting the daemon rigctld!')
print(err)
exit()
return True
def read_frequency_radio(): # Let's now read the frequency from the radio
err, out = launch_process(['rigctl', '-m', model, '-r', serial_port, '-s', baud_rate, 'f'])
# out is str class and I convert it to a normal string
out = str(out)
if len(out) == 0:
return freq_old_radio
else:
out = float(out[:-1]) # Let's remove the trailing \n and convert it to a float
return out # Let's return the frequency
def read_frequency_sdr(): # Let's now read the frequency from the SDR++
out = netcat('localhost', port, '\\get_freq \n')
if len(out) == 0:
return freq_old_sdr
else:
out = float(out[2:-3])
return out # Let's return the frequency
def set_frequency_radio(freq): # Let's now read the frequency from the radio
err, out = launch_process(['rigctl', '-m', model, '-r', serial_port, '-s', baud_rate, 'F', str(freq)])
return # Let's return the frequency
def set_frequency_sdr(freq): # Let's now read the frequency from the SDR++
netcat('localhost', port, '\\set_freq ' + str(freq) + '\n')
return # Let's return the frequency
#------------------------------------------------------------
#------------------------------------------------------------
#------------------------------------------------------------
# Let's start the script
# Let's first check that rigctld is running or launch it otherwise!
check_rigctld()
freq_radio = read_frequency_radio() # read the frequency from the radio
set_frequency_sdr(freq_radio)
freq_old_radio = freq_radio
freq_old_sdr = freq_radio
# Now let's read the of the radio frequency and set SDR accordingly, in an infinite loop
while True:
time.sleep(.02) # wait 20 ms
freq_radio = read_frequency_radio() # read the frequency from the radio
if freq_radio != freq_old_radio: # if the frequency of the radio has changed,
set_frequency_sdr(freq_radio) # set the frequency of the SDR
freq_old_radio = freq_radio # update the old frequency
freq_old_sdr = freq_radio # update the old frequency
freq_sdr = read_frequency_sdr() # read the frequency from the sdr
if freq_sdr != freq_old_sdr: # if the frequency of the radio has changed,
set_frequency_radio(freq_sdr) # set the frequency of the SDR
freq_old_sdr = freq_sdr # update the old frequency
freq_old_radio = freq_radio # update the old frequency
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment