16 Commits

Author SHA1 Message Date
a17541c2e6 up 2025-06-14 01:51:55 +02:00
73e5da15bf remove 2025-06-09 00:55:20 +02:00
b4bbd427aa new slot 2025-06-07 10:36:20 +02:00
f1d156ea84 password 2025-06-07 09:36:56 +02:00
ebdf1336a1 new code for login 2025-06-03 00:15:08 +02:00
db41a32a5b up 2025-06-02 23:21:38 +02:00
b77b013d63 up 2025-06-02 23:16:10 +02:00
f3851e44b6 gotify 2025-05-28 23:04:12 +02:00
95d6e0c4ff gotify 2025-05-28 23:02:35 +02:00
d307c92d25 gotify 2025-05-28 23:00:44 +02:00
9226eb5b2e gotify 2025-05-28 22:52:12 +02:00
ded5c332e2 gotify 2025-05-28 22:50:29 +02:00
026915fdec Merge branch 'main' of https://git.rouggy.com/rouggy/FlexDXCluster 2025-04-06 18:36:32 +02:00
6749289255 up 2025-04-06 18:36:16 +02:00
71c57cb2a1 up 2024-11-30 21:49:00 +07:00
eaa0c62892 correct band guess 2024-11-16 23:03:12 +07:00
14 changed files with 310 additions and 82 deletions

0
.vscode/launch.json vendored Normal file
View File

View File

@ -4,7 +4,7 @@ WORKDIR /app
COPY go.mod go.sum ./ COPY go.mod go.sum ./
COPY clublog.go config.go config.yml database.go flexradio.go HTTPServer.go spot.go main.go TCPClient.go TCPServer.go utils.go log.go ./ COPY config.go config.yml database.go flexradio.go spot.go main.go TCPClient.go TCPServer.go utils.go log.go xml.go ./
COPY templates/* . COPY templates/* .
RUN go build -o bin main.go RUN go build -o bin main.go

View File

@ -18,10 +18,12 @@ type TCPClient struct {
Password string Password string
Address string Address string
Port string Port string
LoggedIn bool
Timeout time.Duration Timeout time.Duration
LogWriter *bufio.Writer LogWriter *bufio.Writer
Reader *bufio.Reader Reader *bufio.Reader
Writer *bufio.Writer Writer *bufio.Writer
Scanner *bufio.Scanner
Conn *net.TCPConn Conn *net.TCPConn
TCPServer TCPServer TCPServer TCPServer
MsgChan chan string MsgChan chan string
@ -38,6 +40,7 @@ func NewTCPClient(TCPServer *TCPServer, Countries Countries) *TCPClient {
Address: Cfg.Cluster.Server, Address: Cfg.Cluster.Server,
Port: Cfg.Cluster.Port, Port: Cfg.Cluster.Port,
Login: Cfg.Cluster.Login, Login: Cfg.Cluster.Login,
Password: Cfg.Cluster.Password,
MsgChan: TCPServer.MsgChan, MsgChan: TCPServer.MsgChan,
CmdChan: TCPServer.CmdChan, CmdChan: TCPServer.CmdChan,
SpotChanToFlex: make(chan TelnetSpot, 100), SpotChanToFlex: make(chan TelnetSpot, 100),
@ -54,6 +57,7 @@ func (c *TCPClient) setDefaultParams() {
if c.LogWriter == nil { if c.LogWriter == nil {
c.LogWriter = bufio.NewWriter(os.Stdout) c.LogWriter = bufio.NewWriter(os.Stdout)
} }
c.LoggedIn = false
} }
func (c *TCPClient) StartClient() { func (c *TCPClient) StartClient() {
@ -69,19 +73,18 @@ func (c *TCPClient) StartClient() {
if err != nil { if err != nil {
Log.Error("Cannot connect to Telnet Client:", err) Log.Error("Cannot connect to Telnet Client:", err)
} }
Log.Infof("Connected to DX cluster %s:%s", c.Address, c.Port)
err = c.Conn.SetKeepAlive(true) // err = c.Conn.SetKeepAlive(true)
if err != nil { // if err != nil {
Log.Error("Error while setting keep alive:", err) // Log.Error("Error while setting keep alive:", err)
} // }
c.Reader = bufio.NewReader(c.Conn) c.Reader = bufio.NewReader(c.Conn)
c.Writer = bufio.NewWriter(c.Conn) c.Writer = bufio.NewWriter(c.Conn)
go func() { go func() {
for message := range c.TCPServer.CmdChan { for message := range c.TCPServer.CmdChan {
Log.Infof("Received DX Command: %s", message) Log.Infof("Received Command: %s", message)
message := message + "\n" message := message + "\n"
c.WriteString(message) c.WriteString(message)
} }
@ -130,34 +133,65 @@ func (c *TCPClient) SetFilters() {
func (c *TCPClient) ReadLine() { func (c *TCPClient) ReadLine() {
for { for {
message, err := c.Reader.ReadString('\n')
// Need to check data with space first to find login and then use \n
if !c.LoggedIn {
message, err := c.Reader.ReadString(' ')
message, _ = strings.CutSuffix(message, "\n") message, _ = strings.CutSuffix(message, "\n")
message, _ = strings.CutSuffix(message, "\r") message, _ = strings.CutSuffix(message, "\r")
if err != nil { if err != nil {
Log.Errorf("Error reading message: %s", err) Log.Errorf("Error reading message: %s", err)
continue c.Conn.Close()
c.StartClient()
} }
if strings.Contains(message, Cfg.Cluster.LoginPrompt) { if strings.Contains(message, Cfg.Cluster.LoginPrompt) {
Log.Debug("Found login prompt...sending callsign") Log.Debug("Found login prompt...sending callsign")
c.Write([]byte(c.Login + "\r\n")) c.Write([]byte(c.Login + "\r\n"))
c.SetFilters() c.LoggedIn = true
if Cfg.Cluster.Command != "" { // c.SetFilters()
c.WriteString(Cfg.Cluster.Command) // if Cfg.Cluster.Command != "" {
} // c.WriteString(Cfg.Cluster.Command + "\n\r")
// }
Log.Infof("Connected to DX cluster %s:%s", Cfg.Cluster.Server, Cfg.Cluster.Port)
Log.Info("Start receiving spots") Log.Info("Start receiving spots")
} else if strings.Contains(message, "Error reading from server: read tcp") { continue
}
}
if c.LoggedIn {
message, err := c.Reader.ReadString('\n')
message, _ = strings.CutSuffix(message, "\n")
message, _ = strings.CutSuffix(message, "\r")
if strings.Contains(message, "password") {
Log.Debug("Found password prompt...sending password")
c.Write([]byte(c.Password + "\r\n"))
}
if err != nil {
Log.Errorf("Error reading message: %s", err)
c.Conn.Close()
c.StartClient()
}
if strings.Contains(message, "Error reading from server: read tcp") {
Log.Error("Disconnected from Telnet Server, reconnecting") Log.Error("Disconnected from Telnet Server, reconnecting")
c.Close() c.Close()
c.StartClient() c.StartClient()
} else { } else {
if c.LoggedIn && strings.Contains(message, "DX") {
ProcessTelnetSpot(spotRe, message, c.SpotChanToFlex, c.SpotChanToHTTPServer, c.Countries) ProcessTelnetSpot(spotRe, message, c.SpotChanToFlex, c.SpotChanToHTTPServer, c.Countries)
} }
}
// Send the spot message to TCP server // Send the spot message to TCP server
c.MsgChan <- message c.MsgChan <- message
} }
}
} }
// Write sends raw data to remove telnet server // Write sends raw data to remove telnet server

View File

@ -27,6 +27,7 @@ type Config struct {
Server string `yaml:"server"` Server string `yaml:"server"`
Port string `yaml:"port"` Port string `yaml:"port"`
Login string `yaml:"login"` Login string `yaml:"login"`
Password string `yaml:"password"`
Skimmer bool `yaml:"skimmer"` Skimmer bool `yaml:"skimmer"`
FT8 bool `yaml:"ft8"` FT8 bool `yaml:"ft8"`
FT4 bool `yaml:"ft4"` FT4 bool `yaml:"ft4"`
@ -44,6 +45,16 @@ type Config struct {
Host string `yaml:"host"` Host string `yaml:"host"`
Port string `yaml:"port"` Port string `yaml:"port"`
} `yaml:"telnetserver"` } `yaml:"telnetserver"`
Gotify struct {
Enable bool `yaml:"enable"`
URL string `yaml:"url"`
Token string `yaml:"token"`
NewDXCC bool `yaml:"NewDXCC"`
NewBand bool `yaml:"NewBand"`
NewMode bool `yaml:"NewMode"`
NewBandAndMode bool `yaml:"NewBandAndMode"`
} `yaml:"gotify"`
} }
func NewConfig(configPath string) *Config { func NewConfig(configPath string) *Config {

View File

@ -5,17 +5,18 @@ general:
telnetserver: true # not in use for now telnetserver: true # not in use for now
flexradiospot: true # not in use for now flexradiospot: true # not in use for now
sqlite: sqlite:
sqlite_path: 'C:\Perso\Seafile\Radio\Logs\Log4OM\Vietnam.SQLite' # SQLite Db oath of Log4OM sqlite_path: 'C:\Perso\Seafile\Radio\Logs\Log4OM\F4BPO.SQLite' # SQLite Db oath of Log4OM
callsign: XV9Q # Log4OM Callsign used to check if you get spotted by someone callsign: F4BPO # Log4OM Callsign used to check if you get spotted by someone
cluster: cluster:
server: dxc.k0xm.net server: cluster.f4bpo.com # dxc.k0xm.net dxc.sm7iun.se
port: 7300 port: 7300
login: xv9q login: f4bpo
password: 89DGgg
skimmer: true skimmer: true
ft8: true ft8: false
ft4: false ft4: false
command: #SET/NOFILTER command:
login_prompt: "Please enter your call:" login_prompt: "login:"
flex: flex:
discovery: true # Radio must be on same LAN than the program discovery: true # Radio must be on same LAN than the program
ip: 10.10.10.120 # if discovery is true no need to put an IP ip: 10.10.10.120 # if discovery is true no need to put an IP
@ -23,3 +24,11 @@ flex:
telnetserver: # Log4OM must be connected to this server ie: localhost:7301 if on same machine as this program else ip:7301 telnetserver: # Log4OM must be connected to this server ie: localhost:7301 if on same machine as this program else ip:7301
host: 0.0.0.0 host: 0.0.0.0
port: 7301 port: 7301
gotify:
enable: false
url: https://gotify.rouggy.com/message
token: ALaGS4MVMWTEMcP
NewDXCC: true
NewBand: false
NewMode: false
NewBandAndMode: false

View File

@ -6713,7 +6713,7 @@
<CountryTag /> <CountryTag />
<CountryPrefixList> <CountryPrefixList>
<CountryPrefix> <CountryPrefix>
<PrefixList>^FO.*</PrefixList> <PrefixList>^FO.*|TX5U</PrefixList>
<StartDate xsi:nil="true" /> <StartDate xsi:nil="true" />
<EndDate>1979-07-18T00:00:00Z</EndDate> <EndDate>1979-07-18T00:00:00Z</EndDate>
</CountryPrefix> </CountryPrefix>
@ -6723,7 +6723,7 @@
<EndDate>1979-07-22T23:59:59Z</EndDate> <EndDate>1979-07-22T23:59:59Z</EndDate>
</CountryPrefix> </CountryPrefix>
<CountryPrefix> <CountryPrefix>
<PrefixList>^FO.*</PrefixList> <PrefixList>^FO.*|TX5U</PrefixList>
<StartDate>1979-07-22T23:59:59Z</StartDate> <StartDate>1979-07-22T23:59:59Z</StartDate>
<EndDate xsi:nil="true" /> <EndDate xsi:nil="true" />
</CountryPrefix> </CountryPrefix>
@ -12832,7 +12832,7 @@
<EndDate>1979-12-31T23:59:59Z</EndDate> <EndDate>1979-12-31T23:59:59Z</EndDate>
</CountryPrefix> </CountryPrefix>
<CountryPrefix> <CountryPrefix>
<PrefixList>^FR.*</PrefixList> <PrefixList>^FR.*|^TO974REF</PrefixList>
<StartDate>1979-12-31T23:59:59Z</StartDate> <StartDate>1979-12-31T23:59:59Z</StartDate>
<EndDate xsi:nil="true" /> <EndDate xsi:nil="true" />
</CountryPrefix> </CountryPrefix>

View File

@ -161,6 +161,52 @@ func (r *Log4OMContactsRepository) ListByCountryMode(countryID string, mode stri
} }
} }
func (r *Log4OMContactsRepository) ListByCountryModeBand(countryID string, band string, mode string, contactsModeBandChan chan []Contact, wg *sync.WaitGroup) {
defer wg.Done()
if mode == "USB" || mode == "LSB" {
rows, err := r.db.Query("SELECT callsign, band, mode, dxcc, stationcallsign, country FROM log WHERE dxcc = ? AND (mode = ? OR mode = ?) AND band = ?", countryID, "USB", "LSB", band)
if err != nil {
log.Error("could not query database", err)
}
defer rows.Close()
contacts := []Contact{}
for rows.Next() {
c := Contact{}
if err := rows.Scan(&c.Callsign, &c.Band, &c.Mode, &c.DXCC, &c.StationCallsign, &c.Country); err != nil {
log.Error("could not query database", err)
}
contacts = append(contacts, c)
}
contactsModeBandChan <- contacts
} else {
rows, err := r.db.Query("SELECT callsign, band, mode, dxcc, stationcallsign, country FROM log WHERE dxcc = ? AND mode = ? AND band = ?", countryID, mode, band)
if err != nil {
log.Error("could not query the database", err)
}
defer rows.Close()
contacts := []Contact{}
for rows.Next() {
c := Contact{}
if err := rows.Scan(&c.Callsign, &c.Band, &c.Mode, &c.DXCC, &c.StationCallsign, &c.Country); err != nil {
fmt.Println(err)
}
contacts = append(contacts, c)
}
contactsModeBandChan <- contacts
}
}
func (r *Log4OMContactsRepository) ListByCountryBand(countryID string, band string, contactsBandChan chan []Contact, wg *sync.WaitGroup) { func (r *Log4OMContactsRepository) ListByCountryBand(countryID string, band string, contactsBandChan chan []Contact, wg *sync.WaitGroup) {
defer wg.Done() defer wg.Done()
rows, err := r.db.Query("SELECT callsign, band, mode, dxcc, stationcallsign, country FROM log WHERE dxcc = ? AND band = ?", countryID, band) rows, err := r.db.Query("SELECT callsign, band, mode, dxcc, stationcallsign, country FROM log WHERE dxcc = ? AND band = ?", countryID, band)

View File

@ -34,6 +34,7 @@ type FlexSpot struct {
NewDXCC bool NewDXCC bool
NewBand bool NewBand bool
NewMode bool NewMode bool
NewSlot bool
Worked bool Worked bool
} }
@ -164,6 +165,7 @@ func (fc *FlexClient) SendSpottoFlex(spot TelnetSpot) {
NewDXCC: spot.NewDXCC, NewDXCC: spot.NewDXCC,
NewBand: spot.NewBand, NewBand: spot.NewBand,
NewMode: spot.NewMode, NewMode: spot.NewMode,
NewSlot: spot.NewSlot,
Worked: spot.CallsignWorked, Worked: spot.CallsignWorked,
} }
@ -180,7 +182,7 @@ func (fc *FlexClient) SendSpottoFlex(spot TelnetSpot) {
flexSpot.Priority = "1" flexSpot.Priority = "1"
flexSpot.BackgroundColor = "#ff000000" flexSpot.BackgroundColor = "#ff000000"
} else if spot.CallsignWorked { } else if spot.CallsignWorked {
flexSpot.Color = "#ff000000" flexSpot.Color = "#ffeaeaea"
flexSpot.BackgroundColor = "#ff00c0c0" flexSpot.BackgroundColor = "#ff00c0c0"
flexSpot.Priority = "5" flexSpot.Priority = "5"
flexSpot.Comment = flexSpot.Comment + " [Worked]" flexSpot.Comment = flexSpot.Comment + " [Worked]"
@ -199,12 +201,24 @@ func (fc *FlexClient) SendSpottoFlex(spot TelnetSpot) {
flexSpot.Priority = "3" flexSpot.Priority = "3"
flexSpot.BackgroundColor = "#ff000000" flexSpot.BackgroundColor = "#ff000000"
flexSpot.Comment = flexSpot.Comment + " [New Band]" 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 { } else if !spot.NewBand && !spot.NewMode && !spot.NewDXCC && !spot.CallsignWorked {
flexSpot.Color = "#ffeaeaea" flexSpot.Color = "#ffeaeaea"
flexSpot.Priority = "5" flexSpot.Priority = "5"
flexSpot.BackgroundColor = "#ff000000" 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") flexSpot.Comment = strings.ReplaceAll(flexSpot.Comment, " ", "\u00A0")
srcFlexSpot, err := fc.Repo.FindDXSameBand(flexSpot) srcFlexSpot, err := fc.Repo.FindDXSameBand(flexSpot)

86
gotify.go Normal file
View File

@ -0,0 +1,86 @@
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
)
type GotifyMessage struct {
Title string `json:"title"`
Message string `json:"message"`
Priority int `json:"priority"`
}
func Gotify(spot FlexSpot) {
if Cfg.Gotify.Enable {
message := fmt.Sprintf("DX: %s\nFrom: %s\nFreq: %s\nMode: %s\n", spot.DX, spot.Source, spot.FrequencyMhz, spot.Mode)
gotifyMsg := GotifyMessage{
Title: "",
Message: message,
Priority: 10,
}
if spot.NewDXCC && Cfg.Gotify.NewDXCC {
title := "FlexDXCluster New DXCC"
gotifyMsg.Title = title
gotifyMsg.Message = message
sendToGotify(gotifyMsg)
}
if spot.NewBand && spot.NewMode && Cfg.Gotify.NewBandAndMode {
title := "FlexDXCluster New Mode & Band"
gotifyMsg.Title = title
gotifyMsg.Message = message
sendToGotify(gotifyMsg)
}
if spot.NewMode && Cfg.Gotify.NewMode && !spot.NewBand {
title := "FlexDXCluster New Mode"
gotifyMsg.Title = title
gotifyMsg.Message = message
sendToGotify(gotifyMsg)
}
if spot.NewBand && Cfg.Gotify.NewBand && !spot.NewMode {
title := "FlexDXCluster New Band"
gotifyMsg.Title = title
gotifyMsg.Message = message
sendToGotify(gotifyMsg)
}
}
}
func sendToGotify(mess GotifyMessage) {
jsonData, err := json.Marshal(mess)
if err != nil {
Log.Errorln("Error marshaling JSON:", err)
return
}
req, err := http.NewRequest("POST", Cfg.Gotify.URL, bytes.NewBuffer(jsonData))
if err != nil {
Log.Errorln("Error creating request:", err)
return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Add("Authorization", "Bearer "+Cfg.Gotify.Token)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
Log.Errorln("Error sending request:", err)
return
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
Log.Errorln("Gotify server returned non-OK status:", resp.Status)
} else {
Log.Debugln("Push successfully sent to Gotify")
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

33
main.go
View File

@ -4,9 +4,7 @@ import (
"flag" "flag"
"log" "log"
"os" "os"
"os/signal"
"path/filepath" "path/filepath"
"syscall"
) )
func ParseFlags() (string, error) { func ParseFlags() (string, error) {
@ -44,11 +42,16 @@ func main() {
cfg := NewConfig(cfgPath) cfg := NewConfig(cfgPath)
log := NewLog() log := NewLog()
log.Info("Running FlexDXCluster version 0.1") log.Info("Running FlexDXCluster version 0.5")
log.Infof("Callsign: %s", cfg.SQLite.Callsign) log.Infof("Callsign: %s", cfg.SQLite.Callsign)
DeleteDatabase("./flex.sqlite", log) DeleteDatabase("./flex.sqlite", log)
log.Infof("Gotify Push Enabled: %v", cfg.Gotify.Enable)
if cfg.Gotify.Enable {
log.Infof("Gotify Push NewDXCC: %v - NewBand: %v - NewMode: %v - NewBandAndMode: %v", cfg.Gotify.NewDXCC, cfg.Gotify.NewBand, cfg.Gotify.NewMode, cfg.Gotify.NewBandAndMode)
}
// Load country.xml to get all the DXCC number // Load country.xml to get all the DXCC number
Countries := LoadCountryFile() Countries := LoadCountryFile()
@ -65,32 +68,10 @@ func main() {
FlexClient := NewFlexClient(*fRepo, TCPServer, TCPClient.SpotChanToFlex) FlexClient := NewFlexClient(*fRepo, TCPServer, TCPClient.SpotChanToFlex)
// HTTPServer := NewHTTPServer(*cRepo, *fRepo, TCPServer, TCPClient.SpotChanToHTTPServer) // HTTPServer := NewHTTPServer(*cRepo, *fRepo, TCPServer, TCPClient.SpotChanToHTTPServer)
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
go FlexClient.StartFlexClient() go FlexClient.StartFlexClient()
go TCPClient.StartClient() go TCPClient.StartClient()
go TCPServer.StartServer() go TCPServer.StartServer()
// Gracely closing all connextions if signal is received CheckSignal(TCPClient, TCPServer, FlexClient, fRepo, cRepo)
for sig := range sigCh {
log.Infof("received signal: %v, shutting down all connections.", sig)
TCPClient.Close()
TCPServer.Conn.Close()
FlexClient.Conn.Close()
if err := fRepo.db.Close(); err != nil {
log.Error("failed to close the database connection properly")
os.Exit(1)
}
if err := cRepo.db.Close(); err != nil {
log.Error("failed to close Log4OM database connection properly")
os.Exit(1)
}
os.Exit(0)
}
} }

47
spot.go
View File

@ -23,6 +23,7 @@ type TelnetSpot struct {
NewDXCC bool NewDXCC bool
NewBand bool NewBand bool
NewMode bool NewMode bool
NewSlot bool
CallsignWorked bool CallsignWorked bool
} }
@ -52,17 +53,19 @@ func ProcessTelnetSpot(re *regexp.Regexp, spotRaw string, SpotChanToFlex chan Te
spot.NewBand = false spot.NewBand = false
spot.NewMode = false spot.NewMode = false
spot.NewDXCC = false spot.NewDXCC = false
spot.NewSlot = false
contactRepo := NewLog4OMContactsRepository(Cfg.SQLite.SQLitePath) contactRepo := NewLog4OMContactsRepository(Cfg.SQLite.SQLitePath)
defer contactRepo.db.Close() defer contactRepo.db.Close()
contactsChan := make(chan []Contact) contactsChan := make(chan []Contact)
contactsModeChan := make(chan []Contact) contactsModeChan := make(chan []Contact)
contactsModeBandChan := make(chan []Contact)
contactsBandChan := make(chan []Contact) contactsBandChan := make(chan []Contact)
contactsCallChan := make(chan []Contact) contactsCallChan := make(chan []Contact)
wg := new(sync.WaitGroup) wg := new(sync.WaitGroup)
wg.Add(4) wg.Add(5)
go contactRepo.ListByCountry(spot.DXCC, contactsChan, wg) go contactRepo.ListByCountry(spot.DXCC, contactsChan, wg)
contacts := <-contactsChan contacts := <-contactsChan
@ -76,6 +79,9 @@ func ProcessTelnetSpot(re *regexp.Regexp, spotRaw string, SpotChanToFlex chan Te
go contactRepo.ListByCallSign(spot.DX, spot.Band, spot.Mode, contactsCallChan, wg) go contactRepo.ListByCallSign(spot.DX, spot.Band, spot.Mode, contactsCallChan, wg)
contactsCall := <-contactsCallChan contactsCall := <-contactsCallChan
go contactRepo.ListByCountryModeBand(spot.DXCC, spot.Band, spot.Mode, contactsModeBandChan, wg)
contactsModeBand := <-contactsModeBandChan
wg.Wait() wg.Wait()
if len(contacts) == 0 { if len(contacts) == 0 {
@ -88,6 +94,11 @@ func ProcessTelnetSpot(re *regexp.Regexp, spotRaw string, SpotChanToFlex chan Te
if len(contactsBand) == 0 { if len(contactsBand) == 0 {
spot.NewBand = true spot.NewBand = true
} }
if len(contactsModeBand) == 0 {
spot.NewSlot = true
}
if len(contactsCall) > 0 { if len(contactsCall) > 0 {
spot.CallsignWorked = true spot.CallsignWorked = true
} }
@ -96,8 +107,8 @@ func ProcessTelnetSpot(re *regexp.Regexp, spotRaw string, SpotChanToFlex chan Te
SpotChanToFlex <- spot SpotChanToFlex <- spot
if spot.NewDXCC { if spot.NewDXCC {
Log.Debugf("(** New DXCC **) DX: %s - Spotter: %s - Freq: %s - Band: %s - Mode: %s - Comment: %s - Time: %s - Command: %v, FlexSpot: %v", Log.Debugf("(** New DXCC **) DX: %s - Spotter: %s - Freq: %s - Band: %s - Mode: %s - Comment: %s - Time: %s - DXCC: %s",
spot.DX, spot.Spotter, spot.Frequency, spot.Band, spot.Mode, spot.Comment, spot.Time, spot.CommandNumber, spot.FlexSpotNumber) spot.DX, spot.Spotter, spot.Frequency, spot.Band, spot.Mode, spot.Comment, spot.Time, spot.DXCC)
} }
if !spot.NewDXCC && spot.NewBand && spot.NewMode { if !spot.NewDXCC && spot.NewBand && spot.NewMode {
@ -115,6 +126,11 @@ func ProcessTelnetSpot(re *regexp.Regexp, spotRaw string, SpotChanToFlex chan Te
spot.DX, spot.Spotter, spot.Frequency, spot.Band, spot.Mode, spot.Comment, spot.Time, spot.DXCC) spot.DX, spot.Spotter, spot.Frequency, spot.Band, spot.Mode, spot.Comment, spot.Time, spot.DXCC)
} }
if !spot.NewDXCC && !spot.NewBand && !spot.NewMode && spot.NewSlot && spot.Mode != "" {
Log.Debugf("(** New Slot **) DX: %s - Spotter: %s - Freq: %s - Band: %s - Mode: %s - Comment: %s - Time: %s - DXCC: %s",
spot.DX, spot.Spotter, spot.Frequency, spot.Band, spot.Mode, spot.Comment, spot.Time, spot.DXCC)
}
if !spot.NewDXCC && !spot.NewBand && !spot.NewMode && spot.CallsignWorked { if !spot.NewDXCC && !spot.NewBand && !spot.NewMode && spot.CallsignWorked {
Log.Debugf("(** Worked **) DX: %s - Spotter: %s - Freq: %s - Band: %s - Mode: %s - Comment: %s - Time: %s - DXCC: %s", Log.Debugf("(** Worked **) DX: %s - Spotter: %s - Freq: %s - Band: %s - Mode: %s - Comment: %s - Time: %s - DXCC: %s",
spot.DX, spot.Spotter, spot.Frequency, spot.Band, spot.Mode, spot.Comment, spot.Time, spot.DXCC) spot.DX, spot.Spotter, spot.Frequency, spot.Band, spot.Mode, spot.Comment, spot.Time, spot.DXCC)
@ -131,60 +147,61 @@ func ProcessTelnetSpot(re *regexp.Regexp, spotRaw string, SpotChanToFlex chan Te
} }
func (spot *TelnetSpot) GetBand() { func (spot *TelnetSpot) GetBand() {
freq := FreqMhztoHz(spot.Frequency)
switch true { switch true {
case strings.HasPrefix(spot.Frequency, "1.8"): case strings.HasPrefix(freq, "1.8"):
spot.Band = "160M" spot.Band = "160M"
if spot.Mode == "SSB" { if spot.Mode == "SSB" {
spot.Mode = "LSB" spot.Mode = "LSB"
} }
case strings.HasPrefix(spot.Frequency, "3"): case strings.HasPrefix(freq, "3."):
spot.Band = "80M" spot.Band = "80M"
if spot.Mode == "SSB" { if spot.Mode == "SSB" {
spot.Mode = "LSB" spot.Mode = "LSB"
} }
case strings.HasPrefix(spot.Frequency, "5."): case strings.HasPrefix(freq, "5."):
spot.Band = "60M" spot.Band = "60M"
if spot.Mode == "SSB" { if spot.Mode == "SSB" {
spot.Mode = "LSB" spot.Mode = "LSB"
} }
case strings.HasPrefix(spot.Frequency, "7"): case strings.HasPrefix(freq, "7."):
spot.Band = "40M" spot.Band = "40M"
if spot.Mode == "SSB" { if spot.Mode == "SSB" {
spot.Mode = "LSB" spot.Mode = "LSB"
} }
case strings.HasPrefix(spot.Frequency, "10"): case strings.HasPrefix(freq, "10."):
spot.Band = "30M" spot.Band = "30M"
case strings.HasPrefix(spot.Frequency, "14"): case strings.HasPrefix(freq, "14."):
spot.Band = "20M" spot.Band = "20M"
if spot.Mode == "SSB" { if spot.Mode == "SSB" {
spot.Mode = "USB" spot.Mode = "USB"
} }
case strings.HasPrefix(spot.Frequency, "18"): case strings.HasPrefix(freq, "18."):
spot.Band = "17M" spot.Band = "17M"
if spot.Mode == "SSB" { if spot.Mode == "SSB" {
spot.Mode = "USB" spot.Mode = "USB"
} }
case strings.HasPrefix(spot.Frequency, "21"): case strings.HasPrefix(freq, "21."):
spot.Band = "15M" spot.Band = "15M"
if spot.Mode == "SSB" { if spot.Mode == "SSB" {
spot.Mode = "USB" spot.Mode = "USB"
} }
case strings.HasPrefix(spot.Frequency, "24"): case strings.HasPrefix(freq, "24."):
spot.Band = "12M" spot.Band = "12M"
if spot.Mode == "SSB" { if spot.Mode == "SSB" {
spot.Mode = "USB" spot.Mode = "USB"
} }
case strings.HasPrefix(spot.Frequency, "28"): case strings.HasPrefix(freq, "28."):
spot.Band = "10M" spot.Band = "10M"
if spot.Mode == "SSB" { if spot.Mode == "SSB" {
spot.Mode = "USB" spot.Mode = "USB"
} }
case strings.HasPrefix(spot.Frequency, "29"): case strings.HasPrefix(freq, "29."):
spot.Band = "10M" spot.Band = "10M"
if spot.Mode == "SSB" { if spot.Mode == "SSB" {
spot.Mode = "USB" spot.Mode = "USB"
} }
case strings.HasPrefix(spot.Frequency, "50"): case strings.HasPrefix(freq, "50."):
spot.Band = "6M" spot.Band = "6M"
if spot.Mode == "SSB" { if spot.Mode == "SSB" {
spot.Mode = "USB" spot.Mode = "USB"

View File

@ -2,7 +2,10 @@ package main
import ( import (
"log" "log"
"os"
"os/signal"
"strconv" "strconv"
"syscall"
) )
func FreqMhztoHz(freq string) string { func FreqMhztoHz(freq string) string {
@ -26,3 +29,30 @@ func FreqHztoMhz(freq string) string {
return strconv.FormatFloat(frequency, 'f', 6, 64) return strconv.FormatFloat(frequency, 'f', 6, 64)
} }
func CheckSignal(TCPClient *TCPClient, TCPServer *TCPServer, FlexClient *FlexClient, fRepo *FlexDXClusterRepository, cRepo *Log4OMContactsRepository) {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)
// Gracely closing all connextions if signal is received
for sig := range sigCh {
Log.Infof("received signal: %v, shutting down all connections.", sig)
TCPClient.Close()
TCPServer.Conn.Close()
FlexClient.Conn.Close()
if err := fRepo.db.Close(); err != nil {
Log.Error("failed to close the database connection properly")
os.Exit(1)
}
if err := cRepo.db.Close(); err != nil {
Log.Error("failed to close Log4OM database connection properly")
os.Exit(1)
}
os.Exit(0)
}
}