Run a cmd (rigctld by default) when connected to the server

This commit is contained in:
Nonoo 2020-10-29 20:28:17 +01:00
parent c2b48b8ea0
commit a0efee9eb4
7 changed files with 77 additions and 61 deletions

View file

@ -59,11 +59,11 @@ After it is connected and logged in:
transmit your voice.
- Starts a **TCP server** on port `4533` for exposing the **serial port**.
This can be used for controlling the server (the transceiver) with
[Hamlib](https://hamlib.github.io/):
```
rigctld -m 3085 -r 127.0.0.1:4533
```
[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 -`.
3085 is the model number for the Icom IC-705. `rigctld` will connect to
kappanhang's TCP serial port server, and waits connections on it's default
@ -84,7 +84,8 @@ Note that the built-in Wi-Fi in the Icom IC-705 has **very limited range**,
and **sensitive to interference**. If you see a lot of retransmits in the log,
or packet loss, then:
- Place the IC-705 close to your Wi-Fi AP/router
- Place the IC-705 close to your Wi-Fi AP/router, or use a Wi-Fi range
extender device.
- Make sure the Wi-Fi bandwith is set to max. 20Mhz in the Wi-Fi router (see
explanation [here](https://superuser.com/questions/542191/does-moving-my-router-from-20mhz-to-40-mhz-increase-my-wireless-speed))
- Try switching Wi-Fi channel on your Wi-Fi router. Only channels 1, 6 or 11

View file

@ -12,6 +12,7 @@ var verboseLog bool
var connectAddress string
var serialTCPPort uint16
var enableSerialDevice bool
var runCmd string
var statusLogInterval time.Duration
func parseArgs() {
@ -20,6 +21,7 @@ func parseArgs() {
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")
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")
i := getopt.Uint16Long("log-interval", 'i', 100, "Status bar/log interval in milliseconds")
getopt.Parse()
@ -34,5 +36,6 @@ func parseArgs() {
connectAddress = *a
serialTCPPort = *t
enableSerialDevice = *s
runCmd = *r
statusLogInterval = time.Duration(*i) * time.Millisecond
}

View file

@ -259,6 +259,8 @@ func (s *controlStream) handleRead(r []byte) error {
s.serialAndAudioStreamOpened = true
statusLog.startPeriodicPrint()
startCmdIfNeeded()
}
}
return nil

72
log.go
View file

@ -27,18 +27,14 @@ func (l *logger) GetCallerFileName(withLine bool) string {
}
}
func (l *logger) Printf(a string, b ...interface{}) {
if statusLog.isRealtime() {
statusLog.clear()
defer statusLog.print()
}
l.logger.Infof(l.GetCallerFileName(false)+": "+a, b...)
}
func (l *logger) Print(a ...interface{}) {
if statusLog.isRealtime() {
statusLog.clear()
defer statusLog.print()
statusLog.mutex.Lock()
statusLog.clearInternal()
defer func() {
statusLog.mutex.Unlock()
statusLog.print()
}()
}
l.logger.Info(append([]interface{}{l.GetCallerFileName(false) + ": "}, a...)...)
}
@ -47,62 +43,42 @@ func (l *logger) PrintStatusLog(a ...interface{}) {
l.logger.Info(append([]interface{}{l.GetCallerFileName(false) + ": "}, a...)...)
}
func (l *logger) Debugf(a string, b ...interface{}) {
if statusLog.isRealtime() {
statusLog.clear()
defer statusLog.print()
}
l.logger.Debugf(l.GetCallerFileName(true)+": "+a, b...)
}
func (l *logger) Debug(a ...interface{}) {
if statusLog.isRealtime() {
statusLog.clear()
defer statusLog.print()
statusLog.mutex.Lock()
statusLog.clearInternal()
defer func() {
statusLog.mutex.Unlock()
statusLog.print()
}()
}
l.logger.Debug(append([]interface{}{l.GetCallerFileName(true) + ": "}, a...)...)
}
func (l *logger) Errorf(a string, b ...interface{}) {
if statusLog.isRealtime() {
statusLog.clear()
defer statusLog.print()
}
l.logger.Errorf(l.GetCallerFileName(true)+": "+a, b...)
}
func (l *logger) Error(a ...interface{}) {
if statusLog.isRealtime() {
statusLog.clear()
defer statusLog.print()
statusLog.mutex.Lock()
statusLog.clearInternal()
defer func() {
statusLog.mutex.Unlock()
statusLog.print()
}()
}
l.logger.Error(append([]interface{}{l.GetCallerFileName(true) + ": "}, a...)...)
}
func (l *logger) ErrorC(a ...interface{}) {
if statusLog.isRealtime() {
statusLog.clear()
defer statusLog.print()
statusLog.mutex.Lock()
statusLog.clearInternal()
defer func() {
statusLog.mutex.Unlock()
statusLog.print()
}()
}
l.logger.Error(a...)
}
func (l *logger) Fatalf(a string, b ...interface{}) {
if statusLog.isRealtime() {
statusLog.clear()
defer statusLog.print()
}
l.logger.Fatalf(l.GetCallerFileName(true)+": "+a, b...)
}
func (l *logger) Fatal(a ...interface{}) {
if statusLog.isRealtime() {
statusLog.clear()
defer statusLog.print()
}
l.logger.Fatal(append([]interface{}{l.GetCallerFileName(true) + ": "}, a...)...)
}
func (l *logger) Init() {
// Example: https://stackoverflow.com/questions/50933936/zap-logger-does-not-print-on-console-rather-print-in-the-log-file/50936341
pe := zap.NewProductionEncoderConfig()

View file

@ -110,6 +110,7 @@ func main() {
}
}
stopCmd()
audio.deinit()
serialTCPSrv.deinit()
serialPort.deinit()

40
runcmd.go Normal file
View file

@ -0,0 +1,40 @@
package main
import (
"os/exec"
"strings"
"time"
)
const startCmdDelay = time.Second
var startedCmd *exec.Cmd
func doStartCmd() {
c := strings.Split(runCmd, " ")
startedCmd = exec.Command(c[0], c[1:]...)
err := startedCmd.Start()
if err == nil {
log.Print("cmd started: ", runCmd)
} else {
log.Error("error starting ", runCmd, " - ", err)
startedCmd = nil
}
}
func startCmdIfNeeded() {
if startedCmd != nil || runCmd == "-" {
return
}
time.AfterFunc(startCmdDelay, doStartCmd)
}
func stopCmd() {
if startedCmd == nil {
return
}
if err := startedCmd.Process.Kill(); err != nil {
log.Error("failed to stop cmd ", runCmd)
}
}

View file

@ -97,13 +97,6 @@ func (s *statusLogStruct) clearInternal() {
fmt.Printf("%c[2K", 27)
}
func (s *statusLogStruct) clear() {
s.mutex.Lock()
defer s.mutex.Unlock()
s.clearInternal()
}
func (s *statusLogStruct) print() {
s.mutex.Lock()
defer s.mutex.Unlock()