RemoteRF 2.0.4__tar.gz → 2.0.8__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.4/src/remoteRF.egg-info → remoterf-2.0.8}/PKG-INFO +77 -2
- {remoterf-2.0.4 → remoterf-2.0.8}/README.md +76 -1
- {remoterf-2.0.4 → remoterf-2.0.8}/setup.py +1 -1
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/common/grpc/grpc_pb2.py +46 -46
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/common/utils/process_arg.py +102 -62
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/core/grpc_client.py +12 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/drivers/dynamic_v2.py +49 -1
- remoterf-2.0.8/src/remoteRF/drivers/hackrf/__init__.py +6 -0
- remoterf-2.0.8/src/remoteRF/drivers/hackrf/hackrf_remote.py +216 -0
- remoterf-2.0.8/src/remoteRF/drivers/rtl_sdr/__init__.py +6 -0
- remoterf-2.0.8/src/remoteRF/drivers/rtl_sdr/rtl_sdr_remote.py +244 -0
- remoterf-2.0.8/src/remoteRF/drivers/support/ti_mmwave.py +295 -0
- remoterf-2.0.8/src/remoteRF/drivers/support/uhd_dsp.py +76 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/drivers/support/uhd_v2.py +17 -1
- remoterf-2.0.8/src/remoteRF/drivers/ti_mmwave/__init__.py +15 -0
- remoterf-2.0.8/src/remoteRF/drivers/ti_mmwave/ti_mmwave_remote.py +163 -0
- remoterf-2.0.8/src/remoteRF/drivers/usrp/usrp_remote.py +8 -0
- {remoterf-2.0.4 → remoterf-2.0.8/src/remoterf.egg-info}/PKG-INFO +77 -2
- remoterf-2.0.8/src/remoterf.egg-info/SOURCES.txt +94 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/tests/test_dynamic_device_codegen.py +65 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/tests/test_dynamic_v2.py +105 -1
- remoterf-2.0.8/tests/test_process_arg.py +218 -0
- remoterf-2.0.8/tests/test_ti_mmwave.py +211 -0
- remoterf-2.0.4/LICENSE +0 -21
- remoterf-2.0.4/src/remoteRF/drivers/usrp/usrp_remote.py +0 -8
- remoterf-2.0.4/src/remoteRF.egg-info/SOURCES.txt +0 -55
- remoterf-2.0.4/tests/test_process_arg.py +0 -110
- {remoterf-2.0.4 → remoterf-2.0.8}/MANIFEST.in +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/setup.cfg +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/__init__.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/common/__init__.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/common/grpc/__init__.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/common/grpc/grpc_pb2_grpc.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/common/grpc/v2_codec.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/common/tos_notice.txt +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/common/utils/__init__.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/common/utils/ansi_codes.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/common/utils/api_token.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/common/utils/list_string.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/config/__init__.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/config/cert_fetcher.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/config/config.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/core/__init__.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/core/acc_login.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/core/app.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/core/banner_note.txt +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/core/dynamic_v2_transport.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/core/grpc_acc.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/core/v2_errors.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/drivers/__init__.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/drivers/adalm_pluto/__init__.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/drivers/adalm_pluto/pluto_remote.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/drivers/dynamic_device.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/drivers/support/__init__.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/drivers/support/uhd.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/drivers/usrp/__init__.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/drivers/usrp/usrp_remote.pyi +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/remoterf_cli.py +0 -0
- {remoterf-2.0.4 → remoterf-2.0.8}/src/remoteRF/version.py +0 -0
- {remoterf-2.0.4/src/remoteRF.egg-info → remoterf-2.0.8/src/remoterf.egg-info}/dependency_links.txt +0 -0
- {remoterf-2.0.4/src/remoteRF.egg-info → remoterf-2.0.8/src/remoterf.egg-info}/entry_points.txt +0 -0
- {remoterf-2.0.4/src/remoteRF.egg-info → remoterf-2.0.8/src/remoterf.egg-info}/requires.txt +0 -0
- {remoterf-2.0.4/src/remoteRF.egg-info → remoterf-2.0.8/src/remoterf.egg-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: remoterf
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.8
|
|
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
|
|
@@ -53,7 +53,13 @@ source venv/bin/activate # Activate virtual environment
|
|
|
53
53
|
pip install remoterf # Install remoteRF
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
## NI USRP-2901
|
|
56
|
+
## NI USRP-2901, Ettus B205-mini, B200-family, and USRP N210
|
|
57
|
+
|
|
58
|
+
The packaged client natively includes the shared USRP schema for the qualified
|
|
59
|
+
NI USRP-2901, Ettus Research USRP B205-mini, the broader USB/B200 family, and
|
|
60
|
+
the Ethernet-connected N210. No custom client driver is required. The B205-mini
|
|
61
|
+
uses the same native-style API and reports its live 1 RX/1 TX channel topology
|
|
62
|
+
through `remoterf_capabilities`.
|
|
57
63
|
|
|
58
64
|
After reserving a server-local `usrp` inventory entry, fetch or refresh its
|
|
59
65
|
Dynamic v2 package with the reservation token:
|
|
@@ -112,6 +118,75 @@ generic native dispatch, but are not release-qualified as exact UHD overload
|
|
|
112
118
|
parity until the server's UHD 4.10 target-introspection and hardware
|
|
113
119
|
differential gates pass.
|
|
114
120
|
|
|
121
|
+
## RTL-SDR
|
|
122
|
+
|
|
123
|
+
RTL-SDR clients are generated from the server's `rtl_sdr` schema. The machine
|
|
124
|
+
running client code does not need `librtlsdr` or PyRtlSdr:
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from remoteRF.drivers import ensure_driver
|
|
128
|
+
|
|
129
|
+
token = "reservation-token"
|
|
130
|
+
ensure_driver(token=token)
|
|
131
|
+
|
|
132
|
+
from remoteRF.drivers.rtl_sdr import RtlSdr
|
|
133
|
+
|
|
134
|
+
sdr = RtlSdr(token)
|
|
135
|
+
sdr.sample_rate = 2_048_000
|
|
136
|
+
sdr.center_freq = 100_000_000
|
|
137
|
+
sdr.gain = "auto"
|
|
138
|
+
sdr.agc_mode = True
|
|
139
|
+
|
|
140
|
+
samples = sdr.read_samples(16_384) # NumPy complex64
|
|
141
|
+
raw_iq = sdr.read_bytes(4096) # packed uint8 I/Q bytes
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The server owns the USB handle for its lifetime, so the generated client does
|
|
145
|
+
not close the physical radio. `read_samples` and `read_bytes` are bounded to a
|
|
146
|
+
4 MiB response. Call them repeatedly for longer captures. Native asynchronous
|
|
147
|
+
callbacks are not transported remotely.
|
|
148
|
+
|
|
149
|
+
When a Tailscale address differs from the IP or DNS identity in the server
|
|
150
|
+
certificate, keep TLS verification enabled and set the expected identity:
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
export REMOTERF_ADDR=rrf2.example.ts.net:61005
|
|
154
|
+
export REMOTERF_TLS_SERVER_NAME=certificate-name.example
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## TI mmWave radar
|
|
158
|
+
|
|
159
|
+
TI radar clients are generated from the server's `ti_mmwave` schema. Only the
|
|
160
|
+
machine physically connected to the radar needs `pyserial` or a CP210x driver.
|
|
161
|
+
The initial parser profile supports xWR68xx mmWave SDK 3 out-of-box TLV output.
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from remoteRF.drivers import ensure_driver
|
|
165
|
+
|
|
166
|
+
token = "reservation-token"
|
|
167
|
+
ensure_driver(token=token)
|
|
168
|
+
|
|
169
|
+
from remoteRF.drivers.ti_mmwave import TiMmWave, decode_frame
|
|
170
|
+
|
|
171
|
+
radar = TiMmWave(token)
|
|
172
|
+
print(radar.device_info)
|
|
173
|
+
print(radar.query_version())
|
|
174
|
+
|
|
175
|
+
radar.apply_config(open("profile.cfg").read(), start=True)
|
|
176
|
+
try:
|
|
177
|
+
packet = radar.read_frame(timeout=1.0)
|
|
178
|
+
frame = decode_frame(packet)
|
|
179
|
+
print(frame.header.frame_number, frame.points, frame.side_info)
|
|
180
|
+
finally:
|
|
181
|
+
radar.stop()
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
`read_frame()` returns one complete binary UART packet. Decoding is client-local
|
|
185
|
+
and retains unknown TLVs as raw bytes, allowing custom firmware to be captured
|
|
186
|
+
before a dedicated parser profile is added. `stream_stats` reports dropped
|
|
187
|
+
frames, queued frames, resynchronization bytes, invalid headers, and reader
|
|
188
|
+
health. Remote firmware flashing is deliberately unsupported.
|
|
189
|
+
|
|
115
190
|
If `pip install` doesn't work, you can clone the [source](https://github.com/WirelessLabAtUCLA/RemoteRF-Client) directly from github.
|
|
116
191
|
|
|
117
192
|
<!-- 1. **Clone the repository:**
|
|
@@ -27,7 +27,13 @@ source venv/bin/activate # Activate virtual environment
|
|
|
27
27
|
pip install remoterf # Install remoteRF
|
|
28
28
|
```
|
|
29
29
|
|
|
30
|
-
## NI USRP-2901
|
|
30
|
+
## NI USRP-2901, Ettus B205-mini, B200-family, and USRP N210
|
|
31
|
+
|
|
32
|
+
The packaged client natively includes the shared USRP schema for the qualified
|
|
33
|
+
NI USRP-2901, Ettus Research USRP B205-mini, the broader USB/B200 family, and
|
|
34
|
+
the Ethernet-connected N210. No custom client driver is required. The B205-mini
|
|
35
|
+
uses the same native-style API and reports its live 1 RX/1 TX channel topology
|
|
36
|
+
through `remoterf_capabilities`.
|
|
31
37
|
|
|
32
38
|
After reserving a server-local `usrp` inventory entry, fetch or refresh its
|
|
33
39
|
Dynamic v2 package with the reservation token:
|
|
@@ -86,6 +92,75 @@ generic native dispatch, but are not release-qualified as exact UHD overload
|
|
|
86
92
|
parity until the server's UHD 4.10 target-introspection and hardware
|
|
87
93
|
differential gates pass.
|
|
88
94
|
|
|
95
|
+
## RTL-SDR
|
|
96
|
+
|
|
97
|
+
RTL-SDR clients are generated from the server's `rtl_sdr` schema. The machine
|
|
98
|
+
running client code does not need `librtlsdr` or PyRtlSdr:
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from remoteRF.drivers import ensure_driver
|
|
102
|
+
|
|
103
|
+
token = "reservation-token"
|
|
104
|
+
ensure_driver(token=token)
|
|
105
|
+
|
|
106
|
+
from remoteRF.drivers.rtl_sdr import RtlSdr
|
|
107
|
+
|
|
108
|
+
sdr = RtlSdr(token)
|
|
109
|
+
sdr.sample_rate = 2_048_000
|
|
110
|
+
sdr.center_freq = 100_000_000
|
|
111
|
+
sdr.gain = "auto"
|
|
112
|
+
sdr.agc_mode = True
|
|
113
|
+
|
|
114
|
+
samples = sdr.read_samples(16_384) # NumPy complex64
|
|
115
|
+
raw_iq = sdr.read_bytes(4096) # packed uint8 I/Q bytes
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The server owns the USB handle for its lifetime, so the generated client does
|
|
119
|
+
not close the physical radio. `read_samples` and `read_bytes` are bounded to a
|
|
120
|
+
4 MiB response. Call them repeatedly for longer captures. Native asynchronous
|
|
121
|
+
callbacks are not transported remotely.
|
|
122
|
+
|
|
123
|
+
When a Tailscale address differs from the IP or DNS identity in the server
|
|
124
|
+
certificate, keep TLS verification enabled and set the expected identity:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
export REMOTERF_ADDR=rrf2.example.ts.net:61005
|
|
128
|
+
export REMOTERF_TLS_SERVER_NAME=certificate-name.example
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## TI mmWave radar
|
|
132
|
+
|
|
133
|
+
TI radar clients are generated from the server's `ti_mmwave` schema. Only the
|
|
134
|
+
machine physically connected to the radar needs `pyserial` or a CP210x driver.
|
|
135
|
+
The initial parser profile supports xWR68xx mmWave SDK 3 out-of-box TLV output.
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from remoteRF.drivers import ensure_driver
|
|
139
|
+
|
|
140
|
+
token = "reservation-token"
|
|
141
|
+
ensure_driver(token=token)
|
|
142
|
+
|
|
143
|
+
from remoteRF.drivers.ti_mmwave import TiMmWave, decode_frame
|
|
144
|
+
|
|
145
|
+
radar = TiMmWave(token)
|
|
146
|
+
print(radar.device_info)
|
|
147
|
+
print(radar.query_version())
|
|
148
|
+
|
|
149
|
+
radar.apply_config(open("profile.cfg").read(), start=True)
|
|
150
|
+
try:
|
|
151
|
+
packet = radar.read_frame(timeout=1.0)
|
|
152
|
+
frame = decode_frame(packet)
|
|
153
|
+
print(frame.header.frame_number, frame.points, frame.side_info)
|
|
154
|
+
finally:
|
|
155
|
+
radar.stop()
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
`read_frame()` returns one complete binary UART packet. Decoding is client-local
|
|
159
|
+
and retains unknown TLVs as raw bytes, allowing custom firmware to be captured
|
|
160
|
+
before a dedicated parser profile is added. `stream_stats` reports dropped
|
|
161
|
+
frames, queued frames, resynchronization bytes, invalid headers, and reader
|
|
162
|
+
health. Remote firmware flashing is deliberately unsupported.
|
|
163
|
+
|
|
89
164
|
If `pip install` doesn't work, you can clone the [source](https://github.com/WirelessLabAtUCLA/RemoteRF-Client) directly from github.
|
|
90
165
|
|
|
91
166
|
<!-- 1. **Clone the repository:**
|
|
@@ -6,7 +6,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
|
|
|
6
6
|
|
|
7
7
|
setup(
|
|
8
8
|
name="remoterf",
|
|
9
|
-
version="2.0.
|
|
9
|
+
version="2.0.8",
|
|
10
10
|
author="Ethan Ge",
|
|
11
11
|
author_email="ethoGalaxy@gmail.com",
|
|
12
12
|
description="A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts.",
|
|
@@ -24,7 +24,7 @@ _sym_db = _symbol_database.Default()
|
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
|
|
27
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\ngrpc.proto\x12\tremote_rf\"\xa2\x01\n\x11GenericRPCRequest\x12\x15\n\rfunction_name\x18\x01 \x01(\t\x12\x34\n\x04\x61rgs\x18\x02 \x03(\x0b\x32&.remote_rf.GenericRPCRequest.ArgsEntry\x1a@\n\tArgsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.remote_rf.Argument:\x02\x38\x01\"\x96\x01\n\x12GenericRPCResponse\x12;\n\x07results\x18\x01 \x03(\x0b\x32*.remote_rf.GenericRPCResponse.ResultsEntry\x1a\x43\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.remote_rf.Argument:\x02\x38\x01\"\x19\n\nArrayShape\x12\x0b\n\x03\x64im\x18\x01 \x03(\x05\"+\n\rComplexNumber\x12\x0c\n\x04real\x18\x01 \x01(\x02\x12\x0c\n\x04imag\x18\x02 \x01(\x02\"a\n\x11\x43omplexNumpyArray\x12$\n\x05shape\x18\x01 \x01(\x0b\x32\x15.remote_rf.ArrayShape\x12&\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32\x18.remote_rf.ComplexNumber\"D\n\x0eRealNumpyArray\x12$\n\x05shape\x18\x01 \x01(\x0b\x32\x15.remote_rf.ArrayShape\x12\x0c\n\x04\x64\x61ta\x18\x02 \x03(\x02\"\
|
|
27
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\ngrpc.proto\x12\tremote_rf\"\xa2\x01\n\x11GenericRPCRequest\x12\x15\n\rfunction_name\x18\x01 \x01(\t\x12\x34\n\x04\x61rgs\x18\x02 \x03(\x0b\x32&.remote_rf.GenericRPCRequest.ArgsEntry\x1a@\n\tArgsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.remote_rf.Argument:\x02\x38\x01\"\x96\x01\n\x12GenericRPCResponse\x12;\n\x07results\x18\x01 \x03(\x0b\x32*.remote_rf.GenericRPCResponse.ResultsEntry\x1a\x43\n\x0cResultsEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\"\n\x05value\x18\x02 \x01(\x0b\x32\x13.remote_rf.Argument:\x02\x38\x01\"\x19\n\nArrayShape\x12\x0b\n\x03\x64im\x18\x01 \x03(\x05\"+\n\rComplexNumber\x12\x0c\n\x04real\x18\x01 \x01(\x02\x12\x0c\n\x04imag\x18\x02 \x01(\x02\"a\n\x11\x43omplexNumpyArray\x12$\n\x05shape\x18\x01 \x01(\x0b\x32\x15.remote_rf.ArrayShape\x12&\n\x04\x64\x61ta\x18\x02 \x03(\x0b\x32\x18.remote_rf.ComplexNumber\"D\n\x0eRealNumpyArray\x12$\n\x05shape\x18\x01 \x01(\x0b\x32\x15.remote_rf.ArrayShape\x12\x0c\n\x04\x64\x61ta\x18\x02 \x03(\x02\"\xb6\x02\n\x08\x41rgument\x12\x16\n\x0cstring_value\x18\x01 \x01(\tH\x00\x12\x15\n\x0bint64_value\x18\x02 \x01(\x03H\x00\x12\x15\n\x0b\x66loat_value\x18\x03 \x01(\x02H\x00\x12\x14\n\nbool_value\x18\x04 \x01(\x08H\x00\x12\x35\n\rcomplex_array\x18\x05 \x01(\x0b\x32\x1c.remote_rf.ComplexNumpyArrayH\x00\x12/\n\nreal_array\x18\x06 \x01(\x0b\x32\x19.remote_rf.RealNumpyArrayH\x00\x12\x14\n\njson_value\x18\x07 \x01(\tH\x00\x12\x15\n\x0b\x62ytes_value\x18\x08 \x01(\x0cH\x00\x12\x30\n\rndarray_value\x18\t \x01(\x0b\x32\x17.remote_rf.NDArrayValueH\x00\x42\x07\n\x05value\":\n\x0cNDArrayValue\x12\r\n\x05\x64type\x18\x01 \x01(\t\x12\r\n\x05shape\x18\x02 \x03(\x03\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\"\xe9\x01\n\x0c\x44ynamicValue\x12\x14\n\nnull_value\x18\x01 \x01(\x08H\x00\x12\x14\n\nbool_value\x18\x02 \x01(\x08H\x00\x12\x15\n\x0bint64_value\x18\x03 \x01(\x12H\x00\x12\x16\n\x0c\x64ouble_value\x18\x04 \x01(\x01H\x00\x12\x16\n\x0cstring_value\x18\x05 \x01(\tH\x00\x12\x15\n\x0b\x62ytes_value\x18\x06 \x01(\x0cH\x00\x12\x14\n\njson_value\x18\x07 \x01(\tH\x00\x12\x30\n\rndarray_value\x18\x08 \x01(\x0b\x32\x17.remote_rf.NDArrayValueH\x00\x42\x07\n\x05value\"B\n\nNamedValue\x12\x0c\n\x04name\x18\x01 \x01(\t\x12&\n\x05value\x18\x02 \x01(\x0b\x32\x17.remote_rf.DynamicValue\"B\n\x08Mutation\x12\x0e\n\x06target\x18\x01 \x01(\t\x12&\n\x05value\x18\x02 \x01(\x0b\x32\x17.remote_rf.DynamicValue\"\xb0\x01\n\rErrorEnvelope\x12\x0c\n\x04\x63ode\x18\x01 \x01(\t\x12\x0f\n\x07message\x18\x02 \x01(\t\x12\x14\n\x0c\x64\x65tails_json\x18\x03 \x01(\t\x12\x0e\n\x06method\x18\x04 \x01(\t\x12\x18\n\x10native_exception\x18\x05 \x01(\t\x12\x13\n\x0buhd_version\x18\x06 \x01(\t\x12\x11\n\tretryable\x18\x07 \x01(\x08\x12\x18\n\x10\x66\x61tal_to_session\x18\x08 \x01(\x08\"s\n\x10NegotiateRequest\x12\x17\n\x0fschema_versions\x18\x01 \x03(\t\x12!\n\x19\x63ontrol_protocol_versions\x18\x02 \x03(\t\x12#\n\x1bstreaming_protocol_versions\x18\x03 \x03(\t\"\x9a\x01\n\x11NegotiateResponse\x12\x16\n\x0eschema_version\x18\x01 \x01(\t\x12 \n\x18\x63ontrol_protocol_version\x18\x02 \x01(\t\x12\"\n\x1astreaming_protocol_version\x18\x03 \x01(\t\x12\'\n\x05\x65rror\x18\x04 \x01(\x0b\x32\x18.remote_rf.ErrorEnvelope\":\n\x10GetSchemaRequest\x12\r\n\x05token\x18\x01 \x01(\t\x12\x17\n\x0fschema_versions\x18\x02 \x03(\t\"~\n\x11GetSchemaResponse\x12\x16\n\x0eschema_version\x18\x01 \x01(\t\x12\x13\n\x0bschema_json\x18\x02 \x01(\t\x12\x13\n\x0bschema_hash\x18\x03 \x01(\t\x12\'\n\x05\x65rror\x18\x04 \x01(\x0b\x32\x18.remote_rf.ErrorEnvelope\"\x88\x01\n\x12OpenSessionRequest\x12\r\n\x05token\x18\x01 \x01(\t\x12\x1d\n\x15requested_schema_hash\x18\x02 \x01(\t\x12 \n\x18\x63ontrol_protocol_version\x18\x03 \x01(\t\x12\"\n\x1astreaming_protocol_version\x18\x04 \x01(\t\"\xee\x01\n\x13OpenSessionResponse\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x15\n\rdevice_handle\x18\x02 \x01(\t\x12\x13\n\x0bschema_json\x18\x03 \x01(\t\x12\x13\n\x0bschema_hash\x18\x04 \x01(\t\x12\x19\n\x11\x63\x61pabilities_json\x18\x05 \x01(\t\x12\x13\n\x0buhd_version\x18\x06 \x01(\t\x12\x0f\n\x07uhd_abi\x18\x07 \x01(\t\x12\x18\n\x10hardware_profile\x18\x08 \x01(\t\x12\'\n\x05\x65rror\x18\t \x01(\x0b\x32\x18.remote_rf.ErrorEnvelope\"}\n\rInvokeRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x0e\n\x06handle\x18\x02 \x01(\t\x12\x0e\n\x06method\x18\x03 \x01(\t\x12\x13\n\x0boverload_id\x18\x04 \x01(\t\x12#\n\x04\x61rgs\x18\x05 \x03(\x0b\x32\x15.remote_rf.NamedValue\"\x8a\x01\n\x0eInvokeResponse\x12\'\n\x06result\x18\x01 \x01(\x0b\x32\x17.remote_rf.DynamicValue\x12&\n\tmutations\x18\x02 \x03(\x0b\x32\x13.remote_rf.Mutation\x12\'\n\x05\x65rror\x18\x03 \x01(\x0b\x32\x18.remote_rf.ErrorEnvelope\"8\n\x12\x43loseHandleRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x0e\n\x06handle\x18\x02 \x01(\t\")\n\x13\x43loseSessionRequest\x12\x12\n\nsession_id\x18\x01 \x01(\t\"H\n\rCloseResponse\x12\x0e\n\x06\x63losed\x18\x01 \x01(\x08\x12\'\n\x05\x65rror\x18\x02 \x01(\x0b\x32\x18.remote_rf.ErrorEnvelope\"\xea\x03\n\x0bSampleFrame\x12\x12\n\nsession_id\x18\x01 \x01(\t\x12\x0e\n\x06handle\x18\x02 \x01(\t\x12\x12\n\ngeneration\x18\x03 \x01(\x04\x12\x14\n\x0coperation_id\x18\x04 \x01(\t\x12\x10\n\x08sequence\x18\x05 \x01(\x04\x12-\n\tdirection\x18\x06 \x01(\x0e\x32\x1a.remote_rf.SampleDirection\x12(\n\x04kind\x18\x07 \x01(\x0e\x32\x1a.remote_rf.SampleFrameKind\x12\r\n\x05\x64type\x18\x08 \x01(\t\x12\r\n\x05shape\x18\t \x03(\x03\x12\x10\n\x08\x63hannels\x18\n \x03(\r\x12\x14\n\x0csample_count\x18\x0b \x01(\x04\x12\x0f\n\x07payload\x18\x0c \x01(\x0c\x12\x15\n\rmetadata_json\x18\r \x01(\t\x12\x18\n\x10\x64\x65vice_time_secs\x18\x0e \x01(\x01\x12\x0f\n\x07\x63redits\x18\x0f \x01(\r\x12\x13\n\x0btimeout_sec\x18\x10 \x01(\x01\x12\x12\n\none_packet\x18\x11 \x01(\x08\x12\x15\n\rend_of_stream\x18\x12 \x01(\x08\x12\x11\n\tcancelled\x18\x13 \x01(\x08\x12\'\n\x05\x65rror\x18\x14 \x01(\x0b\x32\x18.remote_rf.ErrorEnvelope\x12\r\n\x05\x66lags\x18\x15 \x01(\x04*e\n\x0fSampleDirection\x12 \n\x1cSAMPLE_DIRECTION_UNSPECIFIED\x10\x00\x12\x17\n\x13SAMPLE_DIRECTION_RX\x10\x01\x12\x17\n\x13SAMPLE_DIRECTION_TX\x10\x02*\xf2\x01\n\x0fSampleFrameKind\x12\x1c\n\x18SAMPLE_FRAME_UNSPECIFIED\x10\x00\x12\x15\n\x11SAMPLE_FRAME_OPEN\x10\x01\x12\x18\n\x14SAMPLE_FRAME_REQUEST\x10\x02\x12\x15\n\x11SAMPLE_FRAME_DATA\x10\x03\x12\x17\n\x13SAMPLE_FRAME_RESULT\x10\x04\x12\x17\n\x13SAMPLE_FRAME_CREDIT\x10\x05\x12\x17\n\x13SAMPLE_FRAME_CANCEL\x10\x06\x12\x16\n\x12SAMPLE_FRAME_CLOSE\x10\x07\x12\x16\n\x12SAMPLE_FRAME_ERROR\x10\x08\x32Q\n\nGenericRPC\x12\x43\n\x04\x43\x61ll\x12\x1c.remote_rf.GenericRPCRequest\x1a\x1d.remote_rf.GenericRPCResponse2\xc1\x03\n\x10\x44ynamicControlV2\x12\x46\n\tNegotiate\x12\x1b.remote_rf.NegotiateRequest\x1a\x1c.remote_rf.NegotiateResponse\x12\x46\n\tGetSchema\x12\x1b.remote_rf.GetSchemaRequest\x1a\x1c.remote_rf.GetSchemaResponse\x12L\n\x0bOpenSession\x12\x1d.remote_rf.OpenSessionRequest\x1a\x1e.remote_rf.OpenSessionResponse\x12=\n\x06Invoke\x12\x18.remote_rf.InvokeRequest\x1a\x19.remote_rf.InvokeResponse\x12\x46\n\x0b\x43loseHandle\x12\x1d.remote_rf.CloseHandleRequest\x1a\x18.remote_rf.CloseResponse\x12H\n\x0c\x43loseSession\x12\x1e.remote_rf.CloseSessionRequest\x1a\x18.remote_rf.CloseResponse2R\n\x0cSampleDataV1\x12\x42\n\x0cSampleStream\x12\x16.remote_rf.SampleFrame\x1a\x16.remote_rf.SampleFrame(\x01\x30\x01\x42\x1e\n\x10\x63om.example.demoB\nDemoProtosb\x06proto3')
|
|
28
28
|
|
|
29
29
|
_globals = globals()
|
|
30
30
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
@@ -36,10 +36,10 @@ if not _descriptor._USE_C_DESCRIPTORS:
|
|
|
36
36
|
_globals['_GENERICRPCREQUEST_ARGSENTRY']._serialized_options = b'8\001'
|
|
37
37
|
_globals['_GENERICRPCRESPONSE_RESULTSENTRY']._loaded_options = None
|
|
38
38
|
_globals['_GENERICRPCRESPONSE_RESULTSENTRY']._serialized_options = b'8\001'
|
|
39
|
-
_globals['_SAMPLEDIRECTION']._serialized_start=
|
|
40
|
-
_globals['_SAMPLEDIRECTION']._serialized_end=
|
|
41
|
-
_globals['_SAMPLEFRAMEKIND']._serialized_start=
|
|
42
|
-
_globals['_SAMPLEFRAMEKIND']._serialized_end=
|
|
39
|
+
_globals['_SAMPLEDIRECTION']._serialized_start=3286
|
|
40
|
+
_globals['_SAMPLEDIRECTION']._serialized_end=3387
|
|
41
|
+
_globals['_SAMPLEFRAMEKIND']._serialized_start=3390
|
|
42
|
+
_globals['_SAMPLEFRAMEKIND']._serialized_end=3632
|
|
43
43
|
_globals['_GENERICRPCREQUEST']._serialized_start=26
|
|
44
44
|
_globals['_GENERICRPCREQUEST']._serialized_end=188
|
|
45
45
|
_globals['_GENERICRPCREQUEST_ARGSENTRY']._serialized_start=124
|
|
@@ -57,45 +57,45 @@ if not _descriptor._USE_C_DESCRIPTORS:
|
|
|
57
57
|
_globals['_REALNUMPYARRAY']._serialized_start=514
|
|
58
58
|
_globals['_REALNUMPYARRAY']._serialized_end=582
|
|
59
59
|
_globals['_ARGUMENT']._serialized_start=585
|
|
60
|
-
_globals['_ARGUMENT']._serialized_end=
|
|
61
|
-
_globals['_NDARRAYVALUE']._serialized_start=
|
|
62
|
-
_globals['_NDARRAYVALUE']._serialized_end=
|
|
63
|
-
_globals['_DYNAMICVALUE']._serialized_start=
|
|
64
|
-
_globals['_DYNAMICVALUE']._serialized_end=
|
|
65
|
-
_globals['_NAMEDVALUE']._serialized_start=
|
|
66
|
-
_globals['_NAMEDVALUE']._serialized_end=
|
|
67
|
-
_globals['_MUTATION']._serialized_start=
|
|
68
|
-
_globals['_MUTATION']._serialized_end=
|
|
69
|
-
_globals['_ERRORENVELOPE']._serialized_start=
|
|
70
|
-
_globals['_ERRORENVELOPE']._serialized_end=
|
|
71
|
-
_globals['_NEGOTIATEREQUEST']._serialized_start=
|
|
72
|
-
_globals['_NEGOTIATEREQUEST']._serialized_end=
|
|
73
|
-
_globals['_NEGOTIATERESPONSE']._serialized_start=
|
|
74
|
-
_globals['_NEGOTIATERESPONSE']._serialized_end=
|
|
75
|
-
_globals['_GETSCHEMAREQUEST']._serialized_start=
|
|
76
|
-
_globals['_GETSCHEMAREQUEST']._serialized_end=
|
|
77
|
-
_globals['_GETSCHEMARESPONSE']._serialized_start=
|
|
78
|
-
_globals['_GETSCHEMARESPONSE']._serialized_end=
|
|
79
|
-
_globals['_OPENSESSIONREQUEST']._serialized_start=
|
|
80
|
-
_globals['_OPENSESSIONREQUEST']._serialized_end=
|
|
81
|
-
_globals['_OPENSESSIONRESPONSE']._serialized_start=
|
|
82
|
-
_globals['_OPENSESSIONRESPONSE']._serialized_end=
|
|
83
|
-
_globals['_INVOKEREQUEST']._serialized_start=
|
|
84
|
-
_globals['_INVOKEREQUEST']._serialized_end=
|
|
85
|
-
_globals['_INVOKERESPONSE']._serialized_start=
|
|
86
|
-
_globals['_INVOKERESPONSE']._serialized_end=
|
|
87
|
-
_globals['_CLOSEHANDLEREQUEST']._serialized_start=
|
|
88
|
-
_globals['_CLOSEHANDLEREQUEST']._serialized_end=
|
|
89
|
-
_globals['_CLOSESESSIONREQUEST']._serialized_start=
|
|
90
|
-
_globals['_CLOSESESSIONREQUEST']._serialized_end=
|
|
91
|
-
_globals['_CLOSERESPONSE']._serialized_start=
|
|
92
|
-
_globals['_CLOSERESPONSE']._serialized_end=
|
|
93
|
-
_globals['_SAMPLEFRAME']._serialized_start=
|
|
94
|
-
_globals['_SAMPLEFRAME']._serialized_end=
|
|
95
|
-
_globals['_GENERICRPC']._serialized_start=
|
|
96
|
-
_globals['_GENERICRPC']._serialized_end=
|
|
97
|
-
_globals['_DYNAMICCONTROLV2']._serialized_start=
|
|
98
|
-
_globals['_DYNAMICCONTROLV2']._serialized_end=
|
|
99
|
-
_globals['_SAMPLEDATAV1']._serialized_start=
|
|
100
|
-
_globals['_SAMPLEDATAV1']._serialized_end=
|
|
60
|
+
_globals['_ARGUMENT']._serialized_end=895
|
|
61
|
+
_globals['_NDARRAYVALUE']._serialized_start=897
|
|
62
|
+
_globals['_NDARRAYVALUE']._serialized_end=955
|
|
63
|
+
_globals['_DYNAMICVALUE']._serialized_start=958
|
|
64
|
+
_globals['_DYNAMICVALUE']._serialized_end=1191
|
|
65
|
+
_globals['_NAMEDVALUE']._serialized_start=1193
|
|
66
|
+
_globals['_NAMEDVALUE']._serialized_end=1259
|
|
67
|
+
_globals['_MUTATION']._serialized_start=1261
|
|
68
|
+
_globals['_MUTATION']._serialized_end=1327
|
|
69
|
+
_globals['_ERRORENVELOPE']._serialized_start=1330
|
|
70
|
+
_globals['_ERRORENVELOPE']._serialized_end=1506
|
|
71
|
+
_globals['_NEGOTIATEREQUEST']._serialized_start=1508
|
|
72
|
+
_globals['_NEGOTIATEREQUEST']._serialized_end=1623
|
|
73
|
+
_globals['_NEGOTIATERESPONSE']._serialized_start=1626
|
|
74
|
+
_globals['_NEGOTIATERESPONSE']._serialized_end=1780
|
|
75
|
+
_globals['_GETSCHEMAREQUEST']._serialized_start=1782
|
|
76
|
+
_globals['_GETSCHEMAREQUEST']._serialized_end=1840
|
|
77
|
+
_globals['_GETSCHEMARESPONSE']._serialized_start=1842
|
|
78
|
+
_globals['_GETSCHEMARESPONSE']._serialized_end=1968
|
|
79
|
+
_globals['_OPENSESSIONREQUEST']._serialized_start=1971
|
|
80
|
+
_globals['_OPENSESSIONREQUEST']._serialized_end=2107
|
|
81
|
+
_globals['_OPENSESSIONRESPONSE']._serialized_start=2110
|
|
82
|
+
_globals['_OPENSESSIONRESPONSE']._serialized_end=2348
|
|
83
|
+
_globals['_INVOKEREQUEST']._serialized_start=2350
|
|
84
|
+
_globals['_INVOKEREQUEST']._serialized_end=2475
|
|
85
|
+
_globals['_INVOKERESPONSE']._serialized_start=2478
|
|
86
|
+
_globals['_INVOKERESPONSE']._serialized_end=2616
|
|
87
|
+
_globals['_CLOSEHANDLEREQUEST']._serialized_start=2618
|
|
88
|
+
_globals['_CLOSEHANDLEREQUEST']._serialized_end=2674
|
|
89
|
+
_globals['_CLOSESESSIONREQUEST']._serialized_start=2676
|
|
90
|
+
_globals['_CLOSESESSIONREQUEST']._serialized_end=2717
|
|
91
|
+
_globals['_CLOSERESPONSE']._serialized_start=2719
|
|
92
|
+
_globals['_CLOSERESPONSE']._serialized_end=2791
|
|
93
|
+
_globals['_SAMPLEFRAME']._serialized_start=2794
|
|
94
|
+
_globals['_SAMPLEFRAME']._serialized_end=3284
|
|
95
|
+
_globals['_GENERICRPC']._serialized_start=3634
|
|
96
|
+
_globals['_GENERICRPC']._serialized_end=3715
|
|
97
|
+
_globals['_DYNAMICCONTROLV2']._serialized_start=3718
|
|
98
|
+
_globals['_DYNAMICCONTROLV2']._serialized_end=4167
|
|
99
|
+
_globals['_SAMPLEDATAV1']._serialized_start=4169
|
|
100
|
+
_globals['_SAMPLEDATAV1']._serialized_end=4251
|
|
101
101
|
# @@protoc_insertion_point(module_scope)
|
|
@@ -1,10 +1,55 @@
|
|
|
1
|
-
|
|
1
|
+
"""Serialization helpers for the legacy GenericRPC protocol."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
2
4
|
import json
|
|
5
|
+
import math
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
3
8
|
import numpy as np
|
|
4
9
|
|
|
10
|
+
from ..grpc import grpc_pb2
|
|
11
|
+
|
|
5
12
|
_JSON_TYPE_KEY = "__remoterf_json_type__"
|
|
13
|
+
_MAX_NDARRAY_BYTES = 64 * 1024 * 1024
|
|
14
|
+
_MAX_NDARRAY_DIMENSIONS = 8
|
|
15
|
+
_SUPPORTED_NDARRAY_KINDS = {"b", "i", "u", "f", "c"}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _validate_ndarray(dtype: np.dtype, shape) -> int:
|
|
19
|
+
"""Return the expected payload length for a safe numeric ndarray."""
|
|
20
|
+
if dtype.hasobject or dtype.kind not in _SUPPORTED_NDARRAY_KINDS:
|
|
21
|
+
raise ValueError(f"unsupported ndarray dtype: {dtype}")
|
|
22
|
+
|
|
23
|
+
normalized_shape = tuple(int(item) for item in shape)
|
|
24
|
+
if (
|
|
25
|
+
len(normalized_shape) > _MAX_NDARRAY_DIMENSIONS
|
|
26
|
+
or any(item < 0 for item in normalized_shape)
|
|
27
|
+
):
|
|
28
|
+
raise ValueError("invalid ndarray shape")
|
|
29
|
+
|
|
30
|
+
expected = math.prod(normalized_shape) * dtype.itemsize
|
|
31
|
+
if expected > _MAX_NDARRAY_BYTES:
|
|
32
|
+
raise ValueError(f"ndarray exceeds {_MAX_NDARRAY_BYTES} bytes")
|
|
33
|
+
return expected
|
|
6
34
|
|
|
7
|
-
|
|
35
|
+
|
|
36
|
+
def _decode_ndarray(descriptor: grpc_pb2.NDArrayValue) -> np.ndarray:
|
|
37
|
+
try:
|
|
38
|
+
dtype = np.dtype(descriptor.dtype)
|
|
39
|
+
except (TypeError, ValueError) as exc:
|
|
40
|
+
raise ValueError(f"invalid ndarray dtype: {descriptor.dtype!r}") from exc
|
|
41
|
+
|
|
42
|
+
shape = tuple(int(item) for item in descriptor.shape)
|
|
43
|
+
expected = _validate_ndarray(dtype, shape)
|
|
44
|
+
actual = len(descriptor.data)
|
|
45
|
+
if actual != expected:
|
|
46
|
+
raise ValueError(
|
|
47
|
+
f"ndarray byte length mismatch: expected {expected}, got {actual}"
|
|
48
|
+
)
|
|
49
|
+
return np.frombuffer(descriptor.data, dtype=dtype).reshape(shape).copy()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _json_safe(value: Any):
|
|
8
53
|
if hasattr(value, "as_payload"):
|
|
9
54
|
return _json_safe(value.as_payload())
|
|
10
55
|
if isinstance(value, np.ndarray):
|
|
@@ -27,21 +72,26 @@ def _json_safe(value):
|
|
|
27
72
|
"complex": False,
|
|
28
73
|
"data": array.tolist(),
|
|
29
74
|
}
|
|
30
|
-
if isinstance(value,
|
|
75
|
+
if isinstance(value, np.bool_):
|
|
31
76
|
return bool(value)
|
|
32
|
-
if isinstance(value,
|
|
77
|
+
if isinstance(value, np.integer):
|
|
33
78
|
return int(value)
|
|
34
|
-
if isinstance(value,
|
|
79
|
+
if isinstance(value, np.floating):
|
|
35
80
|
return float(value)
|
|
36
81
|
if isinstance(value, complex):
|
|
37
|
-
return {
|
|
82
|
+
return {
|
|
83
|
+
_JSON_TYPE_KEY: "complex",
|
|
84
|
+
"real": float(value.real),
|
|
85
|
+
"imag": float(value.imag),
|
|
86
|
+
}
|
|
38
87
|
if isinstance(value, dict):
|
|
39
88
|
return {str(key): _json_safe(item) for key, item in value.items()}
|
|
40
89
|
if isinstance(value, (list, tuple)):
|
|
41
90
|
return [_json_safe(item) for item in value]
|
|
42
91
|
return value
|
|
43
92
|
|
|
44
|
-
|
|
93
|
+
|
|
94
|
+
def _json_restore(value: Any):
|
|
45
95
|
if isinstance(value, dict):
|
|
46
96
|
kind = value.get(_JSON_TYPE_KEY)
|
|
47
97
|
if kind == "ndarray":
|
|
@@ -58,30 +108,36 @@ def _json_restore(value):
|
|
|
58
108
|
return [_json_restore(item) for item in value]
|
|
59
109
|
return value
|
|
60
110
|
|
|
61
|
-
|
|
62
|
-
|
|
111
|
+
|
|
112
|
+
def unmap_arg(arg: grpc_pb2.Argument):
|
|
113
|
+
kind = arg.WhichOneof("value")
|
|
114
|
+
if kind == "int64_value":
|
|
63
115
|
return arg.int64_value
|
|
64
|
-
|
|
116
|
+
if kind == "float_value":
|
|
65
117
|
return arg.float_value
|
|
66
|
-
|
|
118
|
+
if kind == "string_value":
|
|
67
119
|
return arg.string_value
|
|
68
|
-
|
|
120
|
+
if kind == "bool_value":
|
|
69
121
|
return arg.bool_value
|
|
70
|
-
|
|
122
|
+
if kind == "ndarray_value":
|
|
123
|
+
return _decode_ndarray(arg.ndarray_value)
|
|
124
|
+
if kind == "real_array":
|
|
71
125
|
shape = tuple(arg.real_array.shape.dim)
|
|
72
126
|
return np.array(arg.real_array.data, dtype=np.float64).reshape(shape)
|
|
73
|
-
|
|
127
|
+
if kind == "complex_array":
|
|
74
128
|
shape = tuple(arg.complex_array.shape.dim)
|
|
75
|
-
data = [complex(
|
|
129
|
+
data = [complex(item.real, item.imag) for item in arg.complex_array.data]
|
|
76
130
|
return np.array(data, dtype=np.complex64).reshape(shape)
|
|
77
|
-
|
|
131
|
+
if kind == "json_value":
|
|
78
132
|
return _json_restore(json.loads(arg.json_value))
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
133
|
+
if kind == "bytes_value":
|
|
134
|
+
return bytes(arg.bytes_value)
|
|
135
|
+
raise ValueError(f"Unknown argument type during unmapping: {arg}")
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def map_arg(value: Any) -> grpc_pb2.Argument:
|
|
83
139
|
arg = grpc_pb2.Argument()
|
|
84
|
-
|
|
140
|
+
|
|
85
141
|
if isinstance(value, (bool, np.bool_)):
|
|
86
142
|
arg.bool_value = bool(value)
|
|
87
143
|
elif hasattr(value, "as_payload"):
|
|
@@ -94,6 +150,8 @@ def map_arg(value):
|
|
|
94
150
|
arg.float_value = float(value)
|
|
95
151
|
elif isinstance(value, str):
|
|
96
152
|
arg.string_value = value
|
|
153
|
+
elif isinstance(value, (bytes, bytearray, memoryview)):
|
|
154
|
+
arg.bytes_value = bytes(value)
|
|
97
155
|
elif isinstance(value, (list, tuple)):
|
|
98
156
|
try:
|
|
99
157
|
array = np.asarray(value)
|
|
@@ -110,51 +168,33 @@ def map_arg(value):
|
|
|
110
168
|
elif isinstance(value, np.ndarray):
|
|
111
169
|
if value.dtype == object:
|
|
112
170
|
raise ValueError(f"Cannot map object-dtype array: {value!r}")
|
|
113
|
-
if value.dtype.kind not in
|
|
114
|
-
arg.json_value = json.dumps(
|
|
171
|
+
if value.dtype.kind not in _SUPPORTED_NDARRAY_KINDS:
|
|
172
|
+
arg.json_value = json.dumps(
|
|
173
|
+
_json_safe(value.tolist()), separators=(",", ":")
|
|
174
|
+
)
|
|
115
175
|
return arg
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
float_array.shape.dim.extend(value.shape)
|
|
126
|
-
float_array.data.extend(np.asarray(value, dtype=np.float32).ravel())
|
|
176
|
+
|
|
177
|
+
array = np.asarray(value)
|
|
178
|
+
_validate_ndarray(array.dtype, array.shape)
|
|
179
|
+
if not array.flags.c_contiguous:
|
|
180
|
+
array = np.ascontiguousarray(array)
|
|
181
|
+
descriptor = arg.ndarray_value
|
|
182
|
+
descriptor.dtype = array.dtype.str
|
|
183
|
+
descriptor.shape.extend(array.shape)
|
|
184
|
+
descriptor.data = array.tobytes(order="C")
|
|
127
185
|
else:
|
|
128
186
|
raise ValueError(f"Unknown argument type during mapping: {value}")
|
|
129
187
|
return arg
|
|
130
|
-
|
|
131
|
-
def map_array_proto(np_array):
|
|
132
|
-
arg = grpc_pb2.Argument()
|
|
133
|
-
|
|
134
|
-
# Check if the array is complex
|
|
135
|
-
if np.iscomplexobj(np_array):
|
|
136
|
-
complex_array = grpc_pb2.ComplexArray()
|
|
137
|
-
for num in np_array.flat:
|
|
138
|
-
complex_number = complex_array.data.add()
|
|
139
|
-
complex_number.real = num.real
|
|
140
|
-
complex_number.imag = num.imag
|
|
141
|
-
arg.complex_array.CopyFrom(complex_array)
|
|
142
|
-
else:
|
|
143
|
-
# Handle as a regular float array
|
|
144
|
-
float_array = grpc_pb2.FloatArray()
|
|
145
|
-
float_array.data.extend(np_array.flat)
|
|
146
|
-
arg.float_array.CopyFrom(float_array)
|
|
147
188
|
|
|
148
|
-
return arg
|
|
149
189
|
|
|
150
|
-
def
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
else:
|
|
190
|
+
def map_array_proto(np_array) -> grpc_pb2.Argument:
|
|
191
|
+
"""Backward-compatible wrapper around :func:`map_arg`."""
|
|
192
|
+
return map_arg(np.asarray(np_array))
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def unmap_array_proto(arg: grpc_pb2.Argument) -> np.ndarray:
|
|
196
|
+
"""Backward-compatible array-only wrapper around :func:`unmap_arg`."""
|
|
197
|
+
value = unmap_arg(arg)
|
|
198
|
+
if not isinstance(value, np.ndarray):
|
|
160
199
|
raise ValueError("Argument does not contain a recognizable array.")
|
|
200
|
+
return value
|
|
@@ -49,6 +49,18 @@ options = [
|
|
|
49
49
|
('grpc.max_receive_message_length', 100 * 1024 * 1024),
|
|
50
50
|
]
|
|
51
51
|
|
|
52
|
+
# A server reached over Tailscale may present the same certificate it uses on
|
|
53
|
+
# its public or LAN address. Keep certificate verification enabled while
|
|
54
|
+
# allowing the configured certificate identity to differ from REMOTERF_ADDR.
|
|
55
|
+
tls_server_name = (os.getenv("REMOTERF_TLS_SERVER_NAME") or "").strip()
|
|
56
|
+
if tls_server_name:
|
|
57
|
+
options.extend(
|
|
58
|
+
[
|
|
59
|
+
("grpc.ssl_target_name_override", tls_server_name),
|
|
60
|
+
("grpc.default_authority", tls_server_name),
|
|
61
|
+
]
|
|
62
|
+
)
|
|
63
|
+
|
|
52
64
|
# Server.crt
|
|
53
65
|
certs_path = Path(ca_path).expanduser().resolve()
|
|
54
66
|
with certs_path.open('rb') as f:
|