From 10d3d5c53e82c3885a496b9688c19e9e1546451d Mon Sep 17 00:00:00 2001 From: dj2ls Date: Tue, 18 Jan 2022 19:38:05 +0100 Subject: [PATCH] support for different ways controlling the radio #121 direct, rigctl (for windows), rigctld. Highly experimental. Just to save data. --- gui/daemon.js | 16 +- gui/main.js | 10 +- gui/preload-main.js | 290 +++++++++++------- gui/src/index.html | 716 ++++++++++++++++++++++---------------------- tnc/daemon.py | 66 ++-- tnc/main.py | 17 +- tnc/modem.py | 25 +- tnc/rig.py | 18 +- tnc/rigctl.py | 16 +- tnc/rigctld.py | 81 +++++ tnc/sock.py | 7 +- tnc/static.py | 6 +- 12 files changed, 730 insertions(+), 538 deletions(-) create mode 100644 tnc/rigctld.py diff --git a/gui/daemon.js b/gui/daemon.js index c3626af2..6aff9a13 100644 --- a/gui/daemon.js +++ b/gui/daemon.js @@ -140,7 +140,7 @@ exports.getDaemonState = function() { // START TNC // ` `== multi line string -exports.startTNC = function(mycall, mygrid, rx_audio, tx_audio, devicename, deviceport, pttprotocol, pttport, serialspeed, data_bits, stop_bits, handshake) { +exports.startTNC = function(mycall, mygrid, rx_audio, tx_audio, radiocontrol, devicename, deviceport, pttprotocol, pttport, serialspeed, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port) { var json_command = JSON.stringify({ type: 'SET', command: 'STARTTNC', @@ -149,6 +149,7 @@ exports.startTNC = function(mycall, mygrid, rx_audio, tx_audio, devicename, devi mygrid: mygrid, rx_audio: rx_audio, tx_audio: tx_audio, + radiocontrol: radiocontrol, devicename: devicename, deviceport: deviceport, pttprotocol: pttprotocol, @@ -156,8 +157,9 @@ exports.startTNC = function(mycall, mygrid, rx_audio, tx_audio, devicename, devi serialspeed: serialspeed, data_bits: data_bits, stop_bits: stop_bits, - handshake: handshake - + handshake: handshake, + rigctld_port: rigctld_port, + rigctld_ip: rigctld_ip }] }) @@ -173,12 +175,13 @@ exports.stopTNC = function() { } // TEST HAMLIB -exports.testHamlib = function(devicename, deviceport, serialspeed, pttprotocol, pttport, data_bits, stop_bits, handshake) { +exports.testHamlib = function(radiocontrol, devicename, deviceport, serialspeed, pttprotocol, pttport, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port) { var json_command = JSON.stringify({ type: 'GET', command: 'TEST_HAMLIB', parameter: [{ + radiocontrol: radiocontrol, devicename: devicename, deviceport: deviceport, pttprotocol: pttprotocol, @@ -186,8 +189,9 @@ exports.testHamlib = function(devicename, deviceport, serialspeed, pttprotocol, serialspeed: serialspeed, data_bits: data_bits, stop_bits: stop_bits, - handshake: handshake - + handshake: handshake, + rigctld_port: rigctld_port, + rigctld_ip: rigctld_ip }] }) console.log(json_command) diff --git a/gui/main.js b/gui/main.js index 6642ddad..aa65653e 100644 --- a/gui/main.js +++ b/gui/main.js @@ -34,7 +34,15 @@ var configContent = ` "tnclocation": "localhost", "stop_bits" : "1", "data_bits" : "8", - "handshake" : "None" + "handshake" : "None", + "radiocontrol" : "direct", + "deviceport_rigctl" : "3", + "deviceid_rigctl" : "3", + "serialspeed_rigctl" : "9600", + "pttprotocol_rigctl" : "USB", + "rigctld_port" : "4532", + "rigctld_ip" : "127.0.0.1" + } `; if (!fs.existsSync(configPath)) { diff --git a/gui/preload-main.js b/gui/preload-main.js index c80a9fba..eee95f3e 100644 --- a/gui/preload-main.js +++ b/gui/preload-main.js @@ -24,22 +24,6 @@ setInterval(daemon.getDaemonState, 1000) setInterval(sock.getTncState, 150) setInterval(sock.getRxBuffer, 1000) setInterval(sock.getMsgRxBuffer, 1000) -// UPDATE FFT DEMO -/* -updateFFT = function(fft) { - var fft = Array.from({ - length: 2048 - }, () => Math.floor(Math.random() * 10)); - spectrum.addData(fft); - console.log(fft) -} - -setInterval(updateFFT, 250) -*/ - - - - // WINDOW LISTENER window.addEventListener('DOMContentLoaded', () => { @@ -67,18 +51,19 @@ window.addEventListener('DOMContentLoaded', () => { document.getElementById("myCall").value = config.mycall document.getElementById("myGrid").value = config.mygrid - //document.getElementById("audio_output_selectbox").value = config.tx_audio - //document.getElementById("audio_input_selectbox").value = config.rx_audio - document.getElementById('hamlib_deviceid').value = config.deviceid - //document.getElementById('hamlib_deviceport').value = config.deviceport document.getElementById('hamlib_serialspeed').value = config.serialspeed document.getElementById('hamlib_ptt_protocol').value = config.pttprotocol - //document.getElementById('hamlib_deviceport_advanced').value = config.deviceport + document.getElementById("hamlib_rigctld_ip").value = config.rigctld_ip + document.getElementById("hamlib_rigctld_port").value = config.rigctld_port + + document.getElementById("hamlib_deviceid_rigctl").value = config.deviceid_rigctl + document.getElementById("hamlib_serialspeed_rigctl").value = config.serialspeed_rigctl + document.getElementById("hamlib_ptt_protocol_rigctl").value = config.pttprotocol_rigctl + document.getElementById('hamlib_serialspeed_advanced').value = config.serialspeed document.getElementById('hamlib_ptt_protocol_advanced').value = config.pttprotocol - //document.getElementById('hamlib_ptt_port_advanced').value = config.pttport document.getElementById('hamlib_databits_advanced').value = config.data_bits document.getElementById('hamlib_stopbits_advanced').value = config.stop_bits document.getElementById('hamlib_handshake_advanced').value = config.handshake @@ -101,6 +86,54 @@ window.addEventListener('DOMContentLoaded', () => { document.getElementById("waterfall").style.height = '0px'; } + // radio control element + if (config.radiocontrol == 'rigctl') { + + document.getElementById("radio-control-switch1").checked = false + document.getElementById("radio-control-switch2").checked = true + document.getElementById("radio-control-switch3").checked = false + + document.getElementById("radio-control-direct").style.visibility = 'hidden'; + document.getElementById("radio-control-rigctld").style.visibility = 'hidden'; + document.getElementById("radio-control-direct").style.display = 'none'; + document.getElementById("radio-control-rigctld").style.display = 'none'; + + document.getElementById("radio-control-rigctl").style.display = 'block'; + document.getElementById("radio-control-rigctl").style.visibility = 'visible'; + document.getElementById("radio-control-rigctl").style.height = '100%'; + + } else if (config.radiocontrol == 'rigctld') { + + document.getElementById("radio-control-switch1").checked = false + document.getElementById("radio-control-switch2").checked = false + document.getElementById("radio-control-switch3").checked = true + + document.getElementById("radio-control-direct").style.visibility = 'hidden'; + document.getElementById("radio-control-rigctl").style.visibility = 'hidden'; + document.getElementById("radio-control-direct").style.display = 'none'; + document.getElementById("radio-control-rigctl").style.display = 'none'; + + document.getElementById("radio-control-rigctld").style.display = 'block'; + document.getElementById("radio-control-rigctld").style.visibility = 'visible'; + document.getElementById("radio-control-rigctld").style.height = '100%'; + + } else { + + document.getElementById("radio-control-switch1").checked = true + document.getElementById("radio-control-switch2").checked = false + document.getElementById("radio-control-switch3").checked = false + + document.getElementById("radio-control-rigctl").style.visibility = 'hidden'; + document.getElementById("radio-control-rigctld").style.visibility = 'hidden'; + document.getElementById("radio-control-rigctl").style.display = 'none'; + document.getElementById("radio-control-rigctld").style.display = 'none'; + + document.getElementById("radio-control-direct").style.display = 'block'; + document.getElementById("radio-control-direct").style.visibility = 'visible'; + document.getElementById("radio-control-direct").style.height = '100%'; + + } + // remote tnc if (config.tnclocation == 'remote') { document.getElementById("local-remote-switch1").checked = false @@ -120,63 +153,48 @@ window.addEventListener('DOMContentLoaded', () => { + // on click radio control toggle view + // direct + document.getElementById("radio-control-switch1").addEventListener("click", () => { + document.getElementById("radio-control-rigctl").style.visibility = 'hidden'; + document.getElementById("radio-control-rigctld").style.visibility = 'hidden'; + document.getElementById("radio-control-rigctl").style.display = 'none'; + document.getElementById("radio-control-rigctld").style.display = 'none'; - - // SETUP OF SCATTER DIAGRAM -/* - global.data = { - datasets: [{ - label: 'Scatter Dataset', - data: [{ - x: 0, - y: 0 - }], - backgroundColor: 'rgb(255, 99, 132)' - }], - }; - - var ctx = document.getElementById('scatter').getContext('2d'); - global.myChart = new Chart(ctx, { - type: 'scatter', - data: data, - options: { - animation: false, - legend: { - display: false - }, - - scales: { - display: false, - grid: { - display: false - }, - x: { - type: 'linear', - position: 'bottom', - display: false, - min: -50, - max: 50 - }, - y: { - display: false, - min: -50, - max: 50 - } - - } - } + document.getElementById("radio-control-direct").style.display = 'block'; + document.getElementById("radio-control-direct").style.visibility = 'visible'; + document.getElementById("radio-control-direct").style.height = '100%'; + config.radiocontrol = 'direct' + fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); }); -*/ + // rigctl + document.getElementById("radio-control-switch2").addEventListener("click", () => { + document.getElementById("radio-control-direct").style.visibility = 'hidden'; + document.getElementById("radio-control-rigctld").style.visibility = 'hidden'; + document.getElementById("radio-control-direct").style.display = 'none'; + document.getElementById("radio-control-rigctld").style.display = 'none'; -/* - - // advanced Hamlib Settings - document.getElementById("advancedHamlibSettingsButton").addEventListener("click", () => { -advancedHamlibSettingsModal + document.getElementById("radio-control-rigctl").style.display = 'block'; + document.getElementById("radio-control-rigctl").style.visibility = 'visible'; + document.getElementById("radio-control-rigctl").style.height = '100%'; + config.radiocontrol = 'rigctl' + fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); }); - */ + // rigctld + document.getElementById("radio-control-switch3").addEventListener("click", () => { + document.getElementById("radio-control-direct").style.visibility = 'hidden'; + document.getElementById("radio-control-rigctl").style.visibility = 'hidden'; + document.getElementById("radio-control-direct").style.display = 'none'; + document.getElementById("radio-control-rigctl").style.display = 'none'; + + document.getElementById("radio-control-rigctld").style.display = 'block'; + document.getElementById("radio-control-rigctld").style.visibility = 'visible'; + document.getElementById("radio-control-rigctld").style.height = '100%'; + config.radiocontrol = 'rigctld' + fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); + }); // on click waterfall scatter toggle view @@ -294,15 +312,27 @@ advancedHamlibSettingsModal // startTNC button clicked document.getElementById("startTNC").addEventListener("click", () => { + + + var deviceid_rigctl = document.getElementById("hamlib_deviceid_rigctl").value + var deviceport_rigctl = document.getElementById("hamlib_deviceport_rigctl").value + var serialspeed_rigctl = document.getElementById("hamlib_serialspeed_rigctl").value + var pttprotocol_rigctl = document.getElementById("hamlib_ptt_protocol_rigctl").value + + var rigctld_ip = document.getElementById("hamlib_rigctld_ip").value + var rigctld_port = document.getElementById("hamlib_rigctld_port").value + + var deviceid = document.getElementById("hamlib_deviceid").value + var deviceport = document.getElementById("hamlib_deviceport").value + var serialspeed = document.getElementById("hamlib_serialspeed").value + var pttprotocol = document.getElementById("hamlib_ptt_protocol").value + var mycall = document.getElementById("myCall").value mycall = mycall.toUpperCase() var mygrid = document.getElementById("myGrid").value var rx_audio = document.getElementById("audio_input_selectbox").value var tx_audio = document.getElementById("audio_output_selectbox").value - var deviceid = document.getElementById("hamlib_deviceid").value - var deviceport = document.getElementById("hamlib_deviceport").value - var serialspeed = document.getElementById("hamlib_serialspeed").value - var pttprotocol = document.getElementById("hamlib_ptt_protocol").value + var pttport = document.getElementById("hamlib_ptt_port_advanced").value var data_bits = document.getElementById('hamlib_databits_advanced').value var stop_bits = document.getElementById('hamlib_stopbits_advanced').value @@ -329,6 +359,7 @@ advancedHamlibSettingsModal } } + config.radiocontrol = radiocontrol config.mycall = mycall config.mygrid = mygrid config.deviceid = deviceid @@ -339,6 +370,14 @@ advancedHamlibSettingsModal config.data_bits = data_bits config.stop_bits = stop_bits config.handshake = handshake + config.deviceid_rigctl = deviceid_rigctl + config.serialspeed_rigctl = serialspeed_rigctl + config.pttprotocol_rigctl = pttprotocol_rigctl + config.rigctld_port = rigctld_port + config.rigctld_ip = rigctld_ip + config.deviceport_rigctl = deviceport_rigctl + + fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); @@ -352,9 +391,23 @@ advancedHamlibSettingsModal collapseThirdRow.show() var collapseFourthRow = new bootstrap.Collapse(document.getElementById('collapseFourthRow'), {toggle: false}) collapseFourthRow.show() + + // overriding settings for rigctl / direct + if (document.getElementById("radio-control-switch2").checked){ + var radiocontrol = 'rigctl' + var deviceid = document.getElementById("hamlib_deviceid_rigctl").value + var deviceport = document.getElementById("hamlib_deviceport_rigctl").value + var serialspeed = document.getElementById("hamlib_serialspeed_rigctl").value + var pttprotocol = document.getElementById("hamlib_ptt_protocol_rigctl").value + } else if (document.getElementById("radio-control-switch3").checked) { + var radiocontrol = 'rigctld' - daemon.startTNC(mycall, mygrid, rx_audio, tx_audio, deviceid, deviceport, pttprotocol, pttport, serialspeed, data_bits, stop_bits, handshake) + } else { + var radiocontrol = 'direct' + } + + daemon.startTNC(mycall, mygrid, rx_audio, tx_audio, radiocontrol, deviceid, deviceport, pttprotocol, pttport, serialspeed, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port) }) @@ -402,43 +455,41 @@ advancedHamlibSettingsModal // TEST HAMLIB document.getElementById("testHamlib").addEventListener("click", () => { + - var deviceid = document.getElementById("hamlib_deviceid").value - var deviceport = document.getElementById("hamlib_deviceport").value - var serialspeed = document.getElementById("hamlib_serialspeed").value - var pttprotocol = document.getElementById("hamlib_ptt_protocol").value var data_bits = document.getElementById("hamlib_databits_advanced").value var stop_bits = document.getElementById("hamlib_stopbits_advanced").value var handshake = document.getElementById("hamlib_handshake_advanced").value - var pttport = document.getElementById("hamlib_ptt_port_advanced").value - - daemon.testHamlib(deviceid, deviceport, serialspeed, pttprotocol, pttport, data_bits, stop_bits, handshake) - }) - - /* REMOVED FROM HTML - // TEST HAMLIB ADVANCED - document.getElementById("testHamlibAdvanced").addEventListener("click", () => { - var deviceid = document.getElementById("hamlib_deviceid").value - var deviceport = document.getElementById("hamlib_deviceport_advanced").value - document.getElementById("hamlib_deviceport").value = deviceport + var rigctld_ip = document.getElementById("hamlib_rigctld_ip").value + var rigctld_port = document.getElementById("hamlib_rigctld_port").value + + var deviceid = document.getElementById("hamlib_deviceid").value + var deviceport = document.getElementById("hamlib_deviceport").value + var serialspeed = document.getElementById("hamlib_serialspeed").value + var pttprotocol = document.getElementById("hamlib_ptt_protocol").value + + + // overriding settings for rigctl / direct + if (document.getElementById("radio-control-switch2").checked){ + var radiocontrol = 'rigctl' + var deviceid = document.getElementById("hamlib_deviceid_rigctl").value + var deviceport = document.getElementById("hamlib_deviceport_rigctl").value + var serialspeed = document.getElementById("hamlib_serialspeed_rigctl").value + var pttprotocol = document.getElementById("hamlib_ptt_protocol_rigctl").value - var serialspeed = document.getElementById("hamlib_serialspeed_advanced").value - document.getElementById("hamlib_serialspeed").value = serialspeed - - var pttprotocol = document.getElementById("hamlib_ptt_protocol_advanced").value - document.getElementById("hamlib_ptt_protocol").value = pttprotocol - - var pttport = document.getElementById("hamlib_deviceport").value - - var data_bits = document.getElementById("hamlib_databits_advanced").value - var stop_bits = document.getElementById("hamlib_stopbits_advanced").value - var handshake = document.getElementById("hamlib_handshake_advanced").value - - daemon.testHamlib(deviceid, deviceport, serialspeed, pttprotocol, pttport, data_bits, stop_bits, handshake) - }) - */ + } else if (document.getElementById("radio-control-switch3").checked) { + var radiocontrol = 'rigctld' + + } else { + var radiocontrol = 'direct' + } + + + + daemon.testHamlib(radiocontrol, deviceid, deviceport, serialspeed, pttprotocol, pttport, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port) + }) // START TRANSMISSION @@ -1069,9 +1120,11 @@ ipcRenderer.on('action-update-daemon-state', (event, arg) => { option.setAttribute('selected', true); } document.getElementById("hamlib_deviceport").add(option); + } } - + + // advanced settings if (document.getElementById("hamlib_deviceport_advanced").length != arg.serial_devices.length) { document.getElementById("hamlib_deviceport_advanced").innerHTML = "" for (i = 0; i < arg.serial_devices.length; i++) { @@ -1085,8 +1138,25 @@ ipcRenderer.on('action-update-daemon-state', (event, arg) => { document.getElementById("hamlib_deviceport_advanced").add(option); } } - + + // rigctl settings + if (document.getElementById("hamlib_deviceport_rigctl").length != arg.serial_devices.length) { + document.getElementById("hamlib_deviceport_rigctl").innerHTML = "" + for (i = 0; i < arg.serial_devices.length; i++) { + var option = document.createElement("option"); + option.text = arg.serial_devices[i]['DESCRIPTION']; + option.value = arg.serial_devices[i]['PORT']; + // set device from config if available + if(config.deviceport == option.value){ + option.setAttribute('selected', true); + } + document.getElementById("hamlib_deviceport_rigctl").add(option); + } + } + + } + if (arg.tnc_running_state == "stopped") { if (document.getElementById("hamlib_ptt_port_advanced").length != arg.serial_devices.length) { document.getElementById("hamlib_ptt_port_advanced").innerHTML = "" diff --git a/gui/src/index.html b/gui/src/index.html index 1bfc8e85..20302d92 100644 --- a/gui/src/index.html +++ b/gui/src/index.html @@ -12,7 +12,6 @@ - FreeDATA @@ -143,15 +142,13 @@ - + - - - +
@@ -1128,4 +1144,4 @@
- + \ No newline at end of file diff --git a/tnc/daemon.py b/tnc/daemon.py index a6ccd18f..4b52bd29 100755 --- a/tnc/daemon.py +++ b/tnc/daemon.py @@ -51,6 +51,7 @@ c_error_handler = ERROR_HANDLER_FUNC(py_error_handler) @contextmanager def noalsaerr(): + asound = cdll.LoadLibrary('libasound.so') asound.snd_lib_error_set_handler(c_error_handler) yield @@ -82,7 +83,7 @@ def start_daemon(): class CMDTCPRequestHandler(socketserver.BaseRequestHandler): - def handle(self): + def handle(self, hamlib_version = 0): structlog.get_logger("structlog").debug("[DMN] Client connected", ip=self.client_address[0]) # loop through socket buffer until timeout is reached. then close buffer @@ -97,10 +98,9 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): # we need to loop through buffer until end of chunk is reached or timeout occured while socketTimeout > time.time(): - chunk = self.request.recv(45) - data += chunk + data += self.request.recv(64) # or chunk.endswith(b'\n'): - if chunk.startswith(b'{"type"') and chunk.endswith(b'}\n'): + if data.startswith(b'{"type"') and data.endswith(b'}\n'): break data = data[:-1] # remove b'\n' data = str(data, encoding) @@ -173,8 +173,9 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): data_bits = str(received_json["parameter"][0]["data_bits"]) stop_bits = str(received_json["parameter"][0]["stop_bits"]) handshake = str(received_json["parameter"][0]["handshake"]) - - + radiocontrol = str(received_json["parameter"][0]["radiocontrol"]) + rigctld_ip = str(received_json["parameter"][0]["rigctld_ip"]) + rigctld_port = str(received_json["parameter"][0]["rigctld_port"]) structlog.get_logger("structlog").warning("[DMN] Starting TNC", rig=devicename, port=deviceport) #print(received_json["parameter"][0]) @@ -213,14 +214,14 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): options.append(stop_bits) options.append('--handshake') options.append(handshake) - - if HAMLIB_USE_RIGCTL: - options.append('--rigctl') + options.append('--radiocontrol') + options.append(radiocontrol) + options.append('--rigctld_ip') + options.append(rigctld_ip) + options.append('--rigctld_port') + options.append(rigctld_port) + - - - - # try running tnc from binary, else run from source # this helps running the tnc in a developer environment @@ -256,7 +257,7 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): static.TNCSTARTED = False if received_json["type"] == 'GET' and received_json["command"] == 'DAEMON_STATE': - + data = { 'COMMAND': 'DAEMON_STATE', 'DAEMON_STATE': [], @@ -279,7 +280,7 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): with noalsaerr(): # https://github.com/DJ2LS/FreeDATA/issues/22 p = pyaudio.PyAudio() # else do it the default way - except: + except Exception as e: p = pyaudio.PyAudio() for i in range(0, p.get_device_count()): @@ -336,10 +337,25 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): data_bits = str(received_json["parameter"][0]["data_bits"]) stop_bits = str(received_json["parameter"][0]["stop_bits"]) handshake = str(received_json["parameter"][0]["handshake"]) + radiocontrol = str(received_json["parameter"][0]["radiocontrol"]) + rigctld_ip = str(received_json["parameter"][0]["rigctld_ip"]) + rigctld_port = str(received_json["parameter"][0]["rigctld_port"]) + - + # check how we want to control the radio + if radiocontrol == 'direct': + import rig + elif radiocontrol == 'rigctl': + import rigctl as rig + elif radiocontrol == 'rigctld': + import rigctld as rig + else: + raise NotImplementedError + hamlib = rig.radio() - hamlib.open_rig(devicename=devicename, deviceport=deviceport, hamlib_ptt_type=pttprotocol, serialspeed=serialspeed, pttport=pttport, data_bits=data_bits, stop_bits=stop_bits, handshake=handshake) + hamlib.open_rig(devicename=devicename, deviceport=deviceport, hamlib_ptt_type=pttprotocol, serialspeed=serialspeed, pttport=pttport, data_bits=data_bits, stop_bits=stop_bits, handshake=handshake, rigctld_ip=rigctld_ip, rigctld_port = rigctld_port) + + hamlib_version = rig.hamlib_version hamlib.set_ptt(True) pttstate = hamlib.get_ptt() @@ -363,7 +379,6 @@ class CMDTCPRequestHandler(socketserver.BaseRequestHandler): structlog.get_logger("structlog").error("[DMN] Hamlib: Can't open rig", e = sys.exc_info()[0], error=e) except Exception as e: - #socketTimeout = 0 structlog.get_logger("structlog").error("[DMN] Network error", error=e) structlog.get_logger("structlog").warning("[DMN] Closing client socket", ip=self.client_address[0], port=self.client_address[1]) @@ -373,25 +388,10 @@ if __name__ == '__main__': # --------------------------------------------GET PARAMETER INPUTS PARSER = argparse.ArgumentParser(description='Simons TEST TNC') PARSER.add_argument('--port', dest="socket_port",default=3001, help="Socket port", type=int) - PARSER.add_argument('--rigctl', dest="hamlib_use_rigctl",action="store_true", default=False, help="force using of rigctl") ARGS = PARSER.parse_args() PORT = ARGS.socket_port - HAMLIB_USE_RIGCTL = ARGS.hamlib_use_rigctl - # force use of rigctl when on windows - if sys.platform == 'win32' or sys.platform == 'win64': - HAMLIB_USE_RIGCTL = True - - if HAMLIB_USE_RIGCTL: - structlog.get_logger("structlog").warning("[DMN] Using Hamlib rigctl module...") - hamlib_version = 0 - import rigctl as rig - else: - structlog.get_logger("structlog").info("[DMN] Using Hamlib rig module...") - import rig - hamlib_version = rig.hamlib_version - # --------------------------------------------START CMD SERVER DAEMON_THREAD = threading.Thread(target=start_daemon, name="daemon") diff --git a/tnc/main.py b/tnc/main.py index 4112aa77..2f0f98cc 100644 --- a/tnc/main.py +++ b/tnc/main.py @@ -37,8 +37,12 @@ if __name__ == '__main__': PARSER.add_argument('--data_bits', dest="hamlib_data_bits", default="8", help="Hamlib data bits", type=str) PARSER.add_argument('--stop_bits', dest="hamlib_stop_bits", default="1", help="Hamlib stop bits", type=str) PARSER.add_argument('--handshake', dest="hamlib_handshake", default="None", help="Hamlib handshake", type=str) - PARSER.add_argument('--rigctl', dest="hamlib_use_rigctl", action="store_true", default=False, help="force using of rigctl") - + PARSER.add_argument('--radiocontrol', dest="hamlib_radiocontrol", default="direct", help="Set how you want to control your radio") + PARSER.add_argument('--rigctld_port', dest="rigctld_port", default="direct", help="Set rigctld port") + PARSER.add_argument('--rigctld_ip', dest="rigctld_ip", default="direct", help="Set rigctld ip") + + + ARGS = PARSER.parse_args() @@ -57,12 +61,9 @@ if __name__ == '__main__': static.HAMLIB_DATA_BITS = ARGS.hamlib_data_bits static.HAMLIB_STOP_BITS = ARGS.hamlib_stop_bits static.HAMLIB_HANDSHAKE = ARGS.hamlib_handshake - static.HAMLIB_USE_RIGCTL = ARGS.hamlib_use_rigctl - print(ARGS.hamlib_use_rigctl) - - # force use of rigctl when on windows - if sys.platform == 'win32' or sys.platform == 'win64': - HAMLIB_USE_RIGCTL = True + static.HAMLIB_RADIOCONTROL = ARGS.hamlib_radiocontrol + static.HAMLIB_RGICTLD_IP = ARGS.rigctld_ip + static.HAMLIB_RGICTLD_PORT = ARGS.rigctld_port # we need to wait until we got all parameters from argparse first before we can load the other modules import sock diff --git a/tnc/modem.py b/tnc/modem.py index 955f7a8f..8cb4a62a 100644 --- a/tnc/modem.py +++ b/tnc/modem.py @@ -23,16 +23,6 @@ import re import queue import codec2 -if static.HAMLIB_USE_RIGCTL: - structlog.get_logger("structlog").warning("using rigctl....") - import rigctl as rig -else: - structlog.get_logger("structlog").warning("using rig.......") - import rig - -# option for testing miniaudio instead of audioop for sample rate conversion -#import miniaudio - #################################################### # https://stackoverflow.com/questions/7088672/pyaudio-working-but-spits-out-error-messages-each-time @@ -189,9 +179,20 @@ class RF(): structlog.get_logger("structlog").error("[TNC] starting pyaudio callback failed", e=e) # --------------------------------------------INIT AND OPEN HAMLIB - self.hamlib = rig.radio() - self.hamlib.open_rig(devicename=static.HAMLIB_DEVICE_NAME, deviceport=static.HAMLIB_DEVICE_PORT, hamlib_ptt_type=static.HAMLIB_PTT_TYPE, serialspeed=static.HAMLIB_SERIAL_SPEED, pttport=static.HAMLIB_PTT_PORT, data_bits=static.HAMLIB_DATA_BITS, stop_bits=static.HAMLIB_STOP_BITS, handshake=static.HAMLIB_HANDSHAKE) + # check how we want to control the radio + if static.HAMLIB_RADIOCONTROL == 'direct': + import rig + elif static.HAMLIB_RADIOCONTROL == 'rigctl': + import rigctl as rig + elif static.HAMLIB_RADIOCONTROL == 'rigctld': + import rigctld as rig + else: + raise NotImplementedError + + self.hamlib = rig.radio() + self.hamlib.open_rig(devicename=static.HAMLIB_DEVICE_NAME, deviceport=static.HAMLIB_DEVICE_PORT, hamlib_ptt_type=static.HAMLIB_PTT_TYPE, serialspeed=static.HAMLIB_SERIAL_SPEED, pttport=static.HAMLIB_PTT_PORT, data_bits=static.HAMLIB_DATA_BITS, stop_bits=static.HAMLIB_STOP_BITS, handshake=static.HAMLIB_HANDSHAKE, rigctld_ip = static.HAMLIB_RGICTLD_IP, rigctld_port = static.HAMLIB_RGICTLD_PORT) + # --------------------------------------------START DECODER THREAD fft_thread = threading.Thread(target=self.calculate_fft, name="FFT_THREAD") diff --git a/tnc/rig.py b/tnc/rig.py index 7c27653e..ba4954c8 100644 --- a/tnc/rig.py +++ b/tnc/rig.py @@ -7,6 +7,7 @@ import atexit import subprocess import os + # set global hamlib version hamlib_version = 0 @@ -25,7 +26,7 @@ try: python_version = str(sys.version_info[0]) + "." + str(sys.version_info[1]) # installation path for Ubuntu 20.04 LTS python modules - sys.path.append('/usr/local/lib/python'+ python_version +'/site-packages') + #sys.path.append('/usr/local/lib/python'+ python_version +'/site-packages') # installation path for Ubuntu 20.10 + sys.path.append('/usr/local/lib/') @@ -37,10 +38,11 @@ try: # this is not needed as python will be shipped with app bundle sys.path.append('/usr/local/lib/python3.6/site-packages') sys.path.append('/usr/local/lib/python3.7/site-packages') - sys.path.append('/usr/local/lib/python3.8/site-packages') + #sys.path.append('/usr/local/lib/python3.8/site-packages') sys.path.append('/usr/local/lib/python3.9/site-packages') sys.path.append('/usr/local/lib/python3.10/site-packages') + sys.path.append('lib/hamlib/linux/python3.8/site-packages') import Hamlib # https://stackoverflow.com/a/4703409 @@ -85,7 +87,7 @@ class radio: self.stop_bits = '' self.handshake = '' - def open_rig(self, devicename, deviceport, hamlib_ptt_type, serialspeed, pttport, data_bits, stop_bits, handshake): + def open_rig(self, devicename, deviceport, hamlib_ptt_type, serialspeed, pttport, data_bits, stop_bits, handshake, rigctld_port, rigctld_ip): self.devicename = devicename self.deviceport = str(deviceport) @@ -106,7 +108,7 @@ class radio: self.devicenumber = int(getattr(Hamlib, self.devicename)) print(self.devicenumber) except: - structlog.get_logger("structlog").error("[DMN] Hamlib: rig not supported...") + structlog.get_logger("structlog").error("[RIG] Hamlib: rig not supported...") self.devicenumber = 0 @@ -177,11 +179,11 @@ class radio: error = error[1] if error == 'Permission denied': - structlog.get_logger("structlog").error("[DMN] Hamlib has no permissions", e = error) + structlog.get_logger("structlog").error("[RIG] Hamlib has no permissions", e = error) help_url = 'https://github.com/DJ2LS/FreeDATA/wiki/UBUNTU-Manual-installation#1-permissions' - structlog.get_logger("structlog").error("[DMN] HELP:", check = help_url) + structlog.get_logger("structlog").error("[RIG] HELP:", check = help_url) except: - structlog.get_logger("structlog").info("[DMN] Hamlib device openend", status='SUCCESS') + structlog.get_logger("structlog").info("[RIG] Hamlib device openend", status='SUCCESS') # set ptt to false if ptt is stuck for some reason @@ -194,7 +196,7 @@ class radio: return True except Exception as e: - structlog.get_logger("structlog").error("[TNC] Hamlib - can't open rig", error=e, e=sys.exc_info()[0]) + structlog.get_logger("structlog").error("[RIG] Hamlib - can't open rig", error=e, e=sys.exc_info()[0]) return False def get_frequency(self): diff --git a/tnc/rigctl.py b/tnc/rigctl.py index 02bc7a4d..c0452d52 100644 --- a/tnc/rigctl.py +++ b/tnc/rigctl.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 -# Franco Spinelli, IW2DHW +# Intially created by Franco Spinelli, IW2DHW, 01/2022 +# Updated by DJ2LS +# # # versione mia di rig.py per gestire Ft897D tramite rigctl e senza # fare alcun riferimento alla configurazione @@ -13,6 +15,8 @@ import sys import os # for rig_model -> rig_number only +# set global hamlib version +hamlib_version = 0 class radio: def __init__(self): @@ -28,7 +32,7 @@ class radio: self.stop_bits = '' self.handshake = '' - def open_rig(self, devicename, deviceport, hamlib_ptt_type, serialspeed, pttport, data_bits, stop_bits, handshake): + def open_rig(self, devicename, deviceport, hamlib_ptt_type, serialspeed, pttport, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port): self.devicename = devicename self.deviceport = deviceport @@ -56,8 +60,12 @@ class radio: self.devicenumber = int(self.devicename) else: self.devicenumber = 6 #dummy - structlog.get_logger("structlog").warning("[TNC] RADIO NOT FOUND USING DUMMY!", error=e) - + structlog.get_logger("structlog").warning("[RIGCTL] RADIO NOT FOUND USING DUMMY!", error=e) + + # set deviceport to dummy port, if we selected dummy model + if self.devicenumber == 1 or self.devicenumber == 6: + self.deviceport = '/dev/ttyUSB0' + print(self.devicenumber, self.deviceport, self.serialspeed) diff --git a/tnc/rigctld.py b/tnc/rigctld.py new file mode 100644 index 00000000..c90e03fe --- /dev/null +++ b/tnc/rigctld.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +import socket +import logging +# class taken from darsidelemm +# rigctl - https://github.com/darksidelemm/rotctld-web-gui/blob/master/rotatorgui.py#L35 +# +# modified and adjusted to FreeDATA needs by DJ2LS + +# set global hamlib version +hamlib_version = 0 + +class radio(): + """ rotctld (hamlib) communication class """ + # Note: This is a massive hack. + + def __init__(self, hostname="localhost", port=4532, poll_rate=5, timeout=5): + """ Open a connection to rotctld, and test it for validity """ + self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.sock.settimeout(timeout) + + self.hostname = hostname + self.port = port + + + def open_rig(self, devicename, deviceport, hamlib_ptt_type, serialspeed, pttport, data_bits, stop_bits, handshake, rigctld_ip, rigctld_port): + self.connect() + logging.debug(f"Rigctl intialized") + return True + + def connect(self): + """ Connect to rotctld instance """ + self.sock.connect((self.hostname,self.port)) + ptt = self.get_ptt() + if ptt == None: + # Timeout! + self.close() + raise Exception("Timeout!") + else: + return ptt + + + def close_rig(self): + self.sock.close() + + + def send_command(self, command): + """ Send a command to the connected rotctld instance, + and return the return value. + """ + self.sock.sendall(command+b'\n') + try: + return self.sock.recv(1024) + except: + return None + + def get_mode(self): + data = self.send_command(b"m") + data = data.split(b'\n') + mode = data[0] + return mode.decode("utf-8") + + def get_bandwith(self): + data = self.send_command(b"m") + data = data.split(b'\n') + bandwith = data[1] + return bandwith.decode("utf-8") + + def get_frequency(self): + frequency = self.send_command(b"f") + return frequency.decode("utf-8") + + def get_ptt(self): + return self.send_command(b"t") + + def set_ptt(self, state): + if state: + self.send_command(b"T 1") + else: + self.send_command(b"T 0") + return state + diff --git a/tnc/sock.py b/tnc/sock.py index 601c3e89..add1ded6 100644 --- a/tnc/sock.py +++ b/tnc/sock.py @@ -56,11 +56,10 @@ class ThreadedTCPRequestHandler(socketserver.BaseRequestHandler): # we need to loop through buffer until end of chunk is reached or timeout occured while socketTimeout > time.time(): + + data += self.request.recv(64) # we keep amount of bytes short - chunk = self.request.recv(71) # we keep amount of bytes short - data += chunk - - if chunk.startswith(b'{"type"') and chunk.endswith(b'}\n'): + if data.startswith(b'{"type"') and data.endswith(b'}\n'): break data = data[:-1] # remove b'\n' diff --git a/tnc/static.py b/tnc/static.py index bd669661..65a89c2b 100644 --- a/tnc/static.py +++ b/tnc/static.py @@ -45,8 +45,10 @@ HAMLIB_PTT_PORT = '/dev/ttyUSB0' HAMLIB_STOP_BITS = '1' HAMLIB_DATA_BITS = '8' HAMLIB_HANDSHAKE = 'None' -HAMLIB_USE_RIGCTL = False - +HAMLIB_RADIOCONTROL = 'direct' +HAMLIB_RGICTLD_IP = '127.0.0.1' +HAMLIB_RGICTLD_PORT = '4532' + HAMLIB_FREQUENCY = 0 HAMLIB_MODE = '' HAMLIB_BANDWITH = 0