remoterf-testing 0.0.1__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.
Files changed (35) hide show
  1. remoterf_testing-0.0.1/MANIFEST.in +2 -0
  2. remoterf_testing-0.0.1/PKG-INFO +158 -0
  3. remoterf_testing-0.0.1/README.md +132 -0
  4. remoterf_testing-0.0.1/setup.cfg +4 -0
  5. remoterf_testing-0.0.1/setup.py +45 -0
  6. remoterf_testing-0.0.1/src/remoteRF/__init__.py +0 -0
  7. remoterf_testing-0.0.1/src/remoteRF/common/__init__.py +2 -0
  8. remoterf_testing-0.0.1/src/remoteRF/common/grpc/__init__.py +1 -0
  9. remoterf_testing-0.0.1/src/remoteRF/common/grpc/grpc_pb2.py +59 -0
  10. remoterf_testing-0.0.1/src/remoteRF/common/grpc/grpc_pb2_grpc.py +97 -0
  11. remoterf_testing-0.0.1/src/remoteRF/common/utils/__init__.py +4 -0
  12. remoterf_testing-0.0.1/src/remoteRF/common/utils/ansi_codes.py +120 -0
  13. remoterf_testing-0.0.1/src/remoteRF/common/utils/api_token.py +31 -0
  14. remoterf_testing-0.0.1/src/remoteRF/common/utils/list_string.py +5 -0
  15. remoterf_testing-0.0.1/src/remoteRF/common/utils/process_arg.py +80 -0
  16. remoterf_testing-0.0.1/src/remoteRF/config/__init__.py +0 -0
  17. remoterf_testing-0.0.1/src/remoteRF/config/cert_fetcher.py +170 -0
  18. remoterf_testing-0.0.1/src/remoteRF/config/config.py +133 -0
  19. remoterf_testing-0.0.1/src/remoteRF/core/__init__.py +2 -0
  20. remoterf_testing-0.0.1/src/remoteRF/core/acc_login.py +4 -0
  21. remoterf_testing-0.0.1/src/remoteRF/core/app.py +865 -0
  22. remoterf_testing-0.0.1/src/remoteRF/core/grpc_acc.py +64 -0
  23. remoterf_testing-0.0.1/src/remoteRF/core/grpc_client.py +323 -0
  24. remoterf_testing-0.0.1/src/remoteRF/drivers/__init__.py +1 -0
  25. remoterf_testing-0.0.1/src/remoteRF/drivers/adalm_pluto/__init__.py +1 -0
  26. remoterf_testing-0.0.1/src/remoteRF/drivers/adalm_pluto/pluto_remote.py +249 -0
  27. remoterf_testing-0.0.1/src/remoteRF/drivers/dynamic_device.py +319 -0
  28. remoterf_testing-0.0.1/src/remoteRF/remoterf_cli.py +203 -0
  29. remoterf_testing-0.0.1/src/remoteRF/version.py +8 -0
  30. remoterf_testing-0.0.1/src/remoterf_testing.egg-info/PKG-INFO +158 -0
  31. remoterf_testing-0.0.1/src/remoterf_testing.egg-info/SOURCES.txt +33 -0
  32. remoterf_testing-0.0.1/src/remoterf_testing.egg-info/dependency_links.txt +1 -0
  33. remoterf_testing-0.0.1/src/remoterf_testing.egg-info/entry_points.txt +2 -0
  34. remoterf_testing-0.0.1/src/remoterf_testing.egg-info/requires.txt +6 -0
  35. remoterf_testing-0.0.1/src/remoterf_testing.egg-info/top_level.txt +1 -0
@@ -0,0 +1,2 @@
1
+ # Include all .crt, .key, and .pem files
2
+ recursive-include src/remoteRF *.crt *.key *.pem
@@ -0,0 +1,158 @@
1
+ Metadata-Version: 2.4
2
+ Name: remoterf-testing
3
+ Version: 0.0.1
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<2.0.0,>=1.75.1
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,132 @@
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
+ ```bash
63
+ Welcome to Remote RF Account System.
64
+ Please login or register to continue. (l/r):
65
+ ```
66
+
67
+ - Once in, input `help` to see all avaliable commands.
68
+
69
+ ### 3. **Reserve Device**:
70
+ ```bash
71
+ getdev # To view all avaliable devices
72
+
73
+ # Note the device ID. You will need this later to reserve said device
74
+ ```
75
+
76
+ ```bash
77
+ getres # To view times not avaliable
78
+
79
+ # Optionally, you can also view all reservations, and determine a time slot you want a specific device reserved
80
+ ```
81
+ ```bash
82
+ perms # To view your permissions
83
+
84
+ # Depending on your permission levels, you will be given different restrictions
85
+ ```
86
+
87
+ ```bash
88
+ resdev # To reserve a device
89
+
90
+ # Input the number of days you want to view, and it will display available reservations in that time span.
91
+
92
+ Reservation successful. Thy Token -> example_token
93
+
94
+ # Take note of this token. You will need it to actually access the device.
95
+ ```
96
+
97
+ ## Remote Access
98
+
99
+ 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.
100
+ Here is a explained sample script to get you going!
101
+
102
+ #### Python Script:
103
+
104
+ ```python
105
+ from remoteRF.drivers.adalm_pluto import * # Imports device Pluto SDR remote drivers. Change depending on desired device.
106
+
107
+ sdr = adi.Pluto( # Device initialization.
108
+ token = 'example_token' # Place the prior token here.
109
+ )
110
+
111
+ # You can now use this 'sdr' as you normally would with the default Pluto drivers.
112
+ ```
113
+
114
+ If converting a existing `non-remoteRF` compatible script:
115
+
116
+ ```diff
117
+ - import existing_device_drivers
118
+
119
+ + from remoteRF.drivers.device_drivers import *
120
+
121
+ - device = device(init)
122
+
123
+ + device = device(token = 'sample_token')
124
+ ```
125
+
126
+ Nothing else needs changing!
127
+
128
+ ## Closing
129
+
130
+ 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.
131
+
132
+ **So please submit feedback!** -->
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,45 @@
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-testing",
9
+ version="0.0.1",
10
+ author="Ethan Ge",
11
+ author_email="ethoGalaxy@gmail.com",
12
+ description="A python API to remotely access signal centric hardware. Client-side only! Courtesy of Wireless Lab @ UCLA & Prof. Ian Roberts.",
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.75.1,<2.0.0", "protobuf>=5.0.0,<6.0.0", "numpy", "prompt_toolkit", "python-dotenv", "prompt-toolkit"
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
+ # 'remoterf-v=remoteRF.core.version:main',
32
+ # 'remoterf-config=remoteRF.config.config_cli:main',
33
+ # ],
34
+ # },
35
+
36
+ entry_points={
37
+ "console_scripts": [
38
+ "remoterf=remoteRF.remoterf_cli:main",
39
+ # "remoterf-login=remoteRF.core.acc_login:main",
40
+ # "remoterf-v=remoteRF.core.version:main",
41
+ # "remoterf-config=remoteRF.config.config_cli:main",
42
+ ],
43
+ },
44
+
45
+ )
File without changes
@@ -0,0 +1,2 @@
1
+ from .grpc import *
2
+ from .utils import *
@@ -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,4 @@
1
+ from .api_token import validate_token, generate_token, hash_token
2
+ from .process_arg import unmap_arg, map_arg
3
+ from .ansi_codes import printf, stylize, Sty
4
+ from .list_string import list_to_str, str_to_list
@@ -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!")
@@ -0,0 +1,5 @@
1
+ def list_to_str(list:list) -> str:
2
+ return ','.join(str(x) for x in list)
3
+
4
+ def str_to_list(s:str) -> list[int]:
5
+ return [int(x) for x in s.split(',')]