remotivelabs-cli 0.2.3__tar.gz → 0.3.0__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 remotivelabs-cli might be problematic. Click here for more details.

Files changed (73) hide show
  1. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/PKG-INFO +3 -2
  2. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/broker/lib/broker.py +120 -89
  3. remotivelabs_cli-0.3.0/cli/broker/lib/client.py +224 -0
  4. remotivelabs_cli-0.3.0/cli/broker/lib/helper.py +278 -0
  5. remotivelabs_cli-0.3.0/cli/broker/lib/signalcreator.py +196 -0
  6. remotivelabs_cli-0.2.3/cli/cloud/cloud_cli.py → remotivelabs_cli-0.3.0/cli/cloud/__init__.py +2 -14
  7. remotivelabs_cli-0.3.0/cli/cloud/auth/cmd.py +126 -0
  8. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/auth/login.py +26 -28
  9. remotivelabs_cli-0.3.0/cli/cloud/auth_tokens.py +143 -0
  10. remotivelabs_cli-0.3.0/cli/cloud/licenses/cmd.py +14 -0
  11. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/organisations.py +4 -7
  12. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/service_account_tokens.py +1 -1
  13. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/connect/protopie/protopie.py +1 -1
  14. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/remotive.py +12 -19
  15. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/settings/__init__.py +1 -2
  16. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/settings/config_file.py +2 -0
  17. remotivelabs_cli-0.3.0/cli/settings/core.py +320 -0
  18. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/settings/migration/migrate_config_file.py +13 -6
  19. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/settings/migration/migration_tools.py +4 -3
  20. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/settings/state_file.py +12 -4
  21. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/topology/cmd.py +5 -6
  22. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/utils/rest_helper.py +11 -16
  23. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/utils/versions.py +5 -15
  24. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/pyproject.toml +3 -2
  25. remotivelabs_cli-0.2.3/cli/cloud/auth/cmd.py +0 -88
  26. remotivelabs_cli-0.2.3/cli/cloud/auth_tokens.py +0 -346
  27. remotivelabs_cli-0.2.3/cli/settings/core.py +0 -322
  28. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/LICENSE +0 -0
  29. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/README.md +0 -0
  30. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/.DS_Store +0 -0
  31. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/__init__.py +0 -0
  32. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/api/cloud/tokens.py +0 -0
  33. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/broker/brokers.py +0 -0
  34. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/broker/export.py +0 -0
  35. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/broker/files.py +0 -0
  36. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/broker/lib/__about__.py +0 -0
  37. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/broker/license_flows.py +0 -0
  38. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/broker/licenses.py +0 -0
  39. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/broker/playback.py +0 -0
  40. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/broker/record.py +0 -0
  41. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/broker/scripting.py +0 -0
  42. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/broker/signals.py +0 -0
  43. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/auth/__init__.py +0 -0
  44. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/brokers.py +0 -0
  45. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/configs.py +0 -0
  46. {remotivelabs_cli-0.2.3/cli/cloud → remotivelabs_cli-0.3.0/cli/cloud/licenses}/__init__.py +0 -0
  47. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/projects.py +0 -0
  48. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/recordings.py +0 -0
  49. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/recordings_playback.py +0 -0
  50. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/resumable_upload.py +0 -0
  51. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/sample_recordings.py +0 -0
  52. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/service_accounts.py +0 -0
  53. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/storage/__init__.py +0 -0
  54. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/storage/cmd.py +0 -0
  55. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/storage/copy.py +0 -0
  56. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/storage/uri_or_path.py +0 -0
  57. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/cloud/uri.py +0 -0
  58. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/connect/__init__.py +0 -0
  59. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/connect/connect.py +0 -0
  60. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/errors.py +0 -0
  61. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/settings/migration/__init__.py +0 -0
  62. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/settings/migration/migrate_all_token_files.py +0 -0
  63. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/settings/migration/migrate_legacy_dirs.py +0 -0
  64. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/settings/migration/migrate_token_file.py +0 -0
  65. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/settings/token_file.py +0 -0
  66. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/tools/__init__.py +0 -0
  67. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/tools/can/__init__.py +0 -0
  68. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/tools/can/can.py +0 -0
  69. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/tools/tools.py +0 -0
  70. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/typer/__init__.py +0 -0
  71. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/typer/typer_utils.py +0 -0
  72. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/utils/__init__.py +0 -0
  73. {remotivelabs_cli-0.2.3 → remotivelabs_cli-0.3.0}/cli/utils/time.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: remotivelabs-cli
3
- Version: 0.2.3
3
+ Version: 0.3.0
4
4
  Summary: CLI for operating RemotiveCloud and RemotiveBroker
5
5
  Author: Johan Rask
6
6
  Author-email: johan.rask@remotivelabs.com
@@ -20,7 +20,8 @@ Requires-Dist: pydantic (>=2.11.7,<3.0.0)
20
20
  Requires-Dist: pyjwt (>=2.6,<3.0)
21
21
  Requires-Dist: python-can (>=4.3.1)
22
22
  Requires-Dist: python-socketio (>=4.6.1)
23
- Requires-Dist: remotivelabs-broker (>=0.1.17,<0.2.0)
23
+ Requires-Dist: remotivelabs-broker (>=0.9.1,<0.10.0)
24
+ Requires-Dist: requests (>=2.32.4,<3.0.0)
24
25
  Requires-Dist: rich (>=13.7.0,<13.8.0)
25
26
  Requires-Dist: trogon (>=0.5.0)
26
27
  Requires-Dist: typer (==0.12.5)
@@ -1,6 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import binascii
4
+ import hashlib
5
+ import itertools
4
6
  import ntpath
5
7
  import os
6
8
  import posixpath
@@ -11,18 +13,24 @@ import tempfile
11
13
  import time
12
14
  import zipfile
13
15
  from dataclasses import dataclass
16
+ from glob import glob
14
17
  from threading import Thread
15
- from typing import Any, Callable, Dict, Iterable, List, Sequence, Union
18
+ from typing import Any, BinaryIO, Callable, Dict, Generator, Iterable, List, Sequence, Union
16
19
 
17
20
  import grpc
18
- import remotivelabs.broker.generated.sync.network_api_pb2 as network_api
19
- import remotivelabs.broker.generated.sync.traffic_api_pb2 as traffic_api
20
- import remotivelabs.broker.sync as br
21
- import remotivelabs.broker.sync.helper as br_helper
21
+ import remotivelabs.broker._generated.common_pb2 as common
22
+ import remotivelabs.broker._generated.network_api_pb2 as network_api
23
+ import remotivelabs.broker._generated.network_api_pb2_grpc as network_api_grpc
24
+ import remotivelabs.broker._generated.system_api_pb2 as system_api
25
+ import remotivelabs.broker._generated.system_api_pb2_grpc as system_api_grpc
26
+ import remotivelabs.broker._generated.traffic_api_pb2 as traffic_api
27
+ import remotivelabs.broker._generated.traffic_api_pb2_grpc as traffic_api_grpc
22
28
  import typer
23
29
  from google.protobuf.json_format import MessageToDict
24
30
  from rich.console import Console
25
31
 
32
+ from cli.broker.lib.helper import act_on_scripted_signal, act_on_signal, create_channel
33
+ from cli.broker.lib.signalcreator import SignalCreator
26
34
  from cli.errors import ErrorPrinter
27
35
  from cli.settings import settings
28
36
 
@@ -43,6 +51,27 @@ class LicenseInfo:
43
51
  machine_id: str
44
52
 
45
53
 
54
+ def get_sha256(path: str) -> str:
55
+ """
56
+ Calculate SHA256 for a file.
57
+ """
58
+ with open(path, "rb") as f:
59
+ b = f.read() # read entire file as bytes
60
+ return hashlib.sha256(b).hexdigest()
61
+
62
+
63
+ def generate_data(file: BinaryIO, dest_path: str, chunk_size: int, sha256: str) -> Generator[system_api.FileUploadRequest, None, None]:
64
+ for x in itertools.count(start=0):
65
+ if x == 0:
66
+ file_description = system_api.FileDescription(sha256=sha256, path=dest_path)
67
+ yield system_api.FileUploadRequest(fileDescription=file_description)
68
+ else:
69
+ buf = file.read(chunk_size)
70
+ if not buf:
71
+ break
72
+ yield system_api.FileUploadRequest(chunk=buf)
73
+
74
+
46
75
  class Broker:
47
76
  def __init__(self, url: str, api_key: Union[str, None] = None) -> None:
48
77
  self.url = url
@@ -53,24 +82,24 @@ class Broker:
53
82
 
54
83
  if api_key is None or api_key == "":
55
84
  if url.startswith("https"):
56
- self.intercept_channel = br.create_channel(url, None, settings.get_active_token())
85
+ self.intercept_channel = create_channel(url, None, settings.get_active_token())
57
86
  # TODO - Temporary solution to print proper error message, remove ENV once api-key is gone
58
87
  os.environ["ACCESS_TOKEN"] = "true"
59
88
  else:
60
89
  os.environ["ACCESS_TOKEN"] = "false"
61
- self.intercept_channel = br.create_channel(url, None, None)
90
+ self.intercept_channel = create_channel(url, None, None)
62
91
  else:
63
92
  err_console.print("Option --api-key will is deprecated and will be removed. Use access access tokens by logging in with cli.")
64
93
  os.environ["ACCESS_TOKEN"] = "false"
65
- self.intercept_channel = br.create_channel(url, api_key, None)
94
+ self.intercept_channel = create_channel(url, api_key, None)
66
95
 
67
- self.network_stub = br.network_api_pb2_grpc.NetworkServiceStub(self.intercept_channel)
68
- self.system_stub = br.system_api_pb2_grpc.SystemServiceStub(self.intercept_channel)
69
- self.traffic_stub = br.traffic_api_pb2_grpc.TrafficServiceStub(self.intercept_channel)
70
- self.signal_creator = br.SignalCreator(self.system_stub)
96
+ self.network_stub = network_api_grpc.NetworkServiceStub(self.intercept_channel)
97
+ self.system_stub = system_api_grpc.SystemServiceStub(self.intercept_channel)
98
+ self.traffic_stub = traffic_api_grpc.TrafficServiceStub(self.intercept_channel)
99
+ self.signal_creator = SignalCreator(self.system_stub)
71
100
 
72
101
  @staticmethod
73
- def __check_playbackmode_result(status: br.traffic_api_pb2.PlaybackInfos) -> None:
102
+ def __check_playbackmode_result(status: traffic_api.PlaybackInfos) -> None:
74
103
  err_cnt = 0
75
104
  for mode in status.playbackInfo:
76
105
  if mode.playbackMode.errorMessage:
@@ -79,112 +108,112 @@ class Broker:
79
108
  if err_cnt > 0:
80
109
  raise typer.Exit(1)
81
110
 
82
- def seek(self, recording_and_namespace: List[Any], offset: int, silent: bool = True) -> br.traffic_api_pb2.PlaybackInfos:
111
+ def seek(self, recording_and_namespace: List[Any], offset: int, silent: bool = True) -> traffic_api.PlaybackInfos:
83
112
  def to_playback(rec: Any) -> Dict[str, Any]:
84
- return {"namespace": rec["namespace"], "path": rec["recording"], "mode": br.traffic_api_pb2.Mode.SEEK, "offsettime": offset}
113
+ return {"namespace": rec["namespace"], "path": rec["recording"], "mode": traffic_api.Mode.SEEK, "offsettime": offset}
85
114
 
86
115
  playback_list = map(to_playback, recording_and_namespace)
87
116
 
88
- infos = br.traffic_api_pb2.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
89
- status = self.traffic_stub.PlayTraffic(infos)
117
+ infos = traffic_api.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
118
+ status: traffic_api.PlaybackInfos = self.traffic_stub.PlayTraffic(infos)
90
119
  if not silent:
91
120
  self.__check_playbackmode_result(status)
92
121
  return status
93
122
 
94
- def play(self, recording_and_namespace: List[Any], silent: bool = False) -> br.traffic_api_pb2.PlaybackInfos:
123
+ def play(self, recording_and_namespace: List[Any], silent: bool = False) -> traffic_api.PlaybackInfos:
95
124
  def to_playback(rec: Any) -> Dict[str, Any]:
96
125
  return {
97
126
  "namespace": rec["namespace"],
98
127
  "path": rec["recording"],
99
- "mode": br.traffic_api_pb2.Mode.PLAY,
128
+ "mode": traffic_api.Mode.PLAY,
100
129
  }
101
130
 
102
131
  playback_list = map(to_playback, recording_and_namespace)
103
132
 
104
- status = self.traffic_stub.PlayTraffic(
105
- br.traffic_api_pb2.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
133
+ status: traffic_api.PlaybackInfos = self.traffic_stub.PlayTraffic(
134
+ traffic_api.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
106
135
  )
107
136
 
108
137
  if not silent:
109
138
  self.__check_playbackmode_result(status)
110
139
  return status
111
140
 
112
- def stop_play(self, recording_and_namespace: List[Any], silent: bool = False) -> br.traffic_api_pb2.PlaybackInfos:
141
+ def stop_play(self, recording_and_namespace: List[Any], silent: bool = False) -> traffic_api.PlaybackInfos:
113
142
  def to_playback(rec: Any) -> Dict[str, Any]:
114
143
  return {
115
144
  "namespace": rec["namespace"],
116
145
  "path": rec["recording"],
117
- "mode": br.traffic_api_pb2.Mode.STOP,
146
+ "mode": traffic_api.Mode.STOP,
118
147
  }
119
148
 
120
149
  playback_list = map(to_playback, recording_and_namespace)
121
150
 
122
- status = self.traffic_stub.PlayTraffic(
123
- br.traffic_api_pb2.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
151
+ status: traffic_api.PlaybackInfos = self.traffic_stub.PlayTraffic(
152
+ traffic_api.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
124
153
  )
125
154
  if not silent:
126
155
  self.__check_playbackmode_result(status)
127
156
  return status
128
157
 
129
- def pause_play(self, recording_and_namespace: List[Any], silent: bool = False) -> br.traffic_api_pb2.PlaybackInfos:
158
+ def pause_play(self, recording_and_namespace: List[Any], silent: bool = False) -> traffic_api.PlaybackInfos:
130
159
  def to_playback(rec: Any) -> Dict[str, Any]:
131
160
  return {
132
161
  "namespace": rec["namespace"],
133
162
  "path": rec["recording"],
134
- "mode": br.traffic_api_pb2.Mode.PAUSE,
163
+ "mode": traffic_api.Mode.PAUSE,
135
164
  }
136
165
 
137
166
  playback_list = map(to_playback, recording_and_namespace)
138
167
 
139
- status = self.traffic_stub.PlayTraffic(
140
- br.traffic_api_pb2.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
168
+ status: traffic_api.PlaybackInfos = self.traffic_stub.PlayTraffic(
169
+ traffic_api.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
141
170
  )
142
171
  if not silent:
143
172
  self.__check_playbackmode_result(status)
144
173
  return status
145
174
 
146
- def record_multiple(self, namespaces: List[str], path: str) -> br.traffic_api_pb2.PlaybackInfos:
175
+ def record_multiple(self, namespaces: List[str], path: str) -> traffic_api.PlaybackInfos:
147
176
  def to_playback(namespace: str) -> Dict[str, Any]:
148
177
  return {
149
178
  "namespace": namespace,
150
179
  "path": path + "_" + namespace,
151
- "mode": br.traffic_api_pb2.Mode.RECORD,
180
+ "mode": traffic_api.Mode.RECORD,
152
181
  }
153
182
 
154
183
  playback_list = list(map(to_playback, namespaces))
155
184
 
156
- status = self.traffic_stub.PlayTraffic(
157
- br.traffic_api_pb2.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
185
+ status: traffic_api.PlaybackInfos = self.traffic_stub.PlayTraffic(
186
+ traffic_api.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
158
187
  )
159
188
  self.__check_playbackmode_result(status)
160
189
  return status
161
190
 
162
- def record(self, namespace: str, path: str) -> br.traffic_api_pb2.PlaybackInfos:
191
+ def record(self, namespace: str, path: str) -> traffic_api.PlaybackInfos:
163
192
  playback_list = [
164
193
  {
165
194
  "namespace": namespace,
166
195
  "path": path,
167
- "mode": br.traffic_api_pb2.Mode.RECORD,
196
+ "mode": traffic_api.Mode.RECORD,
168
197
  }
169
198
  ]
170
199
 
171
- status = self.traffic_stub.PlayTraffic(
172
- br.traffic_api_pb2.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
200
+ status: traffic_api.PlaybackInfos = self.traffic_stub.PlayTraffic(
201
+ traffic_api.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
173
202
  )
174
203
  self.__check_playbackmode_result(status)
175
204
  return status
176
205
 
177
- def stop(self, namespace: str, path: str, silent: bool = False) -> br.traffic_api_pb2.PlaybackInfos:
206
+ def stop(self, namespace: str, path: str, silent: bool = False) -> traffic_api.PlaybackInfos:
178
207
  playback_list = [
179
208
  {
180
209
  "namespace": namespace,
181
210
  "path": path,
182
- "mode": br.traffic_api_pb2.Mode.STOP,
211
+ "mode": traffic_api.Mode.STOP,
183
212
  }
184
213
  ]
185
214
 
186
215
  status: traffic_api.PlaybackInfos = self.traffic_stub.PlayTraffic(
187
- br.traffic_api_pb2.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
216
+ traffic_api.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
188
217
  )
189
218
  if not silent:
190
219
  self.__check_playbackmode_result(status)
@@ -202,7 +231,7 @@ class Broker:
202
231
  return "stopped"
203
232
  raise ValueError("Unknown Mode")
204
233
 
205
- sub = self.traffic_stub.PlayTrafficStatus(br.common_pb2.Empty())
234
+ sub = self.traffic_stub.PlayTrafficStatus(common.Empty())
206
235
  for playback_state in sub:
207
236
  # p = typing.cast(br.traffic_api_pb2.PlaybackInfos, playback_state) # REDUNDANT CAST
208
237
  p = playback_state
@@ -221,40 +250,40 @@ class Broker:
221
250
  callback(offset_length, total_length, get_mode(mode))
222
251
 
223
252
  def listen_on_frame_distribution(self, namespace: str, callback: Callable[[Dict[str, Any]], None]) -> None:
224
- config = network_api.FramesDistributionConfig(namespace=br.common_pb2.NameSpace(name=namespace))
253
+ config = network_api.FramesDistributionConfig(namespace=common.NameSpace(name=namespace))
225
254
  frame_distribution_stream = self.network_stub.SubscribeToFramesDistribution(config)
226
255
  for frame in frame_distribution_stream:
227
256
  f = MessageToDict(frame, including_default_value_fields=True, preserving_proto_field_name=True)
228
257
  callback(f)
229
258
 
230
- def pause(self, namespace: str, path: str, silent: bool = False) -> br.traffic_api_pb2.PlaybackInfos:
259
+ def pause(self, namespace: str, path: str, silent: bool = False) -> traffic_api.PlaybackInfos:
231
260
  playback_list = [
232
261
  {
233
262
  "namespace": namespace,
234
263
  "path": path,
235
- "mode": br.traffic_api_pb2.Mode.PAUSE,
264
+ "mode": traffic_api.Mode.PAUSE,
236
265
  }
237
266
  ]
238
267
 
239
268
  status: traffic_api.PlaybackInfos = self.traffic_stub.PlayTraffic(
240
- br.traffic_api_pb2.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
269
+ traffic_api.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
241
270
  )
242
271
  if not silent:
243
272
  self.__check_playbackmode_result(status)
244
273
  return status
245
274
 
246
- def stop_multiple(self, namespaces: List[str], path: str) -> br.traffic_api_pb2.PlaybackInfos:
275
+ def stop_multiple(self, namespaces: List[str], path: str) -> traffic_api.PlaybackInfos:
247
276
  def to_playback(namespace: str) -> Dict[str, Any]:
248
277
  return {
249
278
  "namespace": namespace,
250
279
  "path": path + "_" + namespace,
251
- "mode": br.traffic_api_pb2.Mode.STOP,
280
+ "mode": traffic_api.Mode.STOP,
252
281
  }
253
282
 
254
283
  playback_list = list(map(to_playback, namespaces))
255
284
 
256
- status = self.traffic_stub.PlayTraffic(
257
- br.traffic_api_pb2.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
285
+ status: traffic_api.PlaybackInfos = self.traffic_stub.PlayTraffic(
286
+ traffic_api.PlaybackInfos(playbackInfo=list(map(self.__create_playback_config, playback_list)))
258
287
  )
259
288
  self.__check_playbackmode_result(status)
260
289
  return status
@@ -308,37 +337,40 @@ class Broker:
308
337
  print(f"Namespace {r['namespace']} did not receive any traffic")
309
338
 
310
339
  def upload(self, file: str, dest: str) -> None:
311
- try:
312
- br.helper.upload_file(system_stub=self.system_stub, path=file, dest_path=dest)
313
- except grpc.RpcError as rpc_error:
314
- print(f"Failed to upload file - {rpc_error.details()} ({rpc_error.code()})")
315
- raise typer.Exit(1)
340
+ sha256 = get_sha256(file)
341
+ with open(file, "rb") as f:
342
+ upload_iterator = generate_data(f, dest.replace(ntpath.sep, posixpath.sep), 1000000, sha256)
343
+ try:
344
+ self.system_stub.UploadFile(upload_iterator, compression=grpc.Compression.Gzip)
345
+ except grpc.RpcError as rpc_error:
346
+ print(f"Failed to upload file - {rpc_error.details()} ({rpc_error.code()})")
347
+ raise typer.Exit(1)
316
348
 
317
349
  def delete_files(self, path: List[str], exit_on_faliure: bool) -> None:
318
350
  for file in path:
319
351
  try:
320
352
  self.system_stub.BatchDeleteFiles(
321
- br.system_api_pb2.FileDescriptions(
322
- fileDescriptions=[br.system_api_pb2.FileDescription(path=file.replace(ntpath.sep, posixpath.sep))]
323
- )
353
+ system_api.FileDescriptions(fileDescriptions=[system_api.FileDescription(path=file.replace(ntpath.sep, posixpath.sep))])
324
354
  )
325
355
  except grpc.RpcError as rpc_error:
326
356
  print(f"Failed to delete file - {rpc_error.details()} ({rpc_error.code()})")
327
357
  if exit_on_faliure:
328
358
  raise typer.Exit(1)
329
359
 
330
- # rpc BatchDeleteFiles (FileDescriptions) returns (Empty) {}
331
-
332
360
  def upload_folder(self, folder: str) -> None:
333
- try:
334
- br.helper.upload_folder(system_stub=self.system_stub, folder=folder)
335
- except grpc.RpcError as rpc_error:
336
- print(f"Failed to upload file - {rpc_error.details()} ({rpc_error.code()})")
337
- raise typer.Exit(1)
361
+ files = [y for x in os.walk(folder) for y in glob(os.path.join(x[0], "*")) if not os.path.isdir(y)]
362
+ assert len(files) != 0, "Specified upload folder is empty or does not exist"
363
+ for file in files:
364
+ self.upload(file, file.replace(folder, ""))
338
365
 
339
366
  def download(self, file: str, dest: str, delegate_err: bool = False) -> None:
340
367
  try:
341
- br_helper.download_file(system_stub=self.system_stub, path=file, dest_path=dest)
368
+ with open(dest, "wb") as f:
369
+ for response in self.system_stub.BatchDownloadFiles(
370
+ system_api.FileDescriptions(fileDescriptions=[system_api.FileDescription(path=file.replace(ntpath.sep, posixpath.sep))])
371
+ ):
372
+ assert not response.HasField("errorMessage"), f"Error uploading file, message is: {response.errorMessage}"
373
+ f.write(response.chunk)
342
374
  except grpc.RpcError as rpc_error:
343
375
  if delegate_err:
344
376
  raise rpc_error
@@ -349,7 +381,7 @@ class Broker:
349
381
 
350
382
  def reload_config(self) -> None:
351
383
  try:
352
- request = br.common_pb2.Empty()
384
+ request = common.Empty()
353
385
  response = self.system_stub.ReloadConfiguration(request, timeout=60000)
354
386
  if response.errorMessage:
355
387
  print(f"Failed to reload config: {response.errorMessage}")
@@ -361,7 +393,7 @@ class Broker:
361
393
 
362
394
  def list_namespaces(self) -> List[str]:
363
395
  # Lists available signals
364
- configuration = self.system_stub.GetConfiguration(br.common_pb2.Empty())
396
+ configuration = self.system_stub.GetConfiguration(common.Empty())
365
397
  namespaces = []
366
398
  for network_info in configuration.networkInfo:
367
399
  namespaces.append(network_info.namespace.name)
@@ -369,7 +401,7 @@ class Broker:
369
401
 
370
402
  def list_signal_names(self, prefix: Union[str, None], suffix: Union[str, None]) -> List[Dict[str, Any]]:
371
403
  # Lists available signals
372
- configuration = self.system_stub.GetConfiguration(br.common_pb2.Empty())
404
+ configuration = self.system_stub.GetConfiguration(common.Empty())
373
405
 
374
406
  signal_names = []
375
407
  for network_info in configuration.networkInfo:
@@ -412,13 +444,12 @@ class Broker:
412
444
  def subscribe_on_script(
413
445
  self,
414
446
  script: bytes,
415
- on_frame: Callable[[Sequence[br.network_api_pb2.Signal]], None],
447
+ on_frame: Callable[[Sequence[network_api.Signal]], None],
416
448
  changed_values_only: bool = False,
417
449
  ) -> Any:
418
- client_id = br.common_pb2.ClientId(id="cli")
419
- # sync = queue.Queue()
450
+ client_id = common.ClientId(id="cli")
420
451
  thread = Thread(
421
- target=br.act_on_scripted_signal,
452
+ target=act_on_scripted_signal,
422
453
  args=(
423
454
  client_id,
424
455
  self.network_stub,
@@ -472,20 +503,20 @@ class Broker:
472
503
  def long_name_subscribe(
473
504
  self, signals_to_subscribe_to: List[SubscribableSignal], on_frame: Callable[..., Any], changed_values_only: bool = True
474
505
  ) -> Any:
475
- client_id = br.common_pb2.ClientId(id="cli")
506
+ client_id = common.ClientId(id="cli")
476
507
 
477
508
  # TODO - This can be improved moving forward and we also need to move the validation into api
478
509
  self.validate_and_get_subscribed_signals(
479
510
  list(map(lambda s: s.namespace, signals_to_subscribe_to)), (list(map(lambda s: s.name, signals_to_subscribe_to)))
480
511
  )
481
512
 
482
- def to_protobuf_signal(s: SubscribableSignal) -> br.common_pb2.SignalId:
513
+ def to_protobuf_signal(s: SubscribableSignal) -> common.SignalId:
483
514
  return self.signal_creator.signal(s.name, s.namespace)
484
515
 
485
516
  signals_to_subscribe_on = list(map(to_protobuf_signal, signals_to_subscribe_to))
486
517
 
487
518
  Thread(
488
- target=br.act_on_signal,
519
+ target=act_on_signal,
489
520
  args=(
490
521
  client_id,
491
522
  self.network_stub,
@@ -506,19 +537,19 @@ class Broker:
506
537
  on_frame: Callable[..., Any],
507
538
  changed_values_only: bool = True,
508
539
  ) -> Any:
509
- client_id = br.common_pb2.ClientId(id="cli")
540
+ client_id = common.ClientId(id="cli")
510
541
 
511
542
  signals_to_subscribe_to: List[SubscribableSignal] = self.validate_and_get_subscribed_signals(
512
543
  subscribed_namespaces, subscribed_signals
513
544
  )
514
545
 
515
- def to_protobuf_signal(s: SubscribableSignal) -> br.common_pb2.SignalId:
546
+ def to_protobuf_signal(s: SubscribableSignal) -> common.SignalId:
516
547
  return self.signal_creator.signal(s.name, s.namespace)
517
548
 
518
549
  signals_to_subscribe_on = list(map(to_protobuf_signal, signals_to_subscribe_to))
519
550
 
520
551
  Thread(
521
- target=br.act_on_signal,
552
+ target=act_on_signal,
522
553
  args=(
523
554
  client_id,
524
555
  self.network_stub,
@@ -532,7 +563,7 @@ class Broker:
532
563
  ecu, subscription = self.q.get()
533
564
  return subscription
534
565
 
535
- def __each_signal(self, signals: Iterable[br.network_api_pb2.Signal], callback: Callable[..., Any]) -> None:
566
+ def __each_signal(self, signals: Iterable[network_api.Signal], callback: Callable[..., Any]) -> None:
536
567
  callback(
537
568
  map(
538
569
  lambda s: {"timestamp_us": s.timestamp, "namespace": s.id.namespace.name, "name": s.id.name, "value": self.__get_value(s)},
@@ -541,7 +572,7 @@ class Broker:
541
572
  )
542
573
 
543
574
  @staticmethod
544
- def __get_value(signal: br.network_api_pb2.Signal) -> Any:
575
+ def __get_value(signal: network_api.Signal) -> Any:
545
576
  if signal.raw != b"":
546
577
  return "0x" + binascii.hexlify(signal.raw).decode("ascii")
547
578
  if signal.HasField("integer"):
@@ -553,7 +584,7 @@ class Broker:
553
584
  return "empty"
554
585
 
555
586
  @staticmethod
556
- def __create_playback_config(item: Dict[str, Any]) -> br.traffic_api_pb2.PlaybackInfo:
587
+ def __create_playback_config(item: Dict[str, Any]) -> traffic_api.PlaybackInfo:
557
588
  """Creating configuration for playback
558
589
 
559
590
  Parameters
@@ -573,26 +604,26 @@ class Broker:
573
604
  return int(item["offsettime"])
574
605
  return 0
575
606
 
576
- playback_config = br.traffic_api_pb2.PlaybackConfig(
577
- fileDescription=br.system_api_pb2.FileDescription(path=item["path"]),
578
- namespace=br.common_pb2.NameSpace(name=item["namespace"]),
607
+ playback_config = traffic_api.PlaybackConfig(
608
+ fileDescription=system_api.FileDescription(path=item["path"]),
609
+ namespace=common.NameSpace(name=item["namespace"]),
579
610
  )
580
- return br.traffic_api_pb2.PlaybackInfo(
611
+ return traffic_api.PlaybackInfo(
581
612
  playbackConfig=playback_config,
582
- playbackMode=br.traffic_api_pb2.PlaybackMode(mode=item["mode"], offsetTime=get_offset_time()),
613
+ playbackMode=traffic_api.PlaybackMode(mode=item["mode"], offsetTime=get_offset_time()),
583
614
  )
584
615
 
585
616
  def get_license(self) -> LicenseInfo:
586
- license_info = self.system_stub.GetLicenseInfo(br.common_pb2.Empty())
617
+ license_info = self.system_stub.GetLicenseInfo(common.Empty())
587
618
  return LicenseInfo(
588
- valid=license_info.status == br.system_api_pb2.LicenseStatus.VALID,
619
+ valid=license_info.status == system_api.LicenseStatus.VALID,
589
620
  expires=license_info.expires,
590
621
  email=license_info.requestId,
591
622
  machine_id=license_info.requestMachineId.decode("utf-8"),
592
623
  )
593
624
 
594
625
  def apply_license(self, license_data_b64: bytes) -> LicenseInfo:
595
- license = br.system_api_pb2.License()
626
+ license = system_api.License()
596
627
  license.data = license_data_b64
597
628
  license.termsAgreement = True
598
629
  self.system_stub.SetLicense(license)