FlexDXCluster/flexradio.go

227 lines
6.5 KiB
Go
Raw Normal View History

2024-09-23 16:24:50 +07:00
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
}