update
This commit is contained in:
parent
9ddc3ce347
commit
ab17255bdc
BIN
FlexDXCluster.exe
Normal file
BIN
FlexDXCluster.exe
Normal file
Binary file not shown.
96
TCPClient.go
96
TCPClient.go
@ -13,7 +13,7 @@ import (
|
|||||||
|
|
||||||
var spotRe *regexp.Regexp = regexp.MustCompile(`DX\sde\s([\w\d]+).*:\s+(\d+.\d)\s+([\w\d]+)\s+(CW|SSB|FT8|FT4|RTTY|USB|LSB)?\s+(.*)\s\s\s+([\d]+\w{1})`)
|
var spotRe *regexp.Regexp = regexp.MustCompile(`DX\sde\s([\w\d]+).*:\s+(\d+.\d)\s+([\w\d]+)\s+(CW|SSB|FT8|FT4|RTTY|USB|LSB)?\s+(.*)\s\s\s+([\d]+\w{1})`)
|
||||||
|
|
||||||
type TelnetClient struct {
|
type TCPClient struct {
|
||||||
Login string
|
Login string
|
||||||
Password string
|
Password string
|
||||||
Address string
|
Address string
|
||||||
@ -31,89 +31,107 @@ type TelnetClient struct {
|
|||||||
Log *log.Logger
|
Log *log.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *TelnetClient) setDefaultParams() {
|
func NewTCPClient(cfg Config, TCPServer *TCPServer, FlexClient *FlexClient, log *log.Logger) *TCPClient {
|
||||||
if tc.Timeout == 0 {
|
return &TCPClient{
|
||||||
tc.Timeout = 600 * time.Second
|
Address: Cfg.Cluster.Server,
|
||||||
}
|
Port: Cfg.Cluster.Port,
|
||||||
if tc.LogWriter == nil {
|
Login: Cfg.Cluster.Login,
|
||||||
tc.LogWriter = bufio.NewWriter(os.Stdout)
|
MsgChan: TCPServer.MsgChan,
|
||||||
|
CmdChan: TCPServer.CmdChan,
|
||||||
|
SpotChan: FlexClient.SpotChan,
|
||||||
|
Log: log,
|
||||||
|
TCPServer: *TCPServer,
|
||||||
|
FlexClient: *FlexClient,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *TelnetClient) StartClient() {
|
func (c *TCPClient) setDefaultParams() {
|
||||||
|
if c.Timeout == 0 {
|
||||||
|
c.Timeout = 600 * time.Second
|
||||||
|
}
|
||||||
|
if c.LogWriter == nil {
|
||||||
|
c.LogWriter = bufio.NewWriter(os.Stdout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *TCPClient) StartClient() {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
addr, err := net.ResolveTCPAddr("tcp", tc.Address+":"+tc.Port)
|
addr, err := net.ResolveTCPAddr("tcp", c.Address+":"+c.Port)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tc.Log.Error("cannot resolve Telnet Client address:", err)
|
c.Log.Error("cannot resolve Telnet Client address:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tc.setDefaultParams()
|
c.setDefaultParams()
|
||||||
tc.Conn, err = net.DialTCP("tcp", nil, addr)
|
c.Conn, err = net.DialTCP("tcp", nil, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tc.Log.Error("cannot connect to Telnet Client:", err)
|
c.Log.Error("cannot connect to Telnet Client:", err)
|
||||||
}
|
}
|
||||||
tc.Log.Infof("connected to %s:%s", tc.Address, tc.Port)
|
c.Log.Infof("connected to %s:%s", c.Address, c.Port)
|
||||||
|
|
||||||
err = tc.Conn.SetKeepAlive(true)
|
err = c.Conn.SetKeepAlive(true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tc.Log.Error("error while setting keep alive:", err)
|
c.Log.Error("error while setting keep alive:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
tc.Reader = bufio.NewReader(tc.Conn)
|
c.Reader = bufio.NewReader(c.Conn)
|
||||||
tc.Writer = bufio.NewWriter(tc.Conn)
|
c.Writer = bufio.NewWriter(c.Conn)
|
||||||
|
|
||||||
go tc.ReadLine()
|
go c.ReadLine()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *TelnetClient) Close() {
|
func (c *TCPClient) Close() {
|
||||||
tc.Writer.WriteString("bye")
|
c.Writer.WriteString("bye")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *TelnetClient) SetFilters() {
|
func (c *TCPClient) SetFilters() {
|
||||||
if Cfg.Cluster.FT8 {
|
if Cfg.Cluster.FT8 {
|
||||||
tc.Write([]byte("set/ft8\r\n"))
|
c.Write([]byte("set/ft8\r\n"))
|
||||||
tc.Log.Info("FT8 is on as defined in the config file")
|
c.Log.Info("FT8 is on as defined in the config file")
|
||||||
}
|
}
|
||||||
|
|
||||||
if Cfg.Cluster.Skimmer {
|
if Cfg.Cluster.Skimmer {
|
||||||
tc.Write([]byte("set/skimmer\r\n"))
|
c.Write([]byte("set/skimmer\r\n"))
|
||||||
tc.Log.Info("Skimmer is on as defined in the config file")
|
c.Log.Info("Skimmer is on as defined in the config file")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !Cfg.Cluster.FT8 {
|
if !Cfg.Cluster.FT8 {
|
||||||
tc.Write([]byte("set/noft8\r\n"))
|
c.Write([]byte("set/noft8\r\n"))
|
||||||
tc.Log.Info("FT8 is off as defined in the config file")
|
c.Log.Info("FT8 is off as defined in the config file")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !Cfg.Cluster.Skimmer {
|
if !Cfg.Cluster.Skimmer {
|
||||||
tc.Write([]byte("set/noskimmer\r\n"))
|
c.Write([]byte("set/noskimmer\r\n"))
|
||||||
tc.Log.Info("Skimmer is off as defined in the config file")
|
c.Log.Info("Skimmer is off as defined in the config file")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *TelnetClient) ReadLine() {
|
func (c *TCPClient) ReadLine() {
|
||||||
for {
|
for {
|
||||||
message, err := tc.Reader.ReadString('\n')
|
message, err := c.Reader.ReadString('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tc.Log.Errorf("Error reading message: %s", err)
|
c.Log.Errorf("Error reading message: %s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.Contains(message, "Login: \r\n") || strings.Contains(message, "Please enter your call: \r\n") {
|
if strings.Contains(message, "Login: \r\n") || strings.Contains(message, "Please enter your call: \r\n") {
|
||||||
tc.Log.Info("Found login prompt...sending callsign")
|
c.Log.Info("Found login prompt...sending callsign")
|
||||||
tc.Write([]byte(tc.Login + "\r\n"))
|
c.Write([]byte(c.Login + "\r\n"))
|
||||||
time.Sleep(time.Second * 2)
|
time.Sleep(time.Second * 2)
|
||||||
tc.SetFilters()
|
c.SetFilters()
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessTelnetSpot(spotRe, message, tc.SpotChan, tc.Log)
|
ProcessTelnetSpot(spotRe, message, c.SpotChan, c.Log)
|
||||||
tc.MsgChan <- message
|
|
||||||
|
// Send the spot message to TCP server
|
||||||
|
if len(c.TCPServer.Clients) > 0 {
|
||||||
|
c.MsgChan <- message
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write sends raw data to remove telnet server
|
// Write sends raw data to remove telnet server
|
||||||
func (tc *TelnetClient) Write(data []byte) (n int, err error) {
|
func (tc *TCPClient) Write(data []byte) (n int, err error) {
|
||||||
n, err = tc.Writer.Write(data)
|
n, err = tc.Writer.Write(data)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = tc.Writer.Flush()
|
err = tc.Writer.Flush()
|
||||||
|
26
TCPServer.go
26
TCPServer.go
@ -50,7 +50,7 @@ func (s *TCPServer) StartServer() {
|
|||||||
|
|
||||||
defer s.Listener.Close()
|
defer s.Listener.Close()
|
||||||
|
|
||||||
s.Log.Info("telnet server listening on %s:%s", Cfg.Telnet.Host, Cfg.Telnet.Port)
|
s.Log.Infof("telnet server listening on %s:%s", Cfg.Telnet.Host, Cfg.Telnet.Port)
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for message := range s.MsgChan {
|
for message := range s.MsgChan {
|
||||||
@ -74,39 +74,43 @@ func (s *TCPServer) StartServer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *TCPServer) handleConnection() {
|
func (s *TCPServer) handleConnection() {
|
||||||
defer s.Conn.Close()
|
|
||||||
s.Conn.Write([]byte("Welcome to the FlexDXCluster telnet server! Type 'bye' to exit.\n"))
|
s.Conn.Write([]byte("Welcome to the FlexDXCluster telnet server! Type 'bye' to exit.\n"))
|
||||||
|
|
||||||
// s.Conn.Write([]byte(`To ALL de XV9Q <0234Z> : Clicked on "JH2UNG"\n`))
|
s.Reader = bufio.NewReader(s.Conn)
|
||||||
|
s.Writer = bufio.NewWriter(s.Conn)
|
||||||
|
|
||||||
reader := bufio.NewReader(s.Conn)
|
|
||||||
for {
|
for {
|
||||||
|
|
||||||
message, err := reader.ReadString('\n')
|
message, err := s.Reader.ReadString('\n')
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.Mutex.Lock()
|
s.Mutex.Lock()
|
||||||
delete(s.Clients, s.Conn)
|
delete(s.Clients, s.Conn)
|
||||||
s.Mutex.Unlock()
|
s.Mutex.Unlock()
|
||||||
s.Log.Info("client disconnected")
|
s.Log.Infof("client %s disconnected", s.Conn.RemoteAddr().String())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
message = strings.TrimSpace(message)
|
message = strings.TrimSpace(message)
|
||||||
|
|
||||||
if message == "bye" {
|
s.Log.Infof("Message reçu du client: %s\n", message)
|
||||||
|
|
||||||
|
switch message {
|
||||||
|
case "bye":
|
||||||
s.Mutex.Lock()
|
s.Mutex.Lock()
|
||||||
delete(s.Clients, s.Conn)
|
delete(s.Clients, s.Conn)
|
||||||
s.Mutex.Unlock()
|
s.Mutex.Unlock()
|
||||||
s.Log.Info("client disconnected")
|
s.Log.Infof("client %s disconnected", s.Conn.RemoteAddr().String())
|
||||||
return
|
return
|
||||||
|
case "SH/DX 30":
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
s.Write("cannot identify command\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Log.Info("Message reçu du client: %s\n", message)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TCPServer) Write(message string) (n int, err error) {
|
func (s *TCPServer) Write(message string) (n int, err error) {
|
||||||
n, err = s.Writer.Write([]byte(message))
|
_, err = s.Writer.Write([]byte(message))
|
||||||
if err == nil {
|
if err == nil {
|
||||||
err = s.Writer.Flush()
|
err = s.Writer.Flush()
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ cluster:
|
|||||||
ft8: false
|
ft8: false
|
||||||
flex:
|
flex:
|
||||||
ip: 10.10.10.120
|
ip: 10.10.10.120
|
||||||
spot_life: 300
|
spot_life: 600
|
||||||
clublog:
|
clublog:
|
||||||
api: 5767f19333363a9ef432ee9cd4141fe76b8adf38
|
api: 5767f19333363a9ef432ee9cd4141fe76b8adf38
|
||||||
telnet:
|
telnet:
|
||||||
|
28
database.go
28
database.go
@ -54,7 +54,7 @@ func NewFlexDXDatabase(filePath string, log *log.Logger) *FlexDXClusterRepositor
|
|||||||
`CREATE TABLE IF NOT EXISTS "spots" (
|
`CREATE TABLE IF NOT EXISTS "spots" (
|
||||||
"id" INTEGER NOT NULL UNIQUE,
|
"id" INTEGER NOT NULL UNIQUE,
|
||||||
"commandNumber" INTEGER NOT NULL UNIQUE,
|
"commandNumber" INTEGER NOT NULL UNIQUE,
|
||||||
"flexSpotNumber" INTEGER UNIQUE,
|
"flexSpotNumber" INTEGER,
|
||||||
"dx" TEXT NOT NULL,
|
"dx" TEXT NOT NULL,
|
||||||
"freqMhz" TEXT,
|
"freqMhz" TEXT,
|
||||||
"freqHz" TEXT,
|
"freqHz" TEXT,
|
||||||
@ -63,6 +63,7 @@ func NewFlexDXDatabase(filePath string, log *log.Logger) *FlexDXClusterRepositor
|
|||||||
"spotter" INTEGER,
|
"spotter" INTEGER,
|
||||||
"flexMode" TEXT,
|
"flexMode" TEXT,
|
||||||
"source" TEXT,
|
"source" TEXT,
|
||||||
|
"time" TEXT,
|
||||||
"timestamp" INTEGER,
|
"timestamp" INTEGER,
|
||||||
"lifeTime" TEXT,
|
"lifeTime" TEXT,
|
||||||
"priority" TEXT,
|
"priority" TEXT,
|
||||||
@ -195,7 +196,7 @@ func (r *FlexDXClusterRepository) FindDXSameBand(spot FlexSpot) (*FlexSpot, erro
|
|||||||
|
|
||||||
s := FlexSpot{}
|
s := FlexSpot{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
if err := rows.Scan(&s.ID, &s.CommandNumber, &s.FlexSpotNumber, &s.DX, &s.FrequencyMhz, &s.FrequencyHz, &s.Band, &s.Mode, &s.SpotterCallsign, &s.FlexMode, &s.Source, &s.TimeStamp, &s.LifeTime, &s.Priority,
|
if err := rows.Scan(&s.ID, &s.CommandNumber, &s.FlexSpotNumber, &s.DX, &s.FrequencyMhz, &s.FrequencyHz, &s.Band, &s.Mode, &s.SpotterCallsign, &s.FlexMode, &s.Source, &s.UTCTime, &s.TimeStamp, &s.LifeTime, &s.Priority,
|
||||||
&s.Comment, &s.Color, &s.BackgroundColor); err != nil {
|
&s.Comment, &s.Color, &s.BackgroundColor); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -205,8 +206,8 @@ func (r *FlexDXClusterRepository) FindDXSameBand(spot FlexSpot) (*FlexSpot, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *FlexDXClusterRepository) CreateSpot(spot FlexSpot) {
|
func (r *FlexDXClusterRepository) CreateSpot(spot FlexSpot) {
|
||||||
query := "INSERT INTO `spots` (`commandNumber`, `flexSpotNumber`, `dx`, `freqMhz`, `freqHz`, `band`, `mode`, `spotter`, `flexMode`, `source`, `timestamp`, `lifeTime`, `priority`, `comment`, `color`, `backgroundColor`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
query := "INSERT INTO `spots` (`commandNumber`, `flexSpotNumber`, `dx`, `freqMhz`, `freqHz`, `band`, `mode`, `spotter`, `flexMode`, `source`, `time`, `timestamp`, `lifeTime`, `priority`, `comment`, `color`, `backgroundColor`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||||
insertResult, err := r.db.ExecContext(context.Background(), query, spot.CommandNumber, spot.CommandNumber, spot.DX, spot.FrequencyMhz, spot.FrequencyHz, spot.Band, spot.Mode, spot.SpotterCallsign, spot.FlexMode, spot.Source, time.Now().Unix(), spot.LifeTime, spot.Priority, spot.Comment, spot.Color, spot.BackgroundColor)
|
insertResult, err := r.db.ExecContext(context.Background(), query, spot.CommandNumber, spot.CommandNumber, spot.DX, spot.FrequencyMhz, spot.FrequencyHz, spot.Band, spot.Mode, spot.SpotterCallsign, spot.FlexMode, spot.Source, spot.UTCTime, time.Now().Unix(), spot.LifeTime, spot.Priority, spot.Comment, spot.Color, spot.BackgroundColor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("cannot insert spot in database: %s", err)
|
log.Errorf("cannot insert spot in database: %s", err)
|
||||||
}
|
}
|
||||||
@ -231,7 +232,7 @@ func (r *FlexDXClusterRepository) FindSpotByCommandNumber(commandNumber string)
|
|||||||
|
|
||||||
s := FlexSpot{}
|
s := FlexSpot{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
if err := rows.Scan(&s.ID, &s.CommandNumber, &s.FlexSpotNumber, &s.DX, &s.FrequencyMhz, &s.FrequencyHz, &s.Band, &s.Mode, &s.SpotterCallsign, &s.FlexMode, &s.Source, &s.TimeStamp, &s.LifeTime, &s.Priority,
|
if err := rows.Scan(&s.ID, &s.CommandNumber, &s.FlexSpotNumber, &s.DX, &s.FrequencyMhz, &s.FrequencyHz, &s.Band, &s.Mode, &s.SpotterCallsign, &s.FlexMode, &s.Source, &s.UTCTime, &s.TimeStamp, &s.LifeTime, &s.Priority,
|
||||||
&s.Comment, &s.Color, &s.BackgroundColor); err != nil {
|
&s.Comment, &s.Color, &s.BackgroundColor); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -249,7 +250,7 @@ func (r *FlexDXClusterRepository) FindSpotByFlexSpotNumber(spotNumber string) (*
|
|||||||
|
|
||||||
s := FlexSpot{}
|
s := FlexSpot{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
if err := rows.Scan(&s.ID, &s.CommandNumber, &s.FlexSpotNumber, &s.DX, &s.FrequencyMhz, &s.FrequencyHz, &s.Band, &s.Mode, &s.SpotterCallsign, &s.FlexMode, &s.Source, &s.TimeStamp, &s.LifeTime, &s.Priority,
|
if err := rows.Scan(&s.ID, &s.CommandNumber, &s.FlexSpotNumber, &s.DX, &s.FrequencyMhz, &s.FrequencyHz, &s.Band, &s.Mode, &s.SpotterCallsign, &s.FlexMode, &s.Source, &s.UTCTime, &s.TimeStamp, &s.LifeTime, &s.Priority,
|
||||||
&s.Comment, &s.Color, &s.BackgroundColor); err != nil {
|
&s.Comment, &s.Color, &s.BackgroundColor); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -258,8 +259,8 @@ func (r *FlexDXClusterRepository) FindSpotByFlexSpotNumber(spotNumber string) (*
|
|||||||
return &s, nil
|
return &s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *FlexDXClusterRepository) UpdateFlexSpotNumberByID(flexSpot string, spot FlexSpot) (*FlexSpot, error) {
|
func (r *FlexDXClusterRepository) UpdateFlexSpotNumberByID(flexSpotNumber string, spot FlexSpot) (*FlexSpot, error) {
|
||||||
flexSpotNumberInt, _ := strconv.Atoi(flexSpot)
|
flexSpotNumberInt, _ := strconv.Atoi(flexSpotNumber)
|
||||||
rows, err := r.db.Query(`UPDATE spots SET flexSpotNumber = ? WHERE id = ? RETURNING *`, flexSpotNumberInt, spot.ID)
|
rows, err := r.db.Query(`UPDATE spots SET flexSpotNumber = ? WHERE id = ? RETURNING *`, flexSpotNumberInt, spot.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
r.Log.Errorf("could not update database: %s", err)
|
r.Log.Errorf("could not update database: %s", err)
|
||||||
@ -267,7 +268,7 @@ func (r *FlexDXClusterRepository) UpdateFlexSpotNumberByID(flexSpot string, spot
|
|||||||
|
|
||||||
s := FlexSpot{}
|
s := FlexSpot{}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
if err := rows.Scan(&s.ID, &s.CommandNumber, &s.FlexSpotNumber, &s.DX, &s.FrequencyMhz, &s.FrequencyHz, &s.Band, &s.Mode, &s.SpotterCallsign, &s.FlexMode, &s.Source, &s.TimeStamp, &s.LifeTime, &s.Priority,
|
if err := rows.Scan(&s.ID, &s.CommandNumber, &s.FlexSpotNumber, &s.DX, &s.FrequencyMhz, &s.FrequencyHz, &s.Band, &s.Mode, &s.SpotterCallsign, &s.FlexMode, &s.Source, &s.UTCTime, &s.TimeStamp, &s.LifeTime, &s.Priority,
|
||||||
&s.Comment, &s.Color, &s.BackgroundColor); err != nil {
|
&s.Comment, &s.Color, &s.BackgroundColor); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -277,6 +278,15 @@ func (r *FlexDXClusterRepository) UpdateFlexSpotNumberByID(flexSpot string, spot
|
|||||||
return &s, nil
|
return &s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *FlexDXClusterRepository) DeleteSpotByFlexSpotNumber(flexSpotNumber string) {
|
||||||
|
flexSpotNumberInt, _ := strconv.Atoi(flexSpotNumber)
|
||||||
|
query := "DELETE from spots WHERE flexSpotNumber = ?"
|
||||||
|
_, err := r.db.Exec(query, flexSpotNumberInt)
|
||||||
|
if err != nil {
|
||||||
|
r.Log.Errorf("could not delete spot %v from database", flexSpotNumberInt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func DeleteDatabase(filePath string, log *log.Logger) {
|
func DeleteDatabase(filePath string, log *log.Logger) {
|
||||||
_, err := os.Stat(filePath)
|
_, err := os.Stat(filePath)
|
||||||
if !os.IsNotExist(err) {
|
if !os.IsNotExist(err) {
|
||||||
|
BIN
flex.sqlite
BIN
flex.sqlite
Binary file not shown.
116
flexradio.go
116
flexradio.go
@ -5,14 +5,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var command int = 1
|
var CommandNumber int = 1
|
||||||
|
|
||||||
type FlexSpot struct {
|
type FlexSpot struct {
|
||||||
ID int
|
ID int
|
||||||
@ -27,6 +27,7 @@ type FlexSpot struct {
|
|||||||
Source string
|
Source string
|
||||||
SpotterCallsign string
|
SpotterCallsign string
|
||||||
TimeStamp int64
|
TimeStamp int64
|
||||||
|
UTCTime string
|
||||||
LifeTime string
|
LifeTime string
|
||||||
Priority string
|
Priority string
|
||||||
Comment string
|
Comment string
|
||||||
@ -46,10 +47,10 @@ type FlexClient struct {
|
|||||||
MsgChan chan string
|
MsgChan chan string
|
||||||
Repo FlexDXClusterRepository
|
Repo FlexDXClusterRepository
|
||||||
Log *log.Logger
|
Log *log.Logger
|
||||||
TCPServer *TCPServer
|
TCPServer TCPServer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewFlexClient(repo FlexDXClusterRepository, TCPServer *TCPServer, log *log.Logger) *FlexClient {
|
func NewFlexClient(repo FlexDXClusterRepository, TCPServer TCPServer, log *log.Logger) *FlexClient {
|
||||||
return &FlexClient{
|
return &FlexClient{
|
||||||
Address: Cfg.Flex.IP,
|
Address: Cfg.Flex.IP,
|
||||||
Port: "4992",
|
Port: "4992",
|
||||||
@ -74,7 +75,7 @@ func (fc *FlexClient) StartFlexClient() {
|
|||||||
fc.Timeout = 600 * time.Second
|
fc.Timeout = 600 * time.Second
|
||||||
fc.Conn, err = net.DialTCP("tcp", nil, addr)
|
fc.Conn, err = net.DialTCP("tcp", nil, addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fc.Log.Error("could not dial flex client:", err)
|
fc.Log.Error("could not connect to flex radio, exiting...", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
fc.Log.Infof("connected to %s:%s", fc.Address, fc.Port)
|
fc.Log.Infof("connected to %s:%s", fc.Address, fc.Port)
|
||||||
@ -94,14 +95,22 @@ func (fc *FlexClient) StartFlexClient() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
go fc.ReadLine()
|
go fc.ReadLine()
|
||||||
|
|
||||||
|
subSpotAllCmd := fmt.Sprintf("C%v|sub spot all", CommandNumber)
|
||||||
|
fc.Write(subSpotAllCmd)
|
||||||
|
CommandNumber++
|
||||||
|
|
||||||
|
clrSpotAllCmd := fmt.Sprintf("C%v|spot clear", CommandNumber)
|
||||||
|
fc.Write(clrSpotAllCmd)
|
||||||
|
CommandNumber++
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *FlexClient) SendSpottoFlex(spot TelnetSpot) (n int, err error) {
|
func (fc *FlexClient) SendSpottoFlex(spot TelnetSpot) {
|
||||||
|
|
||||||
freq := FreqMhztoHz(spot.Frequency)
|
freq := FreqMhztoHz(spot.Frequency)
|
||||||
|
|
||||||
flexSpot := FlexSpot{
|
flexSpot := FlexSpot{
|
||||||
CommandNumber: command,
|
CommandNumber: CommandNumber,
|
||||||
DX: spot.DX,
|
DX: spot.DX,
|
||||||
FrequencyMhz: freq,
|
FrequencyMhz: freq,
|
||||||
FrequencyHz: spot.Frequency,
|
FrequencyHz: spot.Frequency,
|
||||||
@ -110,6 +119,7 @@ func (fc *FlexClient) SendSpottoFlex(spot TelnetSpot) (n int, err error) {
|
|||||||
Source: "FlexDXCluster",
|
Source: "FlexDXCluster",
|
||||||
SpotterCallsign: spot.Spotter,
|
SpotterCallsign: spot.Spotter,
|
||||||
TimeStamp: time.Now().Unix(),
|
TimeStamp: time.Now().Unix(),
|
||||||
|
UTCTime: spot.Time,
|
||||||
LifeTime: Cfg.Flex.SpotLife,
|
LifeTime: Cfg.Flex.SpotLife,
|
||||||
Comment: spot.Comment,
|
Comment: spot.Comment,
|
||||||
Color: "#eaeaea",
|
Color: "#eaeaea",
|
||||||
@ -149,70 +159,82 @@ func (fc *FlexClient) SendSpottoFlex(spot TelnetSpot) (n int, err error) {
|
|||||||
fc.Log.Error("could not find the DX in the database: ", err)
|
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 == "" {
|
if srcFlexSpot.DX == "" {
|
||||||
fc.Repo.CreateSpot(flexSpot)
|
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,
|
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)
|
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.SendSpot(stringSpot)
|
||||||
|
} else if srcFlexSpot.DX != "" && srcFlexSpot.Band == flexSpot.Band && srcFlexSpot.FrequencyMhz != flexSpot.FrequencyMhz {
|
||||||
fc.Repo.UpdateSpotSameBand(flexSpot)
|
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,
|
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)
|
|
||||||
} 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)
|
flexSpot.DX, flexSpot.Mode, flexSpot.Source, flexSpot.SpotterCallsign, flexSpot.TimeStamp, flexSpot.LifeTime, flexSpot.Comment, flexSpot.Color, flexSpot.BackgroundColor, flexSpot.Priority)
|
||||||
|
CommandNumber++
|
||||||
|
stringDelete := fmt.Sprintf("C%v|spot remove %v", CommandNumber, srcFlexSpot.FlexSpotNumber)
|
||||||
|
fc.DeleteAndSendSpot(stringSpot, stringDelete)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CommandNumber++
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fc *FlexClient) SendSpot(stringSpot string) {
|
||||||
fc.Write(stringSpot)
|
fc.Write(stringSpot)
|
||||||
|
}
|
||||||
|
|
||||||
command++
|
func (fc *FlexClient) DeleteAndSendSpot(stringSpot string, deleteSpot string) {
|
||||||
return
|
fc.Write(deleteSpot)
|
||||||
|
fc.Write(stringSpot)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *FlexClient) ReadLine() {
|
func (fc *FlexClient) ReadLine() {
|
||||||
|
|
||||||
for {
|
for {
|
||||||
message, err := fc.Reader.ReadString(byte('\n'))
|
message, err := fc.Reader.ReadString(byte('\n'))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fc.Log.Errorf("error reading message: %s", err)
|
fc.Log.Errorf("error reading message from flexradio closing program: %s", err)
|
||||||
continue
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// regRespSpot := *regexp.MustCompile(`R(\d+)\|0\|(\d+)\n`)
|
// msgRaw := strings.TrimSpace(message)
|
||||||
// respSpot := regRespSpot.FindStringSubmatch(message)
|
// fc.Log.Info(msgRaw)
|
||||||
|
|
||||||
// if len(respSpot) > 0 {
|
// Response when spot is added
|
||||||
// spot, _ := fc.Repo.FindSpotByCommandNumber(respSpot[1])
|
regRespSpot := *regexp.MustCompile(`R(\d+)\|0\|(\d+)\n`)
|
||||||
// _, err := fc.Repo.UpdateFlexSpotNumberByID(respSpot[2], *spot)
|
respSpot := regRespSpot.FindStringSubmatch(message)
|
||||||
// if err != nil {
|
|
||||||
// fc.Log.Errorf("could not update flex spot number in database: %s", err)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// regTriggerSpot := *regexp.MustCompile(`.*\|spot\s(\d+)\striggered.*`)
|
if len(respSpot) > 0 {
|
||||||
// respTrigger := regTriggerSpot.FindStringSubmatch(message)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// if len(respTrigger) > 0 {
|
// Response when a spot is clicked
|
||||||
// spot, err := fc.Repo.FindSpotByFlexSpotNumber(respTrigger[1])
|
regTriggerSpot := *regexp.MustCompile(`.*spot (\d+) triggered.*\n`)
|
||||||
// if err != nil {
|
respTrigger := regTriggerSpot.FindStringSubmatch(message)
|
||||||
// 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(respTrigger) > 0 {
|
||||||
// if len(fc.TCPServer.Clients) > 0 {
|
spot, err := fc.Repo.FindSpotByFlexSpotNumber(respTrigger[1])
|
||||||
// fc.MsgChan <- msg
|
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 <%s> : Clicked on "%s" at %s`, Cfg.SQLite.Callsign, spot.UTCTime, spot.DX, spot.FrequencyHz)
|
||||||
|
if len(fc.TCPServer.Clients) > 0 {
|
||||||
|
fc.MsgChan <- msg
|
||||||
|
fc.Log.Infof("%s clicked on spot \"%s\" at %s", Cfg.SQLite.Callsign, spot.DX, spot.FrequencyMhz)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
msg := strings.TrimSpace(message)
|
// Status when a spot is deleted
|
||||||
fc.Log.Info(msg)
|
regSpotDeleted := *regexp.MustCompile(`S\d+\|spot (\d+) removed`)
|
||||||
|
respDelete := regSpotDeleted.FindStringSubmatch(message)
|
||||||
|
|
||||||
|
if len(respDelete) > 0 {
|
||||||
|
fc.Repo.DeleteSpotByFlexSpotNumber(respDelete[1])
|
||||||
|
fc.Log.Infof("deleted spot %v from database", respDelete[1])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
195396
flexradio.log
195396
flexradio.log
File diff suppressed because it is too large
Load Diff
@ -8,8 +8,6 @@ import (
|
|||||||
prefixed "github.com/x-cray/logrus-prefixed-formatter"
|
prefixed "github.com/x-cray/logrus-prefixed-formatter"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Log *log.Logger
|
|
||||||
|
|
||||||
func NewLog() *log.Logger {
|
func NewLog() *log.Logger {
|
||||||
f, err := os.OpenFile("flexradio.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
f, err := os.OpenFile("flexradio.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -18,7 +16,7 @@ func NewLog() *log.Logger {
|
|||||||
|
|
||||||
w := io.MultiWriter(os.Stdout, f)
|
w := io.MultiWriter(os.Stdout, f)
|
||||||
|
|
||||||
Log := &log.Logger{
|
l := &log.Logger{
|
||||||
Out: w,
|
Out: w,
|
||||||
Level: log.DebugLevel,
|
Level: log.DebugLevel,
|
||||||
Formatter: &prefixed.TextFormatter{
|
Formatter: &prefixed.TextFormatter{
|
||||||
@ -29,7 +27,9 @@ func NewLog() *log.Logger {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return Log
|
l.Level = log.DebugLevel
|
||||||
|
|
||||||
|
return l
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info ...
|
// Info ...
|
||||||
@ -47,6 +47,10 @@ func Error(format string, v ...interface{}) {
|
|||||||
log.Errorf(format, v...)
|
log.Errorf(format, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Debug(format string, v ...interface{}) {
|
||||||
|
log.Debugf(format, v...)
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
||||||
// ConfigError ...
|
// ConfigError ...
|
||||||
|
23
main.go
23
main.go
@ -44,33 +44,18 @@ func main() {
|
|||||||
log := logger.NewLog()
|
log := logger.NewLog()
|
||||||
|
|
||||||
log.Info("config loaded.")
|
log.Info("config loaded.")
|
||||||
log.Infof("Callsign: %s\n", Cfg.SQLite.Callsign)
|
log.Infof("Callsign: %s", Cfg.SQLite.Callsign)
|
||||||
|
|
||||||
DeleteDatabase("./flex.sqlite", log)
|
DeleteDatabase("./flex.sqlite", log)
|
||||||
|
|
||||||
repo := NewFlexDXDatabase("flex.sqlite", log)
|
repo := NewFlexDXDatabase("flex.sqlite", log)
|
||||||
|
|
||||||
// Create TelnetServer
|
|
||||||
TCPServer := NewTCPServer(Cfg.Telnet.Host, Cfg.Telnet.Port, log)
|
TCPServer := NewTCPServer(Cfg.Telnet.Host, Cfg.Telnet.Port, log)
|
||||||
|
FlexClient := NewFlexClient(*repo, *TCPServer, log)
|
||||||
|
TCPClient := NewTCPClient(*Cfg, TCPServer, FlexClient, log)
|
||||||
|
|
||||||
// Connect to Flex Radio (ip defined in config file)
|
|
||||||
FlexClient := NewFlexClient(*repo, TCPServer, log)
|
|
||||||
go FlexClient.StartFlexClient()
|
go FlexClient.StartFlexClient()
|
||||||
|
go TCPClient.StartClient()
|
||||||
// Connect to DX Cluster
|
|
||||||
TelnetClient := TelnetClient{
|
|
||||||
Address: Cfg.Cluster.Server,
|
|
||||||
Port: Cfg.Cluster.Port,
|
|
||||||
Login: Cfg.Cluster.Login,
|
|
||||||
MsgChan: TCPServer.MsgChan,
|
|
||||||
CmdChan: TCPServer.CmdChan,
|
|
||||||
SpotChan: FlexClient.SpotChan,
|
|
||||||
Log: log,
|
|
||||||
}
|
|
||||||
|
|
||||||
go TelnetClient.StartClient()
|
|
||||||
|
|
||||||
// Start TelnetServer
|
|
||||||
go TCPServer.StartServer()
|
go TCPServer.StartServer()
|
||||||
|
|
||||||
select {}
|
select {}
|
||||||
|
1
spot.go
1
spot.go
@ -105,6 +105,7 @@ func ProcessTelnetSpot(re *regexp.Regexp, spotRaw string, SpotChan chan TelnetSp
|
|||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// send spot to SpotChan to Flex Client to send the spot to Flex radio
|
||||||
SpotChan <- spot
|
SpotChan <- spot
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user