not1mm 25.1.26.1__py3-none-any.whl → 25.1.27.1__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 +3 -1
- not1mm/data/new_contest.ui +5 -0
- not1mm/lib/version.py +1 -1
- not1mm/plugins/labre_rs_digi.py +634 -0
- {not1mm-25.1.26.1.dist-info → not1mm-25.1.27.1.dist-info}/METADATA +25 -22
- {not1mm-25.1.26.1.dist-info → not1mm-25.1.27.1.dist-info}/RECORD +10 -9
- {not1mm-25.1.26.1.dist-info → not1mm-25.1.27.1.dist-info}/LICENSE +0 -0
- {not1mm-25.1.26.1.dist-info → not1mm-25.1.27.1.dist-info}/WHEEL +0 -0
- {not1mm-25.1.26.1.dist-info → not1mm-25.1.27.1.dist-info}/entry_points.txt +0 -0
- {not1mm-25.1.26.1.dist-info → not1mm-25.1.27.1.dist-info}/top_level.txt +0 -0
not1mm/__main__.py
CHANGED
@@ -725,7 +725,9 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
725
725
|
if VersionTest(__version__).test():
|
726
726
|
self.show_message_box(
|
727
727
|
"There is a newer version of not1mm available.\n"
|
728
|
-
"You can udate to the current version by using:\
|
728
|
+
"You can udate to the current version by using:\n\n"
|
729
|
+
"pip install -U not1mm\n\tor\n"
|
730
|
+
"pipx upgrade not1mm"
|
729
731
|
)
|
730
732
|
|
731
733
|
self.udp_socket = QtNetwork.QUdpSocket()
|
not1mm/data/new_contest.ui
CHANGED
not1mm/lib/version.py
CHANGED
@@ -0,0 +1,634 @@
|
|
1
|
+
"""LABRE-RS Digi"""
|
2
|
+
|
3
|
+
# LABRE-RS Digi Contest
|
4
|
+
# Status: Active
|
5
|
+
# Geographic Focus: Worldwide
|
6
|
+
# Participation: Worldwide
|
7
|
+
# Mode: FT4/8
|
8
|
+
# Bands: 80, 40, 20, 15, 10m
|
9
|
+
# Classes: Single Op(QRP/Low/High)
|
10
|
+
# Multi-Single (Low/High)
|
11
|
+
# Multi-Multi
|
12
|
+
# Max power: HP: 1500 watts
|
13
|
+
# LP: 100 watts
|
14
|
+
# QRP: 5 watts
|
15
|
+
# Exchange: 4-character grid square
|
16
|
+
# Work stations: Once per band
|
17
|
+
# QSO Points: 1 point per QSO
|
18
|
+
# 1 additional point per QSO with PY3,PU3,ZZ3,PP3,etc
|
19
|
+
# Multipliers: Each grid field (first 2 letters of grid square) once per band
|
20
|
+
# Score Calculation: Total score = total QSO points x total mults
|
21
|
+
# E-mail logs to: (none)
|
22
|
+
# Upload log at: https://hampass.org/contests
|
23
|
+
# Mail logs to: (none)
|
24
|
+
# Find rules at: https://labre-rs.org.br/labre-rs-digi-contest/
|
25
|
+
# Cabrillo name: CQWW-DIGI
|
26
|
+
# Cabrillo name aliases:
|
27
|
+
|
28
|
+
# pylint: disable=invalid-name, unused-argument, unused-variable, c-extension-no-member
|
29
|
+
|
30
|
+
import datetime
|
31
|
+
import logging
|
32
|
+
|
33
|
+
from pathlib import Path
|
34
|
+
from PyQt6 import QtWidgets
|
35
|
+
|
36
|
+
from not1mm.lib.ham_utility import get_logged_band
|
37
|
+
from not1mm.lib.plugin_common import gen_adif, get_points, online_score_xml
|
38
|
+
from not1mm.lib.version import __version__
|
39
|
+
|
40
|
+
logger = logging.getLogger(__name__)
|
41
|
+
|
42
|
+
ALTEREGO = None
|
43
|
+
EXCHANGE_HINT = "4-character grid square"
|
44
|
+
|
45
|
+
name = "LABRE-RS Digi"
|
46
|
+
mode = "RTTY" # CW SSB BOTH RTTY
|
47
|
+
cabrillo_name = "CQWW-DIGI"
|
48
|
+
|
49
|
+
columns = [
|
50
|
+
"YYYY-MM-DD HH:MM:SS",
|
51
|
+
"Call",
|
52
|
+
"Freq",
|
53
|
+
"Mode",
|
54
|
+
"SentNr",
|
55
|
+
"RcvNr",
|
56
|
+
"PTS",
|
57
|
+
]
|
58
|
+
|
59
|
+
advance_on_space = [True, True, True, True, True]
|
60
|
+
|
61
|
+
# 1 once per contest, 2 work each band, 3 each band/mode, 4 no dupe checking
|
62
|
+
dupe_type = 2
|
63
|
+
|
64
|
+
|
65
|
+
def init_contest(self):
|
66
|
+
"""setup plugin"""
|
67
|
+
set_tab_next(self)
|
68
|
+
set_tab_prev(self)
|
69
|
+
interface(self)
|
70
|
+
self.next_field = self.other_2
|
71
|
+
|
72
|
+
|
73
|
+
def interface(self):
|
74
|
+
"""Setup user interface"""
|
75
|
+
self.field1.show()
|
76
|
+
self.field2.show()
|
77
|
+
self.field3.show()
|
78
|
+
self.field4.show()
|
79
|
+
self.snt_label.setText("SNT")
|
80
|
+
self.field1.setAccessibleName("RST Sent")
|
81
|
+
self.other_label.setText("SentNR")
|
82
|
+
self.field3.setAccessibleName("Sent Grid")
|
83
|
+
self.exch_label.setText("Grid")
|
84
|
+
self.field4.setAccessibleName("Gridsquare")
|
85
|
+
|
86
|
+
|
87
|
+
def reset_label(self):
|
88
|
+
"""reset label after field cleared"""
|
89
|
+
|
90
|
+
|
91
|
+
def set_tab_next(self):
|
92
|
+
"""Set TAB Advances"""
|
93
|
+
self.tab_next = {
|
94
|
+
self.callsign: self.sent,
|
95
|
+
self.sent: self.receive,
|
96
|
+
self.receive: self.other_1,
|
97
|
+
self.other_1: self.other_2,
|
98
|
+
self.other_2: self.callsign,
|
99
|
+
}
|
100
|
+
|
101
|
+
|
102
|
+
def set_tab_prev(self):
|
103
|
+
"""Set TAB Advances"""
|
104
|
+
self.tab_prev = {
|
105
|
+
self.callsign: self.other_2,
|
106
|
+
self.sent: self.callsign,
|
107
|
+
self.receive: self.sent,
|
108
|
+
self.other_1: self.receive,
|
109
|
+
self.other_2: self.other_1,
|
110
|
+
}
|
111
|
+
|
112
|
+
|
113
|
+
def validate(self):
|
114
|
+
"""doc"""
|
115
|
+
# exchange = self.other_2.text().upper().split()
|
116
|
+
# if len(exchange) == 3:
|
117
|
+
# if exchange[0].isalpha() and exchange[1].isdigit() and exchange[2].isalpha():
|
118
|
+
# return True
|
119
|
+
# return False
|
120
|
+
return True
|
121
|
+
|
122
|
+
|
123
|
+
def set_contact_vars(self):
|
124
|
+
"""Contest Specific"""
|
125
|
+
self.contact["SNT"] = self.sent.text()
|
126
|
+
self.contact["RCV"] = self.receive.text()
|
127
|
+
self.contact["NR"] = self.other_2.text().upper()
|
128
|
+
self.contact["SentNr"] = self.other_1.text()
|
129
|
+
|
130
|
+
|
131
|
+
def predupe(self):
|
132
|
+
"""called after callsign entered"""
|
133
|
+
|
134
|
+
|
135
|
+
def prefill(self):
|
136
|
+
"""Fill sentnr"""
|
137
|
+
result = self.database.get_serial()
|
138
|
+
serial_nr = str(result.get("serial_nr", "1")).zfill(3)
|
139
|
+
if serial_nr == "None":
|
140
|
+
serial_nr = "001"
|
141
|
+
|
142
|
+
exchange = self.contest_settings.get("SentExchange", "").replace("#", serial_nr)
|
143
|
+
if len(self.other_1.text()) == 0:
|
144
|
+
self.other_1.setText(exchange)
|
145
|
+
|
146
|
+
|
147
|
+
def points(self):
|
148
|
+
"""Calc point"""
|
149
|
+
|
150
|
+
# QSO Points: 1 point per QSO
|
151
|
+
# 1 additional point per QSO with PY3,PU3,ZZ3,PP3,etc
|
152
|
+
|
153
|
+
if self.contact.get("Call", "") in ["PY3", "PU3", "ZZ3", "PP3"]:
|
154
|
+
return 2
|
155
|
+
return 1
|
156
|
+
|
157
|
+
|
158
|
+
def show_mults(self):
|
159
|
+
"""Return display string for mults"""
|
160
|
+
# Each grid field (first 2 letters of grid square) once per band
|
161
|
+
|
162
|
+
dx = 0
|
163
|
+
|
164
|
+
sql = (
|
165
|
+
"select count(DISTINCT(SUBSTR(NR,1,2) || ':' || Band)) as mult_count "
|
166
|
+
f"from dxlog where ContestNR = {self.database.current_contest} and typeof(NR) = 'text';"
|
167
|
+
)
|
168
|
+
result = self.database.exec_sql(sql)
|
169
|
+
|
170
|
+
if result:
|
171
|
+
dx = result.get("mult_count", 0)
|
172
|
+
|
173
|
+
return dx
|
174
|
+
|
175
|
+
|
176
|
+
def show_qso(self):
|
177
|
+
"""Return qso count"""
|
178
|
+
result = self.database.fetch_qso_count()
|
179
|
+
if result:
|
180
|
+
return int(result.get("qsos", 0))
|
181
|
+
return 0
|
182
|
+
|
183
|
+
|
184
|
+
def calc_score(self):
|
185
|
+
"""Return calculated score"""
|
186
|
+
# Multipliers: Each US State + DC once per mode
|
187
|
+
_points = get_points(self)
|
188
|
+
_mults = show_mults(self)
|
189
|
+
_power_mult = 1
|
190
|
+
return _points * _power_mult * _mults
|
191
|
+
|
192
|
+
|
193
|
+
def adif(self):
|
194
|
+
"""Call the generate ADIF function"""
|
195
|
+
gen_adif(self, cabrillo_name)
|
196
|
+
|
197
|
+
|
198
|
+
def output_cabrillo_line(line_to_output, ending, file_descriptor, file_encoding):
|
199
|
+
""""""
|
200
|
+
print(
|
201
|
+
line_to_output.encode(file_encoding, errors="ignore").decode(),
|
202
|
+
end=ending,
|
203
|
+
file=file_descriptor,
|
204
|
+
)
|
205
|
+
|
206
|
+
|
207
|
+
def cabrillo(self, file_encoding):
|
208
|
+
"""Generates Cabrillo file. Maybe."""
|
209
|
+
# https://www.cqwpx.com/cabrillo.htm
|
210
|
+
logger.debug("******Cabrillo*****")
|
211
|
+
logger.debug("Station: %s", f"{self.station}")
|
212
|
+
logger.debug("Contest: %s", f"{self.contest_settings}")
|
213
|
+
now = datetime.datetime.now()
|
214
|
+
date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
|
215
|
+
filename = (
|
216
|
+
str(Path.home())
|
217
|
+
+ "/"
|
218
|
+
+ f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
|
219
|
+
)
|
220
|
+
logger.debug("%s", filename)
|
221
|
+
log = self.database.fetch_all_contacts_asc()
|
222
|
+
try:
|
223
|
+
with open(filename, "w", encoding=file_encoding) as file_descriptor:
|
224
|
+
output_cabrillo_line(
|
225
|
+
"START-OF-LOG: 3.0",
|
226
|
+
"\r\n",
|
227
|
+
file_descriptor,
|
228
|
+
file_encoding,
|
229
|
+
)
|
230
|
+
output_cabrillo_line(
|
231
|
+
f"CREATED-BY: Not1MM v{__version__}",
|
232
|
+
"\r\n",
|
233
|
+
file_descriptor,
|
234
|
+
file_encoding,
|
235
|
+
)
|
236
|
+
output_cabrillo_line(
|
237
|
+
f"CONTEST: {cabrillo_name}",
|
238
|
+
"\r\n",
|
239
|
+
file_descriptor,
|
240
|
+
file_encoding,
|
241
|
+
)
|
242
|
+
if self.station.get("Club", ""):
|
243
|
+
output_cabrillo_line(
|
244
|
+
f"CLUB: {self.station.get('Club', '').upper()}",
|
245
|
+
"\r\n",
|
246
|
+
file_descriptor,
|
247
|
+
file_encoding,
|
248
|
+
)
|
249
|
+
output_cabrillo_line(
|
250
|
+
f"CALLSIGN: {self.station.get('Call','')}",
|
251
|
+
"\r\n",
|
252
|
+
file_descriptor,
|
253
|
+
file_encoding,
|
254
|
+
)
|
255
|
+
output_cabrillo_line(
|
256
|
+
f"LOCATION: {self.station.get('ARRLSection', '')}",
|
257
|
+
"\r\n",
|
258
|
+
file_descriptor,
|
259
|
+
file_encoding,
|
260
|
+
)
|
261
|
+
output_cabrillo_line(
|
262
|
+
f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
|
263
|
+
"\r\n",
|
264
|
+
file_descriptor,
|
265
|
+
file_encoding,
|
266
|
+
)
|
267
|
+
output_cabrillo_line(
|
268
|
+
f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
|
269
|
+
"\r\n",
|
270
|
+
file_descriptor,
|
271
|
+
file_encoding,
|
272
|
+
)
|
273
|
+
output_cabrillo_line(
|
274
|
+
f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
|
275
|
+
"\r\n",
|
276
|
+
file_descriptor,
|
277
|
+
file_encoding,
|
278
|
+
)
|
279
|
+
mode = self.contest_settings.get("ModeCategory", "")
|
280
|
+
if mode in ["SSB+CW", "SSB+CW+DIGITAL"]:
|
281
|
+
mode = "MIXED"
|
282
|
+
output_cabrillo_line(
|
283
|
+
f"CATEGORY-MODE: {mode}",
|
284
|
+
"\r\n",
|
285
|
+
file_descriptor,
|
286
|
+
file_encoding,
|
287
|
+
)
|
288
|
+
output_cabrillo_line(
|
289
|
+
f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
|
290
|
+
"\r\n",
|
291
|
+
file_descriptor,
|
292
|
+
file_encoding,
|
293
|
+
)
|
294
|
+
if self.contest_settings.get("OverlayCategory", "") != "N/A":
|
295
|
+
output_cabrillo_line(
|
296
|
+
f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
|
297
|
+
"\r\n",
|
298
|
+
file_descriptor,
|
299
|
+
file_encoding,
|
300
|
+
)
|
301
|
+
output_cabrillo_line(
|
302
|
+
f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
|
303
|
+
"\r\n",
|
304
|
+
file_descriptor,
|
305
|
+
file_encoding,
|
306
|
+
)
|
307
|
+
output_cabrillo_line(
|
308
|
+
f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
|
309
|
+
"\r\n",
|
310
|
+
file_descriptor,
|
311
|
+
file_encoding,
|
312
|
+
)
|
313
|
+
|
314
|
+
output_cabrillo_line(
|
315
|
+
f"CLAIMED-SCORE: {calc_score(self)}",
|
316
|
+
"\r\n",
|
317
|
+
file_descriptor,
|
318
|
+
file_encoding,
|
319
|
+
)
|
320
|
+
ops = f"@{self.station.get('Call','')}"
|
321
|
+
list_of_ops = self.database.get_ops()
|
322
|
+
for op in list_of_ops:
|
323
|
+
ops += f", {op.get('Operator', '')}"
|
324
|
+
output_cabrillo_line(
|
325
|
+
f"OPERATORS: {ops}",
|
326
|
+
"\r\n",
|
327
|
+
file_descriptor,
|
328
|
+
file_encoding,
|
329
|
+
)
|
330
|
+
output_cabrillo_line(
|
331
|
+
f"NAME: {self.station.get('Name', '')}",
|
332
|
+
"\r\n",
|
333
|
+
file_descriptor,
|
334
|
+
file_encoding,
|
335
|
+
)
|
336
|
+
output_cabrillo_line(
|
337
|
+
f"ADDRESS: {self.station.get('Street1', '')}",
|
338
|
+
"\r\n",
|
339
|
+
file_descriptor,
|
340
|
+
file_encoding,
|
341
|
+
)
|
342
|
+
output_cabrillo_line(
|
343
|
+
f"ADDRESS-CITY: {self.station.get('City', '')}",
|
344
|
+
"\r\n",
|
345
|
+
file_descriptor,
|
346
|
+
file_encoding,
|
347
|
+
)
|
348
|
+
output_cabrillo_line(
|
349
|
+
f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
|
350
|
+
"\r\n",
|
351
|
+
file_descriptor,
|
352
|
+
file_encoding,
|
353
|
+
)
|
354
|
+
output_cabrillo_line(
|
355
|
+
f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
|
356
|
+
"\r\n",
|
357
|
+
file_descriptor,
|
358
|
+
file_encoding,
|
359
|
+
)
|
360
|
+
output_cabrillo_line(
|
361
|
+
f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
|
362
|
+
"\r\n",
|
363
|
+
file_descriptor,
|
364
|
+
file_encoding,
|
365
|
+
)
|
366
|
+
output_cabrillo_line(
|
367
|
+
f"EMAIL: {self.station.get('Email', '')}",
|
368
|
+
"\r\n",
|
369
|
+
file_descriptor,
|
370
|
+
file_encoding,
|
371
|
+
)
|
372
|
+
for contact in log:
|
373
|
+
the_date_and_time = contact.get("TS", "")
|
374
|
+
themode = contact.get("Mode", "")
|
375
|
+
|
376
|
+
if themode in ("LSB", "USB", "AM"):
|
377
|
+
themode = "PH"
|
378
|
+
if themode in (
|
379
|
+
"FT8",
|
380
|
+
"FT4",
|
381
|
+
"RTTY",
|
382
|
+
"PSK31",
|
383
|
+
"FSK441",
|
384
|
+
"MSK144",
|
385
|
+
"JT65",
|
386
|
+
"JT9",
|
387
|
+
"Q65",
|
388
|
+
):
|
389
|
+
themode = "DG"
|
390
|
+
freq = int(contact.get("Freq", "0")) / 1000
|
391
|
+
|
392
|
+
frequency = str(int(freq)).rjust(4)
|
393
|
+
|
394
|
+
loggeddate = the_date_and_time[:10]
|
395
|
+
loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
|
396
|
+
output_cabrillo_line(
|
397
|
+
f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
|
398
|
+
f"{contact.get('StationPrefix', '').ljust(13)} "
|
399
|
+
# f"{str(contact.get('SNT', '')).ljust(3)} "
|
400
|
+
f"{str(contact.get('SentNr', '')).ljust(6)} "
|
401
|
+
f"{contact.get('Call', '').ljust(13)} "
|
402
|
+
# f"{str(contact.get('RCV', '')).ljust(3)} "
|
403
|
+
f"{str(contact.get('NR', '')).ljust(6)}",
|
404
|
+
"\r\n",
|
405
|
+
file_descriptor,
|
406
|
+
file_encoding,
|
407
|
+
)
|
408
|
+
output_cabrillo_line("END-OF-LOG:", "\r\n", file_descriptor, file_encoding)
|
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
|
+
|
419
|
+
|
420
|
+
def set_self(the_outie):
|
421
|
+
"""..."""
|
422
|
+
globals()["ALTEREGO"] = the_outie
|
423
|
+
|
424
|
+
|
425
|
+
def ft8_handler(the_packet: dict):
|
426
|
+
"""Process FT8 QSO packets
|
427
|
+
FT8
|
428
|
+
{
|
429
|
+
'CALL': 'KE0OG',
|
430
|
+
'GRIDSQUARE': 'DM10AT',
|
431
|
+
'MODE': 'FT8',
|
432
|
+
'RST_SENT': '',
|
433
|
+
'RST_RCVD': '',
|
434
|
+
'QSO_DATE': '20210329',
|
435
|
+
'TIME_ON': '183213',
|
436
|
+
'QSO_DATE_OFF': '20210329',
|
437
|
+
'TIME_OFF': '183213',
|
438
|
+
'BAND': '20M',
|
439
|
+
'FREQ': '14.074754',
|
440
|
+
'STATION_CALLSIGN': 'K6GTE',
|
441
|
+
'MY_GRIDSQUARE': 'DM13AT',
|
442
|
+
'CONTEST_ID': 'ARRL-FIELD-DAY',
|
443
|
+
'SRX_STRING': '1D UT',
|
444
|
+
'CLASS': '1D',
|
445
|
+
'ARRL_SECT': 'UT'
|
446
|
+
}
|
447
|
+
FlDigi
|
448
|
+
{
|
449
|
+
'FREQ': '7.029500',
|
450
|
+
'CALL': 'DL2DSL',
|
451
|
+
'MODE': 'RTTY',
|
452
|
+
'NAME': 'BOB',
|
453
|
+
'QSO_DATE': '20240904',
|
454
|
+
'QSO_DATE_OFF': '20240904',
|
455
|
+
'TIME_OFF': '212825',
|
456
|
+
'TIME_ON': '212800',
|
457
|
+
'RST_RCVD': '599',
|
458
|
+
'RST_SENT': '599',
|
459
|
+
'BAND': '40M',
|
460
|
+
'COUNTRY': 'FED. REP. OF GERMANY',
|
461
|
+
'CQZ': '14',
|
462
|
+
'STX': '000',
|
463
|
+
'STX_STRING': '1D ORG',
|
464
|
+
'CLASS': '1D',
|
465
|
+
'ARRL_SECT': 'DX',
|
466
|
+
'TX_PWR': '0',
|
467
|
+
'OPERATOR': 'K6GTE',
|
468
|
+
'STATION_CALLSIGN': 'K6GTE',
|
469
|
+
'MY_GRIDSQUARE': 'DM13AT',
|
470
|
+
'MY_CITY': 'ANAHEIM, CA',
|
471
|
+
'MY_STATE': 'CA'
|
472
|
+
}
|
473
|
+
|
474
|
+
"""
|
475
|
+
# print(f"\n{the_packet=}\n")
|
476
|
+
if ALTEREGO is not None:
|
477
|
+
ALTEREGO.callsign.setText(the_packet.get("CALL"))
|
478
|
+
ALTEREGO.contact["Call"] = the_packet.get("CALL", "")
|
479
|
+
ALTEREGO.contact["SNT"] = ALTEREGO.sent.text()
|
480
|
+
ALTEREGO.contact["RCV"] = ALTEREGO.receive.text()
|
481
|
+
my_grid = the_packet.get("MY_GRIDSQUARE", "")
|
482
|
+
if my_grid:
|
483
|
+
if len(my_grid) > 4:
|
484
|
+
my_grid = my_grid[:4]
|
485
|
+
their_grid = the_packet.get("GRIDSQUARE", "")
|
486
|
+
if their_grid:
|
487
|
+
if len(their_grid) > 4:
|
488
|
+
their_grid = their_grid[:4]
|
489
|
+
ALTEREGO.contact["NR"] = their_grid
|
490
|
+
if the_packet.get("SUBMODE"):
|
491
|
+
ALTEREGO.contact["Mode"] = the_packet.get("SUBMODE", "ERR")
|
492
|
+
else:
|
493
|
+
ALTEREGO.contact["Mode"] = the_packet.get("MODE", "ERR")
|
494
|
+
ALTEREGO.contact["Freq"] = round(float(the_packet.get("FREQ", "0.0")) * 1000, 2)
|
495
|
+
ALTEREGO.contact["QSXFreq"] = round(
|
496
|
+
float(the_packet.get("FREQ", "0.0")) * 1000, 2
|
497
|
+
)
|
498
|
+
ALTEREGO.contact["Band"] = get_logged_band(
|
499
|
+
str(int(float(the_packet.get("FREQ", "0.0")) * 1000000))
|
500
|
+
)
|
501
|
+
# print(f"\n{ALTEREGO.contact=}\n")
|
502
|
+
ALTEREGO.other_1.setText(my_grid)
|
503
|
+
ALTEREGO.other_2.setText(their_grid)
|
504
|
+
ALTEREGO.save_contact()
|
505
|
+
|
506
|
+
|
507
|
+
def process_esm(self, new_focused_widget=None, with_enter=False):
|
508
|
+
"""ESM State Machine"""
|
509
|
+
|
510
|
+
# self.pref["run_state"]
|
511
|
+
|
512
|
+
# -----===== Assigned F-Keys =====-----
|
513
|
+
# self.esm_dict["CQ"]
|
514
|
+
# self.esm_dict["EXCH"]
|
515
|
+
# self.esm_dict["QRZ"]
|
516
|
+
# self.esm_dict["AGN"]
|
517
|
+
# self.esm_dict["HISCALL"]
|
518
|
+
# self.esm_dict["MYCALL"]
|
519
|
+
# self.esm_dict["QSOB4"]
|
520
|
+
|
521
|
+
# ----==== text fields ====----
|
522
|
+
# self.callsign
|
523
|
+
# self.sent
|
524
|
+
# self.receive
|
525
|
+
# self.other_1
|
526
|
+
# self.other_2
|
527
|
+
|
528
|
+
if new_focused_widget is not None:
|
529
|
+
self.current_widget = self.inputs_dict.get(new_focused_widget)
|
530
|
+
|
531
|
+
# print(f"checking esm {self.current_widget=} {with_enter=} {self.pref.get("run_state")=}")
|
532
|
+
|
533
|
+
for a_button in [
|
534
|
+
self.esm_dict["CQ"],
|
535
|
+
self.esm_dict["EXCH"],
|
536
|
+
self.esm_dict["QRZ"],
|
537
|
+
self.esm_dict["AGN"],
|
538
|
+
self.esm_dict["HISCALL"],
|
539
|
+
self.esm_dict["MYCALL"],
|
540
|
+
self.esm_dict["QSOB4"],
|
541
|
+
]:
|
542
|
+
if a_button is not None:
|
543
|
+
self.restore_button_color(a_button)
|
544
|
+
|
545
|
+
buttons_to_send = []
|
546
|
+
|
547
|
+
if self.pref.get("run_state"):
|
548
|
+
if self.current_widget == "callsign":
|
549
|
+
if len(self.callsign.text()) < 3:
|
550
|
+
self.make_button_green(self.esm_dict["CQ"])
|
551
|
+
buttons_to_send.append(self.esm_dict["CQ"])
|
552
|
+
elif len(self.callsign.text()) > 2:
|
553
|
+
self.make_button_green(self.esm_dict["HISCALL"])
|
554
|
+
self.make_button_green(self.esm_dict["EXCH"])
|
555
|
+
buttons_to_send.append(self.esm_dict["HISCALL"])
|
556
|
+
buttons_to_send.append(self.esm_dict["EXCH"])
|
557
|
+
|
558
|
+
elif self.current_widget in ["other_2"]:
|
559
|
+
if self.other_2.text() == "":
|
560
|
+
self.make_button_green(self.esm_dict["AGN"])
|
561
|
+
buttons_to_send.append(self.esm_dict["AGN"])
|
562
|
+
else:
|
563
|
+
self.make_button_green(self.esm_dict["QRZ"])
|
564
|
+
buttons_to_send.append(self.esm_dict["QRZ"])
|
565
|
+
buttons_to_send.append("LOGIT")
|
566
|
+
|
567
|
+
if with_enter is True and bool(len(buttons_to_send)):
|
568
|
+
for button in buttons_to_send:
|
569
|
+
if button:
|
570
|
+
if button == "LOGIT":
|
571
|
+
self.save_contact()
|
572
|
+
continue
|
573
|
+
self.process_function_key(button)
|
574
|
+
else:
|
575
|
+
if self.current_widget == "callsign":
|
576
|
+
if len(self.callsign.text()) > 2:
|
577
|
+
self.make_button_green(self.esm_dict["MYCALL"])
|
578
|
+
buttons_to_send.append(self.esm_dict["MYCALL"])
|
579
|
+
|
580
|
+
elif self.current_widget in ["other_2"]:
|
581
|
+
if self.other_2.text() == "":
|
582
|
+
self.make_button_green(self.esm_dict["AGN"])
|
583
|
+
buttons_to_send.append(self.esm_dict["AGN"])
|
584
|
+
else:
|
585
|
+
self.make_button_green(self.esm_dict["EXCH"])
|
586
|
+
buttons_to_send.append(self.esm_dict["EXCH"])
|
587
|
+
buttons_to_send.append("LOGIT")
|
588
|
+
|
589
|
+
if with_enter is True and bool(len(buttons_to_send)):
|
590
|
+
for button in buttons_to_send:
|
591
|
+
if button:
|
592
|
+
if button == "LOGIT":
|
593
|
+
self.save_contact()
|
594
|
+
continue
|
595
|
+
self.process_function_key(button)
|
596
|
+
|
597
|
+
|
598
|
+
def populate_history_info_line(self):
|
599
|
+
result = self.database.fetch_call_history(self.callsign.text())
|
600
|
+
if result:
|
601
|
+
self.history_info.setText(
|
602
|
+
f"{result.get('Call', '')}, {result.get('Name', '')}, {result.get('Loc1', '')}, {result.get('UserText','...')}"
|
603
|
+
)
|
604
|
+
else:
|
605
|
+
self.history_info.setText("")
|
606
|
+
|
607
|
+
|
608
|
+
def check_call_history(self):
|
609
|
+
""""""
|
610
|
+
result = self.database.fetch_call_history(self.callsign.text())
|
611
|
+
if result:
|
612
|
+
self.history_info.setText(f"{result.get('UserText','')}")
|
613
|
+
if self.other_2.text() == "":
|
614
|
+
self.other_2.setText(f"{result.get('Loc1', '')}")
|
615
|
+
|
616
|
+
|
617
|
+
# gridsquare
|
618
|
+
def get_mults(self):
|
619
|
+
""""""
|
620
|
+
|
621
|
+
mults = {}
|
622
|
+
mults["gridsquare"] = show_mults(self)
|
623
|
+
return mults
|
624
|
+
|
625
|
+
|
626
|
+
def just_points(self):
|
627
|
+
""""""
|
628
|
+
result = self.database.fetch_points()
|
629
|
+
if result is not None:
|
630
|
+
score = result.get("Points", "0")
|
631
|
+
if score is None:
|
632
|
+
score = "0"
|
633
|
+
return int(score)
|
634
|
+
return 0
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: not1mm
|
3
|
-
Version: 25.1.
|
3
|
+
Version: 25.1.27.1
|
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
|
@@ -46,22 +46,22 @@ Requires-Dist: Levenshtein
|
|
46
46
|

|
47
47
|
|
48
48
|
- [Not1MM](#not1mm)
|
49
|
-
- [What and
|
50
|
-
- [The
|
49
|
+
- [What and Why is Not1MM](#what-and-why-is-not1mm)
|
50
|
+
- [The Elephant in the Room](#the-elephant-in-the-room)
|
51
51
|
- [The What](#the-what)
|
52
52
|
- [Target Environment](#target-environment)
|
53
53
|
- [The Why](#the-why)
|
54
|
-
- [Current
|
55
|
-
- [Code
|
54
|
+
- [Current State](#current-state)
|
55
|
+
- [Code Maturity](#code-maturity)
|
56
56
|
- [Data and RTTY](#data-and-rtty)
|
57
|
-
- [Other not so
|
57
|
+
- [Other not so Supported Contests](#other-not-so-supported-contests)
|
58
58
|
- [Our Code Contributors ✨](#our-code-contributors-)
|
59
|
-
- [List of
|
60
|
-
- [Recent Changes
|
59
|
+
- [List of Should be Working Contests](#list-of-should-be-working-contests)
|
60
|
+
- [Recent Changes](#recent-changes)
|
61
61
|
- [Flatpak](#flatpak)
|
62
62
|
- [Installation](#installation)
|
63
63
|
- [Prerequisites](#prerequisites)
|
64
|
-
- [Common
|
64
|
+
- [Common Installation Recipes for Ubuntu and Fedora](#common-installation-recipes-for-ubuntu-and-fedora)
|
65
65
|
- [Ubuntu 22.04 LTS](#ubuntu-2204-lts)
|
66
66
|
- [Ubuntu 23.04](#ubuntu-2304)
|
67
67
|
- [Ubuntu 24.04 LTS](#ubuntu-2404-lts)
|
@@ -72,8 +72,8 @@ Requires-Dist: Levenshtein
|
|
72
72
|
- [Python, PyPI, pip and pipx](#python-pypi-pip-and-pipx)
|
73
73
|
- [Bootstrapping pipx](#bootstrapping-pipx)
|
74
74
|
- [Installing with pipx](#installing-with-pipx)
|
75
|
-
- [Installing from GitHub
|
76
|
-
- [After the
|
75
|
+
- [Installing from GitHub Source](#installing-from-github-source)
|
76
|
+
- [After the Install](#after-the-install)
|
77
77
|
- [You may or may not get a warning message like](#you-may-or-may-not-get-a-warning-message-like)
|
78
78
|
- [Or this fan favorite](#or-this-fan-favorite)
|
79
79
|
- [Update your CTY and SCP files](#update-your-cty-and-scp-files)
|
@@ -136,9 +136,9 @@ Requires-Dist: Levenshtein
|
|
136
136
|
- [The exchange](#the-exchange)
|
137
137
|
- [RAEM](#raem)
|
138
138
|
|
139
|
-
## What and
|
139
|
+
## What and Why is Not1MM
|
140
140
|
|
141
|
-
### The
|
141
|
+
### The Elephant in the Room
|
142
142
|
|
143
143
|
Not1MM's interface is a blatant ripoff of N1MM. It is NOT N1MM and any problem
|
144
144
|
you have with this software should in no way reflect on their software.
|
@@ -164,9 +164,9 @@ I'm a casual contester and could not find any contesting software for Linux that
|
|
164
164
|
I wanted to use. There is [Tucnak](http://tucnak.nagano.cz/) which is very robust
|
165
165
|
and mature. It just wasn't for me.
|
166
166
|
|
167
|
-
## Current
|
167
|
+
## Current State
|
168
168
|
|
169
|
-
### Code
|
169
|
+
### Code Maturity
|
170
170
|
|
171
171
|
The current state is "**BETA**".
|
172
172
|
|
@@ -183,7 +183,7 @@ Day and ARRL VHF. Found it works better if you don't use FlDigi for making the Q
|
|
183
183
|
Rather just using it as a RTTY modem and sending the text for it to send from Not1MM
|
184
184
|
using the function keys or ESM.
|
185
185
|
|
186
|
-
### Other not so
|
186
|
+
### Other not so Supported Contests
|
187
187
|
|
188
188
|
Of note, state QSO parties. I haven't worked any yet. And no one has submitted a PR
|
189
189
|
adding one... So there you go. In the near future I'll probably add California, guess
|
@@ -198,9 +198,9 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
|
|
198
198
|
<img src="https://contrib.rocks/image?repo=mbridak/not1mm" alt="Avatar icons for code contributors." />
|
199
199
|
</a>
|
200
200
|
|
201
|
-
## List of
|
201
|
+
## List of Should be Working Contests
|
202
202
|
|
203
|
-
- General Logging
|
203
|
+
- General Logging
|
204
204
|
- 10 10 Fall CW
|
205
205
|
- 10 10 Spring CW
|
206
206
|
- 10 10 Summer Phone
|
@@ -223,6 +223,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
|
|
223
223
|
- ICWC MST
|
224
224
|
- Japan International DX CW, SSB
|
225
225
|
- K1USN Slow Speed Test
|
226
|
+
- Labre RS Digi
|
226
227
|
- LZ DX
|
227
228
|
- NAQP CW, RTTY, SSB
|
228
229
|
- Phone Weekly Test
|
@@ -233,8 +234,10 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
|
|
233
234
|
- Weekly RTTY
|
234
235
|
- Winter Field Day
|
235
236
|
|
236
|
-
## Recent Changes
|
237
|
+
## Recent Changes
|
237
238
|
|
239
|
+
- [25-1-27-1] Add LABRE-RS Digi
|
240
|
+
- [25-1-27] Update pop up about updates...
|
238
241
|
- [25-1-26] Add macros for MARK, SPOT, WIPE, RUN, SANDP.
|
239
242
|
- [25-1-25-2] Add call history to REF CW and SSB.
|
240
243
|
- [25-1-25-1] Fix:ratewindow failed to change stats when contest changed.
|
@@ -267,7 +270,7 @@ Not1MM requires:
|
|
267
270
|
|
268
271
|
You should install these through your distribution's package manager before continuing.
|
269
272
|
|
270
|
-
### Common
|
273
|
+
### Common Installation Recipes for Ubuntu and Fedora
|
271
274
|
|
272
275
|
I've taken the time to install some common Linux distributions into a VM and
|
273
276
|
noted the minimum steps needed to install Not1MM.
|
@@ -405,7 +408,7 @@ pipx upgrade not1mm
|
|
405
408
|
<details>
|
406
409
|
<summary><b>Installing from GitHub source.</b></summary>
|
407
410
|
|
408
|
-
### Installing from GitHub
|
411
|
+
### Installing from GitHub Source
|
409
412
|
|
410
413
|
Since this is packaged for PyPI, if you want to work on your own source branch,
|
411
414
|
after cloning from github you would:
|
@@ -436,7 +439,7 @@ not1mm
|
|
436
439
|
|
437
440
|
</details>
|
438
441
|
|
439
|
-
## After the
|
442
|
+
## After the Install
|
440
443
|
|
441
444
|
You can now open a new terminal and type `not1mm`. On it's first run, it may or
|
442
445
|
may not install a lovely non AI generated icon, which you can later click on to
|
@@ -1,5 +1,5 @@
|
|
1
1
|
not1mm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2
|
-
not1mm/__main__.py,sha256=
|
2
|
+
not1mm/__main__.py,sha256=g0o9K_koq2alfJffLvSYAEB_jjRetCfy1ZyjsSe6-vw,147224
|
3
3
|
not1mm/bandmap.py,sha256=BpaR8ENrDJyyPBDeNiHrNYGPU6vRNMoCl2J8HBx4FtE,31137
|
4
4
|
not1mm/checkwindow.py,sha256=VFAcKYTcoWhmIf91chwY6tyao9FQMWPiUkgDDkkWaog,9670
|
5
5
|
not1mm/fsutils.py,sha256=ukHKxKTeNKxKwqRaJjtzRShL4X5Xl0jRBbADyy3Ifp8,1701
|
@@ -33,7 +33,7 @@ not1mm/data/k6gte.not1mm-64.png,sha256=6ku45Gq1g5ezh04F07osoKRtanb3e4kbx5XdIEh3N
|
|
33
33
|
not1mm/data/logwindow.ui,sha256=f7vULj96tHIQuR1nJMyvPHHcmVgzkhv9D1isyojsnFU,1458
|
34
34
|
not1mm/data/logwindowx.ui,sha256=CwpI-h7cI1yqyldH9quKftsdHL5lTyL9ABOcf80nfqc,1632
|
35
35
|
not1mm/data/main.ui,sha256=LEziByl_8nNTBYR0Z-6CgqDcMbsvQVgfWOfF-B9z3MQ,63537
|
36
|
-
not1mm/data/new_contest.ui,sha256=
|
36
|
+
not1mm/data/new_contest.ui,sha256=UQNSl28_PrtVA6to2uKBCZTa7LCOh5peGOmuxIWHBw8,24063
|
37
37
|
not1mm/data/not1mm.html,sha256=c9-mfjMwDt4f5pySUruz2gREW33CQ2_rCddM2z5CZQo,23273
|
38
38
|
not1mm/data/opon.ui,sha256=QDicqAk2lORG2UWsHa6jHlsGn6uzrrI2R4HSAocpPes,2258
|
39
39
|
not1mm/data/pickcontest.ui,sha256=4hPBszCglObThx_eIWtmK9CEcbr7WBjbB1rKZdI-o3I,1707
|
@@ -116,7 +116,7 @@ not1mm/lib/plugin_common.py,sha256=M5reDYM-v5IjAa2yTROvZTeTDkXYHb3U52W9mc9GxwA,1
|
|
116
116
|
not1mm/lib/select_contest.py,sha256=WsptLuwkouIHeocJL3oZ6-eUfEnhpwdc-x7eMZ_TIVM,359
|
117
117
|
not1mm/lib/settings.py,sha256=j5lIMLHJ-eqIaVr_QhI82gkbOl17_C-5suRkWbHYET8,14717
|
118
118
|
not1mm/lib/super_check_partial.py,sha256=hwT2NRwobu0PLDyw6ltmbmcAtGBD02CKGFbgGWjXMqA,2334
|
119
|
-
not1mm/lib/version.py,sha256=
|
119
|
+
not1mm/lib/version.py,sha256=vfggR4aagLgq0Z-62g_sIFuPURJDRsfYYSPS1gT0eMc,50
|
120
120
|
not1mm/lib/versiontest.py,sha256=8vDNptuBBunn-1IGkjNaquehqBYUJyjrPSF8Igmd4_Y,1286
|
121
121
|
not1mm/plugins/10_10_fall_cw.py,sha256=5QUyGMvGBC-HxcY_z9QbfuxSg3f7p6C9K4qhTxgZE7k,14719
|
122
122
|
not1mm/plugins/10_10_spring_cw.py,sha256=XjYFM263WYyG6nVQzPObW4YC7Z9L93rixSOcVsxPvH4,14722
|
@@ -154,6 +154,7 @@ not1mm/plugins/icwc_mst.py,sha256=XfaIRIj0BxWvpWk2nmy_dMseVuKVOh-_m3UcIGOy6wI,16
|
|
154
154
|
not1mm/plugins/jidx_cw.py,sha256=gSScw21ac2Rpdd7jspgh5gnH9JdiR8h3YOa-41B_T94,15881
|
155
155
|
not1mm/plugins/jidx_ph.py,sha256=0E5xHs0WXh-x2Z6UC2PGqmLdIkn-jWbENOeLopr7rys,14830
|
156
156
|
not1mm/plugins/k1usn_sst.py,sha256=WfRF-emC52IIjOEddGmEQ_gWlMqoBbhCQ7S56nAZ4M8,17134
|
157
|
+
not1mm/plugins/labre_rs_digi.py,sha256=ueytVNrg2mkTEouq9dkWI90EZMgtDLCZ1TWNeXB-iyA,19975
|
157
158
|
not1mm/plugins/lz-dx.py,sha256=HLU7FopHryEHPtAH2-mopeWSY6E_uwNgh8_sM27E2F0,19824
|
158
159
|
not1mm/plugins/naqp_cw.py,sha256=Aq9bRn9uRm6PXd1WVckZJ4GTbiBcPFnPRQAydEVmeAs,18897
|
159
160
|
not1mm/plugins/naqp_rtty.py,sha256=JbjsY9DvVexXdzoPE4k9zSmcYNEMQpB9lrxdRxl_ldc,22639
|
@@ -165,9 +166,9 @@ not1mm/plugins/ref_ssb.py,sha256=Z_XmMpYKcI5dZh4TQqvQDcz-cLpMzpDEKBnb5iHeBLQ,215
|
|
165
166
|
not1mm/plugins/stew_perry_topband.py,sha256=D1hekmMbx-i4BhaP2uzOK3OzaVVMMdgcN3RmfweNqHo,15341
|
166
167
|
not1mm/plugins/weekly_rtty.py,sha256=rdlIrsxBeuj-RQc5OStVNF7sGCtBK5t6inN5Z7DI4tw,20066
|
167
168
|
not1mm/plugins/winter_field_day.py,sha256=JK4r1vfxs7aADR7ZYbjZniz3f5s3_ipSQDZ0GRNWC7I,15222
|
168
|
-
not1mm-25.1.
|
169
|
-
not1mm-25.1.
|
170
|
-
not1mm-25.1.
|
171
|
-
not1mm-25.1.
|
172
|
-
not1mm-25.1.
|
173
|
-
not1mm-25.1.
|
169
|
+
not1mm-25.1.27.1.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
170
|
+
not1mm-25.1.27.1.dist-info/METADATA,sha256=Y28G2qoTsLkqDuE4h-BWmfZBZd9mhQFDQ9ex9gBw7b8,36037
|
171
|
+
not1mm-25.1.27.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
172
|
+
not1mm-25.1.27.1.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
|
173
|
+
not1mm-25.1.27.1.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
|
174
|
+
not1mm-25.1.27.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|