PyFT8 3.0.2__tar.gz → 3.1.0__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.
Files changed (30) hide show
  1. {pyft8-3.0.2 → pyft8-3.1.0}/PKG-INFO +1 -1
  2. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8/databases.py +12 -7
  3. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8/pyft8.py +9 -4
  4. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8/receiver.py +3 -3
  5. pyft8-3.1.0/PyFT8/rigctrl.py +103 -0
  6. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8.egg-info/PKG-INFO +1 -1
  7. {pyft8-3.0.2 → pyft8-3.1.0}/pyproject.toml +1 -1
  8. pyft8-3.0.2/PyFT8/rigctrl.py +0 -43
  9. {pyft8-3.0.2 → pyft8-3.1.0}/LICENSE +0 -0
  10. {pyft8-3.0.2 → pyft8-3.1.0}/MANIFEST.in +0 -0
  11. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8/__init__.py +0 -0
  12. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8/gui.py +0 -0
  13. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8/pskreporter.py +0 -0
  14. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8/time_utils.py +0 -0
  15. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8/transmitter.py +0 -0
  16. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8.egg-info/SOURCES.txt +0 -0
  17. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8.egg-info/dependency_links.txt +0 -0
  18. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8.egg-info/entry_points.txt +0 -0
  19. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8.egg-info/requires.txt +0 -0
  20. {pyft8-3.0.2 → pyft8-3.1.0}/PyFT8.egg-info/top_level.txt +0 -0
  21. {pyft8-3.0.2 → pyft8-3.1.0}/README.md +0 -0
  22. {pyft8-3.0.2 → pyft8-3.1.0}/setup.cfg +0 -0
  23. {pyft8-3.0.2 → pyft8-3.1.0}/tests/dev/CQ AAAA.py +0 -0
  24. {pyft8-3.0.2 → pyft8-3.1.0}/tests/dev/osd.py +0 -0
  25. {pyft8-3.0.2 → pyft8-3.1.0}/tests/dev/test_generate_wav.py +0 -0
  26. {pyft8-3.0.2 → pyft8-3.1.0}/tests/dev/test_loopback_performance.py +0 -0
  27. {pyft8-3.0.2 → pyft8-3.1.0}/tests/dev/view_worked_before.py +0 -0
  28. {pyft8-3.0.2 → pyft8-3.1.0}/tests/plot_baseline.py +0 -0
  29. {pyft8-3.0.2 → pyft8-3.1.0}/tests/spare.py +0 -0
  30. {pyft8-3.0.2 → pyft8-3.1.0}/tests/test_batch_and_live.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyFT8
3
- Version: 3.0.2
3
+ Version: 3.1.0
4
4
  Summary: FT8 Decoding and Encoding in Python with test/loopback code
5
5
  Author-email: G1OJS <g1ojs@yahoo.com>
6
6
  License-Expression: GPL-3.0-or-later
@@ -71,12 +71,17 @@ class DiskDict:
71
71
  pass
72
72
 
73
73
  def save(self):
74
- with self.lock:
75
- with open(self.file, "w") as f:
76
- try:
77
- json.dump(self.data, f)
78
- except:
79
- pass
74
+ if self.data != {}:
75
+ with self.lock:
76
+ with open(f"{self.file}_tmp", "w") as f:
77
+ try:
78
+ json.dump(self.data, f)
79
+ except:
80
+ return
81
+ try:
82
+ os.replace(f"{self.file}_tmp", self.file)
83
+ except:
84
+ return
80
85
 
81
86
  class History:
82
87
  def __init__(self, config_folder, my_call, home_square, pskr_refresh_mins, parse_all_file):
@@ -185,7 +190,7 @@ class History:
185
190
  self._update_new_alert(band, call, historic_data, new_alert_data)
186
191
  historic_data.setdefault(band, {})
187
192
  if call in historic_data[band]:
188
- if t < historic_data[band][call]['t']:
193
+ if int(t) < int(historic_data[band][call]['t']):
189
194
  return
190
195
  historic_data[band][call] = {'t': int(t),'rp':int(rp)}
191
196
 
@@ -9,10 +9,10 @@ from PyFT8.pskreporter import PSKR_upload
9
9
  from PyFT8.gui import Gui
10
10
  from PyFT8.transmitter import AudioOut
11
11
  from PyFT8.time_utils import global_time_utils
12
- from PyFT8.rigctrl import Rig_hamlib
12
+ from PyFT8.rigctrl import Rig_hamlib, Rig_CAT
13
13
  from PyFT8.databases import History, ADIF
14
14
 
15
- VER = '3.0.2'
15
+ VER = '3.1.0'
16
16
 
17
17
  MAX_TX_START_SECONDS = 2.5
18
18
  HEARING_PANEL_LIFE_MINS = 20
@@ -315,8 +315,7 @@ def cli():
315
315
  import time, sys
316
316
  parser = argparse.ArgumentParser(prog='PyFT8rx', description = 'Command Line FT8 decoder')
317
317
  parser.add_argument('-c', '--config_folder', help = 'Location of config folder e.g. C:/Users/drala/Documents/Projects/GitHub/G1OJS/PyFT8_cfg', default = './')
318
- parser.add_argument('-i', '--inputcard_keywords', help = 'Comma-separated keywords to identify the input sound device')
319
- #parser.add_argument('-v','--verbose', action='store_true', help = 'Verbose: include debugging output')
318
+ parser.add_argument('-i', '--inputcard_keywords', help = 'Comma-separated keywords to identify the input sound device')
320
319
  parser.add_argument('-o','--outputcard_keywords', help = 'Comma-separated keywords to identify the output sound device')
321
320
  parser.add_argument('-n','--no_gui', action='store_true', help = "Don't create a gui")
322
321
  parser.add_argument('-m','--transmit_message', nargs='?', help = 'Transmit a message')
@@ -348,6 +347,12 @@ def cli():
348
347
  if config.has_section('hamlib_rig'):
349
348
  console_print("Connecting to rig via Hamlib")
350
349
  rig = Rig_hamlib(config)
350
+ else:
351
+ console_print("Connecting to rig via CAT")
352
+ rig = Rig_CAT(config)
353
+
354
+ if config.has_section('launch'):
355
+ os.system(config['launch']['app'])
351
356
 
352
357
  if args.outputcard_keywords:
353
358
  outputcard_keywords = args.outputcard_keywords.replace(' ','').split(',')
@@ -45,10 +45,10 @@ def unpack(bits):
45
45
  i3, bits74 = get_bitfields(bits,[3])
46
46
  if i3 == 0:
47
47
  n3, bits71 = get_bitfields(bits74,[3])
48
- if n3 == 0:
49
- return ('Free text','not','implemented')
48
+ if n3 <= 4:
49
+ return (['Free text', 'DXpedition','Field Day', 'Field Day', 'Telemetry'][n3],'not','implemented')
50
50
  else:
51
- return (['DXpedition','Field Day', 'Field Day', 'Telemetry'][n3-1],'not','implemented')
51
+ return ('Unknown mode','not','implemented')
52
52
  elif i3 == 1 or i3 == 2: # 1 = Std Msg incl /R 2 = 'EU VHF' = Std Msg incl /P
53
53
  return unpack_std(bits74, i3)
54
54
  elif i3 == 3:
@@ -0,0 +1,103 @@
1
+ import serial, time, socket, subprocess, threading, psutil
2
+
3
+ class Rig_CAT:
4
+ def __init__(self, config, verbose = False):
5
+ self.serial_port = False
6
+ self.port = config['rig']['port']
7
+ self.baud_rate = config['rig']['baud_rate']
8
+ self.ptt_on_cmd = self.parse_configstr(config['rig']['ptt_on_command']) if config['rig']['ptt_on_command']else None
9
+ self.ptt_off_cmd = self.parse_configstr(config['rig']['ptt_off_command']) if config['rig']['ptt_off_command'] else None
10
+ self.set_freq_cmd = self.parse_configstr(config['rig']['set_freq_command']) if config['rig']['set_freq_command'] else None
11
+ self.set_freq_value = config['rig']['set_freq_value'] if config['rig']['set_freq_value'] else None
12
+ self.verbose = verbose
13
+
14
+ def parse_configstr(self, configstr):
15
+ if "." in configstr:
16
+ hexstr = configstr.replace(".", "")
17
+ return bytearray.fromhex(hexstr)
18
+ else:
19
+ return bytearray(configstr.encode())
20
+
21
+ def vprint(self, text):
22
+ if self.verbose:
23
+ print(text)
24
+
25
+ def _sendCAT(self, msg):
26
+ try:
27
+ self.serial_port = serial.Serial(port = self.port, baudrate = self.baud_rate, timeout = 0.1)
28
+ except Exception as e:
29
+ print(f"[CAT] couldn't open {self.port}: {e}")
30
+ if (self.serial_port):
31
+ self.serial_port.reset_input_buffer()
32
+ self.vprint(f"[CAT] send {msg.hex(' ')}")
33
+ try:
34
+ self.serial_port.write(msg)
35
+ time.sleep(0.05)
36
+ self.serial_port.close()
37
+ except Exception as e:
38
+ print(f"[CAT] couldn't send CAT command {msg} on {self.port}: {e}")
39
+
40
+ def set_freq_Hz(self, freqHz):
41
+ if self.set_freq_cmd and self.set_freq_value:
42
+ self.vprint(f"[CAT] SET frequency to {freqHz} Hz")
43
+ start, length, fmt, mult, offset = self.set_freq_value.split("|")
44
+ start, length, mult, offset = int(start), int(length), int(mult), int(offset)
45
+ fVal = freqHz * mult + offset
46
+ nDigits = length if fmt == "text" else 2*length
47
+ s = f"{fVal:0{nDigits}d}"
48
+ if fmt=='text':
49
+ fBytes = s.encode()
50
+ else:
51
+ pairs = [(int(s[i]) << 4) | int(s[i+1]) for i in range(0, len(s), 2)]
52
+ if fmt == "vfBcdLU":
53
+ fBytes = bytes(pairs[::-1])
54
+ else:
55
+ fBytes = bytes(pairs)
56
+ cmd = bytearray(self.set_freq_cmd)
57
+ cmd[start:start+length] = fBytes
58
+ if fmt.startswith("vfBcd"): # CI-V
59
+ cmd = b'\x00' + cmd
60
+ self._sendCAT(cmd)
61
+
62
+ def ptt_on(self):
63
+ if self.ptt_on_cmd:
64
+ self.vprint(f"[CAT] PTT On")
65
+ self._sendCAT(self.ptt_on_cmd)
66
+
67
+ def ptt_off(self):
68
+ if self.ptt_off_cmd:
69
+ self.vprint(f"[CAT] PTT Off")
70
+ self._sendCAT(self.ptt_off_cmd)
71
+
72
+ class Rig_hamlib:
73
+ def __init__(self, config):
74
+ com = config['hamlib_rig']['port']
75
+ s = config['hamlib_rig']['baud_rate']
76
+ rigctld = config['hamlib_rig']['rigctld']
77
+ rig = config['hamlib_rig']['model']
78
+ host, port ="localhost", 4532
79
+ if not any(['rigctld' in i.name() for i in psutil.process_iter()]):
80
+ cmd = f"{rigctld} -m {rig} -r {com} -s {s}"
81
+ threading.Thread(target = subprocess.run, args = (cmd,)).start()
82
+ time.sleep(0.5)
83
+ self.sock = socket.create_connection((host, port))
84
+ self.set_mode("PKTUSB")
85
+
86
+ def cmd(self, command):
87
+ if self.sock:
88
+ self.sock.sendall((command + "\n").encode())
89
+ return self.sock.recv(1024).decode()
90
+
91
+ def set_mode(self, mode):
92
+ self.cmd(f"M {mode} 0")
93
+
94
+ def set_freq_Hz(self, hz):
95
+ self.cmd(f"F {hz}")
96
+
97
+ def ptt_on(self):
98
+ self.cmd(f"T 1")
99
+
100
+ def ptt_off(self):
101
+ self.cmd(f"T 0")
102
+
103
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyFT8
3
- Version: 3.0.2
3
+ Version: 3.1.0
4
4
  Summary: FT8 Decoding and Encoding in Python with test/loopback code
5
5
  Author-email: G1OJS <g1ojs@yahoo.com>
6
6
  License-Expression: GPL-3.0-or-later
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "PyFT8"
3
- version = "3.0.2"
3
+ version = "3.1.0"
4
4
  license = "GPL-3.0-or-later"
5
5
 
6
6
  authors = [
@@ -1,43 +0,0 @@
1
- import time, socket, subprocess, threading
2
-
3
- class Rig_hamlib:
4
- def __init__(self, config):
5
- com = config['hamlib_rig']['port']
6
- s = config['hamlib_rig']['baud_rate']
7
- rigctld = config['hamlib_rig']['rigctld']
8
- rig = config['hamlib_rig']['model']
9
- host, port ="localhost", 4532
10
- cmd = f"{rigctld} -m {rig} -r {com} -s {s}"
11
- self.sock = None
12
- if not self.create_socket(host, port):
13
- threading.Thread(target = subprocess.run, args = (cmd,)).start()
14
- time.sleep(0.5)
15
- if not self.create_socket(host, port):
16
- print(f"Couldn't create socket for hamlib on {host}:{port}")
17
- self.set_mode("PKTUSB")
18
-
19
- def create_socket(self, host, port):
20
- try:
21
- self.sock = socket.create_connection((host, port))
22
- except:
23
- return False
24
- return True
25
-
26
- def cmd(self, command):
27
- if self.sock:
28
- self.sock.sendall((command + "\n").encode())
29
- return self.sock.recv(1024).decode()
30
-
31
- def set_mode(self, mode):
32
- self.cmd(f"M {mode} 0")
33
-
34
- def set_freq_Hz(self, hz):
35
- self.cmd(f"F {hz}")
36
-
37
- def ptt_on(self):
38
- self.cmd(f"T 1")
39
-
40
- def ptt_off(self):
41
- self.cmd(f"T 0")
42
-
43
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes