You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
239 lines
7.4 KiB
239 lines
7.4 KiB
package main
|
|
|
|
import (
|
|
"encoding/xml"
|
|
log "github.com/sirupsen/logrus"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"time"
|
|
"fmt"
|
|
"github.com/tzneal/ham-go/dxcc"
|
|
"github.com/mmcloughlin/geohash"
|
|
"github.com/pd0mz/go-maidenhead"
|
|
)
|
|
|
|
type receptionReports struct {
|
|
XMLName xml.Name `xml:"receptionReports"`
|
|
ActiveReceivers []activeReceiver `xml:"activeReceiver"`
|
|
LastSequenceNumber lastSequenceNumber `xml:"lastSequenceNumber"`
|
|
MaxFlowStartSeconds maxFlowStartSeconds `xml:"maxFlowStartSeconds"`
|
|
ReceptionReport []receptionReport `xml:"receptionReport"`
|
|
SenderSearch senderSearch `xml:"senderSearch"`
|
|
ActiveCallSign []activeCallSign `xml:"activeCallsign"`
|
|
Lotw lotw `xml:"lotw"`
|
|
}
|
|
|
|
type activeReceiver struct {
|
|
XMLName xml.Name `xml:"activeReceiver"`
|
|
CallSign string `xml:"callsign,attr"`
|
|
Locator string `xml:"locator,attr"`
|
|
Frequency string `xml:"frequency,attr"`
|
|
Region string `xml:"region,attr"`
|
|
Dxcc string `xml:"DXCC,attr"`
|
|
DecoderSoftware string `xml:"decoderSoftware,attr"`
|
|
AntennaInformation string `xml:"antennaInformation,attr"`
|
|
Mode string `xml:"mode,attr"`
|
|
}
|
|
|
|
type lastSequenceNumber struct {
|
|
XMLName xml.Name `xml:"lastSequenceNumber"`
|
|
Value int64 `xml:"value,attr"`
|
|
}
|
|
|
|
type maxFlowStartSeconds struct {
|
|
XMLName xml.Name `xml:"maxFlowStartSeconds"`
|
|
Value string `xml:"value,attr"`
|
|
}
|
|
|
|
type receptionReport struct {
|
|
XMLName xml.Name `xml:"receptionReport"`
|
|
ReceiverCallSign string `xml:"receiverCallsign,attr"`
|
|
ReceiverLocator string `xml:"receiverLocator,attr"`
|
|
SenderCallSign string `xml:"senderCallsign,attr"`
|
|
SenderLocator string `xml:"senderLocator,attr"`
|
|
Frequency float64 `xml:"frequency,attr"`
|
|
FlowStartSeconds int64 `xml:"flowStartSeconds,attr"`
|
|
Mode string `xml:"mode,attr"`
|
|
IsSender bool `xml:"isSender,attr"`
|
|
ReceiverDxcc string `xml:"receiverDXCC,attr"`
|
|
ReceiverDxccCode string `xml:"receiverDXCCCode,attr"`
|
|
SenderLotwUpload string `xml:"senderLotwUpload,attr"`
|
|
Snr int `xml:"sNR,attr"`
|
|
}
|
|
|
|
type senderSearch struct {
|
|
XMLName xml.Name `xml:"senderSearch"`
|
|
CallSign string `xml:"callsign,attr"`
|
|
RecentFlowStartSeconds string `xml:"recentFlowStartSeconds,attr"`
|
|
}
|
|
|
|
type activeCallSign struct {
|
|
XMLName xml.Name `xml:"activeCallsign"`
|
|
CallSign string `xml:"callsign"`
|
|
Reports int `xml:"reports"`
|
|
Dxcc string `xml:"DXCC"`
|
|
DxccCode string `xml:"DXCCCode"`
|
|
frequency int `xml:"frequency"`
|
|
}
|
|
|
|
type lotw struct {
|
|
XMLName xml.Name `xml:"lotw"`
|
|
Upload string `xml:"upload,attr"`
|
|
CallSign string `xml:"callsign,attr"`
|
|
}
|
|
|
|
type report struct {
|
|
CallSign string
|
|
Grid string
|
|
Signal int
|
|
Mode string
|
|
Dxcc string
|
|
GeoHash string
|
|
Continent string
|
|
lastReport int64
|
|
Band string
|
|
CQZone int
|
|
ITUZone int
|
|
}
|
|
|
|
func GetBand(freq float64) (string){
|
|
band := "unknown"
|
|
if (freq>1000000 && freq<2000000) {
|
|
band = "160m"
|
|
}
|
|
if (freq>3000000 && freq<4000000) {
|
|
band = "80m"
|
|
}
|
|
if (freq>5000000 && freq<6000000) {
|
|
band = "60m"
|
|
}
|
|
if (freq>7000000 && freq<8000000) {
|
|
band = "40m"
|
|
}
|
|
if (freq>10000000 && freq<11000000) {
|
|
band = "30m"
|
|
}
|
|
if (freq>14000000 && freq<15000000) {
|
|
band = "20m"
|
|
}
|
|
if (freq>18000000 && freq<19000000) {
|
|
band = "17m"
|
|
}
|
|
if (freq>21000000 && freq<22000000) {
|
|
band = "15m"
|
|
}
|
|
if (freq>24000000 && freq<25000000) {
|
|
band = "12m"
|
|
}
|
|
if (freq>28000000 && freq<30000000) {
|
|
band = "10m"
|
|
}
|
|
if (freq>144000000 && freq<145000000) {
|
|
band = "2m"
|
|
}
|
|
if (freq>432000000 && freq<433000000) {
|
|
band = "70cm"
|
|
}
|
|
return band
|
|
}
|
|
|
|
|
|
func handleReport(receiver receptionReport) (report, bool) {
|
|
var r report
|
|
// var i int64
|
|
|
|
Ent, found := dxcc.Lookup(receiver.ReceiverCallSign)
|
|
if !found {
|
|
log.Warnf("erro while lookup up %s",receiver.ReceiverCallSign)
|
|
return r ,false
|
|
}
|
|
|
|
p, err:= maidenhead.ParseLocator(receiver.ReceiverLocator)
|
|
if err != nil {
|
|
log.Error("crazy shit happened while grid parsing..")
|
|
log.Error(err)
|
|
return r, false
|
|
}
|
|
|
|
r.CallSign = receiver.ReceiverCallSign
|
|
r.Grid = receiver.ReceiverLocator
|
|
r.Signal = receiver.Snr
|
|
r.Mode = receiver.Mode
|
|
r.Dxcc = receiver.ReceiverDxcc
|
|
r.Continent = Ent.Continent
|
|
r.CQZone = Ent.CQZone
|
|
r.ITUZone = Ent.ITUZone
|
|
r.lastReport = receiver.FlowStartSeconds
|
|
r.GeoHash = geohash.Encode(p.Latitude, p.Longitude)
|
|
r.Band = GetBand(receiver.Frequency)
|
|
|
|
// i, err := strconv.ParseInt(receiver.FlowStartSeconds, 10, 64)
|
|
// if err != nil {
|
|
// log.WithFields(log.Fields{"err":err}).Error("something went wrong while parsing the timestamp: ",)
|
|
// return r, false
|
|
// }
|
|
// r.lastReport = time.Unix(i, 0)
|
|
|
|
return r, true
|
|
}
|
|
|
|
|
|
func fetchReports(reports chan report) {
|
|
var lastseqno int64
|
|
var url string
|
|
|
|
lastseqno = 0
|
|
|
|
for {
|
|
if lastseqno == 0 {
|
|
url = "https://retrieve.pskreporter.info/query?senderCallsign=" + station + "&rronly=true&appcontact=git@ixyd.net"
|
|
} else {
|
|
url = "https://retrieve.pskreporter.info/query?senderCallsign=" + station + "&lastseqno=" + fmt.Sprintf("%d",lastseqno) + "&rronly=true&appcontact=git@ixyd.net"
|
|
}
|
|
log.WithFields(log.Fields{"url":url}).Debug("fetching reports")
|
|
resp, err := http.Get(url)
|
|
defer resp.Body.Close()
|
|
if err != nil {
|
|
log.Error("well.. shit happened.. 1")
|
|
log.Error(err)
|
|
log.Info("sleeping for 300 seconds..")
|
|
time.Sleep(300 * time.Second)
|
|
continue
|
|
}
|
|
|
|
body,err := ioutil.ReadAll(resp.Body)
|
|
if err !=nil {
|
|
log.Error("well.. shit happened.. 2")
|
|
log.Error(err)
|
|
log.Info("sleeping for 300 seconds..")
|
|
time.Sleep(300 * time.Second)
|
|
continue
|
|
}
|
|
|
|
// phrt.With(prometheus.Labels{"code": fmt.Sprintf("%d",resp.StatusCode)}).Inc()
|
|
if resp.StatusCode >= 200 && resp.StatusCode <= 299 {
|
|
log.Info("fetching reports done.")
|
|
rr := receptionReports{}
|
|
err = xml.Unmarshal(body,&rr)
|
|
if err != nil {
|
|
log.Error("well.. shit happened.. 3")
|
|
log.Error(err)
|
|
log.Info("sleeping for 300 seconds..")
|
|
time.Sleep(300 * time.Second)
|
|
continue
|
|
}
|
|
for _, receiver := range rr.ReceptionReport {
|
|
r, parsed := handleReport(receiver)
|
|
if parsed {
|
|
reports <- r
|
|
}
|
|
}
|
|
lastseqno = rr.LastSequenceNumber.Value
|
|
} else {
|
|
log.WithFields(log.Fields{"response":resp.StatusCode,}).Warn("fetching reports was NOT successfully ")
|
|
log.Warn(string(body))
|
|
}
|
|
log.Info("sleeping for 300 seconds..")
|
|
time.Sleep(300 * time.Second)
|
|
}
|
|
}
|
|
|