This commit is contained in:
2025-10-15 00:28:53 +05:30
parent 5b46ac98ad
commit af52fe8c72
12 changed files with 433 additions and 290 deletions

View File

@@ -8,7 +8,6 @@ import (
"net"
"os"
"regexp"
"strings"
"time"
)
@@ -60,7 +59,6 @@ type FlexClient struct {
Reader *bufio.Reader
Writer *bufio.Writer
Conn *net.TCPConn
SpotChanToFlex chan TelnetSpot
MsgChan chan string
Repo FlexDXClusterRepository
TCPServer *TCPServer
@@ -82,10 +80,10 @@ func NewFlexClient(repo FlexDXClusterRepository, TCPServer *TCPServer, SpotChanT
return &FlexClient{
Port: "4992",
SpotChanToFlex: SpotChanToFlex,
MsgChan: TCPServer.MsgChan,
Repo: repo,
TCPServer: TCPServer,
HTTPServer: httpServer,
IsConnected: false,
Enabled: enabled,
ctx: ctx,
@@ -114,7 +112,6 @@ func (fc *FlexClient) resolveAddress() (string, error) {
if Cfg.Flex.Discover {
Log.Debug("Attempting FlexRadio discovery...")
// Timeout sur la découverte (10 secondes max)
discoveryDone := make(chan struct {
success bool
discovery *Discovery
@@ -197,32 +194,9 @@ func (fc *FlexClient) StartFlexClient() {
if !fc.Enabled {
Log.Info("FlexRadio integration disabled in config - skipping")
// Consommer les spots pour éviter les blocages
go func() {
for {
select {
case <-fc.ctx.Done():
return
case <-fc.SpotChanToFlex:
}
}
}()
return
}
// Goroutine pour envoyer les spots au Flex
go func() {
for {
select {
case <-fc.ctx.Done():
return
case spot := <-fc.SpotChanToFlex:
fc.SendSpottoFlex(spot)
}
}
}()
for {
select {
case <-fc.ctx.Done():
@@ -289,188 +263,7 @@ func (fc *FlexClient) Close() {
}
}
func (fc *FlexClient) SendSpottoFlex(spot TelnetSpot) {
freq := FreqMhztoHz(spot.Frequency)
flexSpot := FlexSpot{
CommandNumber: CommandNumber,
DX: spot.DX,
FrequencyMhz: freq,
FrequencyHz: spot.Frequency,
Band: spot.Band,
Mode: spot.Mode,
Source: "FlexDXCluster",
SpotterCallsign: spot.Spotter,
TimeStamp: time.Now().Unix(),
UTCTime: spot.Time,
LifeTime: Cfg.Flex.SpotLife,
OriginalComment: spot.Comment,
Comment: spot.Comment,
Color: "#ffeaeaea",
BackgroundColor: "#ff000000",
Priority: "5",
NewDXCC: spot.NewDXCC,
NewBand: spot.NewBand,
NewMode: spot.NewMode,
NewSlot: spot.NewSlot,
Worked: spot.CallsignWorked,
InWatchlist: false,
CountryName: spot.CountryName,
DXCC: spot.DXCC,
}
flexSpot.Comment = flexSpot.Comment + " [" + flexSpot.Mode + "] [" + flexSpot.SpotterCallsign + "] [" + flexSpot.UTCTime + "]"
if fc.HTTPServer != nil && fc.HTTPServer.Watchlist != nil {
if fc.HTTPServer.Watchlist.Matches(flexSpot.DX) {
flexSpot.InWatchlist = true
flexSpot.Comment = flexSpot.Comment + " [Watchlist]"
Log.Infof("🎯 Watchlist match: %s", flexSpot.DX)
}
}
// If new DXCC
if spot.NewDXCC {
flexSpot.Priority = "1"
flexSpot.Comment = flexSpot.Comment + " [New DXCC]"
if Cfg.General.SpotColorNewEntity != "" && Cfg.General.BackgroundColorNewEntity != "" {
flexSpot.Color = Cfg.General.SpotColorNewEntity
flexSpot.BackgroundColor = Cfg.General.BackgroundColorNewEntity
} else {
flexSpot.Color = "#ff3bf908"
flexSpot.BackgroundColor = "#ff000000"
}
} else if spot.DX == Cfg.General.Callsign {
flexSpot.Priority = "1"
if Cfg.General.SpotColorMyCallsign != "" && Cfg.General.BackgroundColorMyCallsign != "" {
flexSpot.Color = Cfg.General.SpotColorMyCallsign
flexSpot.BackgroundColor = Cfg.General.BackgroundColorMyCallsign
} else {
flexSpot.Color = "#ffff0000"
flexSpot.BackgroundColor = "#ff000000"
}
} else if spot.CallsignWorked {
flexSpot.Priority = "5"
flexSpot.Comment = flexSpot.Comment + " [Worked]"
if Cfg.General.SpotColorWorked != "" && Cfg.General.BackgroundColorWorked != "" {
flexSpot.Color = Cfg.General.SpotColorWorked
flexSpot.BackgroundColor = Cfg.General.BackgroundColorWorked
} else {
flexSpot.Color = "#ff000000"
flexSpot.BackgroundColor = "#ff00c0c0"
}
} else if spot.NewMode && spot.NewBand {
flexSpot.Priority = "1"
flexSpot.Comment = flexSpot.Comment + " [New Band & Mode]"
if Cfg.General.SpotColorNewBandMode != "" && Cfg.General.BackgroundColorNewBandMode != "" {
flexSpot.Color = Cfg.General.SpotColorNewBandMode
flexSpot.BackgroundColor = Cfg.General.BackgroundColorNewBandMode
} else {
flexSpot.Color = "#ffc603fc"
flexSpot.BackgroundColor = "#ff000000"
}
} else if spot.NewMode && !spot.NewBand {
flexSpot.Priority = "2"
flexSpot.Comment = flexSpot.Comment + " [New Mode]"
if Cfg.General.SpotColorNewMode != "" && Cfg.General.BackgroundColorNewMode != "" {
flexSpot.Color = Cfg.General.SpotColorNewMode
flexSpot.BackgroundColor = Cfg.General.BackgroundColorNewMode
} else {
flexSpot.Color = "#fff9a908"
flexSpot.BackgroundColor = "#ff000000"
}
} else if spot.NewBand && !spot.NewMode {
flexSpot.Color = "#fff9f508"
flexSpot.Priority = "3"
flexSpot.BackgroundColor = "#ff000000"
flexSpot.Comment = flexSpot.Comment + " [New Band]"
} else if !spot.NewBand && !spot.NewMode && !spot.NewDXCC && !spot.CallsignWorked && spot.NewSlot {
flexSpot.Color = "#ff91d2ff"
flexSpot.Priority = "5"
flexSpot.BackgroundColor = "#ff000000"
flexSpot.Comment = flexSpot.Comment + " [New Slot]"
} else if !spot.NewBand && !spot.NewMode && !spot.NewDXCC && !spot.CallsignWorked {
flexSpot.Color = "#ffeaeaea"
flexSpot.Priority = "5"
flexSpot.BackgroundColor = "#ff000000"
} else {
flexSpot.Color = "#ffeaeaea"
flexSpot.Priority = "5"
flexSpot.BackgroundColor = "#ff000000"
}
// Send notification to Gotify
Gotify(flexSpot)
flexSpot.Comment = strings.ReplaceAll(flexSpot.Comment, " ", "\u00A0")
srcFlexSpot, err := fc.Repo.FindDXSameBand(flexSpot)
if err != nil {
Log.Debugf("Could not find the DX in the database: %v", err)
}
var stringSpot string
if srcFlexSpot.DX == "" {
fc.Repo.CreateSpot(flexSpot)
CommandNumber++
if fc.HTTPServer != nil {
fc.HTTPServer.broadcast <- WSMessage{
Type: "spots",
Data: fc.Repo.GetAllSpots("0"),
}
}
if fc.IsConnected {
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)
CommandNumber++
fc.SendSpot(stringSpot)
}
} else if srcFlexSpot.DX != "" && srcFlexSpot.Band == flexSpot.Band {
fc.Repo.DeleteSpotByFlexSpotNumber(string(flexSpot.FlexSpotNumber))
if fc.IsConnected {
stringSpot = fmt.Sprintf("C%v|spot remove %v", flexSpot.CommandNumber, srcFlexSpot.FlexSpotNumber)
fc.SendSpot(stringSpot)
CommandNumber++
}
fc.Repo.CreateSpot(flexSpot)
CommandNumber++
if fc.IsConnected {
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)
CommandNumber++
fc.SendSpot(stringSpot)
}
} else if srcFlexSpot.DX != "" && srcFlexSpot.Band != flexSpot.Band {
fc.Repo.CreateSpot(flexSpot)
CommandNumber++
if fc.IsConnected {
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)
CommandNumber++
fc.SendSpot(stringSpot)
}
}
}
// ✅ SendSpot - Méthode simplifiée pour envoyer une commande au Flex
func (fc *FlexClient) SendSpot(stringSpot string) {
if fc.IsConnected {
fc.Write(stringSpot)