Created
May 10, 2023 20:21
-
-
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++
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# 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