mirror of
https://github.com/nonoo/kappanhang.git
synced 2025-12-06 08:02:00 +01:00
Fix hanging exec cmd instances, rework exec cmdline args
This commit is contained in:
parent
47a22e5cce
commit
c98f1bd7a8
36
README.md
36
README.md
|
|
@ -53,33 +53,19 @@ host **ic-705** (ic-705.local or ic-705.localdomain).
|
|||
After it is connected and logged in:
|
||||
|
||||
- Creates a virtual PulseAudio **sound card** (48kHz, s16le, mono). This can be
|
||||
used to record/play audio from/to the server (the radio). You can also set
|
||||
this sound card in [WSJT-X](https://physics.princeton.edu/pulsar/K1JT/wsjtx.html).
|
||||
|
||||
If you want to listen to the audio coming from this sound card in real time,
|
||||
then you can create a [PulseAudio loopback](https://github.com/alentoghostflame/Python-Pulseaudio-Loopback-Tool)
|
||||
between the kappanhang sound card and your real sound card. You can also
|
||||
create a loopback for your microphone using this tool, so you'll be able to
|
||||
transmit your voice.
|
||||
used to record/play audio from/to the server (the transceiver). You can also
|
||||
set this sound card in [WSJT-X](https://physics.princeton.edu/pulsar/K1JT/wsjtx.html).
|
||||
- Starts a **TCP server** on port `4533` for exposing the **serial port**.
|
||||
- Starts `rigctld` and connects it to kappanhang's TCP serial port server.
|
||||
This can be used for controlling the server (the transceiver) with
|
||||
[Hamlib](https://hamlib.github.io/) (`rigctld`).
|
||||
- Runs the command `rigctld -m 3085 -r :4533` which starts `rigctld` and
|
||||
connects it to kappanhang's TCP serial port server. You can specify a custom
|
||||
command with the `-r` command line argument. Running any command can be
|
||||
disabled with `-r -`. The command is only executed once, as the TCP serial
|
||||
port server will stay on even if the RS-BA1 server disconnects. If the TCP
|
||||
serial port client disconnects (rigctld hangs) then the command will be
|
||||
automatically restarted. This can be disabled with the `-e`.
|
||||
|
||||
3085 is the model number of the Icom IC-705. `rigctld` will connect to
|
||||
kappanhang's TCP serial port server, and waits connections on it's default
|
||||
TCP port `4532`.
|
||||
|
||||
To use this with for example [WSJT-X](https://physics.princeton.edu/pulsar/K1JT/wsjtx.html),
|
||||
open WSJT-X settings, go to the *Radio* tab, set the *rig type* to `Hamlib NET
|
||||
rigctl`, and the *Network server* to `localhost`.
|
||||
|
||||
### Notes on command line arguments
|
||||
|
||||
If the `-s` command line argument is specified, then kappanhang will create a
|
||||
**virtual serial port**, so other apps which don't support Hamlib can access
|
||||
the transceiver directly. Look at the app log to find out the name of the
|
||||
|
|
@ -148,18 +134,12 @@ not available.
|
|||
### Hotkeys
|
||||
|
||||
- `q` (quit): closes the app
|
||||
- `l` (listen): toggles audio stream playback to the default sound device
|
||||
|
||||
- `l` (listen): toggles audio stream playback to the default sound device.
|
||||
This is useful for quickly listening into the audio stream coming from the
|
||||
server (the transceiver).
|
||||
|
||||
Note that audio will be played to the previously created virtual sound card
|
||||
regardless of this setting.
|
||||
- `space`: toggles PTT and audio stream recording from the default sound
|
||||
device
|
||||
|
||||
You can transmit your own voice using a mic attached to your computer for
|
||||
example.
|
||||
device. You can transmit your own voice using a mic attached to your
|
||||
computer for example.
|
||||
|
||||
Some basic CAT control hotkeys are also supported:
|
||||
|
||||
|
|
|
|||
17
args.go
17
args.go
|
|
@ -12,8 +12,9 @@ var verboseLog bool
|
|||
var connectAddress string
|
||||
var serialTCPPort uint16
|
||||
var enableSerialDevice bool
|
||||
var rigctldModel uint
|
||||
var disableRigctld bool
|
||||
var runCmd string
|
||||
var disableReRunCmd bool
|
||||
var runCmdOnSerialPortCreated string
|
||||
var statusLogInterval time.Duration
|
||||
|
||||
|
|
@ -21,11 +22,12 @@ func parseArgs() {
|
|||
h := getopt.BoolLong("help", 'h', "display help")
|
||||
v := getopt.BoolLong("verbose", 'v', "Enable verbose (debug) logging")
|
||||
a := getopt.StringLong("address", 'a', "IC-705", "Connect to address")
|
||||
t := getopt.Uint16Long("serial-tcp-port", 'p', 4533, "Expose radio's serial port on this TCP port")
|
||||
t := getopt.Uint16Long("serial-tcp-port", 't', 4533, "Expose radio's serial port on this TCP port")
|
||||
s := getopt.BoolLong("enable-serial-device", 's', "Expose radio's serial port as a virtual serial port")
|
||||
r := getopt.StringLong("run", 'r', "rigctld -m 3085 -r :4533", "Exec cmd when connected, set to - to disable")
|
||||
e := getopt.BoolLong("disable-rerun", 'e', "Disable re-execing the cmd on TCP serial port disconnect")
|
||||
o := getopt.StringLong("run-serial", 'o', "socat /tmp/kappanhang-IC-705.pty /tmp/vmware.pty", "Exec cmd when virtual serial port is created, set to - to disable")
|
||||
m := getopt.UintLong("rigctld-model", 'm', 3085, "rigctld model number")
|
||||
r := getopt.BoolLong("disable-rigctld", 'r', "Disable starting rigctld")
|
||||
e := getopt.StringLong("exec", 'e', "", "Exec cmd when connected")
|
||||
o := getopt.StringLong("exec-serial", 'o', "socat /tmp/kappanhang-IC-705.pty /tmp/vmware.pty", "Exec cmd when virtual serial port is created, set to - to disable")
|
||||
i := getopt.Uint16Long("log-interval", 'i', 100, "Status bar/log interval in milliseconds")
|
||||
|
||||
getopt.Parse()
|
||||
|
|
@ -40,8 +42,9 @@ func parseArgs() {
|
|||
connectAddress = *a
|
||||
serialTCPPort = *t
|
||||
enableSerialDevice = *s
|
||||
runCmd = *r
|
||||
disableReRunCmd = *e
|
||||
rigctldModel = *m
|
||||
disableRigctld = *r
|
||||
runCmd = *e
|
||||
runCmdOnSerialPortCreated = *o
|
||||
statusLogInterval = time.Duration(*i) * time.Millisecond
|
||||
}
|
||||
|
|
|
|||
|
|
@ -259,9 +259,8 @@ func (s *controlStream) handleRead(r []byte) error {
|
|||
statusLog.startPeriodicPrint()
|
||||
|
||||
startCmdIfNeeded()
|
||||
if enableSerialDevice {
|
||||
startSerialPortCmdIfNeeded()
|
||||
}
|
||||
startSerialPortCmdIfNeeded()
|
||||
startRigctldCmdIfNeeded()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
1
main.go
1
main.go
|
|
@ -134,6 +134,7 @@ func main() {
|
|||
|
||||
stopCmd()
|
||||
stopSerialPortCmd()
|
||||
stopRigctldCmd()
|
||||
audio.deinit()
|
||||
serialTCPSrv.deinit()
|
||||
serialPort.deinit()
|
||||
|
|
|
|||
87
runcmd.go
87
runcmd.go
|
|
@ -1,6 +1,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -8,8 +9,48 @@ import (
|
|||
|
||||
const startCmdDelay = time.Second
|
||||
|
||||
var startedRigctldCmd *exec.Cmd
|
||||
var rigctldCmdStartTimer *time.Timer
|
||||
var startedCmd *exec.Cmd
|
||||
var cmdStartTimer *time.Timer
|
||||
var serialPortStartedCmd *exec.Cmd
|
||||
var serialPortCmdStartTimer *time.Timer
|
||||
|
||||
func doStartRigctldCmd() {
|
||||
startedRigctldCmd = exec.Command("rigctld", "-m", fmt.Sprint(rigctldModel), "-r",
|
||||
fmt.Sprint(":", serialTCPPort))
|
||||
err := startedRigctldCmd.Start()
|
||||
if err == nil {
|
||||
log.Print("rigctld started: ", startedRigctldCmd)
|
||||
} else {
|
||||
log.Error("error starting rigctld: ", err)
|
||||
startedCmd = nil
|
||||
}
|
||||
rigctldCmdStartTimer = nil
|
||||
}
|
||||
|
||||
func startRigctldCmdIfNeeded() {
|
||||
if startedRigctldCmd != nil || disableRigctld {
|
||||
return
|
||||
}
|
||||
|
||||
if rigctldCmdStartTimer != nil {
|
||||
rigctldCmdStartTimer.Stop()
|
||||
}
|
||||
rigctldCmdStartTimer = time.AfterFunc(startCmdDelay, doStartRigctldCmd)
|
||||
}
|
||||
|
||||
func stopRigctldCmd() {
|
||||
if startedRigctldCmd == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := startedRigctldCmd.Process.Kill(); err != nil {
|
||||
log.Error("failed to stop rigctld: ", err)
|
||||
}
|
||||
_ = startedRigctldCmd.Wait()
|
||||
startedRigctldCmd = nil
|
||||
}
|
||||
|
||||
func doStartCmd() {
|
||||
c := strings.Split(runCmd, " ")
|
||||
|
|
@ -21,14 +62,29 @@ func doStartCmd() {
|
|||
log.Error("error starting ", runCmd, ": ", err)
|
||||
startedCmd = nil
|
||||
}
|
||||
cmdStartTimer = nil
|
||||
}
|
||||
|
||||
func startCmdIfNeeded() {
|
||||
if startedCmd != nil || runCmd == "-" {
|
||||
if startedCmd != nil || runCmd == "" {
|
||||
return
|
||||
}
|
||||
|
||||
time.AfterFunc(startCmdDelay, doStartCmd)
|
||||
if cmdStartTimer != nil {
|
||||
cmdStartTimer.Stop()
|
||||
}
|
||||
cmdStartTimer = time.AfterFunc(startCmdDelay, doStartCmd)
|
||||
}
|
||||
|
||||
func stopCmd() {
|
||||
if startedCmd == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := startedCmd.Process.Kill(); err != nil {
|
||||
log.Error("failed to stop cmd ", runCmd, ": ", err)
|
||||
}
|
||||
startedCmd = nil
|
||||
}
|
||||
|
||||
func doSerialPortStartCmd() {
|
||||
|
|
@ -41,30 +97,27 @@ func doSerialPortStartCmd() {
|
|||
log.Error("error starting ", runCmdOnSerialPortCreated, ": ", err)
|
||||
serialPortStartedCmd = nil
|
||||
}
|
||||
serialPortCmdStartTimer = nil
|
||||
}
|
||||
|
||||
func startSerialPortCmdIfNeeded() {
|
||||
if serialPortStartedCmd != nil || runCmdOnSerialPortCreated == "-" {
|
||||
if !enableSerialDevice || serialPortStartedCmd != nil || runCmdOnSerialPortCreated == "-" {
|
||||
return
|
||||
}
|
||||
|
||||
time.AfterFunc(startCmdDelay, doSerialPortStartCmd)
|
||||
}
|
||||
|
||||
func stopCmd() {
|
||||
if startedCmd != nil {
|
||||
if err := startedCmd.Process.Kill(); err != nil {
|
||||
log.Error("failed to stop cmd ", runCmd, ": ", err)
|
||||
}
|
||||
startedCmd = nil
|
||||
if serialPortCmdStartTimer != nil {
|
||||
serialPortCmdStartTimer.Stop()
|
||||
}
|
||||
serialPortCmdStartTimer = time.AfterFunc(startCmdDelay, doSerialPortStartCmd)
|
||||
}
|
||||
|
||||
func stopSerialPortCmd() {
|
||||
if serialPortStartedCmd != nil {
|
||||
if err := serialPortStartedCmd.Process.Kill(); err != nil {
|
||||
log.Error("failed to stop cmd ", runCmdOnSerialPortCreated, ": ", err)
|
||||
}
|
||||
serialPortStartedCmd = nil
|
||||
if serialPortStartedCmd == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err := serialPortStartedCmd.Process.Kill(); err != nil {
|
||||
log.Error("failed to stop cmd ", runCmdOnSerialPortCreated, ": ", err)
|
||||
}
|
||||
serialPortStartedCmd = nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,10 +104,8 @@ func (s *serialTCPSrvStruct) loop() {
|
|||
s.disconnectClient()
|
||||
log.Print("client ", s.client.RemoteAddr().String(), " disconnected")
|
||||
|
||||
if !disableReRunCmd {
|
||||
stopCmd()
|
||||
startCmdIfNeeded()
|
||||
}
|
||||
stopRigctldCmd()
|
||||
startRigctldCmdIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue