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 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, *args, **kwargs):
179
- super().__init__(*args, **kwargs)
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()
@@ -277,6 +277,11 @@
277
277
  <string>CQ WPX CW</string>
278
278
  </property>
279
279
  </item>
280
+ <item>
281
+ <property name="text">
282
+ <string>CQ WPX RTTY</string>
283
+ </property>
284
+ </item>
280
285
  <item>
281
286
  <property name="text">
282
287
  <string>CQ WPX SSB</string>
not1mm/lib/cwinterface.py CHANGED
@@ -55,7 +55,7 @@ class CW:
55
55
  self._sendcw_xmlrpc(texttosend)
56
56
  if self.servertype == 1:
57
57
  self._sendcw_udp(texttosend)
58
- if self.servertype == 3 and self.cw is not None:
58
+ if self.servertype == 3:
59
59
  self._sendcwcat(texttosend)
60
60
 
61
61
  def _sendcw_xmlrpc(self, texttosend):
not1mm/lib/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """It's the version"""
2
2
 
3
- __version__ = "24.10.1"
3
+ __version__ = "24.10.2"
@@ -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.1
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
- pip install not1mm
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
- pip install not1mm
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 ARRL Field Day, ARRL VHF, and Weekly RTTY**
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 SSB, will be
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 or Voice) macros. |
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=88hPgSkZx61iYWfOFkfBflWsE_AcLOm3Wd1KMup4abU,130276
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=jR_bQMvsKgqD3az9iNS2fvPSs3WTf_phs5JXp1Ra8nA,23008
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=FrVB-MfK7CYU2QNjAK7ERrruKTL_NkHpBPIFNNaTvp4,3645
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=9gp4Ngkzl3dx14Khxs97HcvxUfF4KNXRD59UPZmDp0I,48
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.1.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
160
- not1mm-24.10.1.dist-info/METADATA,sha256=C1yfdCg9vuySn9SsuXZFP0LN_u0oTRUuXJUPmKqS9lM,30407
161
- not1mm-24.10.1.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
162
- not1mm-24.10.1.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
163
- not1mm-24.10.1.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
164
- not1mm-24.10.1.dist-info/RECORD,,
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,,