not1mm 24.10.1__py3-none-any.whl → 24.10.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- not1mm/__main__.py +29 -6
- not1mm/data/new_contest.ui +5 -0
- not1mm/lib/cwinterface.py +1 -1
- not1mm/lib/version.py +1 -1
- not1mm/plugins/cq_wpx_rtty.py +507 -0
- {not1mm-24.10.1.dist-info → not1mm-24.10.2.dist-info}/METADATA +21 -9
- {not1mm-24.10.1.dist-info → not1mm-24.10.2.dist-info}/RECORD +11 -10
- {not1mm-24.10.1.dist-info → not1mm-24.10.2.dist-info}/LICENSE +0 -0
- {not1mm-24.10.1.dist-info → not1mm-24.10.2.dist-info}/WHEEL +0 -0
- {not1mm-24.10.1.dist-info → not1mm-24.10.2.dist-info}/entry_points.txt +0 -0
- {not1mm-24.10.1.dist-info → not1mm-24.10.2.dist-info}/top_level.txt +0 -0
not1mm/__main__.py
CHANGED
@@ -175,10 +175,10 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
175
175
|
lookup_service = None
|
176
176
|
fldigi_util = None
|
177
177
|
|
178
|
-
def __init__(self,
|
179
|
-
super().__init__(
|
178
|
+
def __init__(self, splash):
|
179
|
+
super().__init__()
|
180
180
|
logger.info("MainWindow: __init__")
|
181
|
-
|
181
|
+
self.splash = splash
|
182
182
|
self.dock_loc = {
|
183
183
|
"Top": Qt.DockWidgetArea.TopDockWidgetArea,
|
184
184
|
"Right": Qt.DockWidgetArea.RightDockWidgetArea,
|
@@ -519,6 +519,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
519
519
|
QtGui.QIcon(str(fsutils.APP_DATA_PATH / "k6gte.not1mm-32.png"))
|
520
520
|
)
|
521
521
|
|
522
|
+
self.show_splash_msg("Loading CTY file.")
|
523
|
+
|
522
524
|
try:
|
523
525
|
with open(
|
524
526
|
fsutils.APP_DATA_PATH / "cty.json", "rt", encoding="utf-8"
|
@@ -527,11 +529,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
527
529
|
except (IOError, JSONDecodeError, TypeError):
|
528
530
|
logging.CRITICAL("There was an error parsing the BigCity file.")
|
529
531
|
|
532
|
+
self.show_splash_msg("Starting LookUp Service.")
|
533
|
+
|
530
534
|
self.lookup_service = LookupService()
|
531
535
|
self.lookup_service.hide()
|
532
536
|
|
537
|
+
self.show_splash_msg("Reading preferences.")
|
533
538
|
self.readpreferences()
|
534
539
|
|
540
|
+
self.show_splash_msg("Starting voice thread.")
|
535
541
|
self.voice_process = Voice()
|
536
542
|
self.voice_process.moveToThread(self.voice_thread)
|
537
543
|
self.voice_thread.started.connect(self.voice_process.run)
|
@@ -560,7 +566,9 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
560
566
|
self.make_op_dir()
|
561
567
|
|
562
568
|
self.clearinputs()
|
569
|
+
self.show_splash_msg("Loading contest.")
|
563
570
|
self.load_contest()
|
571
|
+
self.show_splash_msg("Reading macros.")
|
564
572
|
self.read_cw_macros()
|
565
573
|
|
566
574
|
# Featureset for wayland
|
@@ -569,6 +577,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
569
577
|
| QtWidgets.QDockWidget.DockWidgetFeature.DockWidgetMovable
|
570
578
|
)
|
571
579
|
|
580
|
+
self.show_splash_msg("Starting FlDigi watcher.")
|
572
581
|
self.fldigi_watcher = FlDigiWatcher()
|
573
582
|
self.fldigi_watcher.moveToThread(self.fldigi_thread)
|
574
583
|
self.fldigi_thread.started.connect(self.fldigi_watcher.run)
|
@@ -576,6 +585,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
576
585
|
self.fldigi_watcher.poll_callback.connect(self.fldigi_qso)
|
577
586
|
self.fldigi_thread.start()
|
578
587
|
|
588
|
+
self.show_splash_msg("Setting up LogWindow.")
|
579
589
|
self.log_window = LogWindow()
|
580
590
|
self.log_window.setObjectName("log-window")
|
581
591
|
if os.environ.get("WAYLAND_DISPLAY"):
|
@@ -583,6 +593,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
583
593
|
self.addDockWidget(Qt.DockWidgetArea.TopDockWidgetArea, self.log_window)
|
584
594
|
self.log_window.hide()
|
585
595
|
|
596
|
+
self.show_splash_msg("Setting up BandMapWindow.")
|
586
597
|
self.bandmap_window = BandMapWindow()
|
587
598
|
self.bandmap_window.setObjectName("bandmap-window")
|
588
599
|
if os.environ.get("WAYLAND_DISPLAY"):
|
@@ -590,6 +601,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
590
601
|
self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, self.bandmap_window)
|
591
602
|
self.bandmap_window.hide()
|
592
603
|
|
604
|
+
self.show_splash_msg("Setting up CheckWindow.")
|
593
605
|
self.check_window = CheckWindow()
|
594
606
|
self.check_window.setObjectName("check-window")
|
595
607
|
if os.environ.get("WAYLAND_DISPLAY"):
|
@@ -597,6 +609,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
597
609
|
self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.check_window)
|
598
610
|
self.check_window.hide()
|
599
611
|
|
612
|
+
self.show_splash_msg("Setting up VFOWindow.")
|
600
613
|
self.vfo_window = VfoWindow()
|
601
614
|
self.vfo_window.setObjectName("vfo-window")
|
602
615
|
if os.environ.get("WAYLAND_DISPLAY"):
|
@@ -604,6 +617,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
604
617
|
self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.vfo_window)
|
605
618
|
self.vfo_window.hide()
|
606
619
|
|
620
|
+
self.show_splash_msg("Restoring window states.")
|
607
621
|
self.settings = QSettings("K6GTE", "not1mm")
|
608
622
|
if self.settings.value("windowState") is not None:
|
609
623
|
self.restoreState(self.settings.value("windowState"))
|
@@ -635,6 +649,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
635
649
|
"You can udate to the current version by using:\npip install -U not1mm"
|
636
650
|
)
|
637
651
|
|
652
|
+
def show_splash_msg(self, msg: str) -> None:
|
653
|
+
"""Show text message in the splash window."""
|
654
|
+
self.splash.showMessage(
|
655
|
+
msg,
|
656
|
+
alignment=Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignCenter,
|
657
|
+
color=QColor(255, 255, 0),
|
658
|
+
)
|
659
|
+
QCoreApplication.processEvents()
|
660
|
+
|
638
661
|
def fldigi_qso(self, result: str):
|
639
662
|
"""
|
640
663
|
gets called when there is a new fldigi qso logged.
|
@@ -3601,7 +3624,7 @@ app = QtWidgets.QApplication(sys.argv)
|
|
3601
3624
|
pixmap = QPixmap(f"{os.fspath(fsutils.APP_DATA_PATH)}/splash.png")
|
3602
3625
|
splash = QSplashScreen(pixmap)
|
3603
3626
|
splash.show()
|
3604
|
-
app.processEvents()
|
3627
|
+
# app.processEvents()
|
3605
3628
|
splash.showMessage(
|
3606
3629
|
"Starting Up",
|
3607
3630
|
alignment=Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignCenter,
|
@@ -3611,10 +3634,10 @@ QCoreApplication.processEvents()
|
|
3611
3634
|
|
3612
3635
|
families = load_fonts_from_dir(os.fspath(fsutils.APP_DATA_PATH))
|
3613
3636
|
logger.info(f"font families {families}")
|
3614
|
-
window = MainWindow()
|
3637
|
+
window = MainWindow(splash)
|
3615
3638
|
window.callsign.setFocus()
|
3616
|
-
window.show()
|
3617
3639
|
splash.finish(window)
|
3640
|
+
window.show()
|
3618
3641
|
|
3619
3642
|
if __name__ == "__main__":
|
3620
3643
|
run()
|
not1mm/data/new_contest.ui
CHANGED
not1mm/lib/cwinterface.py
CHANGED
not1mm/lib/version.py
CHANGED
@@ -0,0 +1,507 @@
|
|
1
|
+
"""CQ WPX RTTY plugin"""
|
2
|
+
|
3
|
+
# pylint: disable=invalid-name, c-extension-no-member, unused-import
|
4
|
+
|
5
|
+
# CQ WW RTTY WPX Contest
|
6
|
+
# Status: Active
|
7
|
+
# Geographic Focus: Worldwide
|
8
|
+
# Participation: Worldwide
|
9
|
+
# Awards: Worldwide
|
10
|
+
# Mode: RTTY
|
11
|
+
# Bands: 80, 40, 20, 15, 10m
|
12
|
+
# Classes: Single Op All Band (QRP/Low/High)
|
13
|
+
# Single Op Single Band (QRP/Low/High)
|
14
|
+
# Single Op Overlays (Tribander/Rookie/Classic/Youth)
|
15
|
+
# Multi-One (Low/High)
|
16
|
+
# Multi-Two
|
17
|
+
# Multi-Multi
|
18
|
+
# Multi-Distributed
|
19
|
+
# Max operating hours: Single Op: 30 hours, offtimes of at least 60 minutes
|
20
|
+
# Multi-Op: 48 hours
|
21
|
+
# Max power: HP: 1500 watts
|
22
|
+
# LP: 100 watts
|
23
|
+
# QRP: 5 watts
|
24
|
+
# Exchange: RST + Serial No.
|
25
|
+
# Work stations: Once per band
|
26
|
+
# QSO Points: 1 point per QSO with same country on 20/15/10m
|
27
|
+
# 2 points per QSO with same country on 80/40m
|
28
|
+
# 2 points per QSO with different countries on same continent on 20/15/10m
|
29
|
+
# 4 points per QSO with different countries on same continent on 80/40m
|
30
|
+
# 3 points per QSO with different continent on 20/15/10m
|
31
|
+
# 6 points per QSO with different continent on 80/40m
|
32
|
+
# Multipliers: Each prefix once
|
33
|
+
# Score Calculation: Total score = total QSO points x total mults
|
34
|
+
# E-mail logs to: (none)
|
35
|
+
# Upload log at: https://www.cqwpxrtty.com/logcheck/
|
36
|
+
# Mail logs to: (none)
|
37
|
+
# Find rules at: https://www.cqwpxrtty.com/rules.htm
|
38
|
+
# Cabrillo name: CQ-WPX-RTTY
|
39
|
+
|
40
|
+
|
41
|
+
import datetime
|
42
|
+
import logging
|
43
|
+
|
44
|
+
from pathlib import Path
|
45
|
+
|
46
|
+
from PyQt6 import QtWidgets
|
47
|
+
|
48
|
+
from not1mm.lib.ham_utility import get_logged_band
|
49
|
+
from not1mm.lib.plugin_common import gen_adif, get_points
|
50
|
+
from not1mm.lib.version import __version__
|
51
|
+
|
52
|
+
logger = logging.getLogger(__name__)
|
53
|
+
|
54
|
+
ALTEREGO = None
|
55
|
+
|
56
|
+
EXCHANGE_HINT = "#"
|
57
|
+
|
58
|
+
name = "CQ WPX RTTY"
|
59
|
+
cabrillo_name = "CQ-WPX-RTTY"
|
60
|
+
mode = "RTTY" # CW SSB BOTH RTTY
|
61
|
+
# columns = [0, 1, 2, 3, 4, 5, 6, 9, 11, 15]
|
62
|
+
columns = [
|
63
|
+
"YYYY-MM-DD HH:MM:SS",
|
64
|
+
"Call",
|
65
|
+
"Freq",
|
66
|
+
"Snt",
|
67
|
+
"Rcv",
|
68
|
+
"SentNr",
|
69
|
+
"RcvNr",
|
70
|
+
"WPX",
|
71
|
+
"M1",
|
72
|
+
"PTS",
|
73
|
+
]
|
74
|
+
|
75
|
+
advance_on_space = [True, True, True, True, True]
|
76
|
+
|
77
|
+
# 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
|
78
|
+
dupe_type = 2
|
79
|
+
|
80
|
+
|
81
|
+
def init_contest(self):
|
82
|
+
"""setup plugin"""
|
83
|
+
set_tab_next(self)
|
84
|
+
set_tab_prev(self)
|
85
|
+
interface(self)
|
86
|
+
self.next_field = self.other_2
|
87
|
+
|
88
|
+
|
89
|
+
def interface(self):
|
90
|
+
"""Setup user interface"""
|
91
|
+
self.field1.show()
|
92
|
+
self.field2.show()
|
93
|
+
self.field3.show()
|
94
|
+
self.field4.show()
|
95
|
+
self.snt_label.setText("SNT")
|
96
|
+
self.field1.setAccessibleName("RST Sent")
|
97
|
+
self.other_label.setText("SentNR")
|
98
|
+
self.field3.setAccessibleName("Sent Number")
|
99
|
+
self.exch_label.setText("RcvNR")
|
100
|
+
self.field4.setAccessibleName("Received Number")
|
101
|
+
|
102
|
+
|
103
|
+
def reset_label(self): # pylint: disable=unused-argument
|
104
|
+
"""reset label after field cleared"""
|
105
|
+
|
106
|
+
|
107
|
+
def set_tab_next(self):
|
108
|
+
"""Set TAB Advances"""
|
109
|
+
self.tab_next = {
|
110
|
+
self.callsign: self.field1.findChild(QtWidgets.QLineEdit),
|
111
|
+
self.field1.findChild(QtWidgets.QLineEdit): self.field2.findChild(
|
112
|
+
QtWidgets.QLineEdit
|
113
|
+
),
|
114
|
+
self.field2.findChild(QtWidgets.QLineEdit): self.field3.findChild(
|
115
|
+
QtWidgets.QLineEdit
|
116
|
+
),
|
117
|
+
self.field3.findChild(QtWidgets.QLineEdit): self.field4.findChild(
|
118
|
+
QtWidgets.QLineEdit
|
119
|
+
),
|
120
|
+
self.field4.findChild(QtWidgets.QLineEdit): self.callsign,
|
121
|
+
}
|
122
|
+
|
123
|
+
|
124
|
+
def set_tab_prev(self):
|
125
|
+
"""Set TAB Advances"""
|
126
|
+
self.tab_prev = {
|
127
|
+
self.callsign: self.field4.findChild(QtWidgets.QLineEdit),
|
128
|
+
self.field1.findChild(QtWidgets.QLineEdit): self.callsign,
|
129
|
+
self.field2.findChild(QtWidgets.QLineEdit): self.field1.findChild(
|
130
|
+
QtWidgets.QLineEdit
|
131
|
+
),
|
132
|
+
self.field3.findChild(QtWidgets.QLineEdit): self.field2.findChild(
|
133
|
+
QtWidgets.QLineEdit
|
134
|
+
),
|
135
|
+
self.field4.findChild(QtWidgets.QLineEdit): self.field3.findChild(
|
136
|
+
QtWidgets.QLineEdit
|
137
|
+
),
|
138
|
+
}
|
139
|
+
|
140
|
+
|
141
|
+
def set_contact_vars(self):
|
142
|
+
"""Contest Specific"""
|
143
|
+
self.contact["SNT"] = self.sent.text()
|
144
|
+
self.contact["RCV"] = self.receive.text()
|
145
|
+
self.contact["SentNr"] = self.other_1.text()
|
146
|
+
self.contact["NR"] = self.other_2.text()
|
147
|
+
if self.contact.get("WPXPrefix", ""):
|
148
|
+
result = self.database.fetch_wpx_exists(self.contact.get("WPXPrefix", ""))
|
149
|
+
if result.get("wpx_count", ""):
|
150
|
+
self.contact["IsMultiplier1"] = 0
|
151
|
+
else:
|
152
|
+
self.contact["IsMultiplier1"] = 1
|
153
|
+
|
154
|
+
|
155
|
+
def predupe(self): # pylint: disable=unused-argument
|
156
|
+
"""called after callsign entered"""
|
157
|
+
|
158
|
+
|
159
|
+
def prefill(self):
|
160
|
+
"""Fill SentNR"""
|
161
|
+
result = self.database.get_serial()
|
162
|
+
serial_nr = str(result.get("serial_nr", "1")).zfill(3)
|
163
|
+
if serial_nr == "None":
|
164
|
+
serial_nr = "001"
|
165
|
+
field = self.field3.findChild(QtWidgets.QLineEdit)
|
166
|
+
if len(field.text()) == 0:
|
167
|
+
field.setText(serial_nr)
|
168
|
+
|
169
|
+
|
170
|
+
def points(self):
|
171
|
+
"""Calc point
|
172
|
+
Contact points:
|
173
|
+
- Different-country contacts within any continent (not just North America) get 2 or 4 points
|
174
|
+
- Same-country contacts get 2 points on the low bands
|
175
|
+
"""
|
176
|
+
result = self.cty_lookup(self.station.get("Call", ""))
|
177
|
+
if result:
|
178
|
+
for item in result.items():
|
179
|
+
my_country = item[1].get("entity", "")
|
180
|
+
my_continent = item[1].get("continent", "")
|
181
|
+
result = self.cty_lookup(self.contact.get("Call", ""))
|
182
|
+
band = int(int(float(self.contact.get("Freq", 0))) / 1000)
|
183
|
+
if result:
|
184
|
+
for item in result.items():
|
185
|
+
their_country = item[1].get("entity", "")
|
186
|
+
their_continent = item[1].get("continent", "")
|
187
|
+
|
188
|
+
# Different Continent
|
189
|
+
if my_continent != their_continent:
|
190
|
+
if band in [28, 21, 14]:
|
191
|
+
return 3
|
192
|
+
return 6
|
193
|
+
|
194
|
+
# Both in same country
|
195
|
+
if my_country.upper() == their_country.upper():
|
196
|
+
return 1
|
197
|
+
|
198
|
+
# Below Same Continent Different Country
|
199
|
+
|
200
|
+
if band in [28, 21, 14]:
|
201
|
+
return 2
|
202
|
+
return 4
|
203
|
+
|
204
|
+
# Something wrong
|
205
|
+
return 0
|
206
|
+
|
207
|
+
|
208
|
+
def show_mults(self):
|
209
|
+
"""Return display string for mults"""
|
210
|
+
result = self.database.fetch_wpx_count()
|
211
|
+
if result:
|
212
|
+
return int(result.get("wpx_count", 0))
|
213
|
+
return 0
|
214
|
+
|
215
|
+
|
216
|
+
def show_qso(self):
|
217
|
+
"""Return qso count"""
|
218
|
+
result = self.database.fetch_qso_count()
|
219
|
+
if result:
|
220
|
+
return int(result.get("qsos", 0))
|
221
|
+
return 0
|
222
|
+
|
223
|
+
|
224
|
+
def calc_score(self):
|
225
|
+
"""Return calculated score"""
|
226
|
+
result = self.database.fetch_points()
|
227
|
+
if result is not None:
|
228
|
+
score = result.get("Points", "0")
|
229
|
+
if score is None:
|
230
|
+
score = "0"
|
231
|
+
contest_points = int(score)
|
232
|
+
result = self.database.fetch_wpx_count()
|
233
|
+
mults = int(result.get("wpx_count", 0))
|
234
|
+
return contest_points * mults
|
235
|
+
return 0
|
236
|
+
|
237
|
+
|
238
|
+
def adif(self):
|
239
|
+
"""Call the generate ADIF function"""
|
240
|
+
gen_adif(self, cabrillo_name, "CQ-WPX-RTTY")
|
241
|
+
|
242
|
+
|
243
|
+
def cabrillo(self):
|
244
|
+
"""Generates Cabrillo file. Maybe."""
|
245
|
+
# https://www.cqwpx.com/cabrillo.htm
|
246
|
+
logger.debug("******Cabrillo*****")
|
247
|
+
logger.debug("Station: %s", f"{self.station}")
|
248
|
+
logger.debug("Contest: %s", f"{self.contest_settings}")
|
249
|
+
now = datetime.datetime.now()
|
250
|
+
date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
|
251
|
+
filename = (
|
252
|
+
str(Path.home())
|
253
|
+
+ "/"
|
254
|
+
+ f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
|
255
|
+
)
|
256
|
+
logger.debug("%s", filename)
|
257
|
+
log = self.database.fetch_all_contacts_asc()
|
258
|
+
try:
|
259
|
+
with open(filename, "w", encoding="ascii") as file_descriptor:
|
260
|
+
print("START-OF-LOG: 3.0", end="\r\n", file=file_descriptor)
|
261
|
+
print(
|
262
|
+
f"CREATED-BY: Not1MM v{__version__}",
|
263
|
+
end="\r\n",
|
264
|
+
file=file_descriptor,
|
265
|
+
)
|
266
|
+
print(
|
267
|
+
f"CONTEST: {cabrillo_name}",
|
268
|
+
end="\r\n",
|
269
|
+
file=file_descriptor,
|
270
|
+
)
|
271
|
+
if self.station.get("Club", ""):
|
272
|
+
print(
|
273
|
+
f"CLUB: {self.station.get('Club', '').upper()}",
|
274
|
+
end="\r\n",
|
275
|
+
file=file_descriptor,
|
276
|
+
)
|
277
|
+
print(
|
278
|
+
f"CALLSIGN: {self.station.get('Call','')}",
|
279
|
+
end="\r\n",
|
280
|
+
file=file_descriptor,
|
281
|
+
)
|
282
|
+
print(
|
283
|
+
f"LOCATION: {self.station.get('ARRLSection', '')}",
|
284
|
+
end="\r\n",
|
285
|
+
file=file_descriptor,
|
286
|
+
)
|
287
|
+
# print(
|
288
|
+
# f"ARRL-SECTION: {self.pref.get('section', '')}",
|
289
|
+
# end="\r\n",
|
290
|
+
# file=file_descriptor,
|
291
|
+
# )
|
292
|
+
print(
|
293
|
+
f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
|
294
|
+
end="\r\n",
|
295
|
+
file=file_descriptor,
|
296
|
+
)
|
297
|
+
print(
|
298
|
+
f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
|
299
|
+
end="\r\n",
|
300
|
+
file=file_descriptor,
|
301
|
+
)
|
302
|
+
print(
|
303
|
+
f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
|
304
|
+
end="\r\n",
|
305
|
+
file=file_descriptor,
|
306
|
+
)
|
307
|
+
print(
|
308
|
+
f"CATEGORY-MODE: {self.contest_settings.get('ModeCategory','')}",
|
309
|
+
end="\r\n",
|
310
|
+
file=file_descriptor,
|
311
|
+
)
|
312
|
+
print(
|
313
|
+
f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
|
314
|
+
end="\r\n",
|
315
|
+
file=file_descriptor,
|
316
|
+
)
|
317
|
+
if self.contest_settings.get("OverlayCategory", "") != "N/A":
|
318
|
+
print(
|
319
|
+
f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
|
320
|
+
end="\r\n",
|
321
|
+
file=file_descriptor,
|
322
|
+
)
|
323
|
+
print(
|
324
|
+
f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
|
325
|
+
end="\r\n",
|
326
|
+
file=file_descriptor,
|
327
|
+
)
|
328
|
+
# print(
|
329
|
+
# f"CATEGORY: {None}",
|
330
|
+
# end="\r\n",
|
331
|
+
# file=file_descriptor,
|
332
|
+
# )
|
333
|
+
print(
|
334
|
+
f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
|
335
|
+
end="\r\n",
|
336
|
+
file=file_descriptor,
|
337
|
+
)
|
338
|
+
|
339
|
+
print(
|
340
|
+
f"CLAIMED-SCORE: {calc_score(self)}",
|
341
|
+
end="\r\n",
|
342
|
+
file=file_descriptor,
|
343
|
+
)
|
344
|
+
ops = f"@{self.station.get('Call','')}"
|
345
|
+
list_of_ops = self.database.get_ops()
|
346
|
+
for op in list_of_ops:
|
347
|
+
ops += f", {op.get('Operator', '')}"
|
348
|
+
print(
|
349
|
+
f"OPERATORS: {ops}",
|
350
|
+
end="\r\n",
|
351
|
+
file=file_descriptor,
|
352
|
+
)
|
353
|
+
print(
|
354
|
+
f"NAME: {self.station.get('Name', '')}",
|
355
|
+
end="\r\n",
|
356
|
+
file=file_descriptor,
|
357
|
+
)
|
358
|
+
print(
|
359
|
+
f"ADDRESS: {self.station.get('Street1', '')}",
|
360
|
+
end="\r\n",
|
361
|
+
file=file_descriptor,
|
362
|
+
)
|
363
|
+
print(
|
364
|
+
f"ADDRESS-CITY: {self.station.get('City', '')}",
|
365
|
+
end="\r\n",
|
366
|
+
file=file_descriptor,
|
367
|
+
)
|
368
|
+
print(
|
369
|
+
f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
|
370
|
+
end="\r\n",
|
371
|
+
file=file_descriptor,
|
372
|
+
)
|
373
|
+
print(
|
374
|
+
f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
|
375
|
+
end="\r\n",
|
376
|
+
file=file_descriptor,
|
377
|
+
)
|
378
|
+
print(
|
379
|
+
f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
|
380
|
+
end="\r\n",
|
381
|
+
file=file_descriptor,
|
382
|
+
)
|
383
|
+
print(
|
384
|
+
f"EMAIL: {self.station.get('Email', '')}",
|
385
|
+
end="\r\n",
|
386
|
+
file=file_descriptor,
|
387
|
+
)
|
388
|
+
for contact in log:
|
389
|
+
the_date_and_time = contact.get("TS", "")
|
390
|
+
themode = contact.get("Mode", "")
|
391
|
+
if themode == "LSB" or themode == "USB":
|
392
|
+
themode = "PH"
|
393
|
+
frequency = str(int(contact.get("Freq", "0"))).rjust(5)
|
394
|
+
|
395
|
+
loggeddate = the_date_and_time[:10]
|
396
|
+
loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
|
397
|
+
print(
|
398
|
+
f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
|
399
|
+
f"{contact.get('StationPrefix', '').ljust(13)} "
|
400
|
+
f"{str(contact.get('SNT', '')).ljust(3)} "
|
401
|
+
f"{str(contact.get('SentNr', '')).ljust(6)} "
|
402
|
+
f"{contact.get('Call', '').ljust(13)} "
|
403
|
+
f"{str(contact.get('RCV', '')).ljust(3)} "
|
404
|
+
f"{str(contact.get('NR', '')).ljust(6)}",
|
405
|
+
end="\r\n",
|
406
|
+
file=file_descriptor,
|
407
|
+
)
|
408
|
+
print("END-OF-LOG:", end="\r\n", file=file_descriptor)
|
409
|
+
self.show_message_box(f"Cabrillo saved to: {filename}")
|
410
|
+
except IOError as exception:
|
411
|
+
logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
|
412
|
+
self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
|
413
|
+
return
|
414
|
+
|
415
|
+
|
416
|
+
def recalculate_mults(self):
|
417
|
+
"""Recalculates multipliers after change in logged qso."""
|
418
|
+
all_contacts = self.database.fetch_all_contacts_asc()
|
419
|
+
for contact in all_contacts:
|
420
|
+
self.contact = contact
|
421
|
+
contact["Points"] = points(self)
|
422
|
+
time_stamp = contact.get("TS", "")
|
423
|
+
wpx = contact.get("WPXPrefix", "")
|
424
|
+
result = self.database.fetch_wpx_exists_before_me(wpx, time_stamp)
|
425
|
+
wpx_count = result.get("wpx_count", 1)
|
426
|
+
if wpx_count == 0:
|
427
|
+
contact["IsMultiplier1"] = 1
|
428
|
+
else:
|
429
|
+
contact["IsMultiplier1"] = 0
|
430
|
+
self.database.change_contact(contact)
|
431
|
+
|
432
|
+
def set_self(the_outie):
|
433
|
+
"""..."""
|
434
|
+
globals()["ALTEREGO"] = the_outie
|
435
|
+
|
436
|
+
|
437
|
+
def ft8_handler(the_packet: dict):
|
438
|
+
"""Process FT8 QSO packets
|
439
|
+
FT8
|
440
|
+
{
|
441
|
+
'CALL': 'KE0OG',
|
442
|
+
'GRIDSQUARE': 'DM10AT',
|
443
|
+
'MODE': 'FT8',
|
444
|
+
'RST_SENT': '',
|
445
|
+
'RST_RCVD': '',
|
446
|
+
'QSO_DATE': '20210329',
|
447
|
+
'TIME_ON': '183213',
|
448
|
+
'QSO_DATE_OFF': '20210329',
|
449
|
+
'TIME_OFF': '183213',
|
450
|
+
'BAND': '20M',
|
451
|
+
'FREQ': '14.074754',
|
452
|
+
'STATION_CALLSIGN': 'K6GTE',
|
453
|
+
'MY_GRIDSQUARE': 'DM13AT',
|
454
|
+
'CONTEST_ID': 'ARRL-FIELD-DAY',
|
455
|
+
'SRX_STRING': '1D UT',
|
456
|
+
'CLASS': '1D',
|
457
|
+
'ARRL_SECT': 'UT'
|
458
|
+
}
|
459
|
+
FlDigi
|
460
|
+
{
|
461
|
+
'FREQ': '7.029500',
|
462
|
+
'CALL': 'DL2DSL',
|
463
|
+
'MODE': 'RTTY',
|
464
|
+
'NAME': 'BOB',
|
465
|
+
'QSO_DATE': '20240904',
|
466
|
+
'QSO_DATE_OFF': '20240904',
|
467
|
+
'TIME_OFF': '212825',
|
468
|
+
'TIME_ON': '212800',
|
469
|
+
'RST_RCVD': '599',
|
470
|
+
'RST_SENT': '599',
|
471
|
+
'BAND': '40M',
|
472
|
+
'COUNTRY': 'FED. REP. OF GERMANY',
|
473
|
+
'CQZ': '14',
|
474
|
+
'STX': '000',
|
475
|
+
'STX_STRING': '1D ORG',
|
476
|
+
'CLASS': '1D',
|
477
|
+
'ARRL_SECT': 'DX',
|
478
|
+
'TX_PWR': '0',
|
479
|
+
'OPERATOR': 'K6GTE',
|
480
|
+
'STATION_CALLSIGN': 'K6GTE',
|
481
|
+
'MY_GRIDSQUARE': 'DM13AT',
|
482
|
+
'MY_CITY': 'ANAHEIM, CA',
|
483
|
+
'MY_STATE': 'CA'
|
484
|
+
}
|
485
|
+
|
486
|
+
"""
|
487
|
+
logger.debug(f"{the_packet=}")
|
488
|
+
|
489
|
+
if ALTEREGO is not None:
|
490
|
+
ALTEREGO.callsign.setText(the_packet.get("CALL"))
|
491
|
+
ALTEREGO.contact["Call"] = the_packet.get("CALL", "")
|
492
|
+
ALTEREGO.contact["SNT"] = ALTEREGO.sent.text()
|
493
|
+
ALTEREGO.contact["RCV"] = ALTEREGO.receive.text()
|
494
|
+
ALTEREGO.contact["Exchange1"] = f"{the_packet.get("STATE", "")}".strip()
|
495
|
+
ALTEREGO.contact["ZN"] = the_packet.get("CQZ", "")
|
496
|
+
ALTEREGO.contact["Mode"] = the_packet.get("MODE", "ERR")
|
497
|
+
ALTEREGO.contact["Freq"] = round(float(the_packet.get("FREQ", "0.0")) * 1000, 2)
|
498
|
+
ALTEREGO.contact["QSXFreq"] = round(
|
499
|
+
float(the_packet.get("FREQ", "0.0")) * 1000, 2
|
500
|
+
)
|
501
|
+
ALTEREGO.contact["Band"] = get_logged_band(
|
502
|
+
str(int(float(the_packet.get("FREQ", "0.0")) * 1000000))
|
503
|
+
)
|
504
|
+
logger.debug(f"{ALTEREGO.contact=}")
|
505
|
+
ALTEREGO.other_1.setText(f"{the_packet.get("STX", "")}".strip())
|
506
|
+
ALTEREGO.other_2.setText(f"{the_packet.get("SRX", "")}".strip())
|
507
|
+
ALTEREGO.save_contact()
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: not1mm
|
3
|
-
Version: 24.10.
|
3
|
+
Version: 24.10.2
|
4
4
|
Summary: NOT1MM Logger
|
5
5
|
Author-email: Michael Bridak <michael.bridak@gmail.com>
|
6
6
|
Project-URL: Homepage, https://github.com/mbridak/not1mm
|
@@ -201,7 +201,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
|
|
201
201
|
- ARRL Sweepstakes CW, SSB
|
202
202
|
- ARRL VHF January, June, September
|
203
203
|
- CQ 160 CW, SSB
|
204
|
-
- CQ WPX CW, SSB
|
204
|
+
- CQ WPX CW, RTTY, SSB
|
205
205
|
- CQ World Wide CW, RTTY, SSB
|
206
206
|
- CWOps CWT
|
207
207
|
- Helvetia
|
@@ -219,6 +219,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
|
|
219
219
|
|
220
220
|
## Recent Changes
|
221
221
|
|
222
|
+
- [24-10-2] Add WPX RTTY.
|
222
223
|
- [24-10-1] Merged PR removing leading zeros from serial numbers. Merged PR correcting the parsing of lookups for previous name and state in the CWT.
|
223
224
|
|
224
225
|
See [CHANGELOG.md](CHANGELOG.md) for prior changes.
|
@@ -294,16 +295,18 @@ source .profile
|
|
294
295
|
|
295
296
|
```bash
|
296
297
|
sudo dnf upgrade --refresh
|
297
|
-
sudo dnf install python3-pip portaudio
|
298
|
-
|
298
|
+
sudo dnf install python3-pip pipx portaudio
|
299
|
+
pipx install not1mm
|
300
|
+
pipx ensurepath
|
299
301
|
```
|
300
302
|
|
301
303
|
#### Fedora 40
|
302
304
|
|
303
305
|
```bash
|
304
306
|
sudo dnf upgrade --refresh
|
305
|
-
sudo dnf install python3-pip python3-pyqt6 portaudio
|
306
|
-
|
307
|
+
sudo dnf install python3-pip pipx python3-pyqt6 portaudio
|
308
|
+
pipx install not1mm
|
309
|
+
pipx ensurepath
|
307
310
|
```
|
308
311
|
|
309
312
|
</details>
|
@@ -598,7 +601,12 @@ appear. Those without will not.
|
|
598
601
|
|
599
602
|
## Logging WSJT-X FT8/FT4/ETC and FLDIGI RTTY contacts
|
600
603
|
|
601
|
-
**Digital modes only working for
|
604
|
+
**Digital modes only working for:**
|
605
|
+
|
606
|
+
- ARRL Field Day
|
607
|
+
- ARRL VHF
|
608
|
+
- Weekly RTTY
|
609
|
+
- CQ WW DX RTTY
|
602
610
|
|
603
611
|
not1mm listens for WSJT-X UDP traffic on the Multicast address 224.0.0.1:2237.
|
604
612
|
No setup is needed to be done on not1mm's side. That's good because I'm lazy.
|
@@ -607,6 +615,10 @@ not1mm polls for fldigi QSOs via it's XMLRPC interface. It does this in a rather
|
|
607
615
|
way. It just keeps asking what was the last QSO and compares it to the previous response.
|
608
616
|
If it's different, it's new. I've added the Weekly RTTY Test so this can be tested.
|
609
617
|
|
618
|
+
The F1-F12 function keys be sent to fldigi via XMLRPC. Fldigi will be placed into TX
|
619
|
+
mode, the message will be sent and a ^r will be tacked onto the end to place it back into
|
620
|
+
RX mode.
|
621
|
+
|
610
622
|
Unlike WSJT, fldigi needs to be setup for this to work. The XMLRPC interface needs to be
|
611
623
|
active. And in fldigi's config dialog go to CONTESTS -> General -> CONTEST and select
|
612
624
|
Generic Contest. Make sure the Text Capture Order field says CALL EXCHANGE.
|
@@ -624,7 +636,7 @@ field.
|
|
624
636
|
|
625
637
|
To edit the macros, choose `File` > `Edit Macros`. This will open your systems
|
626
638
|
registered text editor with current macros loaded. When your done just save the
|
627
|
-
file and close the editor. The file loaded to edit, CW or
|
639
|
+
file and close the editor. The file loaded to edit, CW, SSB or RTTY, will be
|
628
640
|
determined by your current operating mode.
|
629
641
|
|
630
642
|
After editing and saving the macro file. You can force the logger to reload the
|
@@ -707,7 +719,7 @@ is this has happened, since the gridsquare will replace the word "Regional".
|
|
707
719
|
| [Shift-Tab] | Move cursor left One field. |
|
708
720
|
| [SPACE] | When in the callsign field, will move the input to the first field needed for the exchange. |
|
709
721
|
| [Enter] | Submits the fields to the log. |
|
710
|
-
| [F1-F12] | Send (CW
|
722
|
+
| [F1-F12] | Send (CW/RTTY/Voice) macros. |
|
711
723
|
| [CTRL-S] | Spot Callsign to the cluster. |
|
712
724
|
| [CTRL-M] | Mark Callsign to the bandmap window to work later. |
|
713
725
|
| [CTRL-G] | Tune to a spot matching partial text in the callsign entry field (CAT Required). |
|
@@ -1,5 +1,5 @@
|
|
1
1
|
not1mm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
not1mm/__main__.py,sha256=
|
2
|
+
not1mm/__main__.py,sha256=yw-_P3yDCTpvj2WuXqbBvOht4SMpA8DJGwwmldg1Kf8,131265
|
3
3
|
not1mm/bandmap.py,sha256=1b5tXCfGTnpqqn6hPNt7zRA8SmuwSXzSwNHZXhCRt70,31434
|
4
4
|
not1mm/checkwindow.py,sha256=aI-nr8OF90IWV7R_XRdmitvBJ9M85evCs72HoU3Jnvc,10374
|
5
5
|
not1mm/fsutils.py,sha256=ukHKxKTeNKxKwqRaJjtzRShL4X5Xl0jRBbADyy3Ifp8,1701
|
@@ -31,7 +31,7 @@ not1mm/data/k6gte.not1mm-64.png,sha256=6ku45Gq1g5ezh04F07osoKRtanb3e4kbx5XdIEh3N
|
|
31
31
|
not1mm/data/logwindow.ui,sha256=f7vULj96tHIQuR1nJMyvPHHcmVgzkhv9D1isyojsnFU,1458
|
32
32
|
not1mm/data/logwindowx.ui,sha256=CwpI-h7cI1yqyldH9quKftsdHL5lTyL9ABOcf80nfqc,1632
|
33
33
|
not1mm/data/main.ui,sha256=IOrAJfJDhG30bWi08pLBGzDKjBvjKfPNI9-GNpvu0vI,61886
|
34
|
-
not1mm/data/new_contest.ui,sha256=
|
34
|
+
not1mm/data/new_contest.ui,sha256=oIe15jiIN50wc5THeJLIO3KYZWXUyqRt9n_ShD0qO7Y,23116
|
35
35
|
not1mm/data/not1mm.html,sha256=c9-mfjMwDt4f5pySUruz2gREW33CQ2_rCddM2z5CZQo,23273
|
36
36
|
not1mm/data/opon.ui,sha256=QDicqAk2lORG2UWsHa6jHlsGn6uzrrI2R4HSAocpPes,2258
|
37
37
|
not1mm/data/pickcontest.ui,sha256=4hPBszCglObThx_eIWtmK9CEcbr7WBjbB1rKZdI-o3I,1707
|
@@ -95,7 +95,7 @@ not1mm/data/phonetics/z.wav,sha256=arafCi7fwmBLdVDI-PRyaL4U-03PIQDhffwY5noJ_2c,5
|
|
95
95
|
not1mm/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
96
96
|
not1mm/lib/about.py,sha256=sWycfGcruN3SaEe4JmaJ61K6D8Itq0WxpUYT-lEcmYM,416
|
97
97
|
not1mm/lib/cat_interface.py,sha256=FfLldMH4FayArOcwoZBQT3vTU2RoiG7dmaT922Z8i2Y,21459
|
98
|
-
not1mm/lib/cwinterface.py,sha256=
|
98
|
+
not1mm/lib/cwinterface.py,sha256=3H_Ur5qtZCg6AA-CBURdnS3IUcvs3YAcwYLO0S8SUBg,3621
|
99
99
|
not1mm/lib/database.py,sha256=nUVG5H2Dy98PGp6Qdr3xU7zM8-8-IiyqRkXZWlWzIe8,44446
|
100
100
|
not1mm/lib/edit_contact.py,sha256=Ki9bGPpqyQQBB1cU8VIBDCal3lbXeQ6qxhzklmhE2_w,353
|
101
101
|
not1mm/lib/edit_macro.py,sha256=raKWBwsHInj5EUKmvyLQ6gqc3ZFDlstsD3xqoM4PC8E,517
|
@@ -114,7 +114,7 @@ not1mm/lib/plugin_common.py,sha256=TbFUbftjELFt4QRdsjSHbqnXSngZOlSwlCTClqosDXA,9
|
|
114
114
|
not1mm/lib/select_contest.py,sha256=WsptLuwkouIHeocJL3oZ6-eUfEnhpwdc-x7eMZ_TIVM,359
|
115
115
|
not1mm/lib/settings.py,sha256=0Su8BQM4haVhc_P74q8UhzRZxtgWhM40UmVtQdMJQeM,10022
|
116
116
|
not1mm/lib/super_check_partial.py,sha256=p5l3u2ZOCBtlWgbvskC50FpuoaIpR07tfC6zTdRWbh4,2334
|
117
|
-
not1mm/lib/version.py,sha256=
|
117
|
+
not1mm/lib/version.py,sha256=oVIPDmFc6GlXPQNej28LeA_6UeX3YcWigdy6XmGWvx0,48
|
118
118
|
not1mm/lib/versiontest.py,sha256=8vDNptuBBunn-1IGkjNaquehqBYUJyjrPSF8Igmd4_Y,1286
|
119
119
|
not1mm/plugins/10_10_fall_cw.py,sha256=IttjX1yy4nDdACGsiYlPteFG8eVseX_WtoFio6bqHE8,10953
|
120
120
|
not1mm/plugins/10_10_spring_cw.py,sha256=ThCptdM3dX4ywhoy2JRcOEyHSqcJolFaT7O_PYzM1Mg,10958
|
@@ -135,6 +135,7 @@ not1mm/plugins/canada_day.py,sha256=OVpcCl1Chse_zLHf6PayTrgawWM4W-pmrTw40Al-o9s,
|
|
135
135
|
not1mm/plugins/cq_160_cw.py,sha256=5s6rIZdJEnmWe1SI06BEyz7p5vP0N2n9mI4l_mZ0icw,14139
|
136
136
|
not1mm/plugins/cq_160_ssb.py,sha256=zIwSMAjHSt6W2edrDzVbyTf860JowHoFkU9BKO8Enag,14182
|
137
137
|
not1mm/plugins/cq_wpx_cw.py,sha256=9aNzAR-KhznIwUlxUFjAi_hbiw_6RrCMwUBk9I2f6Hs,14037
|
138
|
+
not1mm/plugins/cq_wpx_rtty.py,sha256=d0YsC_RDNEhp0mFGxtm7Ao7tI8wEeJJOACYAXdSWiWw,16473
|
138
139
|
not1mm/plugins/cq_wpx_ssb.py,sha256=-hGRovqHR9rfOUnG4LPOoABTb4heH8VAX6rYdJbCqsw,12687
|
139
140
|
not1mm/plugins/cq_ww_cw.py,sha256=m4Xkqb_qFyXWEgkxqbanvtiCTvI8NNPKNXzHgFZzhnE,12340
|
140
141
|
not1mm/plugins/cq_ww_rtty.py,sha256=N0togQbMSpRyRpGoYvnlGC3mpduR82g-D39Swtp5wjI,16772
|
@@ -156,9 +157,9 @@ not1mm/plugins/ref_cw.py,sha256=aWjHHkqIKutjRUtzh09y5haFfnZK9poRQDWRQMDRxxU,1632
|
|
156
157
|
not1mm/plugins/stew_perry_topband.py,sha256=CKBQbYl4ETxhXJd2dma4fg_C5pag_s7Nf61SCztZtqE,10668
|
157
158
|
not1mm/plugins/weekly_rtty.py,sha256=DQcy3SY0Zn56EdlYGf3NxrRhTnkNa5IqRQPRQdKDSPs,14255
|
158
159
|
not1mm/plugins/winter_field_day.py,sha256=4rcfRtobwjHO6BNL3WOTHzBmyyeuX79BNGBG8PfjrI8,10238
|
159
|
-
not1mm-24.10.
|
160
|
-
not1mm-24.10.
|
161
|
-
not1mm-24.10.
|
162
|
-
not1mm-24.10.
|
163
|
-
not1mm-24.10.
|
164
|
-
not1mm-24.10.
|
160
|
+
not1mm-24.10.2.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
161
|
+
not1mm-24.10.2.dist-info/METADATA,sha256=u5KI88xY0PCI00BaZts4w6c4NvnLOmW_i4CZraKr8fY,30694
|
162
|
+
not1mm-24.10.2.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
|
163
|
+
not1mm-24.10.2.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
|
164
|
+
not1mm-24.10.2.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
|
165
|
+
not1mm-24.10.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|