bosdyn-client 4.1.1__py3-none-any.whl → 5.0.1__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.
- bosdyn/client/__init__.py +1 -0
- bosdyn/client/audio_visual.py +339 -0
- bosdyn/client/audio_visual_helpers.py +112 -0
- bosdyn/client/command_line.py +15 -7
- bosdyn/client/data_acquisition_helpers.py +1 -1
- bosdyn/client/data_acquisition_store.py +2 -2
- bosdyn/client/directory_registration.py +34 -5
- bosdyn/client/error_callback_result.py +29 -0
- bosdyn/client/gps/NMEAParser.py +16 -6
- bosdyn/client/gps/gps_listener.py +31 -1
- bosdyn/client/gps/ntrip_client.py +240 -0
- bosdyn/client/graph_nav.py +16 -1
- bosdyn/client/gripper_camera_param.py +40 -0
- bosdyn/client/image.py +16 -0
- bosdyn/client/image_service_helpers.py +88 -68
- bosdyn/client/keepalive.py +37 -8
- bosdyn/client/log_status.py +6 -0
- bosdyn/client/math_helpers.py +18 -0
- bosdyn/client/payload_registration.py +40 -6
- bosdyn/client/payload_software_update.py +185 -0
- bosdyn/client/payload_software_update_initiation.py +79 -0
- bosdyn/client/point_cloud.py +9 -0
- bosdyn/client/robot.py +9 -4
- bosdyn/client/sdk.py +4 -2
- bosdyn/client/service_customization_helpers.py +19 -6
- bosdyn/client/spot_cam/__init__.py +2 -0
- bosdyn/client/spot_cam/ptz.py +20 -24
- bosdyn/client/token_manager.py +56 -27
- bosdyn/client/util.py +1 -1
- {bosdyn_client-4.1.1.dist-info → bosdyn_client-5.0.1.dist-info}/METADATA +4 -4
- {bosdyn_client-4.1.1.dist-info → bosdyn_client-5.0.1.dist-info}/RECORD +33 -27
- {bosdyn_client-4.1.1.dist-info → bosdyn_client-5.0.1.dist-info}/WHEEL +0 -0
- {bosdyn_client-4.1.1.dist-info → bosdyn_client-5.0.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Copyright (c) 2023 Boston Dynamics, Inc. All rights reserved.
|
|
2
|
+
#
|
|
3
|
+
# Downloading, reproducing, distributing or otherwise using the SDK Software
|
|
4
|
+
# is subject to the terms and conditions of the Boston Dynamics Software
|
|
5
|
+
# Development Kit License (20191101-BDSDK-SL).
|
|
6
|
+
|
|
7
|
+
"""Payload software update initiation gRPC client.
|
|
8
|
+
|
|
9
|
+
This client uses an insecure channel for signaling to a payload that it should
|
|
10
|
+
send its version information or initiate a software update.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from bosdyn.api.payload_software_update_initiation_pb2 import (
|
|
14
|
+
TriggerInitiateUpdateRequest, TriggerSendPayloadSoftwareInfoRequest)
|
|
15
|
+
from bosdyn.api.payload_software_update_initiation_service_pb2_grpc import \
|
|
16
|
+
PayloadSoftwareUpdateInitiationServiceStub
|
|
17
|
+
from bosdyn.client.common import BaseClient
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class PayloadSoftwareUpdateInitiationClient(BaseClient):
|
|
21
|
+
"""A client used to direct a payload to send its version information or start an update."""
|
|
22
|
+
|
|
23
|
+
def __init__(self):
|
|
24
|
+
super(PayloadSoftwareUpdateInitiationClient,
|
|
25
|
+
self).__init__(PayloadSoftwareUpdateInitiationServiceStub)
|
|
26
|
+
|
|
27
|
+
default_service_name = 'payload-software-update-initiation'
|
|
28
|
+
service_type = 'bosdyn.api.PayloadSoftwareUpdateInitiationService'
|
|
29
|
+
|
|
30
|
+
def trigger_send_payload_software_info(self, **kwargs):
|
|
31
|
+
"""Tell a payload to send its current version information to Spot.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
TriggerSendPayloadSoftwareInfoResponse: The response object from the payload. Currently
|
|
35
|
+
this message is empty.
|
|
36
|
+
|
|
37
|
+
Raises:
|
|
38
|
+
RpcError: Problem communicating with the payload.
|
|
39
|
+
"""
|
|
40
|
+
return self.call(self._stub.TriggerSendPayloadSoftwareInfo,
|
|
41
|
+
TriggerSendPayloadSoftwareInfoRequest(), **kwargs)
|
|
42
|
+
|
|
43
|
+
def trigger_send_payload_software_info_async(self, **kwargs):
|
|
44
|
+
"""Async version of trigger_send_payload_software_info().
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
TriggerSendPayloadSoftwareInfoResponse: The response object from the payload. Currently
|
|
48
|
+
this message is empty.
|
|
49
|
+
|
|
50
|
+
Raises:
|
|
51
|
+
RpcError: Problem communicating with the payload.
|
|
52
|
+
"""
|
|
53
|
+
return self.call_async(self._stub.TriggerSendPayloadSoftwareInfo,
|
|
54
|
+
TriggerSendPayloadSoftwareInfoRequest(), **kwargs)
|
|
55
|
+
|
|
56
|
+
def trigger_initiate_update(self, **kwargs):
|
|
57
|
+
"""Tell a payload to initiate its software update logic.
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
TriggerInitiateUpdateResponse: The response object from the payload. Currently this
|
|
61
|
+
message is empty.
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
RpcError: Problem communicating with the payload.
|
|
65
|
+
"""
|
|
66
|
+
return self.call(self._stub.TriggerInitiateUpdate, TriggerInitiateUpdateRequest(), **kwargs)
|
|
67
|
+
|
|
68
|
+
def trigger_initiate_update_async(self, **kwargs):
|
|
69
|
+
"""Async version of trigger_initiate_update().
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
TriggerInitiateUpdateResponse: The response object from the payload. Currently this
|
|
73
|
+
message is empty.
|
|
74
|
+
|
|
75
|
+
Raises:
|
|
76
|
+
RpcError: Problem communicating with the payload.
|
|
77
|
+
"""
|
|
78
|
+
return self.call_async(self._stub.TriggerInitiateUpdate, TriggerInitiateUpdateRequest(),
|
|
79
|
+
**kwargs)
|
bosdyn/client/point_cloud.py
CHANGED
|
@@ -39,6 +39,10 @@ class PointCloudDataError(PointCloudResponseError):
|
|
|
39
39
|
"""System cannot generate point cloud data at this time."""
|
|
40
40
|
|
|
41
41
|
|
|
42
|
+
class PointCloudTypeError(PointCloudResponseError):
|
|
43
|
+
"""System cannot generate point cloud with the request cloud_type."""
|
|
44
|
+
|
|
45
|
+
|
|
42
46
|
_STATUS_TO_ERROR = collections.defaultdict(lambda: (PointCloudResponseError, None))
|
|
43
47
|
_STATUS_TO_ERROR.update({
|
|
44
48
|
point_cloud_protos.PointCloudResponse.STATUS_OK: (None, None),
|
|
@@ -50,6 +54,8 @@ _STATUS_TO_ERROR.update({
|
|
|
50
54
|
error_pair(UnsetStatusError),
|
|
51
55
|
point_cloud_protos.PointCloudResponse.STATUS_POINT_CLOUD_DATA_ERROR:
|
|
52
56
|
error_pair(PointCloudDataError),
|
|
57
|
+
point_cloud_protos.PointCloudResponse.STATUS_UNSUPPORTED_CLOUD_TYPE:
|
|
58
|
+
error_pair(PointCloudTypeError),
|
|
53
59
|
})
|
|
54
60
|
|
|
55
61
|
|
|
@@ -66,6 +72,8 @@ def _error_from_response(response):
|
|
|
66
72
|
return None
|
|
67
73
|
|
|
68
74
|
|
|
75
|
+
|
|
76
|
+
|
|
69
77
|
class PointCloudClient(BaseClient):
|
|
70
78
|
"""A client handling point clouds."""
|
|
71
79
|
|
|
@@ -177,6 +185,7 @@ class PointCloudClient(BaseClient):
|
|
|
177
185
|
return point_cloud_protos.ListPointCloudSourcesRequest()
|
|
178
186
|
|
|
179
187
|
|
|
188
|
+
|
|
180
189
|
def build_pc_request(point_cloud_source_name):
|
|
181
190
|
"""Helper function which builds an PointCloudRequest from a point cloud source name.
|
|
182
191
|
|
bosdyn/client/robot.py
CHANGED
|
@@ -131,6 +131,10 @@ class Robot(object):
|
|
|
131
131
|
self._time_sync_thread = None
|
|
132
132
|
self.executor = None
|
|
133
133
|
|
|
134
|
+
#: Callable[[Exception], ErrorCallbackResult] | None: Optional callback to be invoked when
|
|
135
|
+
#: an error occurs in the token refresh thread.
|
|
136
|
+
self.token_refresh_error_callback = None
|
|
137
|
+
|
|
134
138
|
# Set default max message length for sending and receiving. These values are used when
|
|
135
139
|
# creating channels.
|
|
136
140
|
self.max_send_message_length = DEFAULT_MAX_MESSAGE_LENGTH
|
|
@@ -385,7 +389,7 @@ class Robot(object):
|
|
|
385
389
|
self.update_user_token(user_token, username)
|
|
386
390
|
|
|
387
391
|
def authenticate_from_payload_credentials(self, guid, secret, payload_registration_client=None,
|
|
388
|
-
timeout=None):
|
|
392
|
+
timeout=None, retry_interval=1.0):
|
|
389
393
|
"""Authenticate to this Robot with the guid/secret of the hosting payload.
|
|
390
394
|
|
|
391
395
|
This call is used to authenticate to a robot using payload credentials. If a payload is
|
|
@@ -413,7 +417,7 @@ class Robot(object):
|
|
|
413
417
|
self.logger.warning(
|
|
414
418
|
'Payload is not authorized. Authentication will block until an'
|
|
415
419
|
' operator authorizes the payload in the Admin Console.')
|
|
416
|
-
time.sleep(
|
|
420
|
+
time.sleep(retry_interval)
|
|
417
421
|
self.update_user_token(user_token)
|
|
418
422
|
|
|
419
423
|
def update_user_token(self, user_token, username=None):
|
|
@@ -467,7 +471,8 @@ class Robot(object):
|
|
|
467
471
|
return self.service_type_by_name
|
|
468
472
|
|
|
469
473
|
|
|
470
|
-
def register_payload_and_authenticate(self, payload, secret, timeout=None
|
|
474
|
+
def register_payload_and_authenticate(self, payload, secret, timeout=None,
|
|
475
|
+
auth_retry_interval=1.0):
|
|
471
476
|
"""Register a payload with the robot and request a user_token.
|
|
472
477
|
|
|
473
478
|
This method will block until the payload is authorized by an operator in the robot webpage.
|
|
@@ -486,7 +491,7 @@ class Robot(object):
|
|
|
486
491
|
pass
|
|
487
492
|
self.authenticate_from_payload_credentials(
|
|
488
493
|
payload.GUID, secret, payload_registration_client=payload_registration_client,
|
|
489
|
-
timeout=timeout)
|
|
494
|
+
timeout=timeout, retry_interval=auth_retry_interval)
|
|
490
495
|
|
|
491
496
|
def start_time_sync(self, time_sync_interval_sec=None):
|
|
492
497
|
"""Start time sync thread if needed.
|
bosdyn/client/sdk.py
CHANGED
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
|
|
9
9
|
import datetime
|
|
10
10
|
import glob
|
|
11
|
+
import importlib.resources
|
|
11
12
|
import logging
|
|
12
13
|
import os
|
|
13
14
|
import platform
|
|
14
15
|
from enum import Enum
|
|
15
16
|
|
|
16
17
|
import jwt
|
|
17
|
-
import pkg_resources
|
|
18
18
|
from deprecated.sphinx import deprecated
|
|
19
19
|
|
|
20
20
|
from .arm_surface_contact import ArmSurfaceContactClient
|
|
@@ -178,6 +178,8 @@ def create_standard_sdk(client_name_prefix, service_clients=None, cert_resource_
|
|
|
178
178
|
|
|
179
179
|
|
|
180
180
|
|
|
181
|
+
|
|
182
|
+
|
|
181
183
|
class Sdk(object):
|
|
182
184
|
"""Repository for settings typically common to a single developer and/or robot fleet.
|
|
183
185
|
See also Robot for robot-specific settings.
|
|
@@ -281,7 +283,7 @@ class Sdk(object):
|
|
|
281
283
|
"""
|
|
282
284
|
self.cert = None
|
|
283
285
|
if resource_path_glob is None:
|
|
284
|
-
self.cert =
|
|
286
|
+
self.cert = importlib.resources.read_binary('bosdyn.client.resources', 'robot.pem')
|
|
285
287
|
else:
|
|
286
288
|
cert_paths = [c for c in glob.glob(resource_path_glob) if os.path.isfile(c)]
|
|
287
289
|
if not cert_paths:
|
|
@@ -356,7 +356,7 @@ class _StringParamValidator(_ParamValidatorInterface):
|
|
|
356
356
|
if err:
|
|
357
357
|
return err
|
|
358
358
|
|
|
359
|
-
if len(self.param_spec.options) > 0:
|
|
359
|
+
if not self.param_spec.editable and len(self.param_spec.options) > 0:
|
|
360
360
|
if param_value.value not in self.param_spec.options:
|
|
361
361
|
return CustomParamError(
|
|
362
362
|
status=CustomParamError.STATUS_INVALID_VALUE, error_messages=[
|
|
@@ -404,6 +404,10 @@ class _RegionOfInterestParamValidator(_ParamValidatorInterface):
|
|
|
404
404
|
if self.param_spec.default_area.rectangle:
|
|
405
405
|
raise InvalidCustomParamSpecError(
|
|
406
406
|
["Default area is a rectangle despite not being allowed"])
|
|
407
|
+
if not self.param_spec.allows_polygon:
|
|
408
|
+
if len(self.param_spec.default_area.polygon.vertices) > 0:
|
|
409
|
+
raise InvalidCustomParamSpecError(
|
|
410
|
+
["Default area is a polygon despite not being allowed"])
|
|
407
411
|
|
|
408
412
|
def validate_value(self, param_value):
|
|
409
413
|
err = check_types_match(param_value, self.proto_type)
|
|
@@ -415,6 +419,13 @@ class _RegionOfInterestParamValidator(_ParamValidatorInterface):
|
|
|
415
419
|
return CustomParamError(
|
|
416
420
|
status=CustomParamError.STATUS_INVALID_VALUE,
|
|
417
421
|
error_messages=["Chosen area is a rectangle despite not being allowed"])
|
|
422
|
+
|
|
423
|
+
if not self.param_spec.allows_polygon:
|
|
424
|
+
if len(param_value.area.polygon.vertices) > 0:
|
|
425
|
+
return CustomParamError(
|
|
426
|
+
status=CustomParamError.STATUS_INVALID_VALUE,
|
|
427
|
+
error_messages=["Chosen area is a polygon despite not being allowed"])
|
|
428
|
+
|
|
418
429
|
if param_value.image_cols < 0:
|
|
419
430
|
return CustomParamError(status=CustomParamError.STATUS_INVALID_VALUE,
|
|
420
431
|
error_messages=["Number of columns in image must be positive"])
|
|
@@ -1165,10 +1176,10 @@ def make_bool_param_spec(default_value: Optional[bool] = None) -> BoolParam.Spec
|
|
|
1165
1176
|
return spec
|
|
1166
1177
|
|
|
1167
1178
|
|
|
1168
|
-
def make_region_of_interest_param_spec(
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1179
|
+
def make_region_of_interest_param_spec(service_and_source: Optional[
|
|
1180
|
+
RegionOfInterestParam.ServiceAndSource] = None, default_area: Optional[AreaI] = None,
|
|
1181
|
+
allows_rectangle: bool = False,
|
|
1182
|
+
allows_polygon: bool = False) -> RegionOfInterestParam.Spec:
|
|
1172
1183
|
"""
|
|
1173
1184
|
Helper function to create a RegionOfInterestParam.Spec
|
|
1174
1185
|
|
|
@@ -1176,10 +1187,12 @@ def make_region_of_interest_param_spec(
|
|
|
1176
1187
|
service_and_source: service and source to which the RegionOfInterestParam should adhere
|
|
1177
1188
|
default_area: starting area for the RegionOfInterestParam
|
|
1178
1189
|
allows_rectangle: whether a rectangle may be drawn for the selected area
|
|
1190
|
+
allows_polygon: whether a polygon may be drawn for the selected area
|
|
1179
1191
|
"""
|
|
1180
1192
|
return RegionOfInterestParam.Spec(default_area=default_area,
|
|
1181
1193
|
service_and_source=service_and_source,
|
|
1182
|
-
allows_rectangle=allows_rectangle
|
|
1194
|
+
allows_rectangle=allows_rectangle,
|
|
1195
|
+
allows_polygon=allows_polygon)
|
|
1183
1196
|
|
|
1184
1197
|
|
|
1185
1198
|
|
bosdyn/client/spot_cam/ptz.py
CHANGED
|
@@ -159,18 +159,7 @@ class PtzClient(BaseClient):
|
|
|
159
159
|
Returns:
|
|
160
160
|
SetPtzFocusStateResponse indicating whether the call was successful
|
|
161
161
|
"""
|
|
162
|
-
|
|
163
|
-
if focus_position is not None:
|
|
164
|
-
focus_position_val = Int32Value(value=focus_position)
|
|
165
|
-
approx_distance = None
|
|
166
|
-
elif distance is not None:
|
|
167
|
-
approx_distance = FloatValue(value=distance)
|
|
168
|
-
focus_position_val = None
|
|
169
|
-
else:
|
|
170
|
-
raise ValueError("One of distance or focus_position must be specified.")
|
|
171
|
-
|
|
172
|
-
ptz_focus_state = ptz_pb2.PtzFocusState(mode=focus_mode, approx_distance=approx_distance,
|
|
173
|
-
focus_position=focus_position_val)
|
|
162
|
+
ptz_focus_state = create_focus_state(focus_mode, distance, focus_position)
|
|
174
163
|
request = ptz_pb2.SetPtzFocusStateRequest(focus_state=ptz_focus_state)
|
|
175
164
|
return self.call(self._stub.SetPtzFocusState, request,
|
|
176
165
|
self._set_ptz_focus_state_from_response, common_header_errors,
|
|
@@ -178,18 +167,7 @@ class PtzClient(BaseClient):
|
|
|
178
167
|
|
|
179
168
|
def set_ptz_focus_state_async(self, focus_mode, distance=None, focus_position=None, **kwargs):
|
|
180
169
|
"""Async version of set_ptz_focus_state()"""
|
|
181
|
-
|
|
182
|
-
if focus_position is not None:
|
|
183
|
-
focus_position_val = Int32Value(value=focus_position)
|
|
184
|
-
approx_distance = None
|
|
185
|
-
elif distance is not None:
|
|
186
|
-
approx_distance = FloatValue(value=distance)
|
|
187
|
-
focus_position_val = None
|
|
188
|
-
else:
|
|
189
|
-
raise ValueError("One of distance or focus_position must be specified.")
|
|
190
|
-
|
|
191
|
-
ptz_focus_state = ptz_pb2.PtzFocusState(mode=focus_mode, approx_distance=approx_distance,
|
|
192
|
-
focus_position=focus_position_val)
|
|
170
|
+
ptz_focus_state = create_focus_state(focus_mode, distance, focus_position)
|
|
193
171
|
request = ptz_pb2.SetPtzFocusStateRequest(focus_state=ptz_focus_state)
|
|
194
172
|
return self.call_async(self._stub.SetPtzFocusState, request,
|
|
195
173
|
self._set_ptz_focus_state_from_response, common_header_errors,
|
|
@@ -232,3 +210,21 @@ class PtzClient(BaseClient):
|
|
|
232
210
|
def shift_pan_angle(pan):
|
|
233
211
|
"""Shift the pan angle (degrees) so that it is in the [0,360] range."""
|
|
234
212
|
return recenter_value_mod(pan, 180, 360)
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
def create_focus_state(focus_mode, distance=None, focus_position=None):
|
|
216
|
+
"""Generate a focus state proto."""
|
|
217
|
+
approx_distance = None
|
|
218
|
+
focus_position_val = None
|
|
219
|
+
if focus_mode == ptz_pb2.PtzFocusState.PTZ_FOCUS_MANUAL:
|
|
220
|
+
if focus_position is not None:
|
|
221
|
+
focus_position_val = Int32Value(value=focus_position)
|
|
222
|
+
approx_distance = None
|
|
223
|
+
elif distance is not None:
|
|
224
|
+
approx_distance = FloatValue(value=distance)
|
|
225
|
+
focus_position_val = None
|
|
226
|
+
else:
|
|
227
|
+
raise ValueError("One of distance or focus_position must be specified.")
|
|
228
|
+
|
|
229
|
+
return ptz_pb2.PtzFocusState(mode=focus_mode, approx_distance=approx_distance,
|
|
230
|
+
focus_position=focus_position_val)
|
bosdyn/client/token_manager.py
CHANGED
|
@@ -14,11 +14,15 @@ import logging
|
|
|
14
14
|
import threading
|
|
15
15
|
|
|
16
16
|
from .auth import InvalidTokenError
|
|
17
|
-
from .
|
|
17
|
+
from .error_callback_result import ErrorCallbackResult
|
|
18
|
+
from .exceptions import ResponseError, RpcError, TimedOutError
|
|
18
19
|
from .token_cache import WriteFailedError
|
|
19
20
|
|
|
20
21
|
_LOGGER = logging.getLogger(__name__)
|
|
21
22
|
|
|
23
|
+
USER_TOKEN_REFRESH_TIME_DELTA = datetime.timedelta(hours=1)
|
|
24
|
+
USER_TOKEN_RETRY_INTERVAL_START = datetime.timedelta(seconds=1)
|
|
25
|
+
|
|
22
26
|
|
|
23
27
|
class TokenManager:
|
|
24
28
|
"""Refreshes the user token in the robot object.
|
|
@@ -26,10 +30,13 @@ class TokenManager:
|
|
|
26
30
|
The refresh policy assumes the token is minted and then the manager is
|
|
27
31
|
launched."""
|
|
28
32
|
|
|
29
|
-
def __init__(self, robot, timestamp=None
|
|
33
|
+
def __init__(self, robot, timestamp=None, refresh_interval=USER_TOKEN_REFRESH_TIME_DELTA,
|
|
34
|
+
initial_retry_interval=USER_TOKEN_RETRY_INTERVAL_START):
|
|
30
35
|
self.robot = robot
|
|
31
36
|
|
|
32
37
|
self._last_timestamp = timestamp or datetime.datetime.now()
|
|
38
|
+
self._refresh_interval = refresh_interval
|
|
39
|
+
self._initial_retry_seconds = initial_retry_interval
|
|
33
40
|
|
|
34
41
|
# Daemon threads can still run during shutdown after python has
|
|
35
42
|
# started to clear out things in globals().
|
|
@@ -51,33 +58,55 @@ class TokenManager:
|
|
|
51
58
|
|
|
52
59
|
def update(self):
|
|
53
60
|
"""Refresh the user token as needed."""
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
while not self._exit_thread.
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
except WriteFailedError:
|
|
64
|
-
_LOGGER.exception(
|
|
65
|
-
"Failed to save the token to the cache. Continuing without caching.")
|
|
66
|
-
except (InvalidTokenError, ResponseError, RpcError):
|
|
67
|
-
_LOGGER.exception("Error refreshing the token. Retry in %s", retry_interval)
|
|
68
|
-
|
|
69
|
-
# Exponential back-off on retrying
|
|
70
|
-
self._exit_thread.wait(retry_interval.seconds)
|
|
71
|
-
retry_interval = min(2 * retry_interval, USER_TOKEN_REFRESH_TIME_DELTA)
|
|
72
|
-
continue
|
|
73
|
-
|
|
74
|
-
retry_interval = USER_TOKEN_RETRY_INTERVAL_START
|
|
75
|
-
|
|
76
|
-
# Wait until the specified time or get interrupted by user.
|
|
61
|
+
retry_interval = self._initial_retry_seconds
|
|
62
|
+
wait_time = min(self._refresh_interval - (datetime.datetime.now() - self._last_timestamp),
|
|
63
|
+
self._refresh_interval)
|
|
64
|
+
|
|
65
|
+
while not self._exit_thread.wait(wait_time.total_seconds()):
|
|
66
|
+
start_time = datetime.datetime.now()
|
|
67
|
+
action = ErrorCallbackResult.RESUME_NORMAL_OPERATION
|
|
68
|
+
try:
|
|
69
|
+
self.robot.authenticate_with_token(self.robot.user_token)
|
|
77
70
|
self._last_timestamp = datetime.datetime.now()
|
|
78
|
-
|
|
71
|
+
except WriteFailedError:
|
|
72
|
+
_LOGGER.exception(
|
|
73
|
+
"Failed to save the token to the cache. Continuing without caching.")
|
|
74
|
+
except (InvalidTokenError, ResponseError, RpcError) as exc:
|
|
75
|
+
_LOGGER.exception("Error refreshing the token.")
|
|
76
|
+
# Default course of action is to retry with a back-off, unless the application
|
|
77
|
+
# supplied callback directs us to do otherwise.
|
|
78
|
+
action = ErrorCallbackResult.RETRY_WITH_EXPONENTIAL_BACK_OFF
|
|
79
|
+
# If the application provided a callback and the error was encountered while
|
|
80
|
+
# refreshing the token, invoke the callback so that the application can take
|
|
81
|
+
# appropriate action.
|
|
82
|
+
if self.robot.token_refresh_error_callback is not None and not isinstance(
|
|
83
|
+
exc, TimedOutError):
|
|
84
|
+
try:
|
|
85
|
+
action = self.robot.token_refresh_error_callback(exc)
|
|
86
|
+
except Exception: #pylint: disable=broad-except
|
|
87
|
+
_LOGGER.exception(
|
|
88
|
+
"Exception thrown in the provided token refresh error callback")
|
|
89
|
+
if action == ErrorCallbackResult.RESUME_NORMAL_OPERATION:
|
|
90
|
+
_LOGGER.warning("Refreshing token in %s", self._refresh_interval)
|
|
91
|
+
|
|
92
|
+
elapsed = datetime.datetime.now() - start_time
|
|
93
|
+
if action == ErrorCallbackResult.ABORT:
|
|
94
|
+
_LOGGER.warning(
|
|
95
|
+
"Application-supplied callback directed the token refresh loop to exit.")
|
|
96
|
+
break
|
|
97
|
+
elif action == ErrorCallbackResult.RETRY_IMMEDIATELY:
|
|
98
|
+
_LOGGER.warning("Retrying to refresh token immediately.")
|
|
99
|
+
wait_time = datetime.timedelta(seconds=0)
|
|
100
|
+
elif action == ErrorCallbackResult.RESUME_NORMAL_OPERATION:
|
|
101
|
+
wait_time = self._refresh_interval - elapsed
|
|
102
|
+
retry_interval = self._initial_retry_seconds
|
|
103
|
+
else:
|
|
104
|
+
# action doesn't match one of the enum values or is one of
|
|
105
|
+
# RETRY_WITH_EXPONENTIAL_BACK_OFF or DEFAULT_ACTION
|
|
106
|
+
_LOGGER.warning("Retrying token refresh in %s", retry_interval)
|
|
107
|
+
wait_time = retry_interval - elapsed
|
|
108
|
+
retry_interval = min(2 * retry_interval, self._refresh_interval)
|
|
79
109
|
|
|
80
|
-
self._exit_thread.wait(elapsed_time.seconds)
|
|
81
110
|
message = 'Shutting down monitoring of token belonging to robot {}'.format(
|
|
82
111
|
self.robot.address)
|
|
83
112
|
_LOGGER.debug(message)
|
bosdyn/client/util.py
CHANGED
|
@@ -389,7 +389,7 @@ def add_service_endpoint_arguments(parser):
|
|
|
389
389
|
|
|
390
390
|
def safe_pb_enum_to_string(value, pb_enum_obj):
|
|
391
391
|
"""Safe wrapper to convert a protobuf enum object to its string representation.
|
|
392
|
-
Avoids
|
|
392
|
+
Avoids throwing an exception if the status is unknown by the enum object.
|
|
393
393
|
|
|
394
394
|
Args:
|
|
395
395
|
value: The enum value to convert
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: bosdyn-client
|
|
3
|
-
Version:
|
|
3
|
+
Version: 5.0.1
|
|
4
4
|
Summary: Boston Dynamics API client code and interfaces
|
|
5
5
|
Home-page: https://dev.bostondynamics.com/
|
|
6
6
|
Author: Boston Dynamics
|
|
7
7
|
Author-email: support@bostondynamics.com
|
|
8
8
|
Project-URL: Documentation, https://dev.bostondynamics.com/
|
|
9
9
|
Project-URL: Source, https://github.com/boston-dynamics/spot-sdk/
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
11
10
|
Classifier: Programming Language :: Python :: 3.7
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.8
|
|
13
12
|
Classifier: Programming Language :: Python :: 3.9
|
|
14
13
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
14
|
Classifier: License :: Other/Proprietary License
|
|
16
15
|
Classifier: Operating System :: OS Independent
|
|
16
|
+
Requires-Python: >=3.7
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
|
-
Requires-Dist: bosdyn-api (==
|
|
19
|
-
Requires-Dist: bosdyn-core (==
|
|
18
|
+
Requires-Dist: bosdyn-api (==5.0.1)
|
|
19
|
+
Requires-Dist: bosdyn-core (==5.0.1)
|
|
20
20
|
Requires-Dist: grpcio
|
|
21
21
|
Requires-Dist: pyjwt
|
|
22
22
|
Requires-Dist: numpy
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
bosdyn/__init__.py,sha256=CMQioQKK1NlMk3kZuY49b_Aw-JyvDeOtuqOCAul1I0s,330
|
|
2
|
-
bosdyn/client/__init__.py,sha256=
|
|
2
|
+
bosdyn/client/__init__.py,sha256=PsouppDAVJC_29ETHUpDsGg6LWI6QDYIcQdFZGncWq4,1313
|
|
3
3
|
bosdyn/client/__main__.py,sha256=g__h-0z_Q6yzuiXdHQQTh9AI3C2cSc3PocpvbLVwa3E,466
|
|
4
4
|
bosdyn/client/area_callback.py,sha256=nQnhJR8-f0PMq9uILpKhYitVuIZHl6VViUDndN2K4u8,6270
|
|
5
5
|
bosdyn/client/area_callback_region_handler_base.py,sha256=cr5SwGogXmuMbAbbMeHvQZQBflYyFTOCj7wrUOgsUHQ,16467
|
|
@@ -8,78 +8,84 @@ bosdyn/client/area_callback_service_servicer.py,sha256=o1kYKV83Q-ud-_rmT17XTSqBd
|
|
|
8
8
|
bosdyn/client/area_callback_service_utils.py,sha256=R8ljJe8fPszMI6RyuGRyv_QGu63kw1yZAveZydlpERI,5858
|
|
9
9
|
bosdyn/client/arm_surface_contact.py,sha256=DRfPfsFEzfk6ufe080ViqasUefl2ZUtcvcNENgcf55k,3710
|
|
10
10
|
bosdyn/client/async_tasks.py,sha256=gEPev6_jaUCe-G5PqktMiMGb7ohDy0daunxzQD5jafg,5594
|
|
11
|
+
bosdyn/client/audio_visual.py,sha256=yfGy7qL6WRvYPE_gAzBJLzQ8Aucc_u5Hkb_L8fJ-Jyc,14230
|
|
12
|
+
bosdyn/client/audio_visual_helpers.py,sha256=9qksn7epH5jBdbwa6VVMcm2mn8HCVtJuSW1C847Jo6w,4499
|
|
11
13
|
bosdyn/client/auth.py,sha256=YLo6jP0Ssl_Z6rHtTiPiKUNIweDRYub9w3iHdUe6n40,5302
|
|
12
14
|
bosdyn/client/auto_return.py,sha256=kqT1gaaneLYIPFVAFzpvTHRwa8NYYQ2OBf7wViBQudE,5598
|
|
13
15
|
bosdyn/client/autowalk.py,sha256=e57FcAC4fu2BPD57Yy4j1F8DPIPPic0Qt1E0UM-oZWo,5734
|
|
14
16
|
bosdyn/client/bddf.py,sha256=ok_2JcflSCQfcM25lpEgzKnkEJl0FDcJ16Bgo9Rjyzc,1763
|
|
15
17
|
bosdyn/client/bddf_download.py,sha256=oDztm-aS5J_ABLb-cxomNtwNPrdlnFp8hEuOMVxVRH4,7586
|
|
16
18
|
bosdyn/client/channel.py,sha256=voNa-3S6LXsTlsXPXPLEoqNxYl2Xx5CNP7w9EELEtdY,8840
|
|
17
|
-
bosdyn/client/command_line.py,sha256=
|
|
19
|
+
bosdyn/client/command_line.py,sha256=lg5lhCAOP4Zgt6At8wis21_O2NB_SbGLL6MR22eIHL4,98748
|
|
18
20
|
bosdyn/client/common.py,sha256=n4iTcdLCWTS9k0iH8_qrQAOhryqWjSfoEIgiBynjhOY,24997
|
|
19
21
|
bosdyn/client/data_acquisition.py,sha256=jd3XvrktXsGUh3mlL4zMzs6zSvynayVE2_GodnYgFH4,15226
|
|
20
|
-
bosdyn/client/data_acquisition_helpers.py,sha256=
|
|
22
|
+
bosdyn/client/data_acquisition_helpers.py,sha256=j6nTxk9QP4AsiYX9LPf0g2qDmBf-NU61kC2zZpbEBdA,14805
|
|
21
23
|
bosdyn/client/data_acquisition_plugin.py,sha256=5IG2IYkL5FDPZhPRB8caoBjx34f63Eem5u5oZTHBaxo,6690
|
|
22
24
|
bosdyn/client/data_acquisition_plugin_service.py,sha256=tzUBUg9LVPKvDpgogTqEzkhVdlxvHds2HdxRdNDfIJQ,28217
|
|
23
|
-
bosdyn/client/data_acquisition_store.py,sha256=
|
|
25
|
+
bosdyn/client/data_acquisition_store.py,sha256=n7MUM5LLSzRJ7zC13d4pXCN-gbkduMYkt7YXU2syc1s,19647
|
|
24
26
|
bosdyn/client/data_buffer.py,sha256=Ta-7CCoy_-StzXDm8cLIjvOnMDgKEzKFc9mcDmVkubc,26661
|
|
25
27
|
bosdyn/client/data_chunk.py,sha256=6xq9zqLD-JH72ZxzEQEKYqhXvb34TlcZoeqAYaXRxCw,1959
|
|
26
28
|
bosdyn/client/data_service.py,sha256=aKfXJCciJ2M2WZRKfdWiLS2n-UEKWSRkOgcTnArbc5o,5201
|
|
27
29
|
bosdyn/client/directory.py,sha256=jWBxnPzBJSrfr4fuLf2VuZGsxOo8Q5iX5tEw6Zx2VY0,4906
|
|
28
|
-
bosdyn/client/directory_registration.py,sha256=
|
|
30
|
+
bosdyn/client/directory_registration.py,sha256=SV2xWly0Zu1XaWhyJ9eqXYeWSjFbwfyFmup_RjR3Cdw,20806
|
|
29
31
|
bosdyn/client/docking.py,sha256=hYwZNIir3_pt-WvMFiXzMqDCwW8nA5H1BYOUD6_3-00,17596
|
|
30
32
|
bosdyn/client/door.py,sha256=dbBuGcuoZL3gRhxTQoQHKDlnzcML8ELBtQxCQqomYpo,3110
|
|
33
|
+
bosdyn/client/error_callback_result.py,sha256=B3O9D8ceV1ZsS19UvguISlbvJSjtQ1aZfktVuekZXLU,1317
|
|
31
34
|
bosdyn/client/estop.py,sha256=-dy3SP6lcOryyTB_VXe0C_cFk-qK1TNJdSm9DKSz-MM,32073
|
|
32
35
|
bosdyn/client/exceptions.py,sha256=VQg5cSrzB9_pmFcUCbBaRF2QtBUKfdzpR94N3q2rNx0,5323
|
|
33
36
|
bosdyn/client/fault.py,sha256=ymo4M1Vy-bUasD8uOm1pxE1HnjheCds6qA9hZiJbAzY,6050
|
|
34
37
|
bosdyn/client/frame_helpers.py,sha256=Rrm0Zx10LoaVsJv-FPCX02LVQwNkyKVO28lZz7Bmlvg,12572
|
|
35
|
-
bosdyn/client/graph_nav.py,sha256=
|
|
36
|
-
bosdyn/client/gripper_camera_param.py,sha256=
|
|
37
|
-
bosdyn/client/image.py,sha256=
|
|
38
|
-
bosdyn/client/image_service_helpers.py,sha256=
|
|
38
|
+
bosdyn/client/graph_nav.py,sha256=8sULbBAFaFxJPF3ZdI_kqLYpzA0XbhGO-zECRyVH1J4,70681
|
|
39
|
+
bosdyn/client/gripper_camera_param.py,sha256=kxhBffjbq5R-t1OxWEAFguo_tKW5xGIuasdflSmfAwY,4683
|
|
40
|
+
bosdyn/client/image.py,sha256=fn41QOvaAOH7UT7m2ENXayI4fLXg5NQBZrmpLFZVBBE,21980
|
|
41
|
+
bosdyn/client/image_service_helpers.py,sha256=l2hZKqcG7PI05-_bhh8BLkpN4METmG53JCR0YF3q-8Y,40421
|
|
39
42
|
bosdyn/client/inverse_kinematics.py,sha256=KBgvGdnt-JZJvDzbdJ72Kqw8RHoOsqKq_p9rQtvwuKo,1708
|
|
40
43
|
bosdyn/client/ir_enable_disable.py,sha256=6c5MAuO1Fj0RlVcjkP1vhs-qTLiOpM3RnD8F7_ik1Gw,2153
|
|
41
|
-
bosdyn/client/keepalive.py,sha256=
|
|
44
|
+
bosdyn/client/keepalive.py,sha256=Sz1sobzkyDfamKfaam7-dP3jIVlVOBs4l6JE5qqTjEA,14892
|
|
42
45
|
bosdyn/client/lease.py,sha256=-B698QATgRuddH_pc5YN2LhMkZDacZP1kkf1MeYjqec,45412
|
|
43
46
|
bosdyn/client/lease_resource_hierarchy.py,sha256=b_YpVCeiJwVQzAy1Xh5h-1HYjpbzZvmDZAcREGCOgBc,3070
|
|
44
47
|
bosdyn/client/lease_validator.py,sha256=Vo5-2mtfCh50i7MDXLf4NlOBOgqd28ynPp2FF7NNGx0,14505
|
|
45
48
|
bosdyn/client/license.py,sha256=mJRBtwo3UHUVXqAKq-3eBf35v9U_Za_P9lPRXF9q9Lk,1736
|
|
46
49
|
bosdyn/client/local_grid.py,sha256=YszM_pTmeGuGIwExgRwB76PXJciO6rZqfaL2RHLxAf0,3475
|
|
47
|
-
bosdyn/client/log_status.py,sha256=
|
|
50
|
+
bosdyn/client/log_status.py,sha256=wcKZEFw8GHyWeYKysZ75i3PrLb1r2xVUEAyO3SDmxOI,12656
|
|
48
51
|
bosdyn/client/manipulation_api_client.py,sha256=bdTTqZk73m7l9bty9CNC9Bs-hTTRFEA_wDweMb4mLu4,4204
|
|
49
52
|
bosdyn/client/map_processing.py,sha256=xmwTkAfIIvRbaRnOCj-JTkrfS13n4z_DAqg-sc8hL2Y,10239
|
|
50
|
-
bosdyn/client/math_helpers.py,sha256=
|
|
53
|
+
bosdyn/client/math_helpers.py,sha256=HLJ2pmul--Ualfa2cWHIgdNAZScK8MC6kjwqNKSCX44,48793
|
|
51
54
|
bosdyn/client/metrics_logging.py,sha256=9gjVK5Xu4JpOqMg4_tKMHd-XHOh--xaiU_OP9zcGOMs,6646
|
|
52
55
|
bosdyn/client/network_compute_bridge_client.py,sha256=L7RmgCRKiPBn3SVwIxCqP0hkEkhRhF5k5xz2BpC-Omk,7966
|
|
53
56
|
bosdyn/client/payload.py,sha256=12vZirEI4-gu9KPHsDg6MH0QCmnxbolWR1j81lvgfVw,2271
|
|
54
|
-
bosdyn/client/payload_registration.py,sha256=
|
|
55
|
-
bosdyn/client/
|
|
57
|
+
bosdyn/client/payload_registration.py,sha256=rDGMK3ZtI6nmvCFsjm1MjueYglDNuHHu-7Q5V901VM8,24306
|
|
58
|
+
bosdyn/client/payload_software_update.py,sha256=nYrFOxuikVd-cChkx8aZ9gpVQSxjadgPcxyT6eklwT4,8716
|
|
59
|
+
bosdyn/client/payload_software_update_initiation.py,sha256=LDAe_gDUCLDKOC54MbhC-hsywqNMmT_dtnYjmMaef1g,3216
|
|
60
|
+
bosdyn/client/point_cloud.py,sha256=F_AJBYql8b6Ok_-IEmxpV4ajdXZ_GOahPe_QwWLf7xk,8627
|
|
56
61
|
bosdyn/client/power.py,sha256=teVPBPcwsUHvn996upF06Y5MJsfQrE-93ezMXAAYSmA,26955
|
|
57
62
|
bosdyn/client/processors.py,sha256=Z-Djf_I_lhfokB-f_L0PewAY8J95LThdWVju1zJ2BaE,1275
|
|
58
63
|
bosdyn/client/ray_cast.py,sha256=Ca1yJo0aY6OmVAazb19fy44L-9LzcKVxr_fHt_EoQtg,4465
|
|
59
64
|
bosdyn/client/recording.py,sha256=sQ34G_ckrE-M42ER2GUbYI7UibvdrjHycaia58IpJ2s,25913
|
|
60
|
-
bosdyn/client/robot.py,sha256=
|
|
65
|
+
bosdyn/client/robot.py,sha256=XQCp9NjcwS4Bhhohjup_AcLlYm67DV0tlPxuqZTwU1M,31114
|
|
61
66
|
bosdyn/client/robot_command.py,sha256=LtoVKlJwwhTmADRMvJIWJ4B5rY_MpdhHnL72zKm1ECU,108248
|
|
62
67
|
bosdyn/client/robot_id.py,sha256=0VZHG9hltwTLAm1_Bt26Xq1O6EROswqNwHvjY7kaplk,2482
|
|
63
68
|
bosdyn/client/robot_state.py,sha256=h551ke5eHdAC7NgVuLphY8FZR899Ii8_lYwuoX1w1nk,7073
|
|
64
|
-
bosdyn/client/sdk.py,sha256=
|
|
69
|
+
bosdyn/client/sdk.py,sha256=UFG5sRbnzEiB7hlUBIPm9KVceBrEOLGDuLQJtoIdyzM,12864
|
|
65
70
|
bosdyn/client/server_util.py,sha256=uLT12vs5nAhdJ0ryaKuE82dxXnBOupebyDuzI8tbLRo,10560
|
|
66
|
-
bosdyn/client/service_customization_helpers.py,sha256=
|
|
71
|
+
bosdyn/client/service_customization_helpers.py,sha256=GD23vhBfwCi1S4eBYIBoTbvHe9kwap1cbq0CHXlciGw,49155
|
|
67
72
|
bosdyn/client/signals_helpers.py,sha256=Sp91IrMxVU-PeH6TK2njzFCKmFMyshRJqNa4DYRMqDU,3682
|
|
68
73
|
bosdyn/client/spot_check.py,sha256=PKqN3kwL6oISkqwXEm_R4vz0uixIsfowWY9mC0mM8Cc,14619
|
|
69
74
|
bosdyn/client/time_sync.py,sha256=mDkcR5RlAKfAOwEUoBjwxtJFDKuGFGmiDcrOeCO2P_g,23089
|
|
70
75
|
bosdyn/client/token_cache.py,sha256=Vwf9YfsR7pTyu1fLRzXrvDo9hG5GBJcen8Azlo_5_iA,3507
|
|
71
|
-
bosdyn/client/token_manager.py,sha256=
|
|
76
|
+
bosdyn/client/token_manager.py,sha256=FkF2-xWXrKG1ttTH2omhjx7FtbIGnYkB1vAaKEhg3xM,5112
|
|
72
77
|
bosdyn/client/units_helpers.py,sha256=5SAmL8vsnl06oGNjzb57fUkuUbGvtbeNdg4NgW0wYAY,1084
|
|
73
|
-
bosdyn/client/util.py,sha256=
|
|
78
|
+
bosdyn/client/util.py,sha256=Cr_IB1taOh6Hmu1EdTHa_NU08eXnTEG7kzGX_2xDfoE,19968
|
|
74
79
|
bosdyn/client/world_object.py,sha256=CNfZJxwdTjd-Oh35liNdkZ27sAzdnBVFTkpVIICfRTo,17066
|
|
75
|
-
bosdyn/client/gps/NMEAParser.py,sha256=
|
|
80
|
+
bosdyn/client/gps/NMEAParser.py,sha256=4ZZDt7NbQiDQpeu2Cs7OsgWErUgMk5XtSIWaoEuLfHE,8709
|
|
76
81
|
bosdyn/client/gps/__init__.py,sha256=1qUAbnMKYlERYZvxtGz4ThjYef7Tx-ZBclLoVE_ecjU,265
|
|
77
82
|
bosdyn/client/gps/aggregator_client.py,sha256=hMlmUcFope-QO51h0OAcDKWd_VUmkTkmeI6kLhj7OrU,2361
|
|
78
|
-
bosdyn/client/gps/gps_listener.py,sha256=
|
|
83
|
+
bosdyn/client/gps/gps_listener.py,sha256=Xx-H61o-uV4qO5XWOBnOJckYDi7c9azl9_EyWHjYJbU,7796
|
|
84
|
+
bosdyn/client/gps/ntrip_client.py,sha256=AvFThi3F3LyuES9vm_niHmktSLiGr_-gbIjg7pRku4Q,8311
|
|
79
85
|
bosdyn/client/gps/registration_client.py,sha256=LqDLl_Ezv3HNUr9R1B4n2hcMArmGwLgg1asCkGhe2WA,1901
|
|
80
86
|
bosdyn/client/resources/__init__.py,sha256=1qUAbnMKYlERYZvxtGz4ThjYef7Tx-ZBclLoVE_ecjU,265
|
|
81
87
|
bosdyn/client/resources/robot.pem,sha256=kWAr4xK29RtTVC_EhbwW2_NblIuecYqVudR2YIdTh84,1874
|
|
82
|
-
bosdyn/client/spot_cam/__init__.py,sha256=
|
|
88
|
+
bosdyn/client/spot_cam/__init__.py,sha256=N0FRE-glagSWkK9HQZuGyHvRGCfDzxUyVoPFu0mkrPU,829
|
|
83
89
|
bosdyn/client/spot_cam/audio.py,sha256=8DvUOhfHVYTOXqlQEny5qUjHvvDsijvJ_njqyNJWUrs,9845
|
|
84
90
|
bosdyn/client/spot_cam/compositor.py,sha256=pU3OcyrSX8RukXgTygOC-Eub-slBCxm05u97-b3oKaw,10570
|
|
85
91
|
bosdyn/client/spot_cam/health.py,sha256=HsmLOKVb7iM6bfbZye0UapPezL2naWo4yl_7HQDNGA4,4707
|
|
@@ -88,10 +94,10 @@ bosdyn/client/spot_cam/lights_helper.py,sha256=VWhXwcZ1a5X6OQ6Fd1CzGGPdW4BNQ5j63
|
|
|
88
94
|
bosdyn/client/spot_cam/media_log.py,sha256=CJJepePouHr1QoXuev8oJSMhA-JUYpcm6IBUq4k-Bl4,10379
|
|
89
95
|
bosdyn/client/spot_cam/network.py,sha256=W7z91ERPzba3BCK23jio8byDjVr6kYnucQ9zKg9BqUA,3023
|
|
90
96
|
bosdyn/client/spot_cam/power.py,sha256=HS3nJF8hXq9m1JziOIwLHGLtlNMyLgewWBgs-mRZmTM,5181
|
|
91
|
-
bosdyn/client/spot_cam/ptz.py,sha256=
|
|
97
|
+
bosdyn/client/spot_cam/ptz.py,sha256=O1m7zDZ92zRmvy9qhjojiphMQwAweTO0HVizQFdWFFE,10630
|
|
92
98
|
bosdyn/client/spot_cam/streamquality.py,sha256=e-RjizZPwZSOS4Jlqb5Ds-mC6uKam252dpEHkb58Oc8,6364
|
|
93
99
|
bosdyn/client/spot_cam/version.py,sha256=R82eyCAY9PfZqbN8D6hNzSeZatpgpsFr995dRt1Mbe0,2856
|
|
94
|
-
bosdyn_client-
|
|
95
|
-
bosdyn_client-
|
|
96
|
-
bosdyn_client-
|
|
97
|
-
bosdyn_client-
|
|
100
|
+
bosdyn_client-5.0.1.dist-info/METADATA,sha256=RYhDRNp8XDqkZmc5omW_vvTfEGEEpRYEAy3o961WbZg,3987
|
|
101
|
+
bosdyn_client-5.0.1.dist-info/WHEEL,sha256=AtBG6SXL3KF_v0NxLf0ehyVOh0cold-JbJYXNGorC6Q,92
|
|
102
|
+
bosdyn_client-5.0.1.dist-info/top_level.txt,sha256=an2OWgx1ej2jFjmBjPWNQ68ZglvUfKhmXWW-WhTtDmA,7
|
|
103
|
+
bosdyn_client-5.0.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|