Skip to content

Commit 339bbb4

Browse files
committed
solves review comments
1 parent a425d79 commit 339bbb4

3 files changed

Lines changed: 31 additions & 16 deletions

File tree

radioshaq/radioshaq/config/schema.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,13 @@ def validate_postgres_url(cls, v: str) -> str:
151151
# Normalize 127.0.0.1 to localhost in the host component only (avoid corrupting password/db).
152152
parsed = urlparse(v)
153153
if parsed.hostname == "127.0.0.1":
154-
netloc = parsed.netloc.replace("127.0.0.1", "localhost", 1)
154+
netloc = parsed.netloc
155+
if "@" in netloc:
156+
userinfo, hostport = netloc.rsplit("@", 1)
157+
hostport = hostport.replace("127.0.0.1", "localhost", 1)
158+
netloc = f"{userinfo}@{hostport}"
159+
else:
160+
netloc = netloc.replace("127.0.0.1", "localhost", 1)
155161
v = urlunparse(parsed._replace(netloc=netloc))
156162
return v
157163

radioshaq/radioshaq/radio/sdr_tx.py

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -188,18 +188,20 @@ async def transmit_tone(
188188
self._check_compliance(frequency_hz, occupied_bandwidth_hz=25_000.0)
189189
dev = self._open()
190190
loop = asyncio.get_running_loop()
191-
# Generate int8 interleaved I/Q for a tone (e.g. 1 kHz at sample_rate)
192-
import numpy as np
193-
tone_hz = 1000.0
194-
num_samples = int(duration_sec * sample_rate)
195-
t = np.arange(num_samples, dtype=np.float64) / sample_rate
196-
i = (127 * 0.3 * np.cos(2 * np.pi * tone_hz * t)).astype(np.int8)
197-
q = (127 * 0.3 * np.sin(2 * np.pi * tone_hz * t)).astype(np.int8)
198-
iq = np.empty(2 * num_samples, dtype=np.int8)
199-
iq[0::2] = i
200-
iq[1::2] = q
191+
success = False
201192

202193
def _blocking_tx() -> None:
194+
# Generate int8 interleaved I/Q for a tone (e.g. 1 kHz at sample_rate)
195+
# inside the executor to avoid blocking the event loop.
196+
tone_hz = 1000.0
197+
num_samples = int(duration_sec * sample_rate)
198+
t = np.arange(num_samples, dtype=np.float64) / sample_rate
199+
i = (127 * 0.3 * np.cos(2 * np.pi * tone_hz * t)).astype(np.int8)
200+
q = (127 * 0.3 * np.sin(2 * np.pi * tone_hz * t)).astype(np.int8)
201+
iq = np.empty(2 * num_samples, dtype=np.int8)
202+
iq[0::2] = i
203+
iq[1::2] = q
204+
203205
try:
204206
dev.center_freq = int(frequency_hz)
205207
dev.sample_rate = sample_rate
@@ -210,11 +212,13 @@ def _blocking_tx() -> None:
210212
try:
211213
buf = iq.tobytes()
212214
stream_hackrf_iq_bytes(dev, buf, duration_sec)
213-
except (AttributeError, TypeError, RuntimeError) as e:
215+
except (AttributeError, TypeError) as e:
216+
# Stub/API mismatch: skip hardware TX but still allow audit trail to record attempt.
214217
logger.warning("HackRF TX not available ({}); audit only", repr(e))
215218

216219
try:
217220
await loop.run_in_executor(None, _blocking_tx)
221+
success = True
218222
except RuntimeError as e:
219223
msg = str(e)
220224
if "HACKRF_ERROR_LIBUSB" in msg or "libusb" in msg.lower():
@@ -225,7 +229,7 @@ def _blocking_tx() -> None:
225229
) from e
226230
raise
227231
finally:
228-
self._audit(frequency_hz, duration_sec, "tone")
232+
self._audit(frequency_hz, duration_sec, "tone", success=success)
229233

230234
async def transmit_iq(
231235
self,
@@ -254,6 +258,7 @@ async def transmit_iq(
254258
duration_sec = len(iq) / (2.0 * sample_rate)
255259
dev = self._open()
256260
loop = asyncio.get_running_loop()
261+
success = False
257262

258263
def _blocking_tx() -> None:
259264
try:
@@ -266,11 +271,13 @@ def _blocking_tx() -> None:
266271
try:
267272
buf = iq.tobytes()
268273
stream_hackrf_iq_bytes(dev, buf, duration_sec)
269-
except (AttributeError, TypeError, RuntimeError) as e:
274+
except (AttributeError, TypeError) as e:
275+
# Stub/API mismatch: skip hardware TX but still allow audit trail to record attempt.
270276
logger.warning("HackRF TX not available ({}); audit only", repr(e))
271277

272278
try:
273279
await loop.run_in_executor(None, _blocking_tx)
280+
success = True
274281
except RuntimeError as e:
275282
msg = str(e)
276283
if "HACKRF_ERROR_LIBUSB" in msg or "libusb" in msg.lower():
@@ -281,7 +288,7 @@ def _blocking_tx() -> None:
281288
) from e
282289
raise
283290
finally:
284-
self._audit(frequency_hz, duration_sec, "iq")
291+
self._audit(frequency_hz, duration_sec, "iq", success=success)
285292

286293

287294
class HackRFServiceClient(_ComplianceCheckedTransmitter):

radioshaq/radioshaq/specialized/radio_tx.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,9 @@ async def _transmit_voice(
174174
)
175175
elif mode_name.value == "CW":
176176
# CW audio TX is typically keying; as a minimal baseline, emit a short carrier.
177-
iq = cw_tone_iq(duration_sec=0.5, rf_rate_hz=tx_rate)
177+
iq = await loop.run_in_executor(
178+
None, lambda: cw_tone_iq(duration_sec=0.5, rf_rate_hz=tx_rate)
179+
)
178180
else:
179181
iq = await loop.run_in_executor(
180182
None, lambda: nfm_modulate(data, int(sr), tx_rate, deviation_hz=2_500.0)

0 commit comments

Comments
 (0)