ka9q-python 3.2.0__tar.gz → 3.2.2__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.
- {ka9q_python-3.2.0/ka9q_python.egg-info → ka9q_python-3.2.2}/PKG-INFO +2 -2
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q/__init__.py +1 -1
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q/rtp_recorder.py +5 -1
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q/types.py +8 -7
- {ka9q_python-3.2.0 → ka9q_python-3.2.2/ka9q_python.egg-info}/PKG-INFO +2 -2
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q_python.egg-info/SOURCES.txt +1 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/pyproject.toml +2 -2
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/setup.py +1 -1
- ka9q_python-3.2.2/tests/test_rtp_recorder.py +41 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/LICENSE +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/MANIFEST.in +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/README.md +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/advanced_features_demo.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/channel_cleanup_example.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/codar_oceanography.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/discover_example.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/grape_integration_example.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/hf_band_scanner.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/rtp_recorder_example.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/simple_am_radio.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/stream_example.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/superdarn_recorder.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/test_channel_operations.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/test_improvements.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/test_timing_fields.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/tune.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/examples/tune_example.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q/control.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q/discovery.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q/exceptions.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q/resequencer.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q/stream.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q/stream_quality.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q/utils.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q_python.egg-info/dependency_links.txt +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q_python.egg-info/requires.txt +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/ka9q_python.egg-info/top_level.txt +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/setup.cfg +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/__init__.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/conftest.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_decode_functions.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_encode_functions.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_encode_socket.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_integration.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_listen_multicast.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_multihomed.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_native_discovery.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_performance_fixes.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_remove_channel.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_security_features.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_tune.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_tune_cli.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_tune_debug.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_tune_live.py +0 -0
- {ka9q_python-3.2.0 → ka9q_python-3.2.2}/tests/test_tune_method.py +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ka9q-python
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.2
|
|
4
4
|
Summary: Python interface for ka9q-radio control and monitoring
|
|
5
5
|
Home-page: https://github.com/mijahauan/ka9q-python
|
|
6
6
|
Author: Michael Hauan AC0G
|
|
7
7
|
Author-email: Michael Hauan AC0G <ac0g@hauan.org>
|
|
8
|
-
License
|
|
8
|
+
License: MIT
|
|
9
9
|
Project-URL: Homepage, https://github.com/mijahauan/ka9q-python
|
|
10
10
|
Project-URL: Documentation, https://github.com/mijahauan/ka9q-python/blob/main/README.md
|
|
11
11
|
Project-URL: Repository, https://github.com/mijahauan/ka9q-python
|
|
@@ -30,6 +30,7 @@ logger = logging.getLogger(__name__)
|
|
|
30
30
|
GPS_UTC_OFFSET = 315964800 # GPS epoch (1980-01-06) - Unix epoch (1970-01-01)
|
|
31
31
|
UNIX_EPOCH = 2208988800 # Unix epoch in NTP seconds
|
|
32
32
|
BILLION = 1_000_000_000
|
|
33
|
+
GPS_LEAP_SECONDS = 18 # GPS time is ahead of UTC by 18 seconds (as of 2025)
|
|
33
34
|
|
|
34
35
|
|
|
35
36
|
class RecorderState(Enum):
|
|
@@ -140,7 +141,10 @@ def rtp_to_wallclock(rtp_timestamp: int, channel: ChannelInfo) -> Optional[float
|
|
|
140
141
|
return None
|
|
141
142
|
|
|
142
143
|
# Convert GPS nanoseconds to Unix time
|
|
143
|
-
|
|
144
|
+
# GPS epoch is Jan 6, 1980; Unix epoch is Jan 1, 1970
|
|
145
|
+
# gps_time is nanoseconds since GPS epoch, so add GPS_UTC_OFFSET (in ns)
|
|
146
|
+
# AND subtract current GPS_LEAP_SECONDS (18s) to align with UTC
|
|
147
|
+
sender_time = channel.gps_time + BILLION * (GPS_UTC_OFFSET - GPS_LEAP_SECONDS)
|
|
144
148
|
|
|
145
149
|
# Add offset from RTP timestamp difference
|
|
146
150
|
# Cast to int32 for proper wrapping behavior
|
|
@@ -150,12 +150,13 @@ class StatusType:
|
|
|
150
150
|
# Command packet type
|
|
151
151
|
CMD = 1
|
|
152
152
|
|
|
153
|
-
# Encoding types
|
|
153
|
+
# Encoding types - must match enum encoding in ka9q-radio/src/rtp.h
|
|
154
154
|
class Encoding:
|
|
155
|
-
"""Output encoding types"""
|
|
155
|
+
"""Output encoding types - values must match ka9q-radio/src/rtp.h enum encoding"""
|
|
156
156
|
NO_ENCODING = 0
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
157
|
+
S16LE = 1 # Signed 16-bit little-endian
|
|
158
|
+
S16BE = 2 # Signed 16-bit big-endian
|
|
159
|
+
OPUS = 3 # Opus codec
|
|
160
|
+
F32 = 4 # 32-bit float (F32LE in C)
|
|
161
|
+
AX25 = 5 # AX.25 packet
|
|
162
|
+
F16 = 6 # 16-bit float (F16LE in C)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ka9q-python
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.2
|
|
4
4
|
Summary: Python interface for ka9q-radio control and monitoring
|
|
5
5
|
Home-page: https://github.com/mijahauan/ka9q-python
|
|
6
6
|
Author: Michael Hauan AC0G
|
|
7
7
|
Author-email: Michael Hauan AC0G <ac0g@hauan.org>
|
|
8
|
-
License
|
|
8
|
+
License: MIT
|
|
9
9
|
Project-URL: Homepage, https://github.com/mijahauan/ka9q-python
|
|
10
10
|
Project-URL: Documentation, https://github.com/mijahauan/ka9q-python/blob/main/README.md
|
|
11
11
|
Project-URL: Repository, https://github.com/mijahauan/ka9q-python
|
|
@@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ka9q-python"
|
|
7
|
-
version = "3.2.
|
|
7
|
+
version = "3.2.2"
|
|
8
8
|
description = "Python interface for ka9q-radio control and monitoring"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
authors = [
|
|
11
11
|
{name = "Michael Hauan AC0G", email = "ac0g@hauan.org"}
|
|
12
12
|
]
|
|
13
|
-
license = "MIT"
|
|
13
|
+
license = {text = "MIT"}
|
|
14
14
|
requires-python = ">=3.9"
|
|
15
15
|
classifiers = [
|
|
16
16
|
"Development Status :: 4 - Beta",
|
|
@@ -12,7 +12,7 @@ long_description = readme.read_text() if readme.exists() else ''
|
|
|
12
12
|
|
|
13
13
|
setup(
|
|
14
14
|
name='ka9q-python',
|
|
15
|
-
version='3.2.
|
|
15
|
+
version='3.2.1',
|
|
16
16
|
description='Python interface for ka9q-radio control and monitoring',
|
|
17
17
|
long_description=long_description,
|
|
18
18
|
long_description_content_type='text/markdown',
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Tests for RTP recorder functionality
|
|
3
|
+
"""
|
|
4
|
+
import pytest
|
|
5
|
+
from ka9q.rtp_recorder import rtp_to_wallclock
|
|
6
|
+
from ka9q.discovery import ChannelInfo
|
|
7
|
+
|
|
8
|
+
def test_rtp_to_wallclock():
|
|
9
|
+
"""Test GPS time to Unix time conversion"""
|
|
10
|
+
# Channel info with mocked timing
|
|
11
|
+
# GPS Time: 1234567890000000000 ns (random recent-ish GPS time)
|
|
12
|
+
# This corresponds to some time around 2019
|
|
13
|
+
gps_time_ns = 1234567890000000000
|
|
14
|
+
|
|
15
|
+
# Constants from code
|
|
16
|
+
GPS_UTC_OFFSET = 315964800
|
|
17
|
+
BILLION = 1_000_000_000
|
|
18
|
+
|
|
19
|
+
channel = ChannelInfo(
|
|
20
|
+
ssrc=1234,
|
|
21
|
+
preset="test",
|
|
22
|
+
sample_rate=48000,
|
|
23
|
+
frequency=100.0,
|
|
24
|
+
snr=0.0,
|
|
25
|
+
multicast_address="239.1.2.3",
|
|
26
|
+
port=5004,
|
|
27
|
+
gps_time=gps_time_ns,
|
|
28
|
+
rtp_timesnap=1000
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Case 1: Same RTP timestamp as snapshot
|
|
32
|
+
# Result should be exactly GPS time + offset
|
|
33
|
+
# Expected Unix time = GPS time + Offset - Leap Seconds
|
|
34
|
+
expected_unix_ns = gps_time_ns + (BILLION * (GPS_UTC_OFFSET - 18))
|
|
35
|
+
expected_unix_sec = expected_unix_ns / BILLION
|
|
36
|
+
|
|
37
|
+
assert rtp_to_wallclock(1000, channel) == pytest.approx(expected_unix_sec)
|
|
38
|
+
|
|
39
|
+
# Case 2: One second later
|
|
40
|
+
# 48000 samples later
|
|
41
|
+
assert rtp_to_wallclock(1000 + 48000, channel) == pytest.approx(expected_unix_sec + 1.0)
|
|
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
|
|
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
|
|
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
|
|
File without changes
|