2020-10-28 18:03:35 +01:00
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
2020-10-29 09:39:13 +01:00
|
|
|
"os"
|
2020-10-28 18:03:35 +01:00
|
|
|
"sync"
|
|
|
|
|
"time"
|
2020-10-29 09:39:13 +01:00
|
|
|
|
|
|
|
|
"github.com/fatih/color"
|
|
|
|
|
"github.com/mattn/go-isatty"
|
2020-10-28 18:03:35 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type statusLogStruct struct {
|
|
|
|
|
ticker *time.Ticker
|
|
|
|
|
stopChan chan bool
|
|
|
|
|
stopFinishedChan chan bool
|
|
|
|
|
mutex sync.Mutex
|
|
|
|
|
|
2020-10-29 09:39:13 +01:00
|
|
|
line1 string
|
|
|
|
|
line2 string
|
|
|
|
|
|
|
|
|
|
state struct {
|
|
|
|
|
rxStr string
|
|
|
|
|
txStr string
|
|
|
|
|
tuneStr string
|
|
|
|
|
}
|
|
|
|
|
stateStr string
|
|
|
|
|
frequency float64
|
|
|
|
|
mode string
|
|
|
|
|
filter string
|
2020-10-28 18:03:35 +01:00
|
|
|
|
2020-10-29 10:15:37 +01:00
|
|
|
retransmitsColor *color.Color
|
|
|
|
|
lostColor *color.Color
|
|
|
|
|
|
2020-10-28 18:04:12 +01:00
|
|
|
startTime time.Time
|
|
|
|
|
rttLatency time.Duration
|
2020-10-28 18:03:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var statusLog statusLogStruct
|
|
|
|
|
|
|
|
|
|
func (s *statusLogStruct) reportRTTLatency(l time.Duration) {
|
|
|
|
|
s.mutex.Lock()
|
|
|
|
|
defer s.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
s.rttLatency = l
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 09:39:13 +01:00
|
|
|
func (s *statusLogStruct) reportFrequency(f float64) {
|
|
|
|
|
s.mutex.Lock()
|
|
|
|
|
defer s.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
s.frequency = f
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *statusLogStruct) reportMode(mode, filter string) {
|
|
|
|
|
s.mutex.Lock()
|
|
|
|
|
defer s.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
s.mode = mode
|
|
|
|
|
s.filter = filter
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *statusLogStruct) reportPTT(ptt, tune bool) {
|
|
|
|
|
s.mutex.Lock()
|
|
|
|
|
defer s.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
if tune {
|
|
|
|
|
s.stateStr = s.state.tuneStr
|
|
|
|
|
} else if ptt {
|
|
|
|
|
s.stateStr = s.state.txStr
|
|
|
|
|
} else {
|
|
|
|
|
s.stateStr = s.state.rxStr
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *statusLogStruct) clearInternal() {
|
|
|
|
|
fmt.Printf("%c[2K", 27)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *statusLogStruct) clear() {
|
|
|
|
|
s.mutex.Lock()
|
|
|
|
|
defer s.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
s.clearInternal()
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-28 18:03:35 +01:00
|
|
|
func (s *statusLogStruct) print() {
|
|
|
|
|
s.mutex.Lock()
|
|
|
|
|
defer s.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
if s.isRealtimeInternal() {
|
2020-10-29 09:39:13 +01:00
|
|
|
s.clearInternal()
|
|
|
|
|
fmt.Println(s.line1)
|
|
|
|
|
s.clearInternal()
|
|
|
|
|
fmt.Printf(s.line2+"%c[1A", 27)
|
2020-10-28 18:03:35 +01:00
|
|
|
} else {
|
2020-10-29 09:39:13 +01:00
|
|
|
log.PrintStatusLog(s.line2)
|
2020-10-28 18:03:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *statusLogStruct) update() {
|
|
|
|
|
s.mutex.Lock()
|
|
|
|
|
defer s.mutex.Unlock()
|
|
|
|
|
|
2020-10-29 09:39:13 +01:00
|
|
|
var modeStr string
|
|
|
|
|
if s.mode != "" {
|
|
|
|
|
modeStr = " " + s.mode
|
|
|
|
|
}
|
|
|
|
|
var filterStr string
|
|
|
|
|
if s.filter != "" {
|
|
|
|
|
filterStr = " " + s.filter
|
|
|
|
|
}
|
|
|
|
|
s.line1 = fmt.Sprint("state ", s.stateStr, " freq: ", fmt.Sprintf("%f", s.frequency/1000000), modeStr, filterStr)
|
2020-10-28 18:03:35 +01:00
|
|
|
|
2020-10-29 09:39:13 +01:00
|
|
|
up, down, lost, retransmits := netstat.get()
|
2020-10-29 10:15:37 +01:00
|
|
|
lostStr := "0"
|
|
|
|
|
if lost > 0 {
|
|
|
|
|
lostStr = s.lostColor.Sprint(" ", lost, " ")
|
|
|
|
|
}
|
|
|
|
|
retransmitsStr := "0"
|
|
|
|
|
if retransmits > 0 {
|
|
|
|
|
retransmitsStr = s.retransmitsColor.Sprint(" ", retransmits, " ")
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-29 09:39:13 +01:00
|
|
|
s.line2 = fmt.Sprint("up ", time.Since(s.startTime).Round(time.Second),
|
2020-10-28 18:03:35 +01:00
|
|
|
" rtt ", s.rttLatency.Milliseconds(), "ms up ",
|
|
|
|
|
netstat.formatByteCount(up), "/s down ",
|
2020-10-29 10:15:37 +01:00
|
|
|
netstat.formatByteCount(down), "/s retx ", retransmitsStr, "/1m lost ", lostStr, "/1m\r")
|
2020-10-28 18:03:35 +01:00
|
|
|
|
|
|
|
|
if s.isRealtimeInternal() {
|
2020-10-29 09:39:13 +01:00
|
|
|
t := time.Now().Format("2006-01-02T15:04:05.000Z0700")
|
|
|
|
|
s.line1 = fmt.Sprint(t, " ", s.line1)
|
|
|
|
|
s.line2 = fmt.Sprint(t, " ", s.line2)
|
2020-10-28 18:03:35 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *statusLogStruct) loop() {
|
|
|
|
|
for {
|
|
|
|
|
select {
|
|
|
|
|
case <-s.ticker.C:
|
|
|
|
|
s.update()
|
|
|
|
|
s.print()
|
|
|
|
|
case <-s.stopChan:
|
|
|
|
|
s.stopFinishedChan <- true
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *statusLogStruct) isRealtimeInternal() bool {
|
|
|
|
|
return statusLogInterval < time.Second
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *statusLogStruct) isRealtime() bool {
|
|
|
|
|
s.mutex.Lock()
|
|
|
|
|
defer s.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
return s.ticker != nil && s.isRealtimeInternal()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *statusLogStruct) isActive() bool {
|
|
|
|
|
s.mutex.Lock()
|
|
|
|
|
defer s.mutex.Unlock()
|
|
|
|
|
|
|
|
|
|
return s.ticker != nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *statusLogStruct) startPeriodicPrint() {
|
|
|
|
|
s.mutex.Lock()
|
|
|
|
|
defer s.mutex.Unlock()
|
|
|
|
|
|
2020-10-29 09:39:13 +01:00
|
|
|
if !isatty.IsTerminal(os.Stdout.Fd()) && statusLogInterval < time.Second {
|
|
|
|
|
statusLogInterval = time.Second
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c := color.New(color.FgHiWhite)
|
|
|
|
|
c.Add(color.BgWhite)
|
|
|
|
|
s.stateStr = c.Sprint(" ?? ")
|
|
|
|
|
c = color.New(color.FgHiWhite)
|
|
|
|
|
c.Add(color.BgGreen)
|
|
|
|
|
s.state.rxStr = c.Sprint(" RX ")
|
|
|
|
|
c = color.New(color.FgHiWhite, color.BlinkRapid)
|
|
|
|
|
c.Add(color.BgRed)
|
|
|
|
|
s.state.txStr = c.Sprint(" TX ")
|
|
|
|
|
s.state.tuneStr = c.Sprint(" TUNE ")
|
|
|
|
|
|
2020-10-29 10:15:37 +01:00
|
|
|
s.retransmitsColor = color.New(color.FgHiWhite)
|
|
|
|
|
s.retransmitsColor.Add(color.BgYellow)
|
|
|
|
|
s.lostColor = color.New(color.FgHiWhite)
|
|
|
|
|
s.lostColor.Add(color.BgRed)
|
|
|
|
|
|
2020-10-28 18:03:35 +01:00
|
|
|
s.startTime = time.Now()
|
|
|
|
|
s.stopChan = make(chan bool)
|
|
|
|
|
s.stopFinishedChan = make(chan bool)
|
|
|
|
|
s.ticker = time.NewTicker(statusLogInterval)
|
|
|
|
|
go s.loop()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (s *statusLogStruct) stopPeriodicPrint() {
|
|
|
|
|
if !s.isActive() {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
s.ticker.Stop()
|
|
|
|
|
s.ticker = nil
|
|
|
|
|
|
|
|
|
|
s.stopChan <- true
|
|
|
|
|
<-s.stopFinishedChan
|
2020-10-29 09:39:13 +01:00
|
|
|
|
|
|
|
|
fmt.Println()
|
|
|
|
|
fmt.Println()
|
|
|
|
|
fmt.Println()
|
2020-10-28 18:03:35 +01:00
|
|
|
}
|