RemoteRF 2.0.12__tar.gz → 2.0.13__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.
- {remoterf-2.0.12/src/remoterf.egg-info → remoterf-2.0.13}/PKG-INFO +1 -1
- {remoterf-2.0.12 → remoterf-2.0.13}/setup.py +1 -1
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/dynamic_device.py +5 -1
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/hackrf/hackrf_remote.py +58 -10
- {remoterf-2.0.12 → remoterf-2.0.13/src/remoterf.egg-info}/PKG-INFO +1 -1
- {remoterf-2.0.12 → remoterf-2.0.13}/tests/test_dynamic_device_codegen.py +11 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/LICENSE +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/MANIFEST.in +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/README.md +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/setup.cfg +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/__init__.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/common/__init__.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/common/grpc/__init__.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/common/grpc/grpc_pb2.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/common/grpc/grpc_pb2_grpc.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/common/grpc/v2_codec.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/common/tos_notice.txt +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/common/utils/__init__.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/common/utils/ansi_codes.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/common/utils/api_token.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/common/utils/banner.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/common/utils/list_string.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/common/utils/process_arg.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/config/__init__.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/config/cert_fetcher.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/config/config.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/core/__init__.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/core/acc_login.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/core/app.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/core/banner_note.txt +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/core/dynamic_v2_transport.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/core/grpc_acc.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/core/grpc_client.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/core/v2_errors.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/__init__.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/_virtual.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/adalm_pluto/__init__.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/adalm_pluto/pluto_remote.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/dynamic_v2.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/hackrf/__init__.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/rtl_sdr/__init__.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/rtl_sdr/rtl_sdr_remote.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/support/__init__.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/support/ti_mmwave.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/support/uhd.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/support/uhd_dsp.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/support/uhd_v2.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/ti_mmwave/__init__.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/ti_mmwave/ti_mmwave_remote.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/usrp/__init__.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/usrp/usrp_remote.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/drivers/usrp/usrp_remote.pyi +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/remoterf_cli.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoteRF/version.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoterf.egg-info/SOURCES.txt +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoterf.egg-info/dependency_links.txt +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoterf.egg-info/entry_points.txt +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoterf.egg-info/requires.txt +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/src/remoterf.egg-info/top_level.txt +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/tests/test_banner.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/tests/test_dynamic_v2.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/tests/test_pluto_virtual.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/tests/test_process_arg.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/tests/test_remoterf_cli.py +0 -0
- {remoterf-2.0.12 → remoterf-2.0.13}/tests/test_ti_mmwave.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: remoterf
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.13
|
|
4
4
|
Summary: A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts.
|
|
5
5
|
Author: Ethan Ge
|
|
6
6
|
Author-email: ethoGalaxy@gmail.com
|
|
@@ -21,7 +21,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
21
21
|
|
|
22
22
|
setup(
|
|
23
23
|
name="remoterf",
|
|
24
|
-
version="2.0.
|
|
24
|
+
version="2.0.13",
|
|
25
25
|
author="Ethan Ge",
|
|
26
26
|
author_email="ethoGalaxy@gmail.com",
|
|
27
27
|
description="A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts.",
|
|
@@ -1070,6 +1070,8 @@ def _emit_client_object_bindings(client_objects: dict, *, class_name: str) -> li
|
|
|
1070
1070
|
# Regular string (not f-string) — {_PREFIX}/{prop}/{e} are literal text
|
|
1071
1071
|
# that become f-strings inside the *generated* file.
|
|
1072
1072
|
_HELPERS = '''\
|
|
1073
|
+
import os
|
|
1074
|
+
|
|
1073
1075
|
from importlib import import_module as _import_module
|
|
1074
1076
|
|
|
1075
1077
|
from ...common.utils import map_arg, unmap_arg
|
|
@@ -1230,7 +1232,9 @@ def _codegen(schema: dict) -> str:
|
|
|
1230
1232
|
f' self.token = make_virtual_token(token, device_type="{device_type}")',
|
|
1231
1233
|
" return",
|
|
1232
1234
|
' if token is None:',
|
|
1233
|
-
'
|
|
1235
|
+
' token = os.getenv("REMOTERF_TOKEN")',
|
|
1236
|
+
' if not token:',
|
|
1237
|
+
' raise ValueError("A reservation token is required; pass token= or set REMOTERF_TOKEN")',
|
|
1234
1238
|
" self.token = token",
|
|
1235
1239
|
" from ..dynamic_device import install_driver_if_stale",
|
|
1236
1240
|
" install_driver_if_stale(token=token, current_hash=_SCHEMA_HASH)",
|
|
@@ -14,21 +14,35 @@
|
|
|
14
14
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
15
|
|
|
16
16
|
# Auto-generated from IDL schema — do not edit by hand.
|
|
17
|
-
# device_type: hackrf driver_version: 0.1.1 schema_hash: sha256:
|
|
17
|
+
# device_type: hackrf driver_version: 0.1.1 schema_hash: sha256:6fb625ce99aaf7e190de013ad3e66276265020a5464d9d55d4c0e076dae28f3c
|
|
18
18
|
|
|
19
19
|
_PREFIX = "Hackrf"
|
|
20
|
-
_SCHEMA_HASH = "sha256:
|
|
20
|
+
_SCHEMA_HASH = "sha256:6fb625ce99aaf7e190de013ad3e66276265020a5464d9d55d4c0e076dae28f3c"
|
|
21
21
|
_CLIENT_MODULES = {}
|
|
22
22
|
_CLIENT_OBJECTS = {}
|
|
23
23
|
|
|
24
|
+
import os
|
|
25
|
+
|
|
24
26
|
from importlib import import_module as _import_module
|
|
25
27
|
|
|
26
|
-
from ...core.grpc_client import rpc_client
|
|
27
28
|
from ...common.utils import map_arg, unmap_arg
|
|
29
|
+
from .._virtual import (
|
|
30
|
+
is_virtual_token,
|
|
31
|
+
make_virtual_token,
|
|
32
|
+
virtual_call,
|
|
33
|
+
virtual_get,
|
|
34
|
+
virtual_set,
|
|
35
|
+
)
|
|
28
36
|
|
|
29
37
|
_NO_ARG = object()
|
|
30
38
|
|
|
31
39
|
|
|
40
|
+
def _rpc_client(*, function_name, args):
|
|
41
|
+
from ...core.grpc_client import rpc_client
|
|
42
|
+
|
|
43
|
+
return rpc_client(function_name=function_name, args=args)
|
|
44
|
+
|
|
45
|
+
|
|
32
46
|
for _alias, _module_path in _CLIENT_MODULES.items():
|
|
33
47
|
globals()[_alias] = _import_module(_module_path)
|
|
34
48
|
|
|
@@ -71,27 +85,34 @@ def _wrap_client_return(spec, self_obj, result):
|
|
|
71
85
|
|
|
72
86
|
|
|
73
87
|
def _try_get(prop, token):
|
|
74
|
-
|
|
88
|
+
if is_virtual_token(token):
|
|
89
|
+
return virtual_get(token, prop)
|
|
90
|
+
return unmap_arg(_rpc_client(
|
|
75
91
|
function_name=f"{_PREFIX}:{prop}:GET",
|
|
76
92
|
args={'a': map_arg(token)},
|
|
77
93
|
).results[prop])
|
|
78
94
|
|
|
79
95
|
|
|
80
96
|
def _try_set(prop, value, token):
|
|
81
|
-
|
|
97
|
+
if is_virtual_token(token):
|
|
98
|
+
virtual_set(token, prop, value)
|
|
99
|
+
return None
|
|
100
|
+
_rpc_client(
|
|
82
101
|
function_name=f"{_PREFIX}:{prop}:SET",
|
|
83
102
|
args={prop: map_arg(value), 'a': map_arg(token)},
|
|
84
103
|
)
|
|
85
104
|
|
|
86
105
|
|
|
87
106
|
def _try_call(prop, token, arg=_NO_ARG):
|
|
107
|
+
if is_virtual_token(token):
|
|
108
|
+
return virtual_call(token, prop, arg, has_arg=arg is not _NO_ARG)
|
|
88
109
|
if arg is _NO_ARG:
|
|
89
|
-
resp =
|
|
110
|
+
resp = _rpc_client(
|
|
90
111
|
function_name=f"{_PREFIX}:{prop}:CALL0",
|
|
91
112
|
args={'a': map_arg(token)},
|
|
92
113
|
)
|
|
93
114
|
else:
|
|
94
|
-
resp =
|
|
115
|
+
resp = _rpc_client(
|
|
95
116
|
function_name=f"{_PREFIX}:{prop}:CALL1",
|
|
96
117
|
args={'a': map_arg(token), 'arg1': map_arg(arg)},
|
|
97
118
|
)
|
|
@@ -100,12 +121,15 @@ def _try_call(prop, token, arg=_NO_ARG):
|
|
|
100
121
|
|
|
101
122
|
|
|
102
123
|
def _try_calln(prop, token, kwargs):
|
|
124
|
+
if is_virtual_token(token):
|
|
125
|
+
filtered = {key: value for key, value in dict(kwargs).items() if value is not _NO_ARG}
|
|
126
|
+
return virtual_call(token, prop, filtered, has_arg=True)
|
|
103
127
|
payload = {'a': map_arg(token)}
|
|
104
128
|
for key, value in dict(kwargs).items():
|
|
105
129
|
if value is _NO_ARG:
|
|
106
130
|
continue
|
|
107
131
|
payload[str(key)] = map_arg(value)
|
|
108
|
-
resp =
|
|
132
|
+
resp = _rpc_client(
|
|
109
133
|
function_name=f"{_PREFIX}:{prop}:CALLN",
|
|
110
134
|
args=payload,
|
|
111
135
|
)
|
|
@@ -114,7 +138,15 @@ def _try_calln(prop, token, kwargs):
|
|
|
114
138
|
|
|
115
139
|
class HackRF:
|
|
116
140
|
|
|
117
|
-
def __init__(self, token: str):
|
|
141
|
+
def __init__(self, token: str = None, *, virtual: bool = False):
|
|
142
|
+
self.virtual = bool(virtual)
|
|
143
|
+
if self.virtual:
|
|
144
|
+
self.token = make_virtual_token(token, device_type="hackrf")
|
|
145
|
+
return
|
|
146
|
+
if token is None:
|
|
147
|
+
token = os.getenv("REMOTERF_TOKEN")
|
|
148
|
+
if not token:
|
|
149
|
+
raise ValueError("A reservation token is required; pass token= or set REMOTERF_TOKEN")
|
|
118
150
|
self.token = token
|
|
119
151
|
from ..dynamic_device import install_driver_if_stale
|
|
120
152
|
install_driver_if_stale(token=token, current_hash=_SCHEMA_HASH)
|
|
@@ -204,6 +236,10 @@ class HackRF:
|
|
|
204
236
|
'Clear any captured or queued IQ bytes while the radio is idle.'
|
|
205
237
|
return _try_call("clear_buffer", self.token)
|
|
206
238
|
|
|
239
|
+
def close(self):
|
|
240
|
+
'Safely end this remote TX use without closing the server-owned radio.'
|
|
241
|
+
return _try_call("close", self.token)
|
|
242
|
+
|
|
207
243
|
def enumerate(self):
|
|
208
244
|
'Return attached serials as a JSON array for broad client compatibility.'
|
|
209
245
|
return _try_call("enumerate", self.token)
|
|
@@ -213,7 +249,7 @@ class HackRF:
|
|
|
213
249
|
return _try_call("get_serial_no", self.token)
|
|
214
250
|
|
|
215
251
|
def load_tx_iq(self, samples):
|
|
216
|
-
'
|
|
252
|
+
'Load normalized complex or native interleaved signed-int8 TX IQ.'
|
|
217
253
|
return _try_call("load_tx_iq", self.token, samples)
|
|
218
254
|
|
|
219
255
|
def read_samples(self, num_samples=_NO_ARG):
|
|
@@ -222,6 +258,18 @@ class HackRF:
|
|
|
222
258
|
"num_samples": num_samples,
|
|
223
259
|
})
|
|
224
260
|
|
|
261
|
+
def set_freq(self, value):
|
|
262
|
+
'Compatibility alias for setting the center frequency in Hz.'
|
|
263
|
+
return _try_call("set_freq", self.token, value)
|
|
264
|
+
|
|
265
|
+
def set_sample_rate(self, value):
|
|
266
|
+
'Compatibility alias for setting the complex sample rate in Hz.'
|
|
267
|
+
return _try_call("set_sample_rate", self.token, value)
|
|
268
|
+
|
|
269
|
+
def setup(self):
|
|
270
|
+
'Confirm the already-managed remote HackRF is ready for use.'
|
|
271
|
+
return _try_call("setup", self.token)
|
|
272
|
+
|
|
225
273
|
def start_tx(self):
|
|
226
274
|
'Start transmitting the IQ bytes previously loaded with load_tx_iq().'
|
|
227
275
|
return _try_call("start_tx", self.token)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: remoterf
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.13
|
|
4
4
|
Summary: A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts.
|
|
5
5
|
Author: Ethan Ge
|
|
6
6
|
Author-email: ethoGalaxy@gmail.com
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# You should have received a copy of the GNU General Public License
|
|
14
14
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
15
15
|
|
|
16
|
+
import os
|
|
16
17
|
import unittest
|
|
17
18
|
import sys
|
|
18
19
|
import tempfile
|
|
@@ -413,6 +414,15 @@ class DynamicDeviceCodegenTests(unittest.TestCase):
|
|
|
413
414
|
exec(code, module.__dict__)
|
|
414
415
|
|
|
415
416
|
device = module.FakeDevice("token")
|
|
417
|
+
old_token = os.environ.get("REMOTERF_TOKEN")
|
|
418
|
+
os.environ["REMOTERF_TOKEN"] = "token-from-env"
|
|
419
|
+
try:
|
|
420
|
+
self.assertEqual(module.FakeDevice().token, "token-from-env")
|
|
421
|
+
finally:
|
|
422
|
+
if old_token is None:
|
|
423
|
+
os.environ.pop("REMOTERF_TOKEN", None)
|
|
424
|
+
else:
|
|
425
|
+
os.environ["REMOTERF_TOKEN"] = old_token
|
|
416
426
|
self.assertEqual(device.status, {"raw": True})
|
|
417
427
|
self.assertEqual(device.echo({"payload": 3}), {"payload": 3})
|
|
418
428
|
self.assertEqual(device.configure(1.0), {"configured": True})
|
|
@@ -423,6 +433,7 @@ class DynamicDeviceCodegenTests(unittest.TestCase):
|
|
|
423
433
|
self.assertEqual(
|
|
424
434
|
[item[0] for item in seen],
|
|
425
435
|
[
|
|
436
|
+
"Fake_device:ip:CALL0",
|
|
426
437
|
"Fake_device:ip:CALL0",
|
|
427
438
|
"Fake_device:status:GET",
|
|
428
439
|
"Fake_device:echo:CALL1",
|
|
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
|
|
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
|