remoterf 0.1.0.3__py3-none-any.whl

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.
@@ -0,0 +1,203 @@
1
+ # src/remoteRF/cli.py
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import sys
6
+ from typing import Optional, Sequence
7
+
8
+ import sys
9
+
10
+ from pathlib import Path
11
+
12
+ def _config_root() -> Path:
13
+ return Path.home() / ".config" / "remoterf"
14
+
15
+ def _env_path() -> Path:
16
+ return _config_root() / ".env"
17
+
18
+ def _read_dotenv_kv(path: Path) -> dict[str, str]:
19
+ """
20
+ Tiny dotenv reader (KEY=VALUE lines). Good enough for your use-case.
21
+ """
22
+ out: dict[str, str] = {}
23
+ if not path.exists():
24
+ return out
25
+
26
+ for raw in path.read_text(encoding="utf-8").splitlines():
27
+ line = raw.strip()
28
+ if not line or line.startswith("#") or "=" not in line:
29
+ continue
30
+ k, v = line.split("=", 1)
31
+ k = k.strip()
32
+ v = v.strip().strip('"').strip("'")
33
+ out[k] = v
34
+ return out
35
+
36
+ def _ensure_config_present() -> tuple[bool, str]:
37
+ env_file = _env_path()
38
+ if not env_file.exists():
39
+ return (
40
+ False,
41
+ "RemoteRF is not configured.\n"
42
+ "Run:\n"
43
+ " remoterf --config --addr <host:port>\n"
44
+ "Example:\n"
45
+ " remoterf --config --addr 123.45.654.321:12321\n",
46
+ )
47
+
48
+ kv = _read_dotenv_kv(env_file)
49
+ addr = kv.get("REMOTERF_ADDR", "").strip()
50
+ ca = kv.get("REMOTERF_CA_CERT", "").strip()
51
+
52
+ if not addr or not ca:
53
+ return (
54
+ False,
55
+ "RemoteRF config is incomplete.\n"
56
+ f"Expected REMOTERF_ADDR and REMOTERF_CA_CERT in:\n {env_file}\n"
57
+ "Fix by re-running:\n"
58
+ " remoterf --config --addr <host:port>\n",
59
+ )
60
+
61
+ ca_path = Path(ca).expanduser()
62
+ if not ca_path.exists():
63
+ return (
64
+ False,
65
+ "RemoteRF config points to a missing CA certificate.\n"
66
+ f"REMOTERF_CA_CERT={ca}\n"
67
+ "Fix by re-running:\n"
68
+ " remoterf --config --addr <host:port>\n",
69
+ )
70
+
71
+ return True, ""
72
+
73
+ def print_help() -> None:
74
+ print(
75
+ "RemoteRF CLI Help\n"
76
+ "\n"
77
+ "Usage:\n"
78
+ " remoterf Show this help\n"
79
+ " remoterf -h | --help Show this help\n"
80
+ "\n"
81
+ " remoterf -l | --login Login / register\n"
82
+ " remoterf -v | --version Print version\n"
83
+ "\n"
84
+ " remoterf -c | --config [options]\n"
85
+ " -a, --addr, -addr <host:port> Set target server \n"
86
+ " -w, --wipe, -wipe Delete all local config\n"
87
+ " -y, --yes, -yes Skip wipe confirmation\n"
88
+ "\n"
89
+ "Examples:\n"
90
+ " remoterf --login\n"
91
+ " remoterf --version\n"
92
+ " remoterf --config --addr 123.45.654.321:12321\n"
93
+ " remoterf --config --wipe\n"
94
+ " remoterf --config --wipe --yes\n"
95
+ )
96
+
97
+ def main() -> int:
98
+ argv = list(sys.argv[1:])
99
+
100
+ # ---- Debug ----
101
+ # print(f"argc={len(argv)}")
102
+ # for i, a in enumerate(argv):
103
+ # print(f"argv[{i}] = {a!r}")
104
+
105
+ if len(argv) == 0 or argv[0] in ("--help", "-help", "-h"):
106
+ print_help()
107
+ return 0
108
+
109
+ if argv[0] in ("--login", "-login", "-l"):
110
+ ok, msg = _ensure_config_present()
111
+ if not ok:
112
+ print(msg)
113
+ return 2
114
+
115
+ from remoteRF.core.acc_login import main as _
116
+ return 0
117
+
118
+ if argv[0] in ("--version", "-version", "-v"):
119
+ from remoteRF.core.version import main as version_main
120
+
121
+ print("RemoteRF version:", end=" ")
122
+ version_main()
123
+ return 0
124
+
125
+ if argv[0] in ("--config", "-config", "-c"):
126
+ from remoteRF.config.config import configure, wipe_config
127
+
128
+ addr = None
129
+ wipe = False
130
+ yes = False
131
+
132
+ i = 1
133
+ while i < len(argv):
134
+ tok = argv[i]
135
+
136
+ if tok in ("--addr", "-a", "-addr"):
137
+ if i + 1 >= len(argv):
138
+ print("ERROR: missing required argument after --addr/-a/-addr")
139
+ return 2
140
+ addr = argv[i + 1]
141
+ i += 2
142
+ continue
143
+
144
+ if tok in ("--wipe", "-w", "-wipe"):
145
+ wipe = True
146
+ i += 1
147
+ continue
148
+
149
+ if tok in ("--yes", "-y", "-yes"):
150
+ yes = True
151
+ i += 1
152
+ continue
153
+
154
+ print(f"ERROR: unknown config argument: {tok!r}")
155
+ return 2
156
+
157
+ # Mirror remoterf-config behavior:
158
+ if wipe and addr is not None:
159
+ print("ERROR: cannot use --wipe and --addr together")
160
+ return 2
161
+
162
+ if wipe:
163
+ # wipe_config returns the proper exit code
164
+ return int(wipe_config(yes=yes))
165
+
166
+ if addr is not None:
167
+ # parse host:port (minimal, strict)
168
+ s = addr.strip()
169
+ if "://" in s:
170
+ s = s.split("://", 1)[1]
171
+ if ":" not in s:
172
+ print("ERROR: addr must be in 'host:port' form")
173
+ return 2
174
+
175
+ host, port_str = s.rsplit(":", 1)
176
+ host = host.strip()
177
+ try:
178
+ port = int(port_str.strip())
179
+ except Exception:
180
+ print("ERROR: port must be an integer")
181
+ return 2
182
+
183
+ # configure returns the proper exit code
184
+ cert_port = port + 1
185
+ configure(host, port, cert_port)
186
+ return 0
187
+
188
+ # No args -> same behavior as remoterf-config missing addr (exit code 2)
189
+ print(
190
+ "\nError: missing required argument: host:port\n\n"
191
+ "Usage:\n"
192
+ " remoterf --config --addr <host:port>\n"
193
+ " remoterf -c -a <host:port>\n"
194
+ " remoterf --config --wipe [--yes]\n\n"
195
+ "Example:\n"
196
+ " remoterf --config --addr 123.45.678.901:12345\n"
197
+ )
198
+ return 2
199
+
200
+
201
+ # fallback
202
+ print(f"ERROR: unknown command: {argv[0]!r}")
203
+ return 2
@@ -0,0 +1,158 @@
1
+ Metadata-Version: 2.4
2
+ Name: remoterf
3
+ Version: 0.1.0.3
4
+ Summary: A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts.
5
+ Author: Ethan Ge
6
+ Author-email: ethoGalaxy@gmail.com
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.10
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: grpcio==1.71.0
13
+ Requires-Dist: protobuf<6.0.0,>=5.0.0
14
+ Requires-Dist: numpy
15
+ Requires-Dist: prompt_toolkit
16
+ Requires-Dist: python-dotenv
17
+ Requires-Dist: prompt-toolkit
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: requires-dist
24
+ Dynamic: requires-python
25
+ Dynamic: summary
26
+
27
+ # Remote RF
28
+
29
+ A python API to remotely access signal centric hardware.
30
+
31
+ Courtesy of Wireless Lab @ UCLA. - Ethan Ge
32
+
33
+ ## Prerequisites
34
+
35
+ - **Python 3.10**: This package works in Python 3.10+. If you don’t have Python installed, you can download it from the [official Python website](https://www.python.org/downloads/).
36
+
37
+ To check your current Python version, open a terminal and run:
38
+
39
+ ```bash
40
+ python --version
41
+ ```
42
+
43
+ - **UCLA VPN**: Please ensure that you are connected to the UCLA VPN. You can download and configure the VPN client from the following link: [UCLA VPN Client Download](https://www.it.ucla.edu/it-support-center/services/virtual-private-network-vpn-clients). If you’re not connected to the VPN, you will not have access to the lab servers.
44
+
45
+ ## Installation
46
+
47
+ Use the package manager [pip](https://pip.pypa.io/en/stable/) to install remoteRF. It is recommended that you install this package within a [virtual environment](https://docs.python.org/3/library/venv.html).
48
+
49
+ ```bash
50
+ python3 -m venv venv # Create virtual environment
51
+ source venv/bin/activate # Activate virtual environment
52
+
53
+ pip install remoterf # Install remoteRF
54
+ ```
55
+
56
+ If `pip install` doesn't work, you can clone the [source](https://github.com/WirelessLabAtUCLA/RemoteRF-Client) directly from github.
57
+
58
+ <!-- 1. **Clone the repository:**
59
+ ```bash
60
+ git clone https://github.com/WirelessLabAtUCLA/RemoteRF-Client
61
+ cd repository-name
62
+ ```
63
+ 2. **Install the package using** `pip` **in editable mode:**
64
+ ```bash
65
+ pip install -e .
66
+ ```
67
+ This command installs the package in "editable" mode, allowing for modifications to the local code without reinstalling. For more details on installing packages from local directories, refer to Python Packaging: [Installing from Local Archives](https://packaging.python.org/en/latest/tutorials/installing-packages/#installing-packages-from-local-archives). -->
68
+ <!--
69
+ ## Reservation
70
+
71
+ Usage of the platform requires you to register a account and reserve a device in order to run scripts remotely.
72
+
73
+ ### 1. **Start UCLA VPN**
74
+
75
+ - Start the CISCO Secure client, login and connect to any of the options.
76
+
77
+ ### 2. **Register a account**:
78
+ ```bash
79
+ remoterf-login
80
+ # Run in the terminal
81
+ # where the Python library is installed
82
+
83
+ # Typically, this will be the terminal where you’ve activated the virtual environment if you’re using one
84
+ ```
85
+
86
+ - Input `r` to register a account, or `l` to login to a existing one.
87
+
88
+ ```bash
89
+ Welcome to Remote RF Account System.
90
+ Please login or register to continue. (l/r):
91
+ ```
92
+
93
+ - Once in, input `help` to see all avaliable commands.
94
+
95
+ ### 3. **Reserve Device**:
96
+ ```bash
97
+ getdev # To view all avaliable devices
98
+
99
+ # Note the device ID. You will need this later to reserve said device
100
+ ```
101
+
102
+ ```bash
103
+ getres # To view times not avaliable
104
+
105
+ # Optionally, you can also view all reservations, and determine a time slot you want a specific device reserved
106
+ ```
107
+ ```bash
108
+ perms # To view your permissions
109
+
110
+ # Depending on your permission levels, you will be given different restrictions
111
+ ```
112
+
113
+ ```bash
114
+ resdev # To reserve a device
115
+
116
+ # Input the number of days you want to view, and it will display available reservations in that time span.
117
+
118
+ Reservation successful. Thy Token -> example_token
119
+
120
+ # Take note of this token. You will need it to actually access the device.
121
+ ```
122
+
123
+ ## Remote Access
124
+
125
+ With this token, you can now run scripts remotely. Please keep in mind that you MUST be connected to the UCLA VPN for this to work.
126
+ Here is a explained sample script to get you going!
127
+
128
+ #### Python Script:
129
+
130
+ ```python
131
+ from remoteRF.drivers.adalm_pluto import * # Imports device Pluto SDR remote drivers. Change depending on desired device.
132
+
133
+ sdr = adi.Pluto( # Device initialization.
134
+ token = 'example_token' # Place the prior token here.
135
+ )
136
+
137
+ # You can now use this 'sdr' as you normally would with the default Pluto drivers.
138
+ ```
139
+
140
+ If converting a existing `non-remoteRF` compatible script:
141
+
142
+ ```diff
143
+ - import existing_device_drivers
144
+
145
+ + from remoteRF.drivers.device_drivers import *
146
+
147
+ - device = device(init)
148
+
149
+ + device = device(token = 'sample_token')
150
+ ```
151
+
152
+ Nothing else needs changing!
153
+
154
+ ## Closing
155
+
156
+ This is fundamentally a experimental platform, and there will be many unknown bugs and issues. Some devices do not have universal support for all its functions at the moment, I am working on that aspect.
157
+
158
+ **So please submit feedback!** -->
@@ -0,0 +1,28 @@
1
+ remoteRF/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ remoteRF/remoterf_cli.py,sha256=Oi9uFM6h6xDIV3tbRa6jeKXwUfNo5EI3EsuFGmB8QlU,5924
3
+ remoteRF/common/__init__.py,sha256=8naT0ZphJxv_6uz7RRGvqfNB-UEznkzipJSVPD5n6iM,40
4
+ remoteRF/common/grpc/__init__.py,sha256=GYLHC7riDbjdx2cNOhWymt0GLZ4mtGhuzZAXVRfNynw,37
5
+ remoteRF/common/grpc/grpc_pb2.py,sha256=iMdLw3xly_2WjirEmVaxf7I8iiUmk-3YRqqIiRdNkPs,4082
6
+ remoteRF/common/grpc/grpc_pb2_grpc.py,sha256=NofKaB3t0nAm_uxDgA5WXhWcsRWqsyfuMEEdBrosVKk,3368
7
+ remoteRF/common/utils/__init__.py,sha256=JTP8gH-340HZI4F8oagPW-kxRCoVUnQB-_acmgXPaK4,204
8
+ remoteRF/common/utils/ansi_codes.py,sha256=knGLOJK-lyDjfQHL0Upq5UPTg6J_6WYldga-ZOaerSs,3052
9
+ remoteRF/common/utils/api_token.py,sha256=CdgnAIcKqhkJB_XqrshgJVZzfQIO-xeR8hVMi5bYPSI,1260
10
+ remoteRF/common/utils/list_string.py,sha256=qsch666vX2e3CZ2W5EdYi62dOk37k1v2yPpHHm47a7A,156
11
+ remoteRF/common/utils/process_arg.py,sha256=J1REqgjm-1daqTBdVASgDd-16y-KneOJpCZXPEOklVk,2971
12
+ remoteRF/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
+ remoteRF/config/cert_fetcher.py,sha256=6vOI_v3E36tnS0Lao2pM9t9vX-LuMabQuYBOB2I0wn4,3411
14
+ remoteRF/config/config.py,sha256=Nf-2omCMsYrq2VYsrKpsa6YenK2lzwJPgBwginU_v5w,3744
15
+ remoteRF/core/__init__.py,sha256=XQiCe8kyzM7XLxA883-uDndBmbr-NXo1uvtMJT2h6oA,73
16
+ remoteRF/core/acc_login.py,sha256=UcY3rDLAwHoJ9lYXRfm26z_6yJX0JSoKv-u1mF6n0Gs,49
17
+ remoteRF/core/app.py,sha256=fdGlgsy_l9eoe80gafs03wR3fiKE4oATuRtcPNaCrc8,27004
18
+ remoteRF/core/grpc_acc.py,sha256=iU3earnmoRhMctL1LBxuwDqB9fppx1JH745EEfI2gB0,2862
19
+ remoteRF/core/grpc_client.py,sha256=RqEKQs5GLZC4fiWTZwtdaFznUVAcQMWaVBAHyrPwO5s,9824
20
+ remoteRF/core/version.py,sha256=iMcmRB5ZxCliJZgPU6utwCia5M9HJ-J8E-LpPmcEgS8,182
21
+ remoteRF/drivers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ remoteRF/drivers/adalm_pluto/__init__.py,sha256=_IOOeQXR6paCP7Eciw2aeKBUNvZs-jeBTwW8QqUlFyU,33
23
+ remoteRF/drivers/adalm_pluto/pluto_remote.py,sha256=6TTp6v6HCXnULHFh90GVbLDWk7RXY2oZo7iiCl8EZdI,7460
24
+ remoterf-0.1.0.3.dist-info/METADATA,sha256=FMpjPaOEyhrbCQKnFPtCoeL2unS2mWqL67-QJhixoRE,5163
25
+ remoterf-0.1.0.3.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
26
+ remoterf-0.1.0.3.dist-info/entry_points.txt,sha256=La_TjAqCfqdcVTVjB2WrsJNn5rfgcuIYroe2v-CMwRQ,56
27
+ remoterf-0.1.0.3.dist-info/top_level.txt,sha256=XQJoVTmAOsHV9qtPSP_QSh0ma4jKxsDkxn4IjM_ZuZk,9
28
+ remoterf-0.1.0.3.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ remoterf = remoteRF.remoterf_cli:main
@@ -0,0 +1 @@
1
+ remoteRF