-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpskreporter-sender
executable file
·146 lines (120 loc) · 4.6 KB
/
pskreporter-sender
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/usr/bin/env python
"""
FTx sender to PSKReporter
Usage:
pskreporter-sender [options] <logfile> [<mode>]
pskreporter-sender -h | --help
Options:
-h --help Show this screen.
--no-send Don't send, just print the spots
--callsign=<callsign> The callsign of the reporter
--locator=<locator> The locator for the radio -- at least 6 characters
--antenna=<antenna> The antenna used on the radio
"""
from pskreporter import PskReporter
import re
from datetime import datetime, time
import subprocess
from docopt import docopt
import sys
def get_unix_timestamp(hhmm: str) -> int:
# Get the current date and time
now = datetime.now()
today = now.date()
# Parse the HHMM string
hours = int(hhmm[:2])
minutes = int(hhmm[2:])
# Create a datetime object for today at the specified time
specified_time = datetime.combine(today, time(hours, minutes))
# If the specified time is in the future, move to the previous day
if specified_time > now:
specified_time -= datetime.timedelta(days=1)
# Get the Unix timestamp
unix_timestamp = int(specified_time.timestamp())
return unix_timestamp
def do_wspr(stream, pskreporter, mode):
r1 = re.compile(
r"(?P<ts>[0-9]{4}) +(?P<snr>[-0-9]+) +(?P<u2>[-.0-9]+) +(?P<freq>[0-9.]+) +(?P<u3>[-.0-9]+) +<?(?P<callsign>[A-Z0-9/-]+)>? +(?P<locator>[A-Z0-9]+) +(?P<power>[0-9]+) *$"
)
r2 = re.compile(
r"(?P<ymd>[0-9]{6}) +(?P<ts>[0-9]{4}) +(?P<u1>[-.0-9]+) +(?P<snr>[-0-9]+) +(?P<u2>[-.0-9]+) +(?P<freq>[0-9.]+) +<?(?P<callsign>[A-Z0-9/-]+)>? +(?P<locator>[A-Z0-9]+) +(?P<power>[0-9]+)"
)
for line in stream:
# 0044 -26 0.2 14.097059 0 W5NR EM10 23
# or
# 241104 0024 0.21 -18 0.02 18.1060273 N3BBF FM19 37 0 2
m = r1.search(line.decode("utf-8"))
if not m:
m = r2.search(line.decode("utf-8"))
if m:
ts = get_unix_timestamp(m.group("ts"))
snr = int(m.group("snr"))
freq = 1000000.0 * float(m.group("freq"))
pskreporter.spot(
callsign=m.group("callsign"),
mode=mode,
timestamp=ts,
frequency=freq,
db=snr,
locator=m.group("locator"),
)
elif not line.startswith(b"<Decode"):
print(line)
def submit(stream, pskreporter, mode):
r = re.compile(
r"(?P<ts>[0-9/]+ [0-9:]+) +(?P<snr>[-0-9]+) +(?P<dt>[-+.0-9]+) (?P<freq>[0-9,.]+) ~ (?P<msg>.*)$"
)
cq = re.compile(r"CQ (DX )?(?P<callsign>[A-Z0-9/-]{3,}) (?P<locator>[A-Z][A-Z][0-9][0-9]) *$")
cq2 = re.compile(r"CQ (DX )?(?P<callsign>[A-Z0-9/-]{3,}) *(?P<locator>)$")
tx2 = re.compile(
r"(?P<their_callsign>([A-Z0-9/-]{3,})|(<\.\.\.>)) (?P<callsign>[A-Z0-9/-]{3,}) (?P<locator>[A-Z][A-Z][0-9][0-9]) *$"
)
for line in stream:
# 2024/05/02 02:01:00 18 +1.44 7,075,718.8 ~ CQ NF3R FN20
# 2024/05/02 02:01:00 18 +0.88 7,074,100.0 ~ CQ EA7LZ IM76
m = r.search(line.decode("utf-8"))
if m:
msg = m.group("msg")
match = cq.search(msg)
if not match:
match = cq2.search(msg)
if not match:
match = tx2.search(msg)
if match and match.group("locator") == "RR73":
match = None
if match:
ts = datetime.strptime(m.group("ts"), "%Y/%m/%d %H:%M:%S").timestamp()
snr = -int(m.group("snr"))
freq = float(m.group("freq").replace(",", ""))
pskreporter.spot(
callsign=match.group("callsign"),
mode=mode,
timestamp=ts,
frequency=freq,
db=snr,
locator=match.group("locator"),
)
if __name__ == "__main__":
args = docopt(__doc__)
file = args["<logfile>"]
mode = args["<mode>"]
if not mode:
if "ft8" in file.lower():
mode = "ft8"
elif "ft4" in file.lower():
mode = "ft4"
elif "wspr" in file.lower():
mode = "wspr"
if not mode:
sys.exit("Need to provide the mode argument")
pskreporter = PskReporter(
callsign=args["--callsign"].upper(),
grid=args["--locator"],
antenna=args["--antenna"],
dummy=args["--no-send"],
)
proc = subprocess.Popen(["tail", "-F", file], stdout=subprocess.PIPE)
if mode == "wspr":
do_wspr(proc.stdout, pskreporter, mode.upper())
else:
submit(proc.stdout, pskreporter, mode.upper())