first attempt using rigctld...

This commit is contained in:
DJ2LS 2024-02-10 21:28:07 +01:00
parent 74d79204ec
commit f239a1a3be
4 changed files with 104 additions and 7 deletions

View file

@ -357,7 +357,7 @@ import { serialDeviceOptions } from "../js/deviceFormHelper";
@change="onChange"
v-model.number="settings.remote.RADIO.serial_speed"
>
<option selected value="ignore">-- ignore --</option>
<option selected value="0">-- ignore --</option>
<option value="1200">1200</option>
<option value="2400">2400</option>
<option value="4800">4800</option>
@ -380,7 +380,7 @@ import { serialDeviceOptions } from "../js/deviceFormHelper";
@change="onChange"
v-model.number="settings.remote.RADIO.data_bits"
>
<option selected value="ignore">-- ignore --</option>
<option selected value="0">-- ignore --</option>
<option value="7">7</option>
<option value="8">8</option>
</select>
@ -395,7 +395,7 @@ import { serialDeviceOptions } from "../js/deviceFormHelper";
@change="onChange"
v-model.number="settings.remote.RADIO.stop_bits"
>
<option selected value="ignore">-- ignore --</option>
<option selected value="0">-- ignore --</option>
<option value="1">1</option>
<option value="2">2</option>
</select>

View file

@ -15,7 +15,9 @@ import hmac
import os
import sys
from pathlib import Path
import platform
import subprocess
import psutil
log = structlog.get_logger("helpers")
@ -701,9 +703,54 @@ def set_flag(byte, flag_name, value, flag_dict):
position = flag_dict[flag_name]
return set_bit(byte, position, value)
def get_flag(byte, flag_name, flag_dict):
"""Get the value of the flag from the byte according to the flag dictionary."""
if flag_name not in flag_dict:
raise ValueError(f"Unknown flag name: {flag_name}")
position = flag_dict[flag_name]
return get_bit(byte, position)
def find_binary_path(binary_name="rigctld"):
"""
Search for a binary within the current working directory and its subdirectories,
adjusting the binary name for the operating system.
:param binary_name: The base name of the binary to search for, without extension.
:return: The full path to the binary if found, otherwise None.
"""
# Adjust binary name for Windows
if platform.system() == 'Windows':
binary_name += ".exe"
root_path = os.getcwd() # Get the current working directory
for dirpath, dirnames, filenames in os.walk(root_path):
if binary_name in filenames:
return os.path.join(dirpath, binary_name)
return None
def kill_and_execute(binary_path, additional_args=None):
"""
Kills any running instances of the binary across Linux, macOS, and Windows, then starts a new one non-blocking.
:param binary_path: The full path to the binary to execute.
:param additional_args: A list of additional arguments to pass to the binary.
:return: subprocess.Popen object of the started process
"""
# Kill any existing instances of the binary
for proc in psutil.process_iter(attrs=['pid', 'name', 'cmdline']):
try:
cmdline = proc.info['cmdline']
# Ensure cmdline is iterable and not None
if cmdline and binary_path in ' '.join(cmdline):
proc.kill()
print(f"Killed running instance with PID: {proc.info['pid']}")
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass # Process no longer exists or no permission to kill
# Execute the binary with additional arguments non-blocking
command = [binary_path] + (additional_args if additional_args else [])
process = subprocess.Popen(command)
return process

View file

@ -21,7 +21,7 @@ class RadioManager:
def _init_rig_control(self):
# Check how we want to control the radio
if self.radiocontrol == "rigctld":
self.radio = rigctld.radio(self.state_manager, hostname=self.rigctld_ip,port=self.rigctld_port)
self.radio = rigctld.radio(self.config, self.state_manager, hostname=self.rigctld_ip,port=self.rigctld_port)
elif self.radiocontrol == "tci":
raise NotImplementedError
# self.radio = self.tci_module

View file

@ -1,6 +1,6 @@
import socket
import structlog
import time
import helpers
import threading
class radio:
@ -8,11 +8,12 @@ class radio:
log = structlog.get_logger("radio (rigctld)")
def __init__(self, states, hostname="localhost", port=4532, timeout=5):
def __init__(self, config, states, hostname="localhost", port=4532, timeout=5):
self.hostname = hostname
self.port = port
self.timeout = timeout
self.states = states
self.config = config
self.connection = None
self.connected = False
@ -29,6 +30,9 @@ class radio:
'ptt': False # Initial PTT state is set to False
}
# start rigctld...
self.start_service()
# connect to radio
self.connect()
@ -201,3 +205,49 @@ class radio:
"""Return the latest fetched parameters."""
return self.parameters
def start_service(self):
binary_name = "rigctld"
binary_path = helpers.find_binary_path(binary_name)
additional_args = self.format_rigctld_args()
if binary_path:
self.log.info(f"Rigctld binary found at: {binary_path}")
helpers.kill_and_execute(binary_path, additional_args)
self.log.info(f"Executed rigctld...")
else:
self.log.warning("Rigctld binary not found.")
def format_rigctld_args(self):
config = self.config['RADIO'] # Accessing the 'RADIO' section of the INI file
args = []
# Helper function to check if the value should be ignored
def should_ignore(value):
return value == 'ignore' or value == 0
# Model ID, Serial Port, and Speed
if not should_ignore(config.get('model_id', "0")):
args += ['-m', str(config['model_id'])]
if not should_ignore(config.get('serial_port', "0")):
args += ['-r', config['serial_port']]
if not should_ignore(config.get('serial_speed', "0")):
args += ['-s', str(config['serial_speed'])]
# PTT Port and Type
if not should_ignore(config.get('ptt_port', "0")):
args += ['--ptt-port', config['ptt_port']]
if not should_ignore(config.get('ptt_type', "0")):
args += ['--ptt-type', config['ptt_type']]
# Serial DCD and DTR
if not should_ignore(config.get('serial_dcd', "0")):
args += ['--set-dcd', config['serial_dcd']]
if not should_ignore(config.get('serial_dtr', "0")):
args += ['--set-dtr', config['serial_dtr']]
# Handling Stop Bits with the corrected --set-conf syntax
if not should_ignore(config.get('stop_bits', "0")):
args += ['--set-conf', f'stop_bits={config["stop_bits"]}']
return args