not1mm 23.4.13__tar.gz → 23.4.18__tar.gz
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-23.4.13 → not1mm-23.4.18}/PKG-INFO +46 -22
- {not1mm-23.4.13 → not1mm-23.4.18}/README.md +44 -20
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/__main__.py +115 -15
- not1mm-23.4.18/not1mm/data/alpha bravo charlie delta.txt +4 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/configuration.ui +64 -10
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/main.ui +48 -3
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/new_contest.ui +16 -1
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/settings.ui +1 -1
- not1mm-23.4.18/not1mm/data/ssbmacros.txt +24 -0
- not1mm-23.4.18/not1mm/lib/version.py +2 -0
- not1mm-23.4.18/not1mm/test.py +55 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm.egg-info/PKG-INFO +46 -22
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm.egg-info/SOURCES.txt +2 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm.egg-info/requires.txt +2 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/pyproject.toml +4 -2
- not1mm-23.4.13/not1mm/lib/version.py +0 -2
- not1mm-23.4.13/not1mm/test.py +0 -130
- {not1mm-23.4.13 → not1mm-23.4.18}/LICENSE +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/__init__.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/Combinear.qss +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/JetBrainsMono-Regular.ttf +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/MASTER.SCP +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/about.ui +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/check.png +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/contests.sql +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/cty.json +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/cwmacros.txt +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/editcontact.ui +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/editmacro.ui +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/greendot.png +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/k6gte-not1mm.desktop +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/k6gte.not1mm-128.png +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/k6gte.not1mm-32.png +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/k6gte.not1mm-64.png +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/logwindow.ui +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/opon.ui +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/pickcontest.ui +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/data/reddot.png +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/__init__.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/about.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/cat_interface.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/cwinterface.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/database.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/edit_contact.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/edit_macro.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/edit_opon.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/edit_station.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/ham_utility.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/lookup.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/multicast.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/n1mm.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/new_contest.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/select_contest.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/lib/settings.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/logwindow.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/__init__.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/arrl_dx_cw.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/arrl_dx_phone.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/arrl_field_day.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/arrl_rtty_ru.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/arrl_ss_cw.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/arrl_ss_phone.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/cq_wpx_cw.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/cq_wpx_ssb.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/cq_ww_cw.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/cq_ww_ssb.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/general_logging.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/jidx_cw.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/jidx_ph.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/plugins/winter_field_day.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm/testing/test.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm.egg-info/dependency_links.txt +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm.egg-info/entry_points.txt +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/not1mm.egg-info/top_level.txt +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/setup.cfg +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/testing/test.py +0 -0
- {not1mm-23.4.13 → not1mm-23.4.18}/testing/text2.py +0 -0
@@ -1,12 +1,12 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: not1mm
|
3
|
-
Version: 23.4.
|
3
|
+
Version: 23.4.18
|
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
|
7
7
|
Project-URL: Bug Tracker, https://github.com/mbridak/not1mm/issues
|
8
8
|
Classifier: Programming Language :: Python :: 3
|
9
|
-
Classifier: Development Status ::
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
10
10
|
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
11
11
|
Classifier: Environment :: X11 Applications :: Qt
|
12
12
|
Classifier: Operating System :: POSIX :: Linux
|
@@ -43,11 +43,16 @@ License-File: LICENSE
|
|
43
43
|
- [Revisiting an old friend](#revisiting-an-old-friend)
|
44
44
|
- [Station Settings dialog](#station-settings-dialog)
|
45
45
|
- [Changing station information](#changing-station-information)
|
46
|
-
- [Adding a contest](#adding-a-contest)
|
47
|
-
- [Selecting an
|
46
|
+
- [Adding a contest to the current dababase](#adding-a-contest-to-the-current-dababase)
|
47
|
+
- [Selecting an existing contest as the current contest](#selecting-an-existing-contest-as-the-current-contest)
|
48
48
|
- [Configuration Settings](#configuration-settings)
|
49
|
+
- [Lookup](#lookup)
|
50
|
+
- [CAT](#cat)
|
51
|
+
- [CW Keyer interface](#cw-keyer-interface)
|
49
52
|
- [Hiding screen elements](#hiding-screen-elements)
|
50
53
|
- [Editing macro keys](#editing-macro-keys)
|
54
|
+
- [Macro substitutions](#macro-substitutions)
|
55
|
+
- [Macro use with voice](#macro-use-with-voice)
|
51
56
|
- [cty.dat and QRZ lookups for distance and bearing](#ctydat-and-qrz-lookups-for-distance-and-bearing)
|
52
57
|
- [Other uses for the call field](#other-uses-for-the-call-field)
|
53
58
|
- [Log Display](#log-display)
|
@@ -56,8 +61,6 @@ License-File: LICENSE
|
|
56
61
|
- [Cabrillo](#cabrillo)
|
57
62
|
- [ADIF](#adif)
|
58
63
|
- [Dupe checking](#dupe-checking)
|
59
|
-
- [CAT](#cat)
|
60
|
-
- [CW Keyer interface](#cw-keyer-interface)
|
61
64
|
|
62
65
|
## What and why is Not1MM
|
63
66
|
|
@@ -96,6 +99,8 @@ Feature complete. I'm only one guy, and I'm not what you'd consider to be a cont
|
|
96
99
|
|
97
100
|
## Changes of note
|
98
101
|
|
102
|
+
- [23-4-18] Added voice keying. Fixed a bunch of crashes.
|
103
|
+
- [23-4-15] Corrected tabstops on new contest screen. Changed project state to BETA.
|
99
104
|
- [23-4-12] Dynamic log window columns. Reload settings after changes saved. Altered JIDX displayed log columns.
|
100
105
|
- [23-4-11] Add about dialog. Fix crash when previous working DB is erased. Add CQ WW CW and SSB. When entering station settings, after entering callsign and grid, the cqzone, ituzone, country, latitude and longitude will auto fill.
|
101
106
|
- [23-4-10] Added Configure Settings dialog. Added CW keyer and CAT control settings to Configure Settings dialog.
|
@@ -174,7 +179,7 @@ not1mm
|
|
174
179
|
|
175
180
|
### Data
|
176
181
|
|
177
|
-
If your system has an `XDG_DATA_HOME` environment variable set, the
|
182
|
+
If your system has an `XDG_DATA_HOME` environment variable set, the database and CW macro files can be found there. Otherwise they will be found at `yourhome/.local/share/not1mm`
|
178
183
|
|
179
184
|
### Config
|
180
185
|
|
@@ -196,7 +201,7 @@ You can create a new database by selecting `File` > `New Database` from the main
|
|
196
201
|
|
197
202
|
### Revisiting an old friend
|
198
203
|
|
199
|
-
You can select previously created databases by selecting `File` > `Open Database`.
|
204
|
+
You can select a previously created databases for use by selecting `File` > `Open Database`.
|
200
205
|
|
201
206
|
## Station Settings dialog
|
202
207
|
|
@@ -214,13 +219,13 @@ You can fill. You can fill. Everyone look at your keys.
|
|
214
219
|
|
215
220
|
Station information can be changed any time by going to `File` > `Station Settings` and editing the information.
|
216
221
|
|
217
|
-
## Adding a contest
|
222
|
+
## Adding a contest to the current dababase
|
218
223
|
|
219
224
|
Select `File` > `New Contest`
|
220
225
|
|
221
226
|

|
222
227
|
|
223
|
-
## Selecting an
|
228
|
+
## Selecting an existing contest as the current contest
|
224
229
|
|
225
230
|
Select `File` > `Open Contest`
|
226
231
|
|
@@ -228,10 +233,25 @@ Select `File` > `Open Contest`
|
|
228
233
|
|
229
234
|
## Configuration Settings
|
230
235
|
|
231
|
-
|
236
|
+
To setup your CAT control, CW keyer, Callsign lookups, select `File` > `Configuration Settings`
|
237
|
+
|
238
|
+
The tabs for cloudlog, groups and n1mm are disabled and are for future expansion.
|
232
239
|
|
233
240
|

|
234
241
|
|
242
|
+
### Lookup
|
243
|
+
|
244
|
+
For callsign lookup, several services are supported. QRZ, HamQTH and HamDB. If your service of choice requires a username and password, Enter it here.
|
245
|
+
|
246
|
+
### CAT
|
247
|
+
|
248
|
+
Under the `CAT` TAB, you can choose either `rigctld` normally with an IP of `127.0.0.1` and a port of `4532`. Or `flrig`, IP normally of `127.0.0.1` and a port of `12345`. `None` is always an option, but is it really?
|
249
|
+
|
250
|
+
### CW Keyer interface
|
251
|
+
|
252
|
+
Under the `CW` TAB, There are three options. `cwdaemon`, which normally uses IP `127.0.0.1` and port `6789`. `pywinkeyer` which normally uses IP `127.0.0.1` and port `8000`. Or `None`, if you want to Morse it like it's 1899.
|
253
|
+
|
254
|
+
|
235
255
|
## Hiding screen elements
|
236
256
|
|
237
257
|
You can show or hide certain buttons/indicators by checking and unchecking their boxes under the view menu. You can then resize the screen to make it more compact.
|
@@ -242,15 +262,27 @@ The your choices will be remembered when you relaunch the program.
|
|
242
262
|
|
243
263
|
## Editing macro keys
|
244
264
|
|
245
|
-
To edit the
|
265
|
+
To edit the macros, choose `File` > `Edit Macros`. This will open your systems registered text editor with current macros loaded. When your done just save the file and close the editor. The file loaded to edit will be determined by your current operating mode.
|
266
|
+
|
267
|
+
### Macro substitutions
|
246
268
|
|
247
269
|
You can include a limited set of substitution instructions.
|
248
270
|
|
249
271
|
- {MYCALL} Sends the station call.
|
250
272
|
- {HISCALL} Send what's in the callsign field.
|
251
|
-
- {SNT} Sends 5nn
|
273
|
+
- {SNT} Sends 5nn (cw) or 599 (ssb)
|
252
274
|
- {SENTNR} Sends whats in the SentNR field.
|
253
275
|
|
276
|
+
### Macro use with voice
|
277
|
+
|
278
|
+
The macros when used with voice, will also accept filenames of WAV files to play, excluding the file extension. The filename must be enclosed by brackets. For example `[CQ]` will play `cq.wav`, `[again]` will play `again.wav`. The wav files are stored in the operators personal data directory. The filenames must be in lowercase. See [Various data file locations](#various-data-file-locations) above for the location of your data files. For me, the macro `[cq]` will play `/home/mbridak/.local/share/not1mm/K6GTE/cq.wav`
|
279
|
+
|
280
|
+
The current wav files in place are not the ones you will want to use. They sound like some little kid. You can use something like Audacity to record new wav files in your own voice.
|
281
|
+
|
282
|
+
Aside from the `[filename]` wav files, there are also NATO phonetic wav files for each letter and number. So if your macro key holds `{HISCALL} {SNT} {SENTNR}` and you have entered K5TUX in callsign field during CQ WW SSB while in CQ Zone 3. You'll here Kilo 5 Tango Uniform X-ray, 5 9 9, 3. Hopefully not in a little kids voice.
|
283
|
+
|
284
|
+
Right now, the sound is played out of the default sound device. This is NOT what we want. I still have to code up the dialog to choose the correct sound device to use.
|
285
|
+
|
254
286
|
## cty.dat and QRZ lookups for distance and bearing
|
255
287
|
|
256
288
|
When a callsign is entered, a look up is first done in a cty.dat file to determin the country of origin, geographic center, cq zone and ITU region. Great circle calculations are done to determin the heading and distance from your gridsquare to the grographic center. This information then displayed at the bottom left.
|
@@ -275,7 +307,7 @@ The Log display gets updated automatically when a contact is entered. The top ha
|
|
275
307
|
|
276
308
|

|
277
309
|
|
278
|
-
The bottom half of the log displays contacts sorted by what's currently in the call entry field.
|
310
|
+
The bottom half of the log displays contacts sorted by what's currently in the call entry field. The columns displayed in the log window are dependant on what contests is currently active.
|
279
311
|
|
280
312
|
## Editing a contact
|
281
313
|
|
@@ -316,11 +348,3 @@ Boom... ADIF
|
|
316
348
|
## Dupe checking
|
317
349
|
|
318
350
|
Added dupe checking. Big Red 'Dupe' will appear if it's a dupe...
|
319
|
-
|
320
|
-
## CAT
|
321
|
-
|
322
|
-
Go to `File` > `Configuration Settings`, You will find a `CAT` TAB. You can choose either `rigctld` normally with an IP of `127.0.0.1` and a port of `4532`. Or `flrig`, IP normally of `127.0.0.1` and a port of `12345`. `None` is always an option, but is it really?
|
323
|
-
|
324
|
-
## CW Keyer interface
|
325
|
-
|
326
|
-
Go to `File` > `Configuration Settings`, You will find a `CW` TAB. There are three options. `cwdaemon`, IP `127.0.0.1`, port `6789`. `pywinkeyer`, IP `127.0.0.1`, port `8000`. And `None` if you want to Morse it like it's 1899.
|
@@ -24,11 +24,16 @@
|
|
24
24
|
- [Revisiting an old friend](#revisiting-an-old-friend)
|
25
25
|
- [Station Settings dialog](#station-settings-dialog)
|
26
26
|
- [Changing station information](#changing-station-information)
|
27
|
-
- [Adding a contest](#adding-a-contest)
|
28
|
-
- [Selecting an
|
27
|
+
- [Adding a contest to the current dababase](#adding-a-contest-to-the-current-dababase)
|
28
|
+
- [Selecting an existing contest as the current contest](#selecting-an-existing-contest-as-the-current-contest)
|
29
29
|
- [Configuration Settings](#configuration-settings)
|
30
|
+
- [Lookup](#lookup)
|
31
|
+
- [CAT](#cat)
|
32
|
+
- [CW Keyer interface](#cw-keyer-interface)
|
30
33
|
- [Hiding screen elements](#hiding-screen-elements)
|
31
34
|
- [Editing macro keys](#editing-macro-keys)
|
35
|
+
- [Macro substitutions](#macro-substitutions)
|
36
|
+
- [Macro use with voice](#macro-use-with-voice)
|
32
37
|
- [cty.dat and QRZ lookups for distance and bearing](#ctydat-and-qrz-lookups-for-distance-and-bearing)
|
33
38
|
- [Other uses for the call field](#other-uses-for-the-call-field)
|
34
39
|
- [Log Display](#log-display)
|
@@ -37,8 +42,6 @@
|
|
37
42
|
- [Cabrillo](#cabrillo)
|
38
43
|
- [ADIF](#adif)
|
39
44
|
- [Dupe checking](#dupe-checking)
|
40
|
-
- [CAT](#cat)
|
41
|
-
- [CW Keyer interface](#cw-keyer-interface)
|
42
45
|
|
43
46
|
## What and why is Not1MM
|
44
47
|
|
@@ -77,6 +80,8 @@ Feature complete. I'm only one guy, and I'm not what you'd consider to be a cont
|
|
77
80
|
|
78
81
|
## Changes of note
|
79
82
|
|
83
|
+
- [23-4-18] Added voice keying. Fixed a bunch of crashes.
|
84
|
+
- [23-4-15] Corrected tabstops on new contest screen. Changed project state to BETA.
|
80
85
|
- [23-4-12] Dynamic log window columns. Reload settings after changes saved. Altered JIDX displayed log columns.
|
81
86
|
- [23-4-11] Add about dialog. Fix crash when previous working DB is erased. Add CQ WW CW and SSB. When entering station settings, after entering callsign and grid, the cqzone, ituzone, country, latitude and longitude will auto fill.
|
82
87
|
- [23-4-10] Added Configure Settings dialog. Added CW keyer and CAT control settings to Configure Settings dialog.
|
@@ -155,7 +160,7 @@ not1mm
|
|
155
160
|
|
156
161
|
### Data
|
157
162
|
|
158
|
-
If your system has an `XDG_DATA_HOME` environment variable set, the
|
163
|
+
If your system has an `XDG_DATA_HOME` environment variable set, the database and CW macro files can be found there. Otherwise they will be found at `yourhome/.local/share/not1mm`
|
159
164
|
|
160
165
|
### Config
|
161
166
|
|
@@ -177,7 +182,7 @@ You can create a new database by selecting `File` > `New Database` from the main
|
|
177
182
|
|
178
183
|
### Revisiting an old friend
|
179
184
|
|
180
|
-
You can select previously created databases by selecting `File` > `Open Database`.
|
185
|
+
You can select a previously created databases for use by selecting `File` > `Open Database`.
|
181
186
|
|
182
187
|
## Station Settings dialog
|
183
188
|
|
@@ -195,13 +200,13 @@ You can fill. You can fill. Everyone look at your keys.
|
|
195
200
|
|
196
201
|
Station information can be changed any time by going to `File` > `Station Settings` and editing the information.
|
197
202
|
|
198
|
-
## Adding a contest
|
203
|
+
## Adding a contest to the current dababase
|
199
204
|
|
200
205
|
Select `File` > `New Contest`
|
201
206
|
|
202
207
|

|
203
208
|
|
204
|
-
## Selecting an
|
209
|
+
## Selecting an existing contest as the current contest
|
205
210
|
|
206
211
|
Select `File` > `Open Contest`
|
207
212
|
|
@@ -209,10 +214,25 @@ Select `File` > `Open Contest`
|
|
209
214
|
|
210
215
|
## Configuration Settings
|
211
216
|
|
212
|
-
|
217
|
+
To setup your CAT control, CW keyer, Callsign lookups, select `File` > `Configuration Settings`
|
218
|
+
|
219
|
+
The tabs for cloudlog, groups and n1mm are disabled and are for future expansion.
|
213
220
|
|
214
221
|

|
215
222
|
|
223
|
+
### Lookup
|
224
|
+
|
225
|
+
For callsign lookup, several services are supported. QRZ, HamQTH and HamDB. If your service of choice requires a username and password, Enter it here.
|
226
|
+
|
227
|
+
### CAT
|
228
|
+
|
229
|
+
Under the `CAT` TAB, you can choose either `rigctld` normally with an IP of `127.0.0.1` and a port of `4532`. Or `flrig`, IP normally of `127.0.0.1` and a port of `12345`. `None` is always an option, but is it really?
|
230
|
+
|
231
|
+
### CW Keyer interface
|
232
|
+
|
233
|
+
Under the `CW` TAB, There are three options. `cwdaemon`, which normally uses IP `127.0.0.1` and port `6789`. `pywinkeyer` which normally uses IP `127.0.0.1` and port `8000`. Or `None`, if you want to Morse it like it's 1899.
|
234
|
+
|
235
|
+
|
216
236
|
## Hiding screen elements
|
217
237
|
|
218
238
|
You can show or hide certain buttons/indicators by checking and unchecking their boxes under the view menu. You can then resize the screen to make it more compact.
|
@@ -223,15 +243,27 @@ The your choices will be remembered when you relaunch the program.
|
|
223
243
|
|
224
244
|
## Editing macro keys
|
225
245
|
|
226
|
-
To edit the
|
246
|
+
To edit the macros, choose `File` > `Edit Macros`. This will open your systems registered text editor with current macros loaded. When your done just save the file and close the editor. The file loaded to edit will be determined by your current operating mode.
|
247
|
+
|
248
|
+
### Macro substitutions
|
227
249
|
|
228
250
|
You can include a limited set of substitution instructions.
|
229
251
|
|
230
252
|
- {MYCALL} Sends the station call.
|
231
253
|
- {HISCALL} Send what's in the callsign field.
|
232
|
-
- {SNT} Sends 5nn
|
254
|
+
- {SNT} Sends 5nn (cw) or 599 (ssb)
|
233
255
|
- {SENTNR} Sends whats in the SentNR field.
|
234
256
|
|
257
|
+
### Macro use with voice
|
258
|
+
|
259
|
+
The macros when used with voice, will also accept filenames of WAV files to play, excluding the file extension. The filename must be enclosed by brackets. For example `[CQ]` will play `cq.wav`, `[again]` will play `again.wav`. The wav files are stored in the operators personal data directory. The filenames must be in lowercase. See [Various data file locations](#various-data-file-locations) above for the location of your data files. For me, the macro `[cq]` will play `/home/mbridak/.local/share/not1mm/K6GTE/cq.wav`
|
260
|
+
|
261
|
+
The current wav files in place are not the ones you will want to use. They sound like some little kid. You can use something like Audacity to record new wav files in your own voice.
|
262
|
+
|
263
|
+
Aside from the `[filename]` wav files, there are also NATO phonetic wav files for each letter and number. So if your macro key holds `{HISCALL} {SNT} {SENTNR}` and you have entered K5TUX in callsign field during CQ WW SSB while in CQ Zone 3. You'll here Kilo 5 Tango Uniform X-ray, 5 9 9, 3. Hopefully not in a little kids voice.
|
264
|
+
|
265
|
+
Right now, the sound is played out of the default sound device. This is NOT what we want. I still have to code up the dialog to choose the correct sound device to use.
|
266
|
+
|
235
267
|
## cty.dat and QRZ lookups for distance and bearing
|
236
268
|
|
237
269
|
When a callsign is entered, a look up is first done in a cty.dat file to determin the country of origin, geographic center, cq zone and ITU region. Great circle calculations are done to determin the heading and distance from your gridsquare to the grographic center. This information then displayed at the bottom left.
|
@@ -256,7 +288,7 @@ The Log display gets updated automatically when a contact is entered. The top ha
|
|
256
288
|
|
257
289
|

|
258
290
|
|
259
|
-
The bottom half of the log displays contacts sorted by what's currently in the call entry field.
|
291
|
+
The bottom half of the log displays contacts sorted by what's currently in the call entry field. The columns displayed in the log window are dependant on what contests is currently active.
|
260
292
|
|
261
293
|
## Editing a contact
|
262
294
|
|
@@ -297,11 +329,3 @@ Boom... ADIF
|
|
297
329
|
## Dupe checking
|
298
330
|
|
299
331
|
Added dupe checking. Big Red 'Dupe' will appear if it's a dupe...
|
300
|
-
|
301
|
-
## CAT
|
302
|
-
|
303
|
-
Go to `File` > `Configuration Settings`, You will find a `CAT` TAB. You can choose either `rigctld` normally with an IP of `127.0.0.1` and a port of `4532`. Or `flrig`, IP normally of `127.0.0.1` and a port of `12345`. `None` is always an option, but is it really?
|
304
|
-
|
305
|
-
## CW Keyer interface
|
306
|
-
|
307
|
-
Go to `File` > `Configuration Settings`, You will find a `CW` TAB. There are three options. `cwdaemon`, IP `127.0.0.1`, port `6789`. `pywinkeyer`, IP `127.0.0.1`, port `8000`. And `None` if you want to Morse it like it's 1899.
|
@@ -29,6 +29,8 @@ from PyQt5.QtWidgets import QFileDialog
|
|
29
29
|
from PyQt5.QtCore import QPoint # pylint: disable=no-name-in-module
|
30
30
|
from PyQt5.QtCore import QDir, QRect, QSize, Qt
|
31
31
|
from PyQt5.QtGui import QFontDatabase # pylint: disable=no-name-in-module
|
32
|
+
import sounddevice as sd
|
33
|
+
import soundfile as sf
|
32
34
|
|
33
35
|
from not1mm.lib.about import About
|
34
36
|
from not1mm.lib.cat_interface import CAT
|
@@ -220,7 +222,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
220
222
|
self.actionNew_Database.triggered.connect(self.new_database)
|
221
223
|
self.actionOpen_Database.triggered.connect(self.open_database)
|
222
224
|
|
223
|
-
self.
|
225
|
+
self.actionEdit_Macros.triggered.connect(self.edit_cw_macros)
|
224
226
|
|
225
227
|
self.actionAbout.triggered.connect(self.show_about_dialog)
|
226
228
|
|
@@ -290,6 +292,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
290
292
|
self.station = {}
|
291
293
|
self.contact = self.database.empty_contact
|
292
294
|
self.current_op = self.station.get("Call", "")
|
295
|
+
self.make_op_dir()
|
293
296
|
if self.pref.get("contest"):
|
294
297
|
self.load_contest()
|
295
298
|
|
@@ -379,6 +382,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
379
382
|
if self.station is None:
|
380
383
|
self.station = {}
|
381
384
|
self.current_op = self.station.get("Call", "")
|
385
|
+
self.make_op_dir()
|
382
386
|
cmd = {}
|
383
387
|
cmd["cmd"] = "NEWDB"
|
384
388
|
self.multicast_interface.send_as_json(cmd)
|
@@ -400,6 +404,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
400
404
|
if self.station.get("Call", "") == "":
|
401
405
|
self.edit_station_settings()
|
402
406
|
self.current_op = self.station.get("Call", "")
|
407
|
+
self.make_op_dir()
|
403
408
|
cmd = {}
|
404
409
|
cmd["cmd"] = "NEWDB"
|
405
410
|
self.multicast_interface.send_as_json(cmd)
|
@@ -732,8 +737,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
732
737
|
"""Clears the text input fields and sets focus to callsign field."""
|
733
738
|
self.dupe_indicator.hide()
|
734
739
|
self.contact = self.database.empty_contact
|
735
|
-
self.heading_distance.setText("
|
736
|
-
self.dx_entity.setText("
|
740
|
+
self.heading_distance.setText("")
|
741
|
+
self.dx_entity.setText("")
|
737
742
|
if self.contest:
|
738
743
|
mults = self.contest.show_mults(self)
|
739
744
|
qsos = self.contest.show_qso(self)
|
@@ -955,6 +960,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
955
960
|
self.settings_dialog.close()
|
956
961
|
if self.current_op == "":
|
957
962
|
self.current_op = self.station.get("Call", "")
|
963
|
+
self.make_op_dir()
|
958
964
|
contest_count = self.database.fetch_all_contests()
|
959
965
|
if len(contest_count) == 0:
|
960
966
|
self.new_contest_dialog()
|
@@ -1040,15 +1046,48 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1040
1046
|
def process_macro(self, macro: str) -> str:
|
1041
1047
|
"""Process CW macro substitutions"""
|
1042
1048
|
macro = macro.upper()
|
1043
|
-
macro = macro.replace("{MYCALL}", self.station.get("Call"))
|
1049
|
+
macro = macro.replace("{MYCALL}", self.station.get("Call", ""))
|
1044
1050
|
macro = macro.replace("{HISCALL}", self.callsign.text())
|
1045
|
-
|
1051
|
+
if self.radio_state.get("mode") == "CW":
|
1052
|
+
macro = macro.replace("{SNT}", self.sent.text().replace("9", "n"))
|
1053
|
+
else:
|
1054
|
+
macro = macro.replace("{SNT}", self.sent.text())
|
1046
1055
|
macro = macro.replace("{SENTNR}", self.other_1.text())
|
1047
1056
|
return macro
|
1048
1057
|
|
1058
|
+
def voice_string(self, the_string: str) -> None:
|
1059
|
+
"""voices string using nato phonetics"""
|
1060
|
+
logger.debug("Voicing: %s", the_string)
|
1061
|
+
op_path = Path(DATA_PATH) / self.current_op
|
1062
|
+
if "[" in the_string:
|
1063
|
+
sub_string = the_string.strip("[]").lower()
|
1064
|
+
filename = f"{str(op_path)}/{sub_string}.wav"
|
1065
|
+
if Path(filename).is_file():
|
1066
|
+
logger.debug("Voicing: %s", filename)
|
1067
|
+
data, fs = sf.read(filename, dtype="float32")
|
1068
|
+
|
1069
|
+
sd.play(data, fs)
|
1070
|
+
_status = sd.wait()
|
1071
|
+
return
|
1072
|
+
|
1073
|
+
for letter in the_string.lower():
|
1074
|
+
if letter in "abcdefghijklmnopqrstuvwxyz 1234567890":
|
1075
|
+
if letter == " ":
|
1076
|
+
letter = "space"
|
1077
|
+
filename = f"{str(op_path)}/{letter}.wav"
|
1078
|
+
if Path(filename).is_file():
|
1079
|
+
logger.debug("Voicing: %s", filename)
|
1080
|
+
data, fs = sf.read(filename, dtype="float32")
|
1081
|
+
|
1082
|
+
sd.play(data, fs)
|
1083
|
+
_status = sd.wait()
|
1084
|
+
|
1049
1085
|
def sendf1(self):
|
1050
1086
|
"""stub"""
|
1051
1087
|
logger.debug("F1 Clicked")
|
1088
|
+
if self.radio_state.get("mode") in ["USB", "SSB"]:
|
1089
|
+
self.voice_string(self.process_macro(self.F1.toolTip()))
|
1090
|
+
return
|
1052
1091
|
if self.cw:
|
1053
1092
|
# if self.preference.get("send_n1mm_packets"):
|
1054
1093
|
# self.n1mm.radio_info["FunctionKeyCaption"] = self.F1.text()
|
@@ -1057,66 +1096,99 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1057
1096
|
def sendf2(self):
|
1058
1097
|
"""stub"""
|
1059
1098
|
logger.debug("F2 Clicked")
|
1099
|
+
if self.radio_state.get("mode") in ["USB", "SSB"]:
|
1100
|
+
self.voice_string(self.process_macro(self.F2.toolTip()))
|
1101
|
+
return
|
1060
1102
|
if self.cw:
|
1061
1103
|
self.cw.sendcw(self.process_macro(self.F2.toolTip()))
|
1062
1104
|
|
1063
1105
|
def sendf3(self):
|
1064
1106
|
"""stub"""
|
1065
1107
|
logger.debug("F3 Clicked")
|
1108
|
+
if self.radio_state.get("mode") in ["USB", "SSB"]:
|
1109
|
+
self.voice_string(self.process_macro(self.F3.toolTip()))
|
1110
|
+
return
|
1066
1111
|
if self.cw:
|
1067
1112
|
self.cw.sendcw(self.process_macro(self.F3.toolTip()))
|
1068
1113
|
|
1069
1114
|
def sendf4(self):
|
1070
1115
|
"""stub"""
|
1071
1116
|
logger.debug("F4 Clicked")
|
1117
|
+
if self.radio_state.get("mode") in ["USB", "SSB"]:
|
1118
|
+
self.voice_string(self.process_macro(self.F4.toolTip()))
|
1119
|
+
return
|
1072
1120
|
if self.cw:
|
1073
1121
|
self.cw.sendcw(self.process_macro(self.F4.toolTip()))
|
1074
1122
|
|
1075
1123
|
def sendf5(self):
|
1076
1124
|
"""stub"""
|
1077
1125
|
logger.debug("F5 Clicked")
|
1126
|
+
if self.radio_state.get("mode") in ["USB", "SSB"]:
|
1127
|
+
self.voice_string(self.process_macro(self.F5.toolTip()))
|
1128
|
+
return
|
1078
1129
|
if self.cw:
|
1079
1130
|
self.cw.sendcw(self.process_macro(self.F5.toolTip()))
|
1080
1131
|
|
1081
1132
|
def sendf6(self):
|
1082
1133
|
"""stub"""
|
1083
1134
|
logger.debug("F6 Clicked")
|
1135
|
+
if self.radio_state.get("mode") in ["USB", "SSB"]:
|
1136
|
+
self.voice_string(self.process_macro(self.F6.toolTip()))
|
1137
|
+
return
|
1084
1138
|
if self.cw:
|
1085
1139
|
self.cw.sendcw(self.process_macro(self.F6.toolTip()))
|
1086
1140
|
|
1087
1141
|
def sendf7(self):
|
1088
1142
|
"""stub"""
|
1089
1143
|
logger.debug("F7 Clicked")
|
1144
|
+
if self.radio_state.get("mode") in ["USB", "SSB"]:
|
1145
|
+
self.voice_string(self.process_macro(self.F7.toolTip()))
|
1146
|
+
return
|
1090
1147
|
if self.cw:
|
1091
1148
|
self.cw.sendcw(self.process_macro(self.F7.toolTip()))
|
1092
1149
|
|
1093
1150
|
def sendf8(self):
|
1094
1151
|
"""stub"""
|
1095
1152
|
logger.debug("F8 Clicked")
|
1153
|
+
if self.radio_state.get("mode") in ["USB", "SSB"]:
|
1154
|
+
self.voice_string(self.process_macro(self.F8.toolTip()))
|
1155
|
+
return
|
1096
1156
|
if self.cw:
|
1097
1157
|
self.cw.sendcw(self.process_macro(self.F8.toolTip()))
|
1098
1158
|
|
1099
1159
|
def sendf9(self):
|
1100
1160
|
"""stub"""
|
1101
1161
|
logger.debug("F9 Clicked")
|
1162
|
+
if self.radio_state.get("mode") in ["USB", "SSB"]:
|
1163
|
+
self.voice_string(self.process_macro(self.F9.toolTip()))
|
1164
|
+
return
|
1102
1165
|
if self.cw:
|
1103
1166
|
self.cw.sendcw(self.process_macro(self.F9.toolTip()))
|
1104
1167
|
|
1105
1168
|
def sendf10(self):
|
1106
1169
|
"""stub"""
|
1107
1170
|
logger.debug("F10 Clicked")
|
1171
|
+
if self.radio_state.get("mode") in ["USB", "SSB"]:
|
1172
|
+
self.voice_string(self.process_macro(self.F10.toolTip()))
|
1173
|
+
return
|
1108
1174
|
if self.cw:
|
1109
1175
|
self.cw.sendcw(self.process_macro(self.F10.toolTip()))
|
1110
1176
|
|
1111
1177
|
def sendf11(self):
|
1112
1178
|
"""stub"""
|
1113
1179
|
logger.debug("F11 Clicked")
|
1180
|
+
if self.radio_state.get("mode") in ["USB", "SSB"]:
|
1181
|
+
self.voice_string(self.process_macro(self.F11.toolTip()))
|
1182
|
+
return
|
1114
1183
|
if self.cw:
|
1115
1184
|
self.cw.sendcw(self.process_macro(self.F11.toolTip()))
|
1116
1185
|
|
1117
1186
|
def sendf12(self):
|
1118
1187
|
"""stub"""
|
1119
1188
|
logger.debug("F12 Clicked")
|
1189
|
+
if self.radio_state.get("mode") in ["USB", "SSB"]:
|
1190
|
+
self.voice_string(self.process_macro(self.F12.toolTip()))
|
1191
|
+
return
|
1120
1192
|
if self.cw:
|
1121
1193
|
self.cw.sendcw(self.process_macro(self.F12.toolTip()))
|
1122
1194
|
|
@@ -1380,6 +1452,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1380
1452
|
self.rig_control.set_mode("CW")
|
1381
1453
|
self.set_window_title()
|
1382
1454
|
self.clearinputs()
|
1455
|
+
self.read_cw_macros()
|
1383
1456
|
return
|
1384
1457
|
if stripped_text == "RTTY":
|
1385
1458
|
self.setmode("RTTY")
|
@@ -1401,6 +1474,7 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1401
1474
|
if self.rig_control:
|
1402
1475
|
self.rig_control.set_mode(self.radio_state.get("mode"))
|
1403
1476
|
self.clearinputs()
|
1477
|
+
self.read_cw_macros()
|
1404
1478
|
return
|
1405
1479
|
if stripped_text == "OPON":
|
1406
1480
|
self.get_opon()
|
@@ -1468,7 +1542,8 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1468
1542
|
f"{primary_pfx}: {continent}/{entity} cq:{cq} itu:{itu}"
|
1469
1543
|
)
|
1470
1544
|
if len(callsign) > 2:
|
1471
|
-
self.contest
|
1545
|
+
if self.contest:
|
1546
|
+
self.contest.prefill(self)
|
1472
1547
|
|
1473
1548
|
def check_callsign2(self, callsign):
|
1474
1549
|
"""Check call once entered"""
|
@@ -1544,9 +1619,26 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1544
1619
|
"""Save new OP"""
|
1545
1620
|
if self.opon_dialog.NewOperator.text():
|
1546
1621
|
self.current_op = self.opon_dialog.NewOperator.text().upper()
|
1547
|
-
|
1548
1622
|
self.opon_dialog.close()
|
1549
1623
|
logger.debug("New Op: %s", self.current_op)
|
1624
|
+
self.make_op_dir()
|
1625
|
+
|
1626
|
+
def make_op_dir(self):
|
1627
|
+
"""Create OP directory if it does not exist."""
|
1628
|
+
if self.current_op:
|
1629
|
+
op_path = Path(DATA_PATH) / self.current_op
|
1630
|
+
logger.debug("op_path: %s", str(op_path))
|
1631
|
+
if op_path.is_dir() is False:
|
1632
|
+
logger.debug("Creating Op Directory: %s", str(op_path))
|
1633
|
+
os.mkdir(str(op_path))
|
1634
|
+
if op_path.is_dir():
|
1635
|
+
source_path = Path(WORKING_PATH) / "data" / "phonetics"
|
1636
|
+
logger.debug("source_path: %s", str(source_path))
|
1637
|
+
for child in source_path.iterdir():
|
1638
|
+
destination_file = op_path / child.name
|
1639
|
+
logger.debug("Destination: %s", str(destination_file))
|
1640
|
+
if destination_file.is_file() is False:
|
1641
|
+
destination_file.write_bytes(child.read_bytes())
|
1550
1642
|
|
1551
1643
|
def poll_radio(self):
|
1552
1644
|
"""stub"""
|
@@ -1572,10 +1664,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1572
1664
|
"""
|
1573
1665
|
Calls the default text editor to edit the CW macro file.
|
1574
1666
|
"""
|
1575
|
-
|
1667
|
+
# FIXME
|
1668
|
+
if self.radio_state.get("mode") == "CW":
|
1669
|
+
macro_file = "/cwmacros.txt"
|
1670
|
+
else:
|
1671
|
+
macro_file = "/ssbmacros.txt"
|
1672
|
+
if not Path(DATA_PATH + macro_file).exists():
|
1576
1673
|
logger.debug("read_cw_macros: copying default macro file.")
|
1577
|
-
copyfile(WORKING_PATH + "/data
|
1578
|
-
os.system(f"xdg-open {DATA_PATH}
|
1674
|
+
copyfile(WORKING_PATH + "/data" + macro_file, DATA_PATH + macro_file)
|
1675
|
+
os.system(f"xdg-open {DATA_PATH}{macro_file}")
|
1579
1676
|
self.read_cw_macros()
|
1580
1677
|
|
1581
1678
|
def read_cw_macros(self) -> None:
|
@@ -1585,12 +1682,15 @@ class MainWindow(QtWidgets.QMainWindow):
|
|
1585
1682
|
temp directory this is running from... In theory.
|
1586
1683
|
"""
|
1587
1684
|
|
1588
|
-
if
|
1685
|
+
if self.radio_state.get("mode") == "CW":
|
1686
|
+
macro_file = "/cwmacros.txt"
|
1687
|
+
else:
|
1688
|
+
macro_file = "/ssbmacros.txt"
|
1689
|
+
|
1690
|
+
if not Path(DATA_PATH + macro_file).exists():
|
1589
1691
|
logger.debug("read_cw_macros: copying default macro file.")
|
1590
|
-
copyfile(WORKING_PATH + "/data
|
1591
|
-
with open(
|
1592
|
-
DATA_PATH + "/cwmacros.txt", "r", encoding="utf-8"
|
1593
|
-
) as file_descriptor:
|
1692
|
+
copyfile(WORKING_PATH + "/data" + macro_file, DATA_PATH + macro_file)
|
1693
|
+
with open(DATA_PATH + macro_file, "r", encoding="utf-8") as file_descriptor:
|
1594
1694
|
for line in file_descriptor:
|
1595
1695
|
try:
|
1596
1696
|
mode, fkey, buttonname, cwtext = line.split("|")
|