remoterf 0.0.7.27__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.
Potentially problematic release.
This version of remoterf might be problematic. Click here for more details.
- remoterf-0.0.7.27/LICENSE +21 -0
- remoterf-0.0.7.27/MANIFEST.in +2 -0
- remoterf-0.0.7.27/PKG-INFO +150 -0
- remoterf-0.0.7.27/README.md +133 -0
- remoterf-0.0.7.27/setup.cfg +4 -0
- remoterf-0.0.7.27/setup.py +33 -0
- remoterf-0.0.7.27/src/remoteRF/__init__.py +0 -0
- remoterf-0.0.7.27/src/remoteRF/common/__init__.py +2 -0
- remoterf-0.0.7.27/src/remoteRF/common/grpc/__init__.py +1 -0
- remoterf-0.0.7.27/src/remoteRF/common/grpc/grpc_pb2.py +59 -0
- remoterf-0.0.7.27/src/remoteRF/common/grpc/grpc_pb2_grpc.py +97 -0
- remoterf-0.0.7.27/src/remoteRF/common/utils/__init__.py +4 -0
- remoterf-0.0.7.27/src/remoteRF/common/utils/ansi_codes.py +120 -0
- remoterf-0.0.7.27/src/remoteRF/common/utils/api_token.py +31 -0
- remoterf-0.0.7.27/src/remoteRF/common/utils/list_string.py +5 -0
- remoterf-0.0.7.27/src/remoteRF/common/utils/process_arg.py +80 -0
- remoterf-0.0.7.27/src/remoteRF/core/__init__.py +2 -0
- remoterf-0.0.7.27/src/remoteRF/core/acc_login.py +4 -0
- remoterf-0.0.7.27/src/remoteRF/core/app.py +481 -0
- remoterf-0.0.7.27/src/remoteRF/core/certs/__init__.py +0 -0
- remoterf-0.0.7.27/src/remoteRF/core/certs/ca.crt +32 -0
- remoterf-0.0.7.27/src/remoteRF/core/certs/ca.key +52 -0
- remoterf-0.0.7.27/src/remoteRF/core/certs/cert.pem +19 -0
- remoterf-0.0.7.27/src/remoteRF/core/certs/key.pem +28 -0
- remoterf-0.0.7.27/src/remoteRF/core/certs/server.crt +19 -0
- remoterf-0.0.7.27/src/remoteRF/core/certs/server.key +28 -0
- remoterf-0.0.7.27/src/remoteRF/core/grpc_acc.py +52 -0
- remoterf-0.0.7.27/src/remoteRF/core/grpc_client.py +97 -0
- remoterf-0.0.7.27/src/remoteRF/drivers/__init__.py +0 -0
- remoterf-0.0.7.27/src/remoteRF/drivers/adalm_pluto/__init__.py +1 -0
- remoterf-0.0.7.27/src/remoteRF/drivers/adalm_pluto/pluto_remote.py +250 -0
- remoterf-0.0.7.27/src/remoteRF.egg-info/PKG-INFO +150 -0
- remoterf-0.0.7.27/src/remoteRF.egg-info/SOURCES.txt +41 -0
- remoterf-0.0.7.27/src/remoteRF.egg-info/dependency_links.txt +1 -0
- remoterf-0.0.7.27/src/remoteRF.egg-info/entry_points.txt +2 -0
- remoterf-0.0.7.27/src/remoteRF.egg-info/requires.txt +5 -0
- remoterf-0.0.7.27/src/remoteRF.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Ethan Ge
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: remoterf
|
|
3
|
+
Version: 0.0.7.27
|
|
4
|
+
Summary: A python API to remotely access signal centric hardware. Client-side only!
|
|
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
|
|
14
|
+
Requires-Dist: numpy
|
|
15
|
+
Requires-Dist: prompt_toolkit
|
|
16
|
+
Requires-Dist: python-dotenv
|
|
17
|
+
|
|
18
|
+
# Remote RF
|
|
19
|
+
|
|
20
|
+
A python API to remotely access signal centric hardware.
|
|
21
|
+
|
|
22
|
+
Courtesy of Wireless Lab @ UCLA. - Ethan Ge
|
|
23
|
+
|
|
24
|
+
## Prerequisites
|
|
25
|
+
|
|
26
|
+
- **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/).
|
|
27
|
+
|
|
28
|
+
To check your current Python version, open a terminal and run:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
python --version
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- **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.
|
|
35
|
+
|
|
36
|
+
## Installation
|
|
37
|
+
|
|
38
|
+
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).
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
python3 -m venv venv # Create virtual environment
|
|
42
|
+
source venv/bin/activate # Activate virtual environment
|
|
43
|
+
|
|
44
|
+
pip install remoteRF # Install remoteRF
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
If `pip install` doesn't work, you can clone the [source](https://github.com/WirelessLabAtUCLA/RemoteRF-Client) directly from github.
|
|
48
|
+
|
|
49
|
+
<!-- 1. **Clone the repository:**
|
|
50
|
+
```bash
|
|
51
|
+
git clone https://github.com/WirelessLabAtUCLA/RemoteRF-Client
|
|
52
|
+
cd repository-name
|
|
53
|
+
```
|
|
54
|
+
2. **Install the package using** `pip` **in editable mode:**
|
|
55
|
+
```bash
|
|
56
|
+
pip install -e .
|
|
57
|
+
```
|
|
58
|
+
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). -->
|
|
59
|
+
|
|
60
|
+
## Reservation
|
|
61
|
+
|
|
62
|
+
Usage of the platform requires you to register a account and reserve a device in order to run scripts remotely.
|
|
63
|
+
|
|
64
|
+
### 1. **Start UCLA VPN**
|
|
65
|
+
|
|
66
|
+
- Start the CISCO Secure client, login and connect to any of the options.
|
|
67
|
+
|
|
68
|
+
### 2. **Register a account**:
|
|
69
|
+
```bash
|
|
70
|
+
remoterf-login
|
|
71
|
+
# Run in the terminal
|
|
72
|
+
# where the Python library is installed
|
|
73
|
+
|
|
74
|
+
# Typically, this will be the terminal where you’ve activated the virtual environment if you’re using one
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
- Input `r` to register a account, or `l` to login to a existing one.
|
|
78
|
+
|
|
79
|
+
<!-- 2. **You will be prompted with this**: -->
|
|
80
|
+
```bash
|
|
81
|
+
Welcome to Remote RF Account System.
|
|
82
|
+
Please login or register to continue. (l/r):
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
- Once in, input `help` to see all avaliable commands.
|
|
86
|
+
|
|
87
|
+
### 3. **Reserve Device**:
|
|
88
|
+
```bash
|
|
89
|
+
getdev # To view all avaliable devices
|
|
90
|
+
|
|
91
|
+
# Note the device ID. You will need this later to reserve said device
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
getres # To view times not avaliable
|
|
96
|
+
|
|
97
|
+
# Optionally, you can also view all reservations, and determine a time slot you want a specific device reserved
|
|
98
|
+
```
|
|
99
|
+
```bash
|
|
100
|
+
perms # To view your permissions
|
|
101
|
+
|
|
102
|
+
# Depending on your permission levels, you will be given different restrictions
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
resdev # To reserve a device
|
|
107
|
+
|
|
108
|
+
# Input the number of days you want to view, and it will display available reservations in that time span.
|
|
109
|
+
|
|
110
|
+
Reservation successful. Thy Token -> example_token
|
|
111
|
+
|
|
112
|
+
# Take note of this token. You will need it to actually access the device.
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Remote Access
|
|
116
|
+
|
|
117
|
+
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.
|
|
118
|
+
Here is a explained sample script to get you going!
|
|
119
|
+
|
|
120
|
+
#### Python Script:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from remoteRF.drivers.adalm_pluto import * # Imports device Pluto SDR remote drivers. Change depending on desired device.
|
|
124
|
+
|
|
125
|
+
sdr = adi.Pluto( # Device initialization.
|
|
126
|
+
token = 'example_token' # Place the prior token here.
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# You can now use this 'sdr' as you normally would with the default Pluto drivers.
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
If converting a existing `non-remoteRF` compatible script:
|
|
133
|
+
|
|
134
|
+
```diff
|
|
135
|
+
- import existing_device_drivers
|
|
136
|
+
|
|
137
|
+
+ from remoteRF.drivers.device_drivers import *
|
|
138
|
+
|
|
139
|
+
- device = device(init)
|
|
140
|
+
|
|
141
|
+
+ device = device(token = 'sample_token')
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Nothing else needs changing!
|
|
145
|
+
|
|
146
|
+
## Closing
|
|
147
|
+
|
|
148
|
+
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.
|
|
149
|
+
|
|
150
|
+
**So please submit feedback!**
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Remote RF
|
|
2
|
+
|
|
3
|
+
A python API to remotely access signal centric hardware.
|
|
4
|
+
|
|
5
|
+
Courtesy of Wireless Lab @ UCLA. - Ethan Ge
|
|
6
|
+
|
|
7
|
+
## Prerequisites
|
|
8
|
+
|
|
9
|
+
- **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/).
|
|
10
|
+
|
|
11
|
+
To check your current Python version, open a terminal and run:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
python --version
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- **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.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
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).
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
python3 -m venv venv # Create virtual environment
|
|
25
|
+
source venv/bin/activate # Activate virtual environment
|
|
26
|
+
|
|
27
|
+
pip install remoteRF # Install remoteRF
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If `pip install` doesn't work, you can clone the [source](https://github.com/WirelessLabAtUCLA/RemoteRF-Client) directly from github.
|
|
31
|
+
|
|
32
|
+
<!-- 1. **Clone the repository:**
|
|
33
|
+
```bash
|
|
34
|
+
git clone https://github.com/WirelessLabAtUCLA/RemoteRF-Client
|
|
35
|
+
cd repository-name
|
|
36
|
+
```
|
|
37
|
+
2. **Install the package using** `pip` **in editable mode:**
|
|
38
|
+
```bash
|
|
39
|
+
pip install -e .
|
|
40
|
+
```
|
|
41
|
+
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). -->
|
|
42
|
+
|
|
43
|
+
## Reservation
|
|
44
|
+
|
|
45
|
+
Usage of the platform requires you to register a account and reserve a device in order to run scripts remotely.
|
|
46
|
+
|
|
47
|
+
### 1. **Start UCLA VPN**
|
|
48
|
+
|
|
49
|
+
- Start the CISCO Secure client, login and connect to any of the options.
|
|
50
|
+
|
|
51
|
+
### 2. **Register a account**:
|
|
52
|
+
```bash
|
|
53
|
+
remoterf-login
|
|
54
|
+
# Run in the terminal
|
|
55
|
+
# where the Python library is installed
|
|
56
|
+
|
|
57
|
+
# Typically, this will be the terminal where you’ve activated the virtual environment if you’re using one
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
- Input `r` to register a account, or `l` to login to a existing one.
|
|
61
|
+
|
|
62
|
+
<!-- 2. **You will be prompted with this**: -->
|
|
63
|
+
```bash
|
|
64
|
+
Welcome to Remote RF Account System.
|
|
65
|
+
Please login or register to continue. (l/r):
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- Once in, input `help` to see all avaliable commands.
|
|
69
|
+
|
|
70
|
+
### 3. **Reserve Device**:
|
|
71
|
+
```bash
|
|
72
|
+
getdev # To view all avaliable devices
|
|
73
|
+
|
|
74
|
+
# Note the device ID. You will need this later to reserve said device
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
getres # To view times not avaliable
|
|
79
|
+
|
|
80
|
+
# Optionally, you can also view all reservations, and determine a time slot you want a specific device reserved
|
|
81
|
+
```
|
|
82
|
+
```bash
|
|
83
|
+
perms # To view your permissions
|
|
84
|
+
|
|
85
|
+
# Depending on your permission levels, you will be given different restrictions
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
resdev # To reserve a device
|
|
90
|
+
|
|
91
|
+
# Input the number of days you want to view, and it will display available reservations in that time span.
|
|
92
|
+
|
|
93
|
+
Reservation successful. Thy Token -> example_token
|
|
94
|
+
|
|
95
|
+
# Take note of this token. You will need it to actually access the device.
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Remote Access
|
|
99
|
+
|
|
100
|
+
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.
|
|
101
|
+
Here is a explained sample script to get you going!
|
|
102
|
+
|
|
103
|
+
#### Python Script:
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
from remoteRF.drivers.adalm_pluto import * # Imports device Pluto SDR remote drivers. Change depending on desired device.
|
|
107
|
+
|
|
108
|
+
sdr = adi.Pluto( # Device initialization.
|
|
109
|
+
token = 'example_token' # Place the prior token here.
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# You can now use this 'sdr' as you normally would with the default Pluto drivers.
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
If converting a existing `non-remoteRF` compatible script:
|
|
116
|
+
|
|
117
|
+
```diff
|
|
118
|
+
- import existing_device_drivers
|
|
119
|
+
|
|
120
|
+
+ from remoteRF.drivers.device_drivers import *
|
|
121
|
+
|
|
122
|
+
- device = device(init)
|
|
123
|
+
|
|
124
|
+
+ device = device(token = 'sample_token')
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Nothing else needs changing!
|
|
128
|
+
|
|
129
|
+
## Closing
|
|
130
|
+
|
|
131
|
+
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.
|
|
132
|
+
|
|
133
|
+
**So please submit feedback!**
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
with open("README.md", "r", encoding="utf-8") as fh:
|
|
5
|
+
long_description = fh.read()
|
|
6
|
+
|
|
7
|
+
setup(
|
|
8
|
+
name="remoterf",
|
|
9
|
+
version="0.0.7.27",
|
|
10
|
+
author="Ethan Ge",
|
|
11
|
+
author_email="ethoGalaxy@gmail.com",
|
|
12
|
+
description="A python API to remotely access signal centric hardware. Client-side only!",
|
|
13
|
+
long_description=long_description, # Set the README content here
|
|
14
|
+
long_description_content_type="text/markdown", # Specify that it's Markdown
|
|
15
|
+
packages=find_packages(where="src"), # Automatically finds subpackages like core, deviceA, deviceB
|
|
16
|
+
package_dir={"": "src"},
|
|
17
|
+
license_file='MIT',
|
|
18
|
+
include_package_data=True, # Includes files specified in MANIFEST.in
|
|
19
|
+
install_requires=[
|
|
20
|
+
"grpcio==1.71.0", "protobuf", "numpy", "prompt_toolkit", "python-dotenv"
|
|
21
|
+
],
|
|
22
|
+
classifiers=[
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"License :: OSI Approved :: MIT License",
|
|
25
|
+
"Operating System :: OS Independent",
|
|
26
|
+
],
|
|
27
|
+
python_requires='>=3.10',
|
|
28
|
+
entry_points={
|
|
29
|
+
'console_scripts': [
|
|
30
|
+
'remoterf-login=remoteRF.core.acc_login:main',
|
|
31
|
+
],
|
|
32
|
+
},
|
|
33
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from . import grpc_pb2, grpc_pb2_grpc
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
3
|
+
# NO CHECKED-IN PROTOBUF GENCODE
|
|
4
|
+
# source: grpc.proto
|
|
5
|
+
# Protobuf Python Version: 5.29.0
|
|
6
|
+
"""Generated protocol buffer code."""
|
|
7
|
+
from google.protobuf import descriptor as _descriptor
|
|
8
|
+
from google.protobuf import descriptor_pool as _descriptor_pool
|
|
9
|
+
from google.protobuf import runtime_version as _runtime_version
|
|
10
|
+
from google.protobuf import symbol_database as _symbol_database
|
|
11
|
+
from google.protobuf.internal import builder as _builder
|
|
12
|
+
_runtime_version.ValidateProtobufRuntimeVersion(
|
|
13
|
+
_runtime_version.Domain.PUBLIC,
|
|
14
|
+
5,
|
|
15
|
+
29,
|
|
16
|
+
0,
|
|
17
|
+
'',
|
|
18
|
+
'grpc.proto'
|
|
19
|
+
)
|
|
20
|
+
# @@protoc_insertion_point(imports)
|
|
21
|
+
|
|
22
|
+
_sym_db = _symbol_database.Default()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
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\"\xd7\x01\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\x42\x07\n\x05value2Q\n\nGenericRPC\x12\x43\n\x04\x43\x61ll\x12\x1c.remote_rf.GenericRPCRequest\x1a\x1d.remote_rf.GenericRPCResponseB\x1e\n\x10\x63om.example.demoB\nDemoProtosb\x06proto3')
|
|
28
|
+
|
|
29
|
+
_globals = globals()
|
|
30
|
+
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
|
31
|
+
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'grpc_pb2', _globals)
|
|
32
|
+
if not _descriptor._USE_C_DESCRIPTORS:
|
|
33
|
+
_globals['DESCRIPTOR']._loaded_options = None
|
|
34
|
+
_globals['DESCRIPTOR']._serialized_options = b'\n\020com.example.demoB\nDemoProtos'
|
|
35
|
+
_globals['_GENERICRPCREQUEST_ARGSENTRY']._loaded_options = None
|
|
36
|
+
_globals['_GENERICRPCREQUEST_ARGSENTRY']._serialized_options = b'8\001'
|
|
37
|
+
_globals['_GENERICRPCRESPONSE_RESULTSENTRY']._loaded_options = None
|
|
38
|
+
_globals['_GENERICRPCRESPONSE_RESULTSENTRY']._serialized_options = b'8\001'
|
|
39
|
+
_globals['_GENERICRPCREQUEST']._serialized_start=26
|
|
40
|
+
_globals['_GENERICRPCREQUEST']._serialized_end=188
|
|
41
|
+
_globals['_GENERICRPCREQUEST_ARGSENTRY']._serialized_start=124
|
|
42
|
+
_globals['_GENERICRPCREQUEST_ARGSENTRY']._serialized_end=188
|
|
43
|
+
_globals['_GENERICRPCRESPONSE']._serialized_start=191
|
|
44
|
+
_globals['_GENERICRPCRESPONSE']._serialized_end=341
|
|
45
|
+
_globals['_GENERICRPCRESPONSE_RESULTSENTRY']._serialized_start=274
|
|
46
|
+
_globals['_GENERICRPCRESPONSE_RESULTSENTRY']._serialized_end=341
|
|
47
|
+
_globals['_ARRAYSHAPE']._serialized_start=343
|
|
48
|
+
_globals['_ARRAYSHAPE']._serialized_end=368
|
|
49
|
+
_globals['_COMPLEXNUMBER']._serialized_start=370
|
|
50
|
+
_globals['_COMPLEXNUMBER']._serialized_end=413
|
|
51
|
+
_globals['_COMPLEXNUMPYARRAY']._serialized_start=415
|
|
52
|
+
_globals['_COMPLEXNUMPYARRAY']._serialized_end=512
|
|
53
|
+
_globals['_REALNUMPYARRAY']._serialized_start=514
|
|
54
|
+
_globals['_REALNUMPYARRAY']._serialized_end=582
|
|
55
|
+
_globals['_ARGUMENT']._serialized_start=585
|
|
56
|
+
_globals['_ARGUMENT']._serialized_end=800
|
|
57
|
+
_globals['_GENERICRPC']._serialized_start=802
|
|
58
|
+
_globals['_GENERICRPC']._serialized_end=883
|
|
59
|
+
# @@protoc_insertion_point(module_scope)
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
|
|
2
|
+
"""Client and server classes corresponding to protobuf-defined services."""
|
|
3
|
+
import grpc
|
|
4
|
+
import warnings
|
|
5
|
+
|
|
6
|
+
from . import grpc_pb2 as grpc__pb2
|
|
7
|
+
|
|
8
|
+
GRPC_GENERATED_VERSION = '1.71.0'
|
|
9
|
+
GRPC_VERSION = grpc.__version__
|
|
10
|
+
_version_not_supported = False
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
from grpc._utilities import first_version_is_lower
|
|
14
|
+
_version_not_supported = first_version_is_lower(GRPC_VERSION, GRPC_GENERATED_VERSION)
|
|
15
|
+
except ImportError:
|
|
16
|
+
_version_not_supported = True
|
|
17
|
+
|
|
18
|
+
if _version_not_supported:
|
|
19
|
+
raise RuntimeError(
|
|
20
|
+
f'The grpc package installed is at version {GRPC_VERSION},'
|
|
21
|
+
+ f' but the generated code in grpc_pb2_grpc.py depends on'
|
|
22
|
+
+ f' grpcio>={GRPC_GENERATED_VERSION}.'
|
|
23
|
+
+ f' Please upgrade your grpc module to grpcio>={GRPC_GENERATED_VERSION}'
|
|
24
|
+
+ f' or downgrade your generated code using grpcio-tools<={GRPC_VERSION}.'
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class GenericRPCStub(object):
|
|
29
|
+
"""Missing associated documentation comment in .proto file."""
|
|
30
|
+
|
|
31
|
+
def __init__(self, channel):
|
|
32
|
+
"""Constructor.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
channel: A grpc.Channel.
|
|
36
|
+
"""
|
|
37
|
+
self.Call = channel.unary_unary(
|
|
38
|
+
'/remote_rf.GenericRPC/Call',
|
|
39
|
+
request_serializer=grpc__pb2.GenericRPCRequest.SerializeToString,
|
|
40
|
+
response_deserializer=grpc__pb2.GenericRPCResponse.FromString,
|
|
41
|
+
_registered_method=True)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class GenericRPCServicer(object):
|
|
45
|
+
"""Missing associated documentation comment in .proto file."""
|
|
46
|
+
|
|
47
|
+
def Call(self, request, context):
|
|
48
|
+
"""Missing associated documentation comment in .proto file."""
|
|
49
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
|
50
|
+
context.set_details('Method not implemented!')
|
|
51
|
+
raise NotImplementedError('Method not implemented!')
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def add_GenericRPCServicer_to_server(servicer, server):
|
|
55
|
+
rpc_method_handlers = {
|
|
56
|
+
'Call': grpc.unary_unary_rpc_method_handler(
|
|
57
|
+
servicer.Call,
|
|
58
|
+
request_deserializer=grpc__pb2.GenericRPCRequest.FromString,
|
|
59
|
+
response_serializer=grpc__pb2.GenericRPCResponse.SerializeToString,
|
|
60
|
+
),
|
|
61
|
+
}
|
|
62
|
+
generic_handler = grpc.method_handlers_generic_handler(
|
|
63
|
+
'remote_rf.GenericRPC', rpc_method_handlers)
|
|
64
|
+
server.add_generic_rpc_handlers((generic_handler,))
|
|
65
|
+
server.add_registered_method_handlers('remote_rf.GenericRPC', rpc_method_handlers)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# This class is part of an EXPERIMENTAL API.
|
|
69
|
+
class GenericRPC(object):
|
|
70
|
+
"""Missing associated documentation comment in .proto file."""
|
|
71
|
+
|
|
72
|
+
@staticmethod
|
|
73
|
+
def Call(request,
|
|
74
|
+
target,
|
|
75
|
+
options=(),
|
|
76
|
+
channel_credentials=None,
|
|
77
|
+
call_credentials=None,
|
|
78
|
+
insecure=False,
|
|
79
|
+
compression=None,
|
|
80
|
+
wait_for_ready=None,
|
|
81
|
+
timeout=None,
|
|
82
|
+
metadata=None):
|
|
83
|
+
return grpc.experimental.unary_unary(
|
|
84
|
+
request,
|
|
85
|
+
target,
|
|
86
|
+
'/remote_rf.GenericRPC/Call',
|
|
87
|
+
grpc__pb2.GenericRPCRequest.SerializeToString,
|
|
88
|
+
grpc__pb2.GenericRPCResponse.FromString,
|
|
89
|
+
options,
|
|
90
|
+
channel_credentials,
|
|
91
|
+
insecure,
|
|
92
|
+
call_credentials,
|
|
93
|
+
compression,
|
|
94
|
+
wait_for_ready,
|
|
95
|
+
timeout,
|
|
96
|
+
metadata,
|
|
97
|
+
_registered_method=True)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
from prompt_toolkit.styles import Style
|
|
2
|
+
from prompt_toolkit.formatted_text import FormattedText
|
|
3
|
+
from prompt_toolkit import print_formatted_text
|
|
4
|
+
from enum import Enum
|
|
5
|
+
|
|
6
|
+
class Sty(Enum):
|
|
7
|
+
# Basic colors
|
|
8
|
+
RED = 'red'
|
|
9
|
+
GREEN = 'green'
|
|
10
|
+
BLUE = 'blue'
|
|
11
|
+
YELLOW = 'yellow'
|
|
12
|
+
MAGENTA = 'magenta'
|
|
13
|
+
CYAN = 'cyan'
|
|
14
|
+
GRAY = 'gray'
|
|
15
|
+
|
|
16
|
+
# Background colors
|
|
17
|
+
BG_RED = 'bg-red'
|
|
18
|
+
BG_GREEN = 'bg-green'
|
|
19
|
+
BG_BLUE = 'bg-blue'
|
|
20
|
+
|
|
21
|
+
# Bright versions
|
|
22
|
+
BRIGHT_RED = 'bright-red'
|
|
23
|
+
BRIGHT_GREEN = 'bright-green'
|
|
24
|
+
BRIGHT_BLUE = 'bright-blue'
|
|
25
|
+
|
|
26
|
+
# Formatting
|
|
27
|
+
BOLD = 'bold'
|
|
28
|
+
ITALIC = 'italic'
|
|
29
|
+
UNDERLINE = 'underline'
|
|
30
|
+
BLINK = 'blink'
|
|
31
|
+
REVERSE = 'reverse'
|
|
32
|
+
|
|
33
|
+
# Combinations
|
|
34
|
+
ERROR = 'error'
|
|
35
|
+
WARNING = 'warning'
|
|
36
|
+
INFO = 'info'
|
|
37
|
+
|
|
38
|
+
# Special
|
|
39
|
+
SELECTED = 'selected'
|
|
40
|
+
DEFAULT = 'default'
|
|
41
|
+
|
|
42
|
+
# Define the styles based on ANSI codes
|
|
43
|
+
style = Style.from_dict({
|
|
44
|
+
# Basic colors
|
|
45
|
+
'red': 'fg:#110000',
|
|
46
|
+
'green': 'fg:#003300',
|
|
47
|
+
'blue': 'fg:#0000ff',
|
|
48
|
+
'yellow': 'fg:#ffff00',
|
|
49
|
+
'magenta': 'fg:#ff00ff',
|
|
50
|
+
'cyan': 'fg:#00ffff',
|
|
51
|
+
'gray': 'fg:#808080',
|
|
52
|
+
|
|
53
|
+
# Bright versions
|
|
54
|
+
'bright-red': 'fg:#ff5555',
|
|
55
|
+
'bright-green': 'fg:#00ff00',
|
|
56
|
+
'bright-blue': 'fg:#5555ff',
|
|
57
|
+
|
|
58
|
+
# Formatting
|
|
59
|
+
'bold': 'bold',
|
|
60
|
+
'italic': 'italic',
|
|
61
|
+
'underline': 'underline',
|
|
62
|
+
'reverse': 'reverse',
|
|
63
|
+
|
|
64
|
+
# Combinations
|
|
65
|
+
'error': 'bg:#ff0000 fg:#ffffff bold',
|
|
66
|
+
'warning': 'bg:#ffff00 fg:#000000 bold',
|
|
67
|
+
'info': 'bg:#0000ff fg:#ffffff italic underline',
|
|
68
|
+
|
|
69
|
+
# Special
|
|
70
|
+
'selected': 'bg:#ffffff #000000 reverse',
|
|
71
|
+
'default':''
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
def printf(*args) -> str:
|
|
75
|
+
if len(args) % 2 != 0:
|
|
76
|
+
raise ValueError('Arguments must be in pairs of two.')
|
|
77
|
+
|
|
78
|
+
# Create formatted text using the defined style
|
|
79
|
+
formatted_text = []
|
|
80
|
+
|
|
81
|
+
for i in range(0, len(args), 2):
|
|
82
|
+
message = args[i]
|
|
83
|
+
styles = args[i+1]
|
|
84
|
+
|
|
85
|
+
if not isinstance(styles, tuple):
|
|
86
|
+
styles = (styles,)
|
|
87
|
+
|
|
88
|
+
resolved_styles = (s.value if isinstance(s, Enum) else s for s in styles)
|
|
89
|
+
|
|
90
|
+
style_class = ' '.join(resolved_styles)
|
|
91
|
+
|
|
92
|
+
formatted_text.append(('class:' + style_class, message))
|
|
93
|
+
|
|
94
|
+
# Create FormattedText object from pairs
|
|
95
|
+
text = FormattedText(formatted_text)
|
|
96
|
+
|
|
97
|
+
print_formatted_text(text, style=style)
|
|
98
|
+
return text
|
|
99
|
+
|
|
100
|
+
def stylize(*args):
|
|
101
|
+
"""
|
|
102
|
+
Create a styled prompt text based on pairs of (text, (Sty, ...), ...).
|
|
103
|
+
"""
|
|
104
|
+
if len(args) % 2 != 0:
|
|
105
|
+
raise ValueError("Arguments must be in pairs of (text, style_class).")
|
|
106
|
+
|
|
107
|
+
styled_parts = []
|
|
108
|
+
for i in range(0, len(args), 2):
|
|
109
|
+
text = args[i]
|
|
110
|
+
styles = args[i + 1]
|
|
111
|
+
|
|
112
|
+
if not isinstance(styles, tuple):
|
|
113
|
+
styles = (styles,)
|
|
114
|
+
|
|
115
|
+
resolved_styles = (s.value if isinstance(s, Enum) else s for s in styles)
|
|
116
|
+
|
|
117
|
+
style_class = ' '.join(resolved_styles)
|
|
118
|
+
styled_parts.append(('class:' + style_class, text))
|
|
119
|
+
|
|
120
|
+
return FormattedText(styled_parts)
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import hashlib
|
|
3
|
+
import base64
|
|
4
|
+
import secrets
|
|
5
|
+
from dotenv import load_dotenv, find_dotenv
|
|
6
|
+
|
|
7
|
+
### API Token Management
|
|
8
|
+
# API Tokens are used to authenticate clients to the device
|
|
9
|
+
# API Tokens are stored locally on the device in its .env file
|
|
10
|
+
|
|
11
|
+
def generate_token(length=8) -> tuple[str, str, str]:
|
|
12
|
+
random_bytes = secrets.token_bytes(length) # Generate a random byte string
|
|
13
|
+
token = base64.urlsafe_b64encode(random_bytes).decode('utf-8').rstrip('=') # Encode the byte string in a URL-safe base64 format
|
|
14
|
+
salt = os.urandom(16).hex() # 16 bytes of random salt
|
|
15
|
+
hashed = hashlib.sha256(bytes.fromhex(salt) + token.encode()).hexdigest() # Hash to sha256 standard
|
|
16
|
+
return salt, hashed, token
|
|
17
|
+
|
|
18
|
+
def validate_token(salt, hash, token) -> bool:
|
|
19
|
+
new_hashed = hashlib.sha256(bytes.fromhex(salt) + token.encode()).hexdigest()
|
|
20
|
+
return new_hashed == hash
|
|
21
|
+
|
|
22
|
+
def hash_token(token: str) -> tuple[str, str]:
|
|
23
|
+
salt = os.urandom(16).hex()
|
|
24
|
+
hashed = hashlib.sha256(bytes.fromhex(salt) + token.encode()).hexdigest()
|
|
25
|
+
return salt, hashed
|
|
26
|
+
|
|
27
|
+
# Example Usage:
|
|
28
|
+
# if __name__ == '__main__':
|
|
29
|
+
# okay = generate_token()
|
|
30
|
+
# assert validate_token(okay[0], okay[1], okay[2] + "s"), "Token validation failed!"
|
|
31
|
+
# print("Token validation succeeded!")
|