227 lines
6.5 KiB
Go
227 lines
6.5 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
var command int = 1
|
|
|
|
type FlexSpot struct {
|
|
ID int
|
|
CommandNumber int
|
|
FlexSpotNumber int
|
|
DX string
|
|
FrequencyMhz string
|
|
FrequencyHz string
|
|
Band string
|
|
Mode string
|
|
FlexMode string
|
|
Source string
|
|
SpotterCallsign string
|
|
TimeStamp int64
|
|
LifeTime string
|
|
Priority string
|
|
Comment string
|
|
Color string
|
|
BackgroundColor string
|
|
}
|
|
|
|
type FlexClient struct {
|
|
Address string
|
|
Port string
|
|
Timeout time.Duration
|
|
LogWriter *bufio.Writer
|
|
Reader *bufio.Reader
|
|
Writer *bufio.Writer
|
|
Conn *net.TCPConn
|
|
SpotChan chan TelnetSpot
|
|
MsgChan chan string
|
|
Repo FlexDXClusterRepository
|
|
Log *log.Logger
|
|
TCPServer *TCPServer
|
|
}
|
|
|
|
func NewFlexClient(repo FlexDXClusterRepository, TCPServer *TCPServer, log *log.Logger) *FlexClient {
|
|
return &FlexClient{
|
|
Address: Cfg.Flex.IP,
|
|
Port: "4992",
|
|
SpotChan: make(chan TelnetSpot),
|
|
MsgChan: TCPServer.MsgChan,
|
|
Repo: repo,
|
|
TCPServer: TCPServer,
|
|
Log: log,
|
|
}
|
|
}
|
|
|
|
func (fc *FlexClient) StartFlexClient() {
|
|
var err error
|
|
|
|
addr, err := net.ResolveTCPAddr("tcp", fc.Address+":"+fc.Port)
|
|
if err != nil {
|
|
fc.Log.Error("cannot resolve Telnet Client address:", err)
|
|
}
|
|
|
|
fc.LogWriter = bufio.NewWriter(os.Stdout)
|
|
|
|
fc.Timeout = 600 * time.Second
|
|
fc.Conn, err = net.DialTCP("tcp", nil, addr)
|
|
if err != nil {
|
|
fc.Log.Error("could not dial flex client:", err)
|
|
os.Exit(1)
|
|
}
|
|
fc.Log.Infof("connected to %s:%s", fc.Address, fc.Port)
|
|
|
|
go func() {
|
|
for message := range fc.SpotChan {
|
|
fc.SendSpottoFlex(message)
|
|
}
|
|
}()
|
|
|
|
fc.Reader = bufio.NewReader(fc.Conn)
|
|
fc.Writer = bufio.NewWriter(fc.Conn)
|
|
|
|
err = fc.Conn.SetKeepAlive(true)
|
|
if err != nil {
|
|
fc.Log.Error("error while setting keep alive:", err)
|
|
}
|
|
|
|
go fc.ReadLine()
|
|
}
|
|
|
|
func (fc *FlexClient) SendSpottoFlex(spot TelnetSpot) (n int, err error) {
|
|
|
|
freq := FreqMhztoHz(spot.Frequency)
|
|
|
|
flexSpot := FlexSpot{
|
|
CommandNumber: command,
|
|
DX: spot.DX,
|
|
FrequencyMhz: freq,
|
|
FrequencyHz: spot.Frequency,
|
|
Band: spot.Band,
|
|
Mode: spot.Mode,
|
|
Source: "FlexDXCluster",
|
|
SpotterCallsign: spot.Spotter,
|
|
TimeStamp: time.Now().Unix(),
|
|
LifeTime: Cfg.Flex.SpotLife,
|
|
Comment: spot.Comment,
|
|
Color: "#eaeaea",
|
|
BackgroundColor: "#000000",
|
|
Priority: "5",
|
|
}
|
|
|
|
if spot.NewDXCC {
|
|
flexSpot.Color = "#3bf908"
|
|
flexSpot.Priority = "1"
|
|
flexSpot.BackgroundColor = "#000000"
|
|
}
|
|
|
|
if spot.NewBand || spot.NewMode && spot.Mode != "" {
|
|
flexSpot.Color = "#f9f508"
|
|
flexSpot.Priority = "2"
|
|
flexSpot.BackgroundColor = "#000000"
|
|
}
|
|
|
|
if !spot.NewBand && !spot.NewMode && !spot.NewDXCC && !spot.CallsignWorked {
|
|
flexSpot.Color = "#eaeaea"
|
|
flexSpot.Priority = "5"
|
|
flexSpot.BackgroundColor = "#000000"
|
|
}
|
|
|
|
if spot.CallsignWorked {
|
|
flexSpot.Color = "#000000"
|
|
flexSpot.BackgroundColor = "#00c0c0"
|
|
flexSpot.Priority = "5"
|
|
}
|
|
|
|
flexSpot.Comment = strings.ReplaceAll(flexSpot.Comment, " ", "\u00A0")
|
|
flexSpot.Comment = flexSpot.Comment + "\u00A0" + "[" + flexSpot.Mode + "]"
|
|
|
|
srcFlexSpot, err := fc.Repo.FindDXSameBand(flexSpot)
|
|
if err != nil {
|
|
fc.Log.Error("could not find the DX in the database: ", err)
|
|
}
|
|
|
|
var stringSpot string
|
|
spotLife, _ := strconv.Atoi(Cfg.Flex.SpotLife)
|
|
spotTime := time.Unix(srcFlexSpot.TimeStamp, 0)
|
|
elapsed := time.Since(spotTime)
|
|
|
|
if srcFlexSpot.DX == "" {
|
|
fc.Repo.CreateSpot(flexSpot)
|
|
stringSpot = fmt.Sprintf("C%v|spot add rx_freq=%v callsign=%s mode=%s source=%s spotter_callsign=%s timestamp=%v lifetime_seconds=%s comment=%s color=%s background_color=%s priority=%s", flexSpot.CommandNumber, flexSpot.FrequencyMhz,
|
|
flexSpot.DX, flexSpot.Mode, flexSpot.Source, flexSpot.SpotterCallsign, flexSpot.TimeStamp, flexSpot.LifeTime, flexSpot.Comment, flexSpot.Color, flexSpot.BackgroundColor, flexSpot.Priority)
|
|
} else if srcFlexSpot.DX != "" && elapsed > time.Duration(spotLife) {
|
|
fc.Repo.UpdateSpotSameBand(flexSpot)
|
|
stringSpot = fmt.Sprintf("C%v|spot add rx_freq=%v callsign=%s mode=%s source=%s spotter_callsign=%s timestamp=%v lifetime_seconds=%s comment=%s color=%s background_color=%s priority=%s", flexSpot.CommandNumber, flexSpot.FrequencyMhz,
|
|
flexSpot.DX, flexSpot.Mode, flexSpot.Source, flexSpot.SpotterCallsign, flexSpot.TimeStamp, flexSpot.LifeTime, flexSpot.Comment, flexSpot.Color, flexSpot.BackgroundColor, flexSpot.Priority)
|
|
} else if srcFlexSpot.DX != "" && srcFlexSpot.Band == flexSpot.Band && srcFlexSpot.FrequencyMhz != flexSpot.FrequencyMhz && elapsed < time.Duration(spotLife) {
|
|
fc.Repo.UpdateSpotSameBand(flexSpot)
|
|
stringSpot = fmt.Sprintf("C%v|spot set %v rx_freq=%v callsign=%s mode=%s source=%s spotter_callsign=%s timestamp=%v lifetime_seconds=%s comment=%s color=%s background_color=%s priority=%s", flexSpot.CommandNumber, srcFlexSpot.CommandNumber, flexSpot.FrequencyMhz,
|
|
flexSpot.DX, flexSpot.Mode, flexSpot.Source, flexSpot.SpotterCallsign, flexSpot.TimeStamp, flexSpot.LifeTime, flexSpot.Comment, flexSpot.Color, flexSpot.BackgroundColor, flexSpot.Priority)
|
|
}
|
|
|
|
fc.Write(stringSpot)
|
|
|
|
command++
|
|
return
|
|
|
|
}
|
|
|
|
func (fc *FlexClient) ReadLine() {
|
|
for {
|
|
message, err := fc.Reader.ReadString(byte('\n'))
|
|
if err != nil {
|
|
fc.Log.Errorf("error reading message: %s", err)
|
|
continue
|
|
}
|
|
|
|
// regRespSpot := *regexp.MustCompile(`R(\d+)\|0\|(\d+)\n`)
|
|
// respSpot := regRespSpot.FindStringSubmatch(message)
|
|
|
|
// if len(respSpot) > 0 {
|
|
// spot, _ := fc.Repo.FindSpotByCommandNumber(respSpot[1])
|
|
// _, err := fc.Repo.UpdateFlexSpotNumberByID(respSpot[2], *spot)
|
|
// if err != nil {
|
|
// fc.Log.Errorf("could not update flex spot number in database: %s", err)
|
|
// }
|
|
// }
|
|
|
|
// regTriggerSpot := *regexp.MustCompile(`.*\|spot\s(\d+)\striggered.*`)
|
|
// respTrigger := regTriggerSpot.FindStringSubmatch(message)
|
|
|
|
// if len(respTrigger) > 0 {
|
|
// spot, err := fc.Repo.FindSpotByFlexSpotNumber(respTrigger[1])
|
|
// if err != nil {
|
|
// fc.Log.Errorf("could not find spot by flex spot number in database: %s", err)
|
|
// }
|
|
|
|
// msg := fmt.Sprintf(`To ALL de %s <0233z> : Clicked on %s at %s`, Cfg.SQLite.Callsign, spot.DX, spot.FrequencyHz)
|
|
// if len(fc.TCPServer.Clients) > 0 {
|
|
// fc.MsgChan <- msg
|
|
// }
|
|
|
|
// }
|
|
|
|
msg := strings.TrimSpace(message)
|
|
fc.Log.Info(msg)
|
|
|
|
}
|
|
}
|
|
|
|
// Write sends raw data to remove telnet server
|
|
func (fc *FlexClient) Write(data string) (n int, err error) {
|
|
n, err = fc.Writer.Write([]byte(data + "\n"))
|
|
if err == nil {
|
|
err = fc.Writer.Flush()
|
|
}
|
|
return
|
|
}
|