update dxcc

This commit is contained in:
Gregory Salaun 2024-10-21 23:38:16 +07:00
parent ef84b7d7f9
commit ecedb0ea5d
14 changed files with 17966 additions and 346 deletions

Binary file not shown.

View File

@ -31,9 +31,10 @@ type TCPClient struct {
SpotChan chan TelnetSpot
Log *log.Logger
Config *Config
Countries Countries
}
func NewTCPClient(TCPServer *TCPServer, FlexClient *FlexClient, log *log.Logger) *TCPClient {
func NewTCPClient(TCPServer *TCPServer, FlexClient *FlexClient, log *log.Logger, Countries Countries) *TCPClient {
return &TCPClient{
Address: Cfg.Cluster.Server,
Port: Cfg.Cluster.Port,
@ -44,6 +45,7 @@ func NewTCPClient(TCPServer *TCPServer, FlexClient *FlexClient, log *log.Logger)
Log: log,
TCPServer: *TCPServer,
FlexClient: *FlexClient,
Countries: Countries,
}
}
@ -106,11 +108,21 @@ func (c *TCPClient) SetFilters() {
c.Log.Debug("Skimmer is on as defined in the config file")
}
if Cfg.Cluster.FT4 {
c.Write([]byte("set/ft4\r\n"))
c.Log.Debug("FT4 is on as defined in the config file")
}
if !Cfg.Cluster.FT8 {
c.Write([]byte("set/noft8\r\n"))
c.Log.Debug("FT8 is off as defined in the config file")
}
if !Cfg.Cluster.FT4 {
c.Write([]byte("set/noft4\r\n"))
c.Log.Debug("FT4 is off as defined in the config file")
}
if !Cfg.Cluster.Skimmer {
c.Write([]byte("set/noskimmer\r\n"))
c.Log.Debug("Skimmer is off as defined in the config file")
@ -138,7 +150,10 @@ func (c *TCPClient) ReadLine() {
c.Log.Info("start receiving spots")
}
ProcessTelnetSpot(spotRe, message, c.SpotChan, c.Log)
start := time.Now()
ProcessTelnetSpot(spotRe, message, c.SpotChan, c.Log, c.Countries)
elapsed := time.Since(start)
Log.Infof("Total time for processing spot: %s", elapsed)
// Send the spot message to TCP server
if len(c.TCPServer.Clients) > 0 {

View File

@ -36,7 +36,7 @@ func NewTCPServer(address string, port string, log *log.Logger) *TCPServer {
Address: address,
Port: port,
Clients: make(map[net.Conn]bool),
MsgChan: make(chan string),
MsgChan: make(chan string, 100),
CmdChan: make(chan string),
Log: log,
Mutex: new(sync.Mutex),
@ -102,7 +102,7 @@ func (s *TCPServer) handleConnection() {
s.Log.Infof("client %s disconnected", s.Conn.RemoteAddr().String())
}
if strings.Contains(message, "DX") && message != "SH/DX 30" {
if strings.Contains(message, "DX") || strings.Contains(message, "SH/DX") || strings.Contains(message, "set") || strings.Contains(message, "SET") {
// send DX spot to the client
s.CmdChan <- message
}

View File

@ -1,24 +0,0 @@
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func CheckClubogDXCC(callsign string) (string, error) {
// Clublog check DXCC
clublogURL := "https://clublog.org/dxcc?call=" + callsign + "&api=5767f19333363a9ef432ee9cd4141fe76b8adf38"
resp, err := http.Get(clublogURL)
if err != nil {
fmt.Println("error while getting DXCC from Clublog")
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Println("could not get dxcc from clublog", err)
}
return string(body), nil
}

View File

@ -30,6 +30,7 @@ type Config struct {
Login string `yaml:"login"`
Skimmer bool `yaml:"skimmer"`
FT8 bool `yaml:"ft8"`
FT4 bool `yaml:"ft4"`
Command string `yanl:"command"`
LoginPrompt string `yaml:"login_prompt"`
} `yaml:"cluster"`

View File

@ -2,7 +2,7 @@ general:
delete_log_file_at_start: true
log_to_file: true
log_level: DEBUG
httpserver: false
httpserver: true
telnetserver: true
flexradiospot: true
sqlite:
@ -13,11 +13,12 @@ cluster:
port: 7300
login: xv9q-2
skimmer: true
ft8: true
ft8: false
ft4: false
command: #SET/NOFILTER
login_prompt: "Please enter your call:"
flex:
ip: 113.161.103.129
ip: 10.10.10.120 #113.161.103.129
spot_life: 600
clublog:
api: 5767f19333363a9ef432ee9cd4141fe76b8adf38

16915
country.xml Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -59,8 +59,8 @@ func NewFlexClient(repo FlexDXClusterRepository, TCPServer *TCPServer, log *log.
return &FlexClient{
Address: Cfg.Flex.IP,
Port: "4992",
SpotChan: make(chan TelnetSpot),
FlexSpotChan: make(chan FlexSpot),
SpotChan: make(chan TelnetSpot, 100),
FlexSpotChan: make(chan FlexSpot, 100),
MsgChan: TCPServer.MsgChan,
Repo: repo,
TCPServer: TCPServer,

File diff suppressed because it is too large Load Diff

14
log.go
View File

@ -8,6 +8,8 @@ import (
prefixed "github.com/x-cray/logrus-prefixed-formatter"
)
var Log *log.Logger
func NewLog() *log.Logger {
if Cfg.General.DeleteLogFileAtStart {
@ -27,7 +29,7 @@ func NewLog() *log.Logger {
w = io.Writer(os.Stdout)
}
l := &log.Logger{
Log = &log.Logger{
Out: w,
Formatter: &prefixed.TextFormatter{
DisableColors: false,
@ -38,16 +40,16 @@ func NewLog() *log.Logger {
}
if Cfg.General.LogLevel == "DEBUG" {
l.Level = log.DebugLevel
Log.Level = log.DebugLevel
} else if Cfg.General.LogLevel == "INFO" {
l.Level = log.InfoLevel
Log.Level = log.InfoLevel
} else if Cfg.General.LogLevel == "WARN" {
l.Level = log.WarnLevel
Log.Level = log.WarnLevel
} else {
l.Level = log.InfoLevel
Log.Level = log.InfoLevel
}
return l
return Log
}
// Info ...

View File

@ -52,12 +52,14 @@ func main() {
cfg := NewConfig(cfgPath)
log := NewLog()
log.Info("config loaded.")
log.Infof("Callsign: %s", cfg.SQLite.Callsign)
DeleteDatabase("./flex.sqlite", log)
// Load country.xml to get all the DXCC
Countries := LoadCountryFile()
fRepo := NewFlexDXDatabase("flex.sqlite", log)
defer fRepo.db.Close()
@ -67,7 +69,7 @@ func main() {
TCPServer := NewTCPServer(cfg.TelnetServer.Host, cfg.TelnetServer.Port, log)
FlexClient := NewFlexClient(*fRepo, TCPServer, log)
TCPClient := NewTCPClient(TCPServer, FlexClient, log)
TCPClient := NewTCPClient(TCPServer, FlexClient, log, Countries)
HTTPServer := NewHTTPServer(*cRepo, *fRepo, FlexClient, TCPServer, log)
sigCh := make(chan os.Signal, 1)

139
spot.go
View File

@ -1,10 +1,10 @@
package main
import (
"fmt"
"regexp"
"strconv"
"strings"
"time"
_ "github.com/mattn/go-sqlite3"
log "github.com/sirupsen/logrus"
@ -27,7 +27,7 @@ type TelnetSpot struct {
CallsignWorked bool
}
func ProcessTelnetSpot(re *regexp.Regexp, spotRaw string, SpotChan chan TelnetSpot, log *log.Logger) {
func ProcessTelnetSpot(re *regexp.Regexp, spotRaw string, SpotChan chan TelnetSpot, log *log.Logger, Countries Countries) {
match := re.FindStringSubmatch(spotRaw)
if len(match) != 0 {
@ -40,9 +40,14 @@ func ProcessTelnetSpot(re *regexp.Regexp, spotRaw string, SpotChan chan TelnetSp
Time: match[6],
}
start := time.Now()
spot.DXCC = GetDXCC(spot.DX, Countries)
elapsed := time.Since(start)
Log.Infof("Loop for DXCC: %s", elapsed)
spot.GetBand()
spot.GuessMode()
spot.DXCC, _ = CheckClubogDXCC(spot.DX)
spot.CallsignWorked = false
spot.NewBand = false
spot.NewMode = false
@ -52,10 +57,13 @@ func ProcessTelnetSpot(re *regexp.Regexp, spotRaw string, SpotChan chan TelnetSp
defer contactRepo.db.Close()
start = time.Now()
contacts, _ := contactRepo.ListByCountry(spot.DXCC)
contactsMode, _ := contactRepo.ListByCountryMode(spot.DXCC, spot.Mode)
contactsBand, _ := contactRepo.ListByCountryBand(spot.DXCC, spot.Band)
contactsCall, _ := contactRepo.ListByCallSign(spot.DX, spot.Band, spot.Mode)
elapsed = time.Since(start)
Log.Infof("Elapsed db checking %s", elapsed)
if len(contacts) == 0 {
switch spot.DXCC {
@ -74,6 +82,9 @@ func ProcessTelnetSpot(re *regexp.Regexp, spotRaw string, SpotChan chan TelnetSp
spot.CallsignWorked = true
}
// send spot to SpotChan to Flex Client to send the spot to Flex radio
SpotChan <- spot
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",
spot.DX, spot.Spotter, spot.Frequency, spot.Band, spot.Mode, spot.Comment, spot.Time, spot.CommandNumber, spot.FlexSpotNumber)
@ -103,10 +114,6 @@ func ProcessTelnetSpot(re *regexp.Regexp, spotRaw string, SpotChan chan TelnetSp
log.Debugf("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)
}
// send spot to SpotChan to Flex Client to send the spot to Flex radio
SpotChan <- spot
}
}
@ -169,27 +176,131 @@ func (spot *TelnetSpot) GuessMode() {
if spot.Mode == "" {
freqInt, err := strconv.ParseFloat(spot.Frequency, 32)
if err != nil {
fmt.Println("could not convert frequency string in float64:", err)
Log.Errorf("could not convert frequency string in float64:", err)
}
switch spot.Band {
case "160M":
if freqInt <= 1840 && freqInt >= 1800 {
if freqInt >= 1800 && freqInt <= 1840 {
spot.Mode = "CW"
}
if freqInt >= 1840 && freqInt <= 1840 {
spot.Mode = "CW"
}
case "40M":
if freqInt <= 7045.49 && freqInt >= 7000 {
if freqInt >= 7000 && freqInt < 7045.5 {
spot.Mode = "CW"
} else if freqInt <= 7048.49 && freqInt >= 7045.49 {
}
if freqInt >= 7045.5 && freqInt < 7048.5 {
spot.Mode = "FT4"
} else if freqInt <= 7073.99 && freqInt > 7048.49 {
}
if freqInt >= 7048.5 && freqInt < 7074 {
spot.Mode = "CW"
} else if freqInt <= 7077 && freqInt > 7073.99 {
}
if freqInt >= 7074 && freqInt < 7078 {
spot.Mode = "FT8"
} else if freqInt <= 7200 && freqInt > 7077 {
}
if freqInt >= 7078 && freqInt <= 7200 {
spot.Mode = "LSB"
}
case "30M":
if freqInt >= 10100 && freqInt < 10130 {
spot.Mode = "CW"
}
if freqInt >= 10130 && freqInt < 10140 {
spot.Mode = "FT8"
}
if freqInt >= 10140 && freqInt <= 10150 {
spot.Mode = "FT4"
}
case "20M":
if freqInt >= 14000 && freqInt < 14074 {
spot.Mode = "CW"
}
if freqInt >= 14074 && freqInt < 14078 {
spot.Mode = "FT8"
}
if freqInt >= 14074 && freqInt < 14078 {
spot.Mode = "FT8"
}
if freqInt >= 14078 && freqInt < 14083 {
spot.Mode = "FT4"
}
if freqInt >= 14083 && freqInt < 14119 {
spot.Mode = "FT8"
}
if freqInt >= 14119 && freqInt < 14350 {
spot.Mode = "USB"
}
case "17M":
if freqInt >= 18068 && freqInt < 18095 {
spot.Mode = "CW"
}
if freqInt >= 18095 && freqInt < 18104 {
spot.Mode = "FT8"
}
if freqInt >= 18104 && freqInt < 18108 {
spot.Mode = "FT4"
}
if freqInt >= 18108 && freqInt <= 18168 {
spot.Mode = "USB"
}
case "15M":
if freqInt >= 21000 && freqInt < 21074 {
spot.Mode = "CW"
}
if freqInt >= 21074 && freqInt < 21100 {
spot.Mode = "FT8"
}
if freqInt >= 21100 && freqInt < 21140 {
spot.Mode = "RTTY"
}
if freqInt >= 21140 && freqInt < 21144 {
spot.Mode = "FT4"
}
if freqInt >= 21144 && freqInt <= 21450 {
spot.Mode = "USB"
}
case "12M":
if freqInt >= 24890 && freqInt < 24915 {
spot.Mode = "CW"
}
if freqInt >= 24915 && freqInt < 24919 {
spot.Mode = "FT8"
}
if freqInt >= 24919 && freqInt < 24930 {
spot.Mode = "CW"
}
if freqInt >= 24930 && freqInt <= 24990 {
spot.Mode = "USB"
}
case "10M":
if freqInt >= 28000 && freqInt < 28074 {
spot.Mode = "CW"
}
if freqInt >= 28074 && freqInt < 28080 {
spot.Mode = "FT8"
}
if freqInt >= 28080 && freqInt < 28100 {
spot.Mode = "RTTY"
}
if freqInt >= 28100 && freqInt < 28300 {
spot.Mode = "CW"
}
if freqInt >= 28300 && freqInt < 29000 {
spot.Mode = "USB"
}
if freqInt >= 29000 && freqInt <= 29700 {
spot.Mode = "FM"
}
}
}
if spot.Mode == "" {
Log.Infof("Could not identify mode for %s on %s", spot.DX, spot.Frequency)
}
}

78
xml.go Normal file
View File

@ -0,0 +1,78 @@
package main
import (
"encoding/xml"
"io"
"os"
"regexp"
)
type Countries struct {
XMLName xml.Name `xml:"Countries"`
Countries []Country `xml:"Country"`
}
type Country struct {
XMLName xml.Name `xml:"Country"`
ArrlPrefix string `xml:"ArrlPrefix"`
Comment string `xml:"Comment"`
Continent string `xml:"Continent"`
CountryName string `xml:"CountryName"`
CqZone string `xml:"CqZone"`
CqZoneList string `xml:"CqZoneList"`
Dxcc string `xml:"Dxcc"`
ItuZone string `xml:"ItuZone"`
IaruRegion string `xml:"IaruRegion"`
ItuZoneList string `xml:"ItuZoneList"`
Latitude string `xml:"Latitude"`
Longitude string `xml:"Longitude"`
Active string `xml:"Active"`
CountryTag string `xml:"CountryTag"`
CountryPrefixList CountryPrefixList `xml:"CountryPrefixList"`
}
type CountryPrefixList struct {
XMLName xml.Name `xml:"CountryPrefixList"`
CountryPrefixList []CountryPrefix `xml:"CountryPrefix"`
}
type CountryPrefix struct {
XMLName xml.Name `xml:"CountryPrefix"`
PrefixList string `xml:"PrefixList"`
StartDate string `xml:"StartDate"`
EndDate string `xml:"EndDate"`
}
func LoadCountryFile() Countries {
// Open our xmlFile
xmlFile, err := os.Open("country.xml")
// if we os.Open returns an error then handle it
if err != nil {
Log.Errorln(err)
}
Log.Infoln("Successfully loaded country.xml")
// defer the closing of our xmlFile so that we can parse it later on
defer xmlFile.Close()
// read our opened xmlFile as a byte array.
byteValue, _ := io.ReadAll(xmlFile)
var countries Countries
xml.Unmarshal(byteValue, &countries)
return countries
}
func GetDXCC(dxCall string, Countries Countries) string {
for i := 0; i < len(Countries.Countries); i++ {
for j := 0; j < len(Countries.Countries[i].CountryPrefixList.CountryPrefixList); j++ {
regExp := regexp.MustCompile(Countries.Countries[i].CountryPrefixList.CountryPrefixList[j].PrefixList)
match := regExp.FindStringSubmatch(dxCall)
if len(match) != 0 {
return Countries.Countries[i].Dxcc
}
}
}
return ""
}