viam-sdk 0.25.2__py3-none-linux_armv7l.whl → 0.62.0__py3-none-linux_armv7l.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.
- viam/app/_logs.py +3 -6
- viam/app/app_client.py +606 -262
- viam/app/billing_client.py +60 -18
- viam/app/data_client.py +1086 -315
- viam/app/ml_training_client.py +51 -48
- viam/app/provisioning_client.py +3 -5
- viam/app/viam_client.py +105 -11
- viam/components/arm/__init__.py +1 -25
- viam/components/arm/arm.py +21 -22
- viam/components/arm/client.py +27 -30
- viam/components/arm/service.py +3 -3
- viam/components/audio_in/__init__.py +24 -0
- viam/components/audio_in/audio_in.py +74 -0
- viam/components/audio_in/client.py +76 -0
- viam/components/audio_in/service.py +83 -0
- viam/components/audio_input/__init__.py +1 -1
- viam/components/audio_input/audio_input.py +4 -3
- viam/components/audio_input/client.py +19 -8
- viam/components/audio_input/service.py +10 -0
- viam/components/audio_out/__init__.py +21 -0
- viam/components/audio_out/audio_out.py +72 -0
- viam/components/audio_out/client.py +67 -0
- viam/components/audio_out/service.py +63 -0
- viam/components/base/__init__.py +2 -10
- viam/components/base/base.py +20 -20
- viam/components/base/client.py +27 -30
- viam/components/board/__init__.py +2 -25
- viam/components/board/board.py +39 -77
- viam/components/board/client.py +39 -73
- viam/components/button/__init__.py +10 -0
- viam/components/button/button.py +41 -0
- viam/components/button/client.py +52 -0
- viam/components/button/service.py +46 -0
- viam/components/camera/__init__.py +1 -1
- viam/components/camera/camera.py +31 -22
- viam/components/camera/client.py +30 -20
- viam/components/camera/service.py +14 -12
- viam/components/component_base.py +10 -7
- viam/components/encoder/__init__.py +1 -1
- viam/components/encoder/client.py +15 -16
- viam/components/encoder/encoder.py +9 -9
- viam/components/gantry/__init__.py +1 -13
- viam/components/gantry/client.py +41 -28
- viam/components/gantry/gantry.py +48 -17
- viam/components/gantry/service.py +21 -5
- viam/components/generic/__init__.py +1 -1
- viam/components/generic/client.py +11 -7
- viam/components/generic/generic.py +3 -3
- viam/components/gripper/__init__.py +3 -12
- viam/components/gripper/client.py +43 -20
- viam/components/gripper/gripper.py +87 -12
- viam/components/gripper/service.py +32 -3
- viam/components/input/__init__.py +1 -14
- viam/components/input/client.py +22 -23
- viam/components/input/input.py +18 -12
- viam/components/motor/__init__.py +1 -21
- viam/components/motor/client.py +36 -42
- viam/components/motor/motor.py +24 -24
- viam/components/movement_sensor/__init__.py +1 -1
- viam/components/movement_sensor/client.py +33 -40
- viam/components/movement_sensor/movement_sensor.py +12 -12
- viam/components/pose_tracker/__init__.py +1 -1
- viam/components/pose_tracker/client.py +9 -8
- viam/components/pose_tracker/pose_tracker.py +2 -2
- viam/components/power_sensor/__init__.py +1 -1
- viam/components/power_sensor/client.py +15 -18
- viam/components/power_sensor/power_sensor.py +12 -12
- viam/components/sensor/__init__.py +1 -1
- viam/components/sensor/client.py +9 -8
- viam/components/sensor/sensor.py +5 -5
- viam/components/servo/__init__.py +1 -13
- viam/components/servo/client.py +18 -18
- viam/components/servo/servo.py +12 -12
- viam/components/switch/__init__.py +10 -0
- viam/components/switch/client.py +83 -0
- viam/components/switch/service.py +72 -0
- viam/components/switch/switch.py +95 -0
- viam/gen/app/agent/v1/agent_pb2.py +40 -29
- viam/gen/app/agent/v1/agent_pb2.pyi +73 -11
- viam/gen/app/cloudslam/v1/cloud_slam_pb2.py +45 -42
- viam/gen/app/data/v1/data_grpc.py +98 -2
- viam/gen/app/data/v1/data_pb2.py +238 -119
- viam/gen/app/data/v1/data_pb2.pyi +804 -34
- viam/gen/app/datapipelines/v1/data_pipelines_grpc.py +84 -0
- viam/gen/app/datapipelines/v1/data_pipelines_pb2.py +57 -0
- viam/gen/app/datapipelines/v1/data_pipelines_pb2.pyi +387 -0
- viam/gen/app/dataset/v1/dataset_grpc.py +10 -2
- viam/gen/app/dataset/v1/dataset_pb2.py +38 -31
- viam/gen/app/dataset/v1/dataset_pb2.pyi +36 -1
- viam/gen/app/datasync/v1/data_sync_grpc.py +1 -1
- viam/gen/app/datasync/v1/data_sync_pb2.py +61 -51
- viam/gen/app/datasync/v1/data_sync_pb2.pyi +52 -12
- viam/gen/app/mlinference/__init__.py +0 -0
- viam/gen/app/mlinference/v1/__init__.py +0 -0
- viam/gen/app/mlinference/v1/ml_inference_grpc.py +28 -0
- viam/gen/app/mlinference/v1/ml_inference_pb2.py +23 -0
- viam/gen/app/mlinference/v1/ml_inference_pb2.pyi +63 -0
- viam/gen/app/mltraining/v1/ml_training_grpc.py +18 -2
- viam/gen/app/mltraining/v1/ml_training_pb2.py +134 -101
- viam/gen/app/mltraining/v1/ml_training_pb2.pyi +193 -7
- viam/gen/app/packages/v1/packages_pb2.py +43 -40
- viam/gen/app/v1/app_grpc.py +290 -2
- viam/gen/app/v1/app_pb2.py +670 -453
- viam/gen/app/v1/app_pb2.pyi +3133 -947
- viam/gen/app/v1/billing_grpc.py +34 -2
- viam/gen/app/v1/billing_pb2.py +94 -35
- viam/gen/app/v1/billing_pb2.pyi +314 -61
- viam/gen/app/v1/end_user_pb2.py +50 -29
- viam/gen/app/v1/robot_pb2.py +120 -111
- viam/gen/app/v1/robot_pb2.pyi +137 -15
- viam/gen/common/v1/common_pb2.py +86 -66
- viam/gen/common/v1/common_pb2.pyi +184 -8
- viam/gen/component/arm/v1/arm_grpc.py +18 -2
- viam/gen/component/arm/v1/arm_pb2.py +68 -55
- viam/gen/component/arm/v1/arm_pb2.pyi +73 -3
- viam/gen/component/audioin/__init__.py +0 -0
- viam/gen/component/audioin/v1/__init__.py +0 -0
- viam/gen/component/audioin/v1/audioin_grpc.py +54 -0
- viam/gen/component/audioin/v1/audioin_pb2.py +34 -0
- viam/gen/component/audioin/v1/audioin_pb2.pyi +94 -0
- viam/gen/component/audioinput/v1/audioinput_pb2.py +35 -32
- viam/gen/component/audioout/__init__.py +0 -0
- viam/gen/component/audioout/v1/__init__.py +0 -0
- viam/gen/component/audioout/v1/audioout_grpc.py +54 -0
- viam/gen/component/audioout/v1/audioout_pb2.py +32 -0
- viam/gen/component/audioout/v1/audioout_pb2.pyi +47 -0
- viam/gen/component/base/v1/base_pb2.py +57 -54
- viam/gen/component/board/v1/board_pb2.py +93 -90
- viam/gen/component/button/__init__.py +0 -0
- viam/gen/component/button/v1/__init__.py +0 -0
- viam/gen/component/button/v1/button_grpc.py +38 -0
- viam/gen/component/button/v1/button_pb2.py +28 -0
- viam/gen/component/button/v1/button_pb2.pyi +39 -0
- viam/gen/component/camera/v1/camera_pb2.py +58 -55
- viam/gen/component/camera/v1/camera_pb2.pyi +31 -7
- viam/gen/component/encoder/v1/encoder_pb2.py +35 -32
- viam/gen/component/gantry/v1/gantry_grpc.py +9 -1
- viam/gen/component/gantry/v1/gantry_pb2.py +56 -51
- viam/gen/component/generic/v1/generic_pb2.py +15 -12
- viam/gen/component/gripper/v1/gripper_grpc.py +18 -2
- viam/gen/component/gripper/v1/gripper_pb2.py +48 -37
- viam/gen/component/gripper/v1/gripper_pb2.pyi +43 -1
- viam/gen/component/inputcontroller/v1/input_controller_pb2.py +45 -42
- viam/gen/component/motor/v1/motor_pb2.py +77 -74
- viam/gen/component/movementsensor/v1/movementsensor_pb2.py +69 -66
- viam/gen/component/posetracker/v1/pose_tracker_pb2.py +25 -22
- viam/gen/component/powersensor/v1/powersensor_pb2.py +33 -30
- viam/gen/component/sensor/v1/sensor_pb2.py +17 -14
- viam/gen/component/servo/v1/servo_pb2.py +41 -38
- viam/gen/component/switch/__init__.py +0 -0
- viam/gen/component/switch/v1/__init__.py +0 -0
- viam/gen/component/switch/v1/switch_grpc.py +54 -0
- viam/gen/component/switch/v1/switch_pb2.py +40 -0
- viam/gen/component/switch/v1/switch_pb2.pyi +116 -0
- viam/gen/component/testecho/v1/testecho_pb2.py +29 -26
- viam/gen/module/v1/module_pb2.py +36 -33
- viam/gen/module/v1/module_pb2.pyi +7 -2
- viam/gen/proto/rpc/examples/echo/v1/echo_pb2.py +26 -23
- viam/gen/proto/rpc/examples/echoresource/v1/echoresource_pb2.py +23 -20
- viam/gen/proto/rpc/v1/auth_pb2.py +27 -24
- viam/gen/proto/rpc/webrtc/v1/grpc_pb2.py +35 -32
- viam/gen/proto/rpc/webrtc/v1/signaling_pb2.py +62 -57
- viam/gen/proto/rpc/webrtc/v1/signaling_pb2.pyi +18 -4
- viam/gen/provisioning/v1/provisioning_grpc.py +10 -2
- viam/gen/provisioning/v1/provisioning_pb2.py +38 -31
- viam/gen/provisioning/v1/provisioning_pb2.pyi +20 -2
- viam/gen/robot/v1/robot_grpc.py +61 -29
- viam/gen/robot/v1/robot_pb2.py +186 -155
- viam/gen/robot/v1/robot_pb2.pyi +278 -59
- viam/gen/service/datamanager/v1/data_manager_grpc.py +11 -2
- viam/gen/service/datamanager/v1/data_manager_pb2.py +27 -17
- viam/gen/service/datamanager/v1/data_manager_pb2.pyi +47 -1
- viam/gen/service/discovery/__init__.py +0 -0
- viam/gen/service/discovery/v1/__init__.py +0 -0
- viam/gen/service/discovery/v1/discovery_grpc.py +39 -0
- viam/gen/service/discovery/v1/discovery_pb2.py +29 -0
- viam/gen/service/discovery/v1/discovery_pb2.pyi +51 -0
- viam/gen/service/generic/v1/generic_pb2.py +13 -10
- viam/gen/service/mlmodel/v1/mlmodel_pb2.py +75 -72
- viam/gen/service/motion/v1/motion_pb2.py +118 -85
- viam/gen/service/motion/v1/motion_pb2.pyi +130 -68
- viam/gen/service/navigation/v1/navigation_pb2.py +75 -72
- viam/gen/service/sensors/v1/sensors_pb2.py +59 -56
- viam/gen/service/shell/v1/shell_pb2.py +35 -32
- viam/gen/service/slam/v1/slam_pb2.py +43 -40
- viam/gen/service/slam/v1/slam_pb2.pyi +1 -1
- viam/gen/service/video/__init__.py +0 -0
- viam/gen/service/video/v1/__init__.py +0 -0
- viam/gen/service/video/v1/video_grpc.py +39 -0
- viam/gen/service/video/v1/video_pb2.py +29 -0
- viam/gen/service/video/v1/video_pb2.pyi +72 -0
- viam/gen/service/vision/v1/vision_pb2.py +60 -57
- viam/gen/service/vision/v1/vision_pb2.pyi +28 -3
- viam/gen/service/worldstatestore/__init__.py +0 -0
- viam/gen/service/worldstatestore/v1/__init__.py +0 -0
- viam/gen/service/worldstatestore/v1/world_state_store_grpc.py +55 -0
- viam/gen/service/worldstatestore/v1/world_state_store_pb2.py +39 -0
- viam/gen/service/worldstatestore/v1/world_state_store_pb2.pyi +171 -0
- viam/gen/stream/v1/stream_grpc.py +17 -1
- viam/gen/stream/v1/stream_pb2.py +34 -21
- viam/gen/stream/v1/stream_pb2.pyi +79 -1
- viam/gen/tagger/v1/tagger_pb2.py +9 -8
- viam/logging.py +77 -18
- viam/media/audio.py +28 -0
- viam/media/utils/pil/__init__.py +7 -3
- viam/media/video.py +80 -17
- viam/module/module.py +111 -38
- viam/module/resource_data_consumer.py +41 -0
- viam/module/service.py +9 -1
- viam/module/types.py +2 -4
- viam/proto/app/__init__.py +199 -0
- viam/proto/app/agent/__init__.py +5 -2
- viam/proto/app/billing.py +31 -4
- viam/proto/app/cloudslam/__init__.py +1 -0
- viam/proto/app/data/__init__.py +63 -0
- viam/proto/app/datapipelines/__init__.py +56 -0
- viam/proto/app/dataset/__init__.py +5 -0
- viam/proto/app/datasync/__init__.py +3 -0
- viam/proto/app/end_user.py +1 -0
- viam/proto/app/mlinference/__init__.py +15 -0
- viam/proto/app/mltraining/__init__.py +13 -0
- viam/proto/app/packages/__init__.py +1 -0
- viam/proto/app/robot.py +7 -0
- viam/proto/common/__init__.py +15 -0
- viam/proto/component/arm/__init__.py +7 -0
- viam/proto/component/audioin/__init__.py +16 -0
- viam/proto/component/audioinput/__init__.py +1 -0
- viam/proto/component/audioout/__init__.py +15 -0
- viam/proto/component/base/__init__.py +1 -0
- viam/proto/component/board/__init__.py +1 -0
- viam/proto/component/button/__init__.py +15 -0
- viam/proto/component/camera/__init__.py +1 -0
- viam/proto/component/encoder/__init__.py +1 -0
- viam/proto/component/gantry/__init__.py +1 -0
- viam/proto/component/generic/__init__.py +1 -0
- viam/proto/component/gripper/__init__.py +5 -0
- viam/proto/component/inputcontroller/__init__.py +1 -0
- viam/proto/component/motor/__init__.py +1 -0
- viam/proto/component/movementsensor/__init__.py +1 -0
- viam/proto/component/posetracker/__init__.py +1 -0
- viam/proto/component/powersensor/__init__.py +1 -0
- viam/proto/component/sensor/__init__.py +1 -0
- viam/proto/component/servo/__init__.py +1 -0
- viam/proto/component/switch/__init__.py +26 -0
- viam/proto/component/testecho/__init__.py +1 -0
- viam/proto/module/__init__.py +1 -0
- viam/proto/provisioning/__init__.py +5 -0
- viam/proto/robot/__init__.py +29 -8
- viam/proto/rpc/auth.py +1 -0
- viam/proto/rpc/examples/echo/__init__.py +1 -0
- viam/proto/rpc/examples/echoresource/__init__.py +1 -0
- viam/proto/rpc/webrtc/grpc.py +1 -0
- viam/proto/rpc/webrtc/signaling.py +3 -0
- viam/proto/service/datamanager/__init__.py +9 -1
- viam/proto/service/discovery/__init__.py +15 -0
- viam/proto/service/generic/__init__.py +1 -0
- viam/proto/service/mlmodel/__init__.py +1 -0
- viam/proto/service/motion/__init__.py +3 -0
- viam/proto/service/navigation/__init__.py +1 -0
- viam/proto/service/sensors/__init__.py +1 -0
- viam/proto/service/shell/__init__.py +1 -0
- viam/proto/service/slam/__init__.py +1 -0
- viam/proto/service/video/__init__.py +15 -0
- viam/proto/service/vision/__init__.py +1 -0
- viam/proto/service/worldstatestore/__init__.py +32 -0
- viam/proto/stream/__init__.py +11 -0
- viam/py.typed +0 -0
- viam/resource/base.py +12 -8
- viam/resource/easy_resource.py +24 -13
- viam/resource/manager.py +6 -5
- viam/resource/registry.py +39 -51
- viam/resource/rpc_client_base.py +33 -1
- viam/resource/types.py +13 -14
- viam/robot/client.py +190 -122
- viam/robot/service.py +2 -50
- viam/rpc/dial.py +54 -4
- viam/rpc/libviam_rust_utils.so +0 -0
- viam/rpc/server.py +25 -11
- viam/rpc/types.py +2 -4
- viam/services/discovery/__init__.py +12 -0
- viam/services/discovery/client.py +55 -0
- viam/services/discovery/discovery.py +52 -0
- viam/services/discovery/service.py +43 -0
- viam/services/generic/__init__.py +1 -1
- viam/services/generic/client.py +8 -5
- viam/services/generic/generic.py +2 -2
- viam/services/mlmodel/__init__.py +1 -1
- viam/services/mlmodel/client.py +17 -7
- viam/services/mlmodel/mlmodel.py +23 -12
- viam/services/mlmodel/service.py +5 -2
- viam/services/mlmodel/utils.py +11 -1
- viam/services/motion/__init__.py +2 -2
- viam/services/motion/client.py +32 -32
- viam/services/motion/motion.py +66 -62
- viam/services/navigation/__init__.py +1 -1
- viam/services/navigation/client.py +30 -20
- viam/services/navigation/navigation.py +23 -23
- viam/services/service_base.py +13 -9
- viam/services/service_client_base.py +3 -3
- viam/services/slam/__init__.py +1 -1
- viam/services/slam/client.py +15 -10
- viam/services/slam/slam.py +11 -11
- viam/services/vision/__init__.py +1 -1
- viam/services/vision/client.py +31 -24
- viam/services/vision/service.py +8 -8
- viam/services/vision/vision.py +36 -53
- viam/services/worldstatestore/__init__.py +18 -0
- viam/services/worldstatestore/client.py +94 -0
- viam/services/worldstatestore/service.py +55 -0
- viam/services/worldstatestore/worldstatestore.py +90 -0
- viam/sessions_client.py +115 -46
- viam/streams.py +3 -6
- viam/utils.py +44 -14
- viam/version_metadata.py +4 -0
- {viam_sdk-0.25.2.dist-info → viam_sdk-0.62.0.dist-info}/METADATA +27 -28
- viam_sdk-0.62.0.dist-info/RECORD +514 -0
- {viam_sdk-0.25.2.dist-info → viam_sdk-0.62.0.dist-info}/WHEEL +1 -1
- viam/gen/proto/rpc/examples/fileupload/v1/fileupload_grpc.py +0 -27
- viam/gen/proto/rpc/examples/fileupload/v1/fileupload_pb2.py +0 -18
- viam/gen/proto/rpc/examples/fileupload/v1/fileupload_pb2.pyi +0 -45
- viam/proto/rpc/examples/fileupload/__init__.py +0 -18
- viam/services/sensors/__init__.py +0 -5
- viam/services/sensors/client.py +0 -65
- viam_sdk-0.25.2.dist-info/LICENSE +0 -202
- viam_sdk-0.25.2.dist-info/RECORD +0 -442
- /viam/gen/{proto/rpc/examples/fileupload → app/datapipelines}/__init__.py +0 -0
- /viam/gen/{proto/rpc/examples/fileupload → app/datapipelines}/v1/__init__.py +0 -0
- /LICENSE → /viam_sdk-0.62.0.dist-info/licenses/LICENSE +0 -0
viam/app/data_client.py
CHANGED
|
@@ -2,10 +2,12 @@ import warnings
|
|
|
2
2
|
from dataclasses import dataclass
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Any, Dict, List, Mapping, Optional, Sequence, Tuple
|
|
5
|
+
from typing import Any, Dict, List, Mapping, Optional, Sequence, Tuple, Union, cast
|
|
6
6
|
|
|
7
|
+
import bson
|
|
7
8
|
from google.protobuf.struct_pb2 import Struct
|
|
8
9
|
from grpclib.client import Channel, Stream
|
|
10
|
+
from typing_extensions import Self
|
|
9
11
|
|
|
10
12
|
from viam import logging
|
|
11
13
|
from viam.proto.app.data import (
|
|
@@ -22,19 +24,32 @@ from viam.proto.app.data import (
|
|
|
22
24
|
BinaryID,
|
|
23
25
|
BoundingBoxLabelsByFilterRequest,
|
|
24
26
|
BoundingBoxLabelsByFilterResponse,
|
|
27
|
+
CaptureInterval,
|
|
25
28
|
CaptureMetadata,
|
|
26
29
|
ConfigureDatabaseUserRequest,
|
|
30
|
+
CreateBinaryDataSignedURLRequest,
|
|
31
|
+
CreateBinaryDataSignedURLResponse,
|
|
32
|
+
CreateIndexRequest,
|
|
27
33
|
DataRequest,
|
|
28
34
|
DataServiceStub,
|
|
29
35
|
DeleteBinaryDataByFilterRequest,
|
|
30
36
|
DeleteBinaryDataByFilterResponse,
|
|
31
37
|
DeleteBinaryDataByIDsRequest,
|
|
32
38
|
DeleteBinaryDataByIDsResponse,
|
|
39
|
+
DeleteIndexRequest,
|
|
33
40
|
DeleteTabularDataRequest,
|
|
34
41
|
DeleteTabularDataResponse,
|
|
42
|
+
ExportTabularDataRequest,
|
|
43
|
+
ExportTabularDataResponse,
|
|
35
44
|
Filter,
|
|
36
45
|
GetDatabaseConnectionRequest,
|
|
37
46
|
GetDatabaseConnectionResponse,
|
|
47
|
+
GetLatestTabularDataRequest,
|
|
48
|
+
GetLatestTabularDataResponse,
|
|
49
|
+
Index,
|
|
50
|
+
IndexableCollection,
|
|
51
|
+
ListIndexesRequest,
|
|
52
|
+
ListIndexesResponse,
|
|
38
53
|
Order,
|
|
39
54
|
RemoveBinaryDataFromDatasetByIDsRequest,
|
|
40
55
|
RemoveBoundingBoxFromImageByIDRequest,
|
|
@@ -48,9 +63,31 @@ from viam.proto.app.data import (
|
|
|
48
63
|
TabularDataByMQLResponse,
|
|
49
64
|
TabularDataBySQLRequest,
|
|
50
65
|
TabularDataBySQLResponse,
|
|
66
|
+
TabularDataSource,
|
|
67
|
+
TabularDataSourceType,
|
|
51
68
|
TagsByFilterRequest,
|
|
52
69
|
TagsByFilterResponse,
|
|
53
70
|
)
|
|
71
|
+
from viam.proto.app.datapipelines import (
|
|
72
|
+
CreateDataPipelineRequest,
|
|
73
|
+
CreateDataPipelineResponse,
|
|
74
|
+
DataPipelineRunStatus,
|
|
75
|
+
DataPipelinesServiceStub,
|
|
76
|
+
DeleteDataPipelineRequest,
|
|
77
|
+
GetDataPipelineRequest,
|
|
78
|
+
GetDataPipelineResponse,
|
|
79
|
+
ListDataPipelineRunsRequest,
|
|
80
|
+
ListDataPipelineRunsResponse,
|
|
81
|
+
ListDataPipelinesRequest,
|
|
82
|
+
ListDataPipelinesResponse,
|
|
83
|
+
RenameDataPipelineRequest,
|
|
84
|
+
)
|
|
85
|
+
from viam.proto.app.datapipelines import (
|
|
86
|
+
DataPipeline as ProtoDataPipeline,
|
|
87
|
+
)
|
|
88
|
+
from viam.proto.app.datapipelines import (
|
|
89
|
+
DataPipelineRun as ProtoDataPipelineRun,
|
|
90
|
+
)
|
|
54
91
|
from viam.proto.app.dataset import (
|
|
55
92
|
CreateDatasetRequest,
|
|
56
93
|
CreateDatasetResponse,
|
|
@@ -61,6 +98,8 @@ from viam.proto.app.dataset import (
|
|
|
61
98
|
ListDatasetsByIDsResponse,
|
|
62
99
|
ListDatasetsByOrganizationIDRequest,
|
|
63
100
|
ListDatasetsByOrganizationIDResponse,
|
|
101
|
+
MergeDatasetsRequest,
|
|
102
|
+
MergeDatasetsResponse,
|
|
64
103
|
RenameDatasetRequest,
|
|
65
104
|
)
|
|
66
105
|
from viam.proto.app.datasync import (
|
|
@@ -78,7 +117,7 @@ from viam.proto.app.datasync import (
|
|
|
78
117
|
StreamingDataCaptureUploadResponse,
|
|
79
118
|
UploadMetadata,
|
|
80
119
|
)
|
|
81
|
-
from viam.utils import ValueTypes, create_filter, datetime_to_timestamp, struct_to_dict
|
|
120
|
+
from viam.utils import ValueTypes, _alias_param, create_filter, datetime_to_timestamp, dict_to_struct, struct_to_dict
|
|
82
121
|
|
|
83
122
|
LOGGER = logging.getLogger(__name__)
|
|
84
123
|
|
|
@@ -86,10 +125,10 @@ LOGGER = logging.getLogger(__name__)
|
|
|
86
125
|
class DataClient:
|
|
87
126
|
"""gRPC client for uploading and retrieving data from app.
|
|
88
127
|
|
|
89
|
-
|
|
90
|
-
|
|
128
|
+
This class's constructor instantiates relevant service stubs. Always make :class:`DataClient` method calls through an instance of
|
|
129
|
+
:class:`ViamClient`.
|
|
91
130
|
|
|
92
|
-
Establish a
|
|
131
|
+
Establish a connection::
|
|
93
132
|
|
|
94
133
|
import asyncio
|
|
95
134
|
|
|
@@ -105,17 +144,15 @@ class DataClient:
|
|
|
105
144
|
|
|
106
145
|
async def main():
|
|
107
146
|
# Make a ViamClient
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
viam_client.close()
|
|
147
|
+
async with await connect() as viam_client:
|
|
148
|
+
# Instantiate a DataClient to run data client API methods on
|
|
149
|
+
data_client = viam_client.data_client
|
|
113
150
|
|
|
114
151
|
if __name__ == '__main__':
|
|
115
152
|
asyncio.run(main())
|
|
116
153
|
|
|
117
154
|
|
|
118
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
155
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/>`_.
|
|
119
156
|
"""
|
|
120
157
|
|
|
121
158
|
@dataclass
|
|
@@ -142,8 +179,203 @@ class DataClient:
|
|
|
142
179
|
return str(self) == str(other)
|
|
143
180
|
return False
|
|
144
181
|
|
|
182
|
+
@dataclass
|
|
183
|
+
class TabularDataPoint:
|
|
184
|
+
"""Represents a tabular data point and its associated metadata."""
|
|
185
|
+
|
|
186
|
+
part_id: str
|
|
187
|
+
"""The robot part ID"""
|
|
188
|
+
|
|
189
|
+
resource_name: str
|
|
190
|
+
"""The resource name"""
|
|
191
|
+
|
|
192
|
+
resource_api: str
|
|
193
|
+
"""The resource API. For example, rdk:component:sensor"""
|
|
194
|
+
|
|
195
|
+
method_name: str
|
|
196
|
+
"""The method used for data capture. For example, Readings"""
|
|
197
|
+
|
|
198
|
+
time_captured: datetime
|
|
199
|
+
"""The time at which the data point was captured"""
|
|
200
|
+
|
|
201
|
+
organization_id: str
|
|
202
|
+
"""The organization ID"""
|
|
203
|
+
|
|
204
|
+
location_id: str
|
|
205
|
+
"""The location ID"""
|
|
206
|
+
|
|
207
|
+
robot_name: str
|
|
208
|
+
"""The robot name"""
|
|
209
|
+
|
|
210
|
+
robot_id: str
|
|
211
|
+
"""The robot ID"""
|
|
212
|
+
|
|
213
|
+
part_name: str
|
|
214
|
+
"""The robot part name"""
|
|
215
|
+
|
|
216
|
+
method_parameters: Mapping[str, ValueTypes]
|
|
217
|
+
"""Additional parameters associated with the data capture method"""
|
|
218
|
+
|
|
219
|
+
tags: List[str]
|
|
220
|
+
"""A list of tags associated with the data point"""
|
|
221
|
+
|
|
222
|
+
payload: Mapping[str, ValueTypes]
|
|
223
|
+
"""The captured data"""
|
|
224
|
+
|
|
225
|
+
def __str__(self) -> str:
|
|
226
|
+
return (
|
|
227
|
+
f"TabularDataPoint("
|
|
228
|
+
f"robot='{self.robot_name}' (id={self.robot_id}), "
|
|
229
|
+
f"part='{self.part_name}' (id={self.part_id}), "
|
|
230
|
+
f"resource='{self.resource_name}' ({self.resource_api}), "
|
|
231
|
+
f"method='{self.method_name}', "
|
|
232
|
+
f"org={self.organization_id}, "
|
|
233
|
+
f"location={self.location_id}, "
|
|
234
|
+
f"time='{self.time_captured.isoformat()}', "
|
|
235
|
+
f"params={self.method_parameters}, "
|
|
236
|
+
f"tags={self.tags}, "
|
|
237
|
+
f"payload={self.payload})"
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
def __eq__(self, other: object) -> bool:
|
|
241
|
+
if isinstance(other, DataClient.TabularDataPoint):
|
|
242
|
+
return str(self) == str(other)
|
|
243
|
+
return False
|
|
244
|
+
|
|
245
|
+
@property
|
|
246
|
+
def resource_subtype(self) -> str:
|
|
247
|
+
warnings.warn(
|
|
248
|
+
"`TabularDataPoint.resource_subtype` is deprecated. Use `TabularDataPoint.resource_api` instead.",
|
|
249
|
+
DeprecationWarning,
|
|
250
|
+
stacklevel=2,
|
|
251
|
+
)
|
|
252
|
+
return self.resource_api
|
|
253
|
+
|
|
254
|
+
@dataclass
|
|
255
|
+
class DataPipeline:
|
|
256
|
+
"""Represents a data pipeline and its associated metadata."""
|
|
257
|
+
|
|
258
|
+
id: str
|
|
259
|
+
"""The ID of the data pipeline"""
|
|
260
|
+
|
|
261
|
+
organization_id: str
|
|
262
|
+
"""The organization ID"""
|
|
263
|
+
|
|
264
|
+
name: str
|
|
265
|
+
"""The name of the data pipeline"""
|
|
266
|
+
|
|
267
|
+
mql_binary: List[Dict[str, Any]]
|
|
268
|
+
"""The MQL binary of the data pipeline"""
|
|
269
|
+
|
|
270
|
+
schedule: str
|
|
271
|
+
"""The schedule of the data pipeline"""
|
|
272
|
+
|
|
273
|
+
created_on: datetime
|
|
274
|
+
"""The time the data pipeline was created"""
|
|
275
|
+
|
|
276
|
+
updated_at: datetime
|
|
277
|
+
"""The time the data pipeline was last updated"""
|
|
278
|
+
|
|
279
|
+
enabled: bool
|
|
280
|
+
"""Whether the data pipeline is enabled"""
|
|
281
|
+
|
|
282
|
+
data_source_type: TabularDataSourceType.ValueType
|
|
283
|
+
"""The type of data source for the data pipeline"""
|
|
284
|
+
|
|
285
|
+
@classmethod
|
|
286
|
+
def from_proto(cls, data_pipeline: ProtoDataPipeline) -> Self:
|
|
287
|
+
return cls(
|
|
288
|
+
id=data_pipeline.id,
|
|
289
|
+
organization_id=data_pipeline.organization_id,
|
|
290
|
+
name=data_pipeline.name,
|
|
291
|
+
mql_binary=[bson.decode(bson_bytes) for bson_bytes in data_pipeline.mql_binary],
|
|
292
|
+
schedule=data_pipeline.schedule,
|
|
293
|
+
created_on=data_pipeline.created_on.ToDatetime(),
|
|
294
|
+
updated_at=data_pipeline.updated_at.ToDatetime(),
|
|
295
|
+
enabled=data_pipeline.enabled,
|
|
296
|
+
data_source_type=data_pipeline.data_source_type,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
@dataclass
|
|
300
|
+
class DataPipelineRun:
|
|
301
|
+
"""Represents a data pipeline run and its associated metadata."""
|
|
302
|
+
|
|
303
|
+
id: str
|
|
304
|
+
"""The ID of the data pipeline run"""
|
|
305
|
+
|
|
306
|
+
status: DataPipelineRunStatus.ValueType
|
|
307
|
+
"""The status of the data pipeline run"""
|
|
308
|
+
|
|
309
|
+
start_time: datetime
|
|
310
|
+
"""The time the data pipeline run started"""
|
|
311
|
+
|
|
312
|
+
end_time: datetime
|
|
313
|
+
"""The time the data pipeline run ended"""
|
|
314
|
+
|
|
315
|
+
data_start_time: datetime
|
|
316
|
+
"""The start time of the data that was processed in the run."""
|
|
317
|
+
data_end_time: datetime
|
|
318
|
+
"""The end time of the data that was processed in the run."""
|
|
319
|
+
|
|
320
|
+
error_message: str
|
|
321
|
+
"""The error message of the data pipeline run. Only set if the run failed."""
|
|
322
|
+
|
|
323
|
+
@classmethod
|
|
324
|
+
def from_proto(cls, data_pipeline_run: ProtoDataPipelineRun) -> Self:
|
|
325
|
+
return cls(
|
|
326
|
+
id=data_pipeline_run.id,
|
|
327
|
+
status=data_pipeline_run.status,
|
|
328
|
+
start_time=data_pipeline_run.start_time.ToDatetime(),
|
|
329
|
+
end_time=data_pipeline_run.end_time.ToDatetime(),
|
|
330
|
+
data_start_time=data_pipeline_run.data_start_time.ToDatetime(),
|
|
331
|
+
data_end_time=data_pipeline_run.data_end_time.ToDatetime(),
|
|
332
|
+
error_message=data_pipeline_run.error_message,
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
@dataclass
|
|
336
|
+
class DataPipelineRunsPage:
|
|
337
|
+
"""Represents a page of data pipeline runs and provides pagination functionality."""
|
|
338
|
+
|
|
339
|
+
_client: "DataClient"
|
|
340
|
+
"""The data client used to make API calls"""
|
|
341
|
+
|
|
342
|
+
pipeline_id: str
|
|
343
|
+
"""The ID of the pipeline these runs belong to"""
|
|
344
|
+
|
|
345
|
+
page_size: int
|
|
346
|
+
"""The number of runs per page"""
|
|
347
|
+
|
|
348
|
+
runs: List["DataClient.DataPipelineRun"]
|
|
349
|
+
"""The list of runs in this page"""
|
|
350
|
+
|
|
351
|
+
next_page_token: str
|
|
352
|
+
"""The token to use to get the next page of results"""
|
|
353
|
+
|
|
354
|
+
async def next_page(self) -> "DataClient.DataPipelineRunsPage":
|
|
355
|
+
"""Get the next page of data pipeline runs.
|
|
356
|
+
|
|
357
|
+
Returns:
|
|
358
|
+
DataPipelineRunsPage: The next page of runs, or an empty page if there are no more runs
|
|
359
|
+
"""
|
|
360
|
+
if not self.next_page_token:
|
|
361
|
+
# no token, return empty next page
|
|
362
|
+
return DataClient.DataPipelineRunsPage(
|
|
363
|
+
_client=self._client, pipeline_id=self.pipeline_id, page_size=self.page_size, runs=[], next_page_token=""
|
|
364
|
+
)
|
|
365
|
+
return await self._client._list_data_pipeline_runs(self.pipeline_id, self.page_size, self.next_page_token)
|
|
366
|
+
|
|
367
|
+
@classmethod
|
|
368
|
+
def from_proto(cls, data_pipeline_runs_page: ListDataPipelineRunsResponse, client: "DataClient", page_size: int) -> Self:
|
|
369
|
+
return cls(
|
|
370
|
+
_client=client,
|
|
371
|
+
pipeline_id=data_pipeline_runs_page.pipeline_id,
|
|
372
|
+
page_size=page_size,
|
|
373
|
+
runs=[DataClient.DataPipelineRun.from_proto(run) for run in data_pipeline_runs_page.runs],
|
|
374
|
+
next_page_token=data_pipeline_runs_page.next_page_token,
|
|
375
|
+
)
|
|
376
|
+
|
|
145
377
|
def __init__(self, channel: Channel, metadata: Mapping[str, str]):
|
|
146
|
-
"""Create a
|
|
378
|
+
"""Create a :class:`DataClient` that maintains a connection to app.
|
|
147
379
|
|
|
148
380
|
Args:
|
|
149
381
|
channel (grpclib.client.Channel): Connection to app.
|
|
@@ -153,11 +385,13 @@ class DataClient:
|
|
|
153
385
|
self._data_client = DataServiceStub(channel)
|
|
154
386
|
self._data_sync_client = DataSyncServiceStub(channel)
|
|
155
387
|
self._dataset_client = DatasetServiceStub(channel)
|
|
388
|
+
self._data_pipelines_client = DataPipelinesServiceStub(channel)
|
|
156
389
|
self._channel = channel
|
|
157
390
|
|
|
158
391
|
_data_client: DataServiceStub
|
|
159
392
|
_data_sync_client: DataSyncServiceStub
|
|
160
393
|
_dataset_client: DatasetServiceStub
|
|
394
|
+
_data_pipelines_client: DataPipelinesServiceStub
|
|
161
395
|
_metadata: Mapping[str, str]
|
|
162
396
|
_channel: Channel
|
|
163
397
|
|
|
@@ -171,44 +405,44 @@ class DataClient:
|
|
|
171
405
|
include_internal_data: bool = False,
|
|
172
406
|
dest: Optional[str] = None,
|
|
173
407
|
) -> Tuple[List[TabularData], int, str]:
|
|
174
|
-
"""Filter and download tabular data. The data will be paginated into pages of
|
|
175
|
-
|
|
176
|
-
If the file is not empty, it will be overwritten.
|
|
408
|
+
"""Filter and download tabular data. The data will be paginated into pages of ``limit`` items; the returned tuple will include
|
|
409
|
+
the pagination ID. If a destination is provided, this method saves returned data to that file, overwriting any existing file content.
|
|
177
410
|
|
|
178
411
|
::
|
|
179
412
|
|
|
180
413
|
from viam.utils import create_filter
|
|
181
414
|
|
|
182
415
|
my_data = []
|
|
416
|
+
my_filter = create_filter(component_name="motor-1")
|
|
183
417
|
last = None
|
|
184
|
-
my_filter = create_filter(component_name="left_motor")
|
|
185
418
|
while True:
|
|
186
|
-
tabular_data, count, last = await data_client.tabular_data_by_filter(my_filter, last)
|
|
419
|
+
tabular_data, count, last = await data_client.tabular_data_by_filter(my_filter, last=last)
|
|
187
420
|
if not tabular_data:
|
|
188
421
|
break
|
|
189
422
|
my_data.extend(tabular_data)
|
|
190
423
|
|
|
424
|
+
print(f"My data: {my_data}")
|
|
191
425
|
|
|
192
426
|
Args:
|
|
193
|
-
filter (viam.proto.app.data.Filter): Optional
|
|
194
|
-
data.
|
|
427
|
+
filter (~viam.proto.app.data.Filter): Optional, specifies tabular data to retrieve. If missing, matches all tabular data.
|
|
195
428
|
limit (int): The maximum number of entries to include in a page. Defaults to 50 if unspecified.
|
|
196
|
-
sort_order (viam.proto.app.data.Order): The desired sort order of the data.
|
|
429
|
+
sort_order (~viam.proto.app.data.Order): The desired sort order of the data.
|
|
197
430
|
last (str): Optional string indicating the object identifier of the last-returned data.
|
|
198
|
-
|
|
199
|
-
|
|
431
|
+
Returned by calls to :class:`TabularDataByFilter` as the ``last`` value.
|
|
432
|
+
If provided, the server returns the next data entries after the last object identifier.
|
|
200
433
|
count_only (bool): Whether to return only the total count of entries.
|
|
201
434
|
include_internal_data (bool): Whether to return the internal data. Internal data is used for Viam-specific data ingestion,
|
|
202
|
-
|
|
435
|
+
like cloud SLAM. Defaults to ``False``.
|
|
203
436
|
dest (str): Optional filepath for writing retrieved data.
|
|
204
437
|
|
|
205
438
|
Returns:
|
|
206
439
|
Tuple[List[TabularData], int, str]: A tuple containing the following:
|
|
207
|
-
List[TabularData]: The tabular data,
|
|
208
|
-
int: The count (number of entries),
|
|
209
|
-
str: The last-returned page ID.
|
|
210
440
|
|
|
211
|
-
|
|
441
|
+
- ``tabular_data`` (*List[TabularData]*): The tabular data.
|
|
442
|
+
- ``count`` (*int*): The count (number of entries).
|
|
443
|
+
- ``last`` (*str*): The last-returned page ID.
|
|
444
|
+
|
|
445
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#tabulardatabyfilter>`_.
|
|
212
446
|
"""
|
|
213
447
|
filter = filter if filter else Filter()
|
|
214
448
|
|
|
@@ -240,62 +474,218 @@ class DataClient:
|
|
|
240
474
|
LOGGER.error(f"Failed to write tabular data to file {dest}", exc_info=e)
|
|
241
475
|
return data, response.count, response.last
|
|
242
476
|
|
|
243
|
-
async def tabular_data_by_sql(self, organization_id: str, sql_query: str) -> List[Dict[str, ValueTypes]]:
|
|
477
|
+
async def tabular_data_by_sql(self, organization_id: str, sql_query: str) -> List[Dict[str, Union[ValueTypes, datetime]]]:
|
|
244
478
|
"""Obtain unified tabular data and metadata, queried with SQL.
|
|
479
|
+
Make sure your API key has permissions at the organization level in order to use this.
|
|
245
480
|
|
|
246
481
|
::
|
|
247
482
|
|
|
248
|
-
data = await data_client.tabular_data_by_sql(
|
|
249
|
-
|
|
483
|
+
data = await data_client.tabular_data_by_sql(
|
|
484
|
+
organization_id="<YOUR-ORG-ID>",
|
|
485
|
+
sql_query="SELECT * FROM readings LIMIT 5"
|
|
486
|
+
)
|
|
250
487
|
|
|
251
488
|
Args:
|
|
252
489
|
organization_id (str): The ID of the organization that owns the data.
|
|
253
|
-
|
|
490
|
+
To find your organization ID, visit the organization settings page.
|
|
254
491
|
sql_query (str): The SQL query to run.
|
|
255
492
|
|
|
256
493
|
Returns:
|
|
257
|
-
List[Dict[str, ValueTypes]]: An array of data objects.
|
|
494
|
+
List[Dict[str, Union[ValueTypes, datetime]]]: An array of decoded BSON data objects.
|
|
258
495
|
|
|
259
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
496
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#tabulardatabysql>`_.
|
|
260
497
|
"""
|
|
261
498
|
request = TabularDataBySQLRequest(organization_id=organization_id, sql_query=sql_query)
|
|
262
499
|
response: TabularDataBySQLResponse = await self._data_client.TabularDataBySQL(request, metadata=self._metadata)
|
|
263
|
-
return [
|
|
500
|
+
return [bson.decode(bson_bytes) for bson_bytes in response.raw_data]
|
|
264
501
|
|
|
265
|
-
|
|
502
|
+
@_alias_param("query", param_alias="mql_binary")
|
|
503
|
+
async def tabular_data_by_mql(
|
|
504
|
+
self,
|
|
505
|
+
organization_id: str,
|
|
506
|
+
query: Union[List[bytes], List[Dict[str, Any]]],
|
|
507
|
+
use_recent_data: Optional[bool] = None,
|
|
508
|
+
tabular_data_source_type: TabularDataSourceType.ValueType = TabularDataSourceType.TABULAR_DATA_SOURCE_TYPE_STANDARD,
|
|
509
|
+
pipeline_id: Optional[str] = None,
|
|
510
|
+
query_prefix_name: Optional[str] = None,
|
|
511
|
+
) -> List[Dict[str, Union[ValueTypes, datetime]]]:
|
|
266
512
|
"""Obtain unified tabular data and metadata, queried with MQL.
|
|
267
513
|
|
|
268
514
|
::
|
|
269
515
|
|
|
270
|
-
# using bson
|
|
271
516
|
import bson
|
|
272
|
-
tabular_data = await data_client.tabular_data_by_mql(org_id="<your-org-id>", mql_binary=[
|
|
273
|
-
bson.dumps({ '$match': { 'location_id': '<location-id>' } }),
|
|
274
|
-
bson.dumps({ "$limit": 5 })
|
|
275
|
-
])
|
|
276
517
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
bson.encode({ '$match': { 'location_id': '<location-id>' } }),
|
|
281
|
-
bson.encode({ "$limit": 5 })
|
|
518
|
+
tabular_data = await data_client.tabular_data_by_mql(organization_id="<YOUR-ORG-ID>", query=[
|
|
519
|
+
{ '$match': { 'location_id': '<YOUR-LOCATION-ID>' } },
|
|
520
|
+
{ "$limit": 5 }
|
|
282
521
|
])
|
|
283
522
|
|
|
523
|
+
print(f"Tabular Data: {tabular_data}")
|
|
284
524
|
|
|
285
525
|
Args:
|
|
286
526
|
organization_id (str): The ID of the organization that owns the data.
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
527
|
+
To find your organization ID, visit the organization settings page.
|
|
528
|
+
query (Union[List[bytes], List[Dict[str, Any]]]): The MQL query to run, as a list of MongoDB aggregation pipeline stages.
|
|
529
|
+
Each stage can be provided as either a dictionary or raw BSON bytes, but support for bytes will be removed in the
|
|
530
|
+
future, so prefer the dictionary option.
|
|
531
|
+
use_recent_data (bool): Whether to query blob storage or your recent data store. Defaults to ``False``..
|
|
532
|
+
Deprecated, use `tabular_data_source_type` instead.
|
|
533
|
+
tabular_data_source_type (viam.proto.app.data.TabularDataSourceType): The data source to query.
|
|
534
|
+
Defaults to `TABULAR_DATA_SOURCE_TYPE_STANDARD`.
|
|
535
|
+
pipeline_id (str): The ID of the data pipeline to query. Defaults to `None`.
|
|
536
|
+
Required if `tabular_data_source_type` is `TABULAR_DATA_SOURCE_TYPE_PIPELINE_SINK`.
|
|
537
|
+
query_prefix_name (str): Optional field that can be used to specify a saved query to run.
|
|
290
538
|
|
|
291
539
|
Returns:
|
|
292
|
-
List[Dict[str, ValueTypes]]: An array of data objects.
|
|
540
|
+
List[Dict[str, Union[ValueTypes, datetime]]]: An array of decoded BSON data objects.
|
|
293
541
|
|
|
294
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
542
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#tabulardatabymql>`_.
|
|
295
543
|
"""
|
|
296
|
-
|
|
544
|
+
binary: List[bytes] = [bson.encode(query) for query in query] if isinstance(query[0], dict) else query # type: ignore
|
|
545
|
+
data_source = TabularDataSource(type=tabular_data_source_type, pipeline_id=pipeline_id)
|
|
546
|
+
if use_recent_data:
|
|
547
|
+
data_source.type = TabularDataSourceType.TABULAR_DATA_SOURCE_TYPE_HOT_STORAGE
|
|
548
|
+
request = TabularDataByMQLRequest(
|
|
549
|
+
organization_id=organization_id,
|
|
550
|
+
mql_binary=binary,
|
|
551
|
+
data_source=data_source,
|
|
552
|
+
query_prefix_name=query_prefix_name,
|
|
553
|
+
)
|
|
297
554
|
response: TabularDataByMQLResponse = await self._data_client.TabularDataByMQL(request, metadata=self._metadata)
|
|
298
|
-
return [
|
|
555
|
+
return [bson.decode(bson_bytes) for bson_bytes in response.raw_data]
|
|
556
|
+
|
|
557
|
+
@_alias_param("resource_api", param_alias="resource_subtype")
|
|
558
|
+
async def get_latest_tabular_data(
|
|
559
|
+
self,
|
|
560
|
+
part_id: str,
|
|
561
|
+
resource_name: str,
|
|
562
|
+
resource_api: str,
|
|
563
|
+
method_name: str,
|
|
564
|
+
additional_params: Optional[Mapping[str, ValueTypes]] = None,
|
|
565
|
+
) -> Optional[Tuple[datetime, datetime, Dict[str, ValueTypes]]]:
|
|
566
|
+
"""Gets the most recent tabular data captured from the specified data source, as long as it was synced within the last year.
|
|
567
|
+
|
|
568
|
+
::
|
|
569
|
+
|
|
570
|
+
tabular_data = await data_client.get_latest_tabular_data(
|
|
571
|
+
part_id="77ae3145-7b91-123a-a234-e567cdca8910",
|
|
572
|
+
resource_name="camera-1",
|
|
573
|
+
resource_api="rdk:component:camera",
|
|
574
|
+
method_name="GetImage",
|
|
575
|
+
additional_params={"docommand_input": {"test": "test"}}
|
|
576
|
+
)
|
|
577
|
+
|
|
578
|
+
if tabular_data:
|
|
579
|
+
time_captured, time_synced, payload = tabular_data
|
|
580
|
+
print(f"Time Captured: {time_captured}")
|
|
581
|
+
print(f"Time Synced: {time_synced}")
|
|
582
|
+
print(f"Payload: {payload}")
|
|
583
|
+
else:
|
|
584
|
+
print(f"No data returned: {tabular_data}")
|
|
585
|
+
|
|
586
|
+
Args:
|
|
587
|
+
part_id (str): The ID of the part that owns the data.
|
|
588
|
+
resource_name (str): The name of the requested resource that captured the data. For example, "my-sensor".
|
|
589
|
+
resource_api (str): The API of the requested resource that captured the data. For example, "rdk:component:sensor".
|
|
590
|
+
method_name (str): The data capture method name. For exampe, "Readings".
|
|
591
|
+
additional_params (dict): Optional additional parameters of the resource that captured the data.
|
|
592
|
+
|
|
593
|
+
Returns:
|
|
594
|
+
Optional[Tuple[datetime, datetime, Dict[str, ValueTypes]]]:
|
|
595
|
+
A return value of ``None`` means that this data source
|
|
596
|
+
has not synced data in the last year. Otherwise, the data source has synced some data in the last year, so the returned
|
|
597
|
+
tuple contains the following:
|
|
598
|
+
|
|
599
|
+
- ``time_captured`` (*datetime*): The time captured.
|
|
600
|
+
- ``time_synced`` (*datetime*): The time synced.
|
|
601
|
+
- ``payload`` (*Dict[str, ValueTypes]*): The latest tabular data captured from the specified data source.
|
|
602
|
+
|
|
603
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#getlatesttabulardata>`_.
|
|
604
|
+
"""
|
|
605
|
+
|
|
606
|
+
request = GetLatestTabularDataRequest(
|
|
607
|
+
part_id=part_id,
|
|
608
|
+
resource_name=resource_name,
|
|
609
|
+
resource_subtype=resource_api,
|
|
610
|
+
method_name=method_name,
|
|
611
|
+
additional_parameters=dict_to_struct(additional_params) if additional_params is not None else None,
|
|
612
|
+
)
|
|
613
|
+
response: GetLatestTabularDataResponse = await self._data_client.GetLatestTabularData(request, metadata=self._metadata)
|
|
614
|
+
if not response.payload:
|
|
615
|
+
return None
|
|
616
|
+
return response.time_captured.ToDatetime(), response.time_synced.ToDatetime(), struct_to_dict(response.payload)
|
|
617
|
+
|
|
618
|
+
@_alias_param("resource_api", param_alias="resource_subtype")
|
|
619
|
+
async def export_tabular_data(
|
|
620
|
+
self,
|
|
621
|
+
part_id: str,
|
|
622
|
+
resource_name: str,
|
|
623
|
+
resource_api: str,
|
|
624
|
+
method_name: str,
|
|
625
|
+
start_time: Optional[datetime] = None,
|
|
626
|
+
end_time: Optional[datetime] = None,
|
|
627
|
+
additional_params: Optional[Mapping[str, ValueTypes]] = None,
|
|
628
|
+
) -> List[TabularDataPoint]:
|
|
629
|
+
"""Obtain unified tabular data and metadata from the specified data source.
|
|
630
|
+
|
|
631
|
+
::
|
|
632
|
+
|
|
633
|
+
tabular_data = await data_client.export_tabular_data(
|
|
634
|
+
part_id="<PART-ID>",
|
|
635
|
+
resource_name="<RESOURCE-NAME>",
|
|
636
|
+
resource_api="<RESOURCE-API>",
|
|
637
|
+
method_name="<METHOD-NAME>",
|
|
638
|
+
start_time="<START_TIME>"
|
|
639
|
+
end_time="<END_TIME>"
|
|
640
|
+
additional_params="<ADDITIONAL_PARAMETERS>"
|
|
641
|
+
)
|
|
642
|
+
|
|
643
|
+
print(f"My data: {tabular_data}")
|
|
644
|
+
|
|
645
|
+
Args:
|
|
646
|
+
part_id (str): The ID of the part that owns the data.
|
|
647
|
+
resource_name (str): The name of the requested resource that captured the data.
|
|
648
|
+
resource_api (str): The API of the requested resource that captured the data.
|
|
649
|
+
method_name (str): The data capture method name.
|
|
650
|
+
start_time (datetime): Optional start time for requesting a specific range of data.
|
|
651
|
+
end_time (datetime): Optional end time for requesting a specific range of data.
|
|
652
|
+
additional_params (dict): Optional additional parameters of the resource that captured the data.
|
|
653
|
+
|
|
654
|
+
Returns:
|
|
655
|
+
List[TabularDataPoint]: The unified tabular data and metadata.
|
|
656
|
+
|
|
657
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#exporttabulardata>`_.
|
|
658
|
+
"""
|
|
659
|
+
|
|
660
|
+
interval = CaptureInterval(start=datetime_to_timestamp(start_time), end=datetime_to_timestamp(end_time))
|
|
661
|
+
request = ExportTabularDataRequest(
|
|
662
|
+
part_id=part_id,
|
|
663
|
+
resource_name=resource_name,
|
|
664
|
+
resource_subtype=resource_api,
|
|
665
|
+
method_name=method_name,
|
|
666
|
+
interval=interval,
|
|
667
|
+
additional_parameters=dict_to_struct(additional_params) if additional_params is not None else None,
|
|
668
|
+
)
|
|
669
|
+
response: List[ExportTabularDataResponse] = await self._data_client.ExportTabularData(request, metadata=self._metadata)
|
|
670
|
+
|
|
671
|
+
return [
|
|
672
|
+
DataClient.TabularDataPoint(
|
|
673
|
+
part_id=resp.part_id,
|
|
674
|
+
resource_name=resp.resource_name,
|
|
675
|
+
resource_api=resp.resource_subtype,
|
|
676
|
+
method_name=resp.method_name,
|
|
677
|
+
time_captured=resp.time_captured.ToDatetime(),
|
|
678
|
+
organization_id=resp.organization_id,
|
|
679
|
+
location_id=resp.location_id,
|
|
680
|
+
robot_name=resp.robot_name,
|
|
681
|
+
robot_id=resp.robot_id,
|
|
682
|
+
part_name=resp.part_name,
|
|
683
|
+
method_parameters=struct_to_dict(resp.method_parameters),
|
|
684
|
+
tags=list(resp.tags),
|
|
685
|
+
payload=struct_to_dict(resp.payload),
|
|
686
|
+
)
|
|
687
|
+
for resp in response
|
|
688
|
+
]
|
|
299
689
|
|
|
300
690
|
async def binary_data_by_filter(
|
|
301
691
|
self,
|
|
@@ -308,46 +698,68 @@ class DataClient:
|
|
|
308
698
|
include_internal_data: bool = False,
|
|
309
699
|
dest: Optional[str] = None,
|
|
310
700
|
) -> Tuple[List[BinaryData], int, str]:
|
|
311
|
-
"""Filter and download binary data. The data will be paginated into pages of
|
|
312
|
-
in the returned tuple
|
|
313
|
-
|
|
701
|
+
"""Filter and download binary data. The data will be paginated into pages of ``limit`` items, and the pagination ID will be included
|
|
702
|
+
in the returned tuple as ``last``. If a destination is provided, this method saves returned data to that file,
|
|
703
|
+
overwriting any existing file content.
|
|
314
704
|
|
|
315
705
|
::
|
|
316
706
|
|
|
317
707
|
from viam.utils import create_filter
|
|
708
|
+
from viam.proto.app.data import Filter, TagsFilter, TagsFilterType
|
|
318
709
|
|
|
319
|
-
|
|
710
|
+
# Get data captured from camera components
|
|
320
711
|
my_data = []
|
|
321
712
|
last = None
|
|
322
|
-
my_filter = create_filter(component_name="camera")
|
|
713
|
+
my_filter = create_filter(component_name="camera-1")
|
|
714
|
+
|
|
323
715
|
while True:
|
|
324
|
-
data, count, last = await data_client.binary_data_by_filter(
|
|
716
|
+
data, count, last = await data_client.binary_data_by_filter(
|
|
717
|
+
my_filter, limit=1, last=last)
|
|
325
718
|
if not data:
|
|
326
719
|
break
|
|
327
720
|
my_data.extend(data)
|
|
328
721
|
|
|
722
|
+
print(f"My data: {my_data}")
|
|
723
|
+
|
|
724
|
+
# Get untagged data from a dataset
|
|
725
|
+
|
|
726
|
+
my_untagged_data = []
|
|
727
|
+
last = None
|
|
728
|
+
tags_filter = TagsFilter(type=TagsFilterType.TAGS_FILTER_TYPE_UNTAGGED)
|
|
729
|
+
my_filter = Filter(
|
|
730
|
+
dataset_id="66db6fe7d93d1ade24cd1dc3",
|
|
731
|
+
tags_filter=tags_filter
|
|
732
|
+
)
|
|
733
|
+
|
|
734
|
+
while True:
|
|
735
|
+
data, count, last = await data_client.binary_data_by_filter(
|
|
736
|
+
my_filter, last=last, include_binary_data=False)
|
|
737
|
+
if not data:
|
|
738
|
+
break
|
|
739
|
+
my_untagged_data.extend(data)
|
|
740
|
+
|
|
329
741
|
Args:
|
|
330
|
-
filter (viam.proto.app.data.Filter): Optional
|
|
331
|
-
data.
|
|
742
|
+
filter (~viam.proto.app.data.Filter): Optional, specifies tabular data to retrieve. An empty filter matches all binary data.
|
|
332
743
|
limit (int): The maximum number of entries to include in a page. Defaults to 50 if unspecified.
|
|
333
|
-
sort_order (viam.proto.app.data.Order): The desired sort order of the data.
|
|
744
|
+
sort_order (~viam.proto.app.data.Order): The desired sort order of the data.
|
|
334
745
|
last (str): Optional string indicating the object identifier of the last-returned data.
|
|
335
|
-
|
|
336
|
-
|
|
746
|
+
This object identifier is returned by calls to :meth:`binary_data_by_filter` as the ``last`` value.
|
|
747
|
+
If provided, the server will return the next data entries after the last object identifier.
|
|
337
748
|
include_binary_data (bool): Boolean specifying whether to actually include the binary file data with each retrieved file.
|
|
338
|
-
|
|
749
|
+
Defaults to true (that is, both the files' data and metadata are returned).
|
|
339
750
|
count_only (bool): Whether to return only the total count of entries.
|
|
340
751
|
include_internal_data (bool): Whether to return the internal data. Internal data is used for Viam-specific data ingestion,
|
|
341
|
-
|
|
752
|
+
like cloud SLAM. Defaults to ``False``.
|
|
342
753
|
dest (str): Optional filepath for writing retrieved data.
|
|
343
754
|
|
|
344
755
|
Returns:
|
|
345
|
-
Tuple[List[viam.proto.app.data.BinaryData], int, str]: A tuple containing the following:
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
756
|
+
Tuple[List[~viam.proto.app.data.BinaryData], int, str]: A tuple containing the following:
|
|
757
|
+
|
|
758
|
+
- ``data`` (*List[* :class:`~viam.proto.app.data.BinaryData` *]*): The binary data.
|
|
759
|
+
- ``count`` (*int*): The count (number of entries).
|
|
760
|
+
- ``last`` (*str*): The last-returned page ID.
|
|
349
761
|
|
|
350
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
762
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#binarydatabyfilter>`_.
|
|
351
763
|
"""
|
|
352
764
|
|
|
353
765
|
data_request = DataRequest(filter=filter)
|
|
@@ -377,45 +789,46 @@ class DataClient:
|
|
|
377
789
|
|
|
378
790
|
async def binary_data_by_ids(
|
|
379
791
|
self,
|
|
380
|
-
binary_ids: List[BinaryID],
|
|
792
|
+
binary_ids: Union[List[BinaryID], List[str]],
|
|
381
793
|
dest: Optional[str] = None,
|
|
382
794
|
) -> List[BinaryData]:
|
|
383
795
|
"""Filter and download binary data.
|
|
384
796
|
|
|
385
797
|
::
|
|
386
798
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
binary_metadata = await data_client.binary_data_by_filter(
|
|
390
|
-
include_file_data=False
|
|
799
|
+
binary_metadata, count, last = await data_client.binary_data_by_filter(
|
|
800
|
+
include_binary_data=False
|
|
391
801
|
)
|
|
392
802
|
|
|
393
803
|
my_ids = []
|
|
394
804
|
|
|
395
805
|
for obj in binary_metadata:
|
|
396
|
-
my_ids.append(
|
|
397
|
-
BinaryID(
|
|
398
|
-
file_id=obj.metadata.id,
|
|
399
|
-
organization_id=obj.metadata.capture_metadata.organization_id,
|
|
400
|
-
location_id=obj.metadata.capture_metadata.location_id
|
|
401
|
-
)
|
|
402
|
-
)
|
|
806
|
+
my_ids.append(obj.metadata.binary_data_id)
|
|
403
807
|
|
|
404
808
|
binary_data = await data_client.binary_data_by_ids(my_ids)
|
|
405
809
|
|
|
406
810
|
Args:
|
|
407
|
-
binary_ids (List[viam.proto.app.data.BinaryID]):
|
|
811
|
+
binary_ids (Union[List[~viam.proto.app.data.BinaryID], List[str]]): Binary data ID strings specifying the desired data or
|
|
812
|
+
:class:`BinaryID` objects. Must be non-empty.
|
|
813
|
+
*DEPRECATED:* :class:`BinaryID` *is deprecated and will be removed in a future release. Instead, pass binary data IDs as a
|
|
814
|
+
list of strings.*
|
|
408
815
|
dest (str): Optional filepath for writing retrieved data.
|
|
409
816
|
|
|
410
817
|
Raises:
|
|
411
|
-
GRPCError: If no
|
|
818
|
+
GRPCError: If no binary data ID strings or :class:`BinaryID` objects are provided.
|
|
412
819
|
|
|
413
820
|
Returns:
|
|
414
|
-
List[viam.proto.app.data.BinaryData]: The binary data.
|
|
821
|
+
List[~viam.proto.app.data.BinaryData]: The binary data.
|
|
415
822
|
|
|
416
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
823
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#binarydatabyids>`_.
|
|
417
824
|
"""
|
|
418
|
-
request = BinaryDataByIDsRequest(
|
|
825
|
+
request = BinaryDataByIDsRequest()
|
|
826
|
+
if len(binary_ids) > 0 and isinstance(binary_ids[0], str):
|
|
827
|
+
binary_data_ids = cast(List[str], binary_ids)
|
|
828
|
+
request = BinaryDataByIDsRequest(binary_data_ids=binary_data_ids, include_binary=True)
|
|
829
|
+
else:
|
|
830
|
+
bin_ids = cast(List[BinaryID], binary_ids)
|
|
831
|
+
request = BinaryDataByIDsRequest(binary_ids=bin_ids, include_binary=True)
|
|
419
832
|
response: BinaryDataByIDsResponse = await self._data_client.BinaryDataByIDs(request, metadata=self._metadata)
|
|
420
833
|
if dest:
|
|
421
834
|
try:
|
|
@@ -431,30 +844,28 @@ class DataClient:
|
|
|
431
844
|
|
|
432
845
|
::
|
|
433
846
|
|
|
434
|
-
from viam.utils import create_filter
|
|
435
|
-
|
|
436
|
-
my_filter = create_filter(component_name="left_motor")
|
|
437
|
-
days_of_data_to_delete = 10
|
|
438
847
|
tabular_data = await data_client.delete_tabular_data(
|
|
439
|
-
|
|
848
|
+
organization_id="<YOUR-ORG-ID>",
|
|
849
|
+
delete_older_than_days=150
|
|
850
|
+
)
|
|
440
851
|
|
|
441
852
|
Args:
|
|
442
|
-
organization_id (str): ID of organization to delete data from.
|
|
443
|
-
|
|
444
|
-
delete_older_than_days (int): Delete data that was captured up to this many days ago. For example
|
|
445
|
-
|
|
853
|
+
organization_id (str): The ID of the organization to delete the data from.
|
|
854
|
+
To find your organization ID, visit the organization settings page.
|
|
855
|
+
delete_older_than_days (int): Delete data that was captured up to *this many* days ago. For example, a value of
|
|
856
|
+
10 deletes any data that was captured up to 10 days ago. A value of 0 deletes *all* existing data.
|
|
446
857
|
|
|
447
858
|
Returns:
|
|
448
859
|
int: The number of items deleted.
|
|
449
860
|
|
|
450
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
861
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#deletetabulardata>`_.
|
|
451
862
|
"""
|
|
452
863
|
request = DeleteTabularDataRequest(organization_id=organization_id, delete_older_than_days=delete_older_than_days)
|
|
453
864
|
response: DeleteTabularDataResponse = await self._data_client.DeleteTabularData(request, metadata=self._metadata)
|
|
454
865
|
return response.deleted_count
|
|
455
866
|
|
|
456
867
|
async def delete_tabular_data_by_filter(self, filter: Optional[Filter]) -> int:
|
|
457
|
-
"""Deprecated: use delete_tabular_data instead."""
|
|
868
|
+
"""Deprecated: use :meth:`delete_tabular_data` instead."""
|
|
458
869
|
raise NotImplementedError()
|
|
459
870
|
|
|
460
871
|
async def delete_binary_data_by_filter(self, filter: Optional[Filter]) -> int:
|
|
@@ -464,98 +875,118 @@ class DataClient:
|
|
|
464
875
|
|
|
465
876
|
from viam.utils import create_filter
|
|
466
877
|
|
|
467
|
-
my_filter = create_filter(component_name="left_motor")
|
|
878
|
+
my_filter = create_filter(component_name="left_motor", organization_ids=["<YOUR-ORG-ID>"])
|
|
879
|
+
|
|
468
880
|
res = await data_client.delete_binary_data_by_filter(my_filter)
|
|
469
881
|
|
|
470
882
|
Args:
|
|
471
|
-
filter (viam.proto.app.data.Filter): Optional
|
|
472
|
-
|
|
883
|
+
filter (~viam.proto.app.data.Filter): Optional, specifies binary data to delete.
|
|
884
|
+
**CAUTION: Passing an empty** ``Filter`` **deletes all binary data!**
|
|
885
|
+
You must specify an organization ID with ``organization_ids`` when using this option.
|
|
886
|
+
To find your organization ID, visit the organization settings page.
|
|
473
887
|
|
|
474
888
|
Returns:
|
|
475
889
|
int: The number of items deleted.
|
|
476
890
|
|
|
477
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
891
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#deletebinarydatabyfilter>`_.
|
|
478
892
|
"""
|
|
479
893
|
filter = filter if filter else Filter()
|
|
480
894
|
request = DeleteBinaryDataByFilterRequest(filter=filter)
|
|
481
895
|
response: DeleteBinaryDataByFilterResponse = await self._data_client.DeleteBinaryDataByFilter(request, metadata=self._metadata)
|
|
482
896
|
return response.deleted_count
|
|
483
897
|
|
|
484
|
-
async def delete_binary_data_by_ids(self, binary_ids: List[BinaryID]) -> int:
|
|
898
|
+
async def delete_binary_data_by_ids(self, binary_ids: Union[List[BinaryID], List[str]]) -> int:
|
|
485
899
|
"""Filter and delete binary data.
|
|
486
900
|
|
|
487
901
|
::
|
|
488
902
|
|
|
489
903
|
from viam.proto.app.data import BinaryID
|
|
904
|
+
from viam.utils import create_filter
|
|
490
905
|
|
|
491
|
-
|
|
492
|
-
|
|
906
|
+
my_filter = create_filter(component_name="camera-1", organization_ids=["<YOUR-ORG-ID>"])
|
|
907
|
+
binary_metadata, count, last = await data_client.binary_data_by_filter(
|
|
908
|
+
filter=my_filter,
|
|
909
|
+
limit=20,
|
|
910
|
+
include_binary_data=False
|
|
493
911
|
)
|
|
494
912
|
|
|
495
913
|
my_ids = []
|
|
496
914
|
|
|
497
915
|
for obj in binary_metadata:
|
|
498
916
|
my_ids.append(
|
|
499
|
-
|
|
500
|
-
file_id=obj.metadata.id,
|
|
501
|
-
organization_id=obj.metadata.capture_metadata.organization_id,
|
|
502
|
-
location_id=obj.metadata.capture_metadata.location_id
|
|
503
|
-
)
|
|
917
|
+
obj.metadata.binary_data_id
|
|
504
918
|
)
|
|
505
919
|
|
|
506
920
|
binary_data = await data_client.delete_binary_data_by_ids(my_ids)
|
|
507
921
|
|
|
508
922
|
Args:
|
|
509
|
-
binary_ids (List[viam.proto.app.data.BinaryID]):
|
|
923
|
+
binary_ids (Union[List[~viam.proto.app.data.BinaryID], List[str]]): Binary data ID strings specifying the data to be deleted or
|
|
924
|
+
:class:`BinaryID` objects. Must be non-empty.
|
|
925
|
+
*DEPRECATED:* :class:`BinaryID` *is deprecated and will be removed in a future release. Instead, pass binary data IDs as a
|
|
926
|
+
list of strings.*
|
|
510
927
|
|
|
511
928
|
Raises:
|
|
512
|
-
GRPCError: If no
|
|
929
|
+
GRPCError: If no binary data ID strings or :class:`BinaryID` objects are provided.
|
|
513
930
|
|
|
514
931
|
Returns:
|
|
515
932
|
int: The number of items deleted.
|
|
516
933
|
|
|
517
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
934
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#deletebinarydatabyids>`_.
|
|
518
935
|
"""
|
|
519
|
-
request = DeleteBinaryDataByIDsRequest(
|
|
936
|
+
request = DeleteBinaryDataByIDsRequest()
|
|
937
|
+
if len(binary_ids) > 0 and isinstance(binary_ids[0], str):
|
|
938
|
+
binary_data_ids = cast(List[str], binary_ids)
|
|
939
|
+
request = DeleteBinaryDataByIDsRequest(binary_data_ids=binary_data_ids)
|
|
940
|
+
else:
|
|
941
|
+
bin_ids = cast(List[BinaryID], binary_ids)
|
|
942
|
+
request = DeleteBinaryDataByIDsRequest(binary_ids=bin_ids)
|
|
520
943
|
response: DeleteBinaryDataByIDsResponse = await self._data_client.DeleteBinaryDataByIDs(request, metadata=self._metadata)
|
|
521
944
|
return response.deleted_count
|
|
522
945
|
|
|
523
|
-
async def add_tags_to_binary_data_by_ids(self, tags: List[str], binary_ids: List[BinaryID]) -> None:
|
|
946
|
+
async def add_tags_to_binary_data_by_ids(self, tags: List[str], binary_ids: Union[List[BinaryID], List[str]]) -> None:
|
|
524
947
|
"""Add tags to binary data.
|
|
525
948
|
|
|
526
949
|
::
|
|
527
950
|
|
|
528
|
-
from viam.
|
|
951
|
+
from viam.utils import create_filter
|
|
529
952
|
|
|
530
953
|
tags = ["tag1", "tag2"]
|
|
531
954
|
|
|
532
|
-
|
|
533
|
-
|
|
955
|
+
my_filter = create_filter(component_name="camera-1", organization_ids=["<YOUR-ORG-ID>"])
|
|
956
|
+
binary_metadata, count, last = await data_client.binary_data_by_filter(
|
|
957
|
+
filter=my_filter,
|
|
958
|
+
limit=20,
|
|
959
|
+
include_binary_data=False
|
|
534
960
|
)
|
|
535
961
|
|
|
536
962
|
my_ids = []
|
|
537
963
|
|
|
538
964
|
for obj in binary_metadata:
|
|
539
965
|
my_ids.append(
|
|
540
|
-
|
|
541
|
-
file_id=obj.metadata.id,
|
|
542
|
-
organization_id=obj.metadata.capture_metadata.organization_id,
|
|
543
|
-
location_id=obj.metadata.capture_metadata.location_id
|
|
544
|
-
)
|
|
966
|
+
obj.metadata.binary_data_id
|
|
545
967
|
)
|
|
546
968
|
|
|
547
969
|
binary_data = await data_client.add_tags_to_binary_data_by_ids(tags, my_ids)
|
|
548
970
|
|
|
549
971
|
Args:
|
|
550
972
|
tags (List[str]): List of tags to add to specified binary data. Must be non-empty.
|
|
551
|
-
binary_ids (List[viam.app.
|
|
973
|
+
binary_ids (Union[List[~viam.proto.app.data.BinaryID], List[str]]): Binary data ID strings specifying the data to be tagged or
|
|
974
|
+
:class:`BinaryID` objects. Must be non-empty.
|
|
975
|
+
*DEPRECATED:* :class:`BinaryID` *is deprecated and will be removed in a future release. Instead, pass binary data IDs as a
|
|
976
|
+
list of strings.*
|
|
552
977
|
|
|
553
978
|
Raises:
|
|
554
|
-
GRPCError: If no
|
|
979
|
+
GRPCError: If no binary data ID strings or :class:`BinaryID` objects are provided.
|
|
555
980
|
|
|
556
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
981
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#addtagstobinarydatabyids>`_.
|
|
557
982
|
"""
|
|
558
|
-
request = AddTagsToBinaryDataByIDsRequest(
|
|
983
|
+
request = AddTagsToBinaryDataByIDsRequest()
|
|
984
|
+
if len(binary_ids) > 0 and isinstance(binary_ids[0], str):
|
|
985
|
+
binary_data_ids = cast(List[str], binary_ids)
|
|
986
|
+
request = AddTagsToBinaryDataByIDsRequest(binary_data_ids=binary_data_ids, tags=tags)
|
|
987
|
+
else:
|
|
988
|
+
bin_ids = cast(List[BinaryID], binary_ids)
|
|
989
|
+
request = AddTagsToBinaryDataByIDsRequest(binary_ids=bin_ids, tags=tags)
|
|
559
990
|
await self._data_client.AddTagsToBinaryDataByIDs(request, metadata=self._metadata)
|
|
560
991
|
|
|
561
992
|
async def add_tags_to_binary_data_by_filter(self, tags: List[str], filter: Optional[Filter] = None) -> None:
|
|
@@ -567,44 +998,43 @@ class DataClient:
|
|
|
567
998
|
|
|
568
999
|
my_filter = create_filter(component_name="my_camera")
|
|
569
1000
|
tags = ["tag1", "tag2"]
|
|
570
|
-
|
|
1001
|
+
await data_client.add_tags_to_binary_data_by_filter(tags, my_filter)
|
|
571
1002
|
|
|
572
1003
|
Args:
|
|
573
1004
|
tags (List[str]): List of tags to add to specified binary data. Must be non-empty.
|
|
574
|
-
filter (viam.proto.app.data.Filter):
|
|
575
|
-
tagged.
|
|
1005
|
+
filter (~viam.proto.app.data.Filter): Specifies binary data to tag. If none is provided, tags all data.
|
|
576
1006
|
|
|
577
1007
|
Raises:
|
|
578
1008
|
GRPCError: If no tags are provided.
|
|
579
1009
|
|
|
580
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1010
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#addtagstobinarydatabyfilter>`_.
|
|
581
1011
|
"""
|
|
582
1012
|
filter = filter if filter else Filter()
|
|
583
1013
|
request = AddTagsToBinaryDataByFilterRequest(filter=filter, tags=tags)
|
|
584
1014
|
await self._data_client.AddTagsToBinaryDataByFilter(request, metadata=self._metadata)
|
|
585
1015
|
|
|
586
|
-
async def remove_tags_from_binary_data_by_ids(self, tags: List[str], binary_ids: List[BinaryID]) -> int:
|
|
1016
|
+
async def remove_tags_from_binary_data_by_ids(self, tags: List[str], binary_ids: Union[List[BinaryID], List[str]]) -> int:
|
|
587
1017
|
"""Remove tags from binary data by IDs.
|
|
588
1018
|
|
|
589
1019
|
::
|
|
590
1020
|
|
|
591
|
-
from viam.
|
|
1021
|
+
from viam.utils import create_filter
|
|
592
1022
|
|
|
593
1023
|
tags = ["tag1", "tag2"]
|
|
594
1024
|
|
|
595
|
-
|
|
596
|
-
|
|
1025
|
+
my_filter = create_filter(component_name="camera-1")
|
|
1026
|
+
|
|
1027
|
+
binary_metadata, count, last = await data_client.binary_data_by_filter(
|
|
1028
|
+
filter=my_filter,
|
|
1029
|
+
limit=50,
|
|
1030
|
+
include_binary_data=False
|
|
597
1031
|
)
|
|
598
1032
|
|
|
599
1033
|
my_ids = []
|
|
600
1034
|
|
|
601
1035
|
for obj in binary_metadata:
|
|
602
1036
|
my_ids.append(
|
|
603
|
-
|
|
604
|
-
file_id=obj.metadata.id,
|
|
605
|
-
organization_id=obj.metadata.capture_metadata.organization_id,
|
|
606
|
-
location_id=obj.metadata.capture_metadata.location_id
|
|
607
|
-
)
|
|
1037
|
+
obj.metadata.binary_data_id
|
|
608
1038
|
)
|
|
609
1039
|
|
|
610
1040
|
binary_data = await data_client.remove_tags_from_binary_data_by_ids(
|
|
@@ -612,17 +1042,26 @@ class DataClient:
|
|
|
612
1042
|
|
|
613
1043
|
Args:
|
|
614
1044
|
tags (List[str]): List of tags to remove from specified binary data. Must be non-empty.
|
|
615
|
-
binary_ids (List[BinaryID]):
|
|
1045
|
+
binary_ids (Union[List[~viam.proto.app.data.BinaryID], List[str]]): Binary data ID strings specifying the data to be untagged
|
|
1046
|
+
or `BinaryID` objects. Must be non-empty.
|
|
1047
|
+
*DEPRECATED:* :class:`BinaryID` *is deprecated and will be removed in a future release. Instead, pass binary data IDs as a
|
|
1048
|
+
list of strings.*
|
|
616
1049
|
|
|
617
1050
|
Raises:
|
|
618
|
-
GRPCError: If no
|
|
1051
|
+
GRPCError: If no binary data ID strings, :class:`BinaryID` objects, or tags are provided.
|
|
619
1052
|
|
|
620
1053
|
Returns:
|
|
621
1054
|
int: The number of tags removed.
|
|
622
1055
|
|
|
623
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1056
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#removetagsfrombinarydatabyids>`_.
|
|
624
1057
|
"""
|
|
625
|
-
request = RemoveTagsFromBinaryDataByIDsRequest(
|
|
1058
|
+
request = RemoveTagsFromBinaryDataByIDsRequest(tags=tags)
|
|
1059
|
+
if len(binary_ids) > 0 and isinstance(binary_ids[0], str):
|
|
1060
|
+
binary_data_ids = cast(List[str], binary_ids)
|
|
1061
|
+
request = RemoveTagsFromBinaryDataByIDsRequest(binary_data_ids=binary_data_ids, tags=tags)
|
|
1062
|
+
else:
|
|
1063
|
+
bin_ids = cast(List[BinaryID], binary_ids)
|
|
1064
|
+
request = RemoveTagsFromBinaryDataByIDsRequest(binary_ids=bin_ids, tags=tags)
|
|
626
1065
|
response: RemoveTagsFromBinaryDataByIDsResponse = await self._data_client.RemoveTagsFromBinaryDataByIDs(
|
|
627
1066
|
request, metadata=self._metadata
|
|
628
1067
|
)
|
|
@@ -641,8 +1080,7 @@ class DataClient:
|
|
|
641
1080
|
|
|
642
1081
|
Args:
|
|
643
1082
|
tags (List[str]): List of tags to remove from specified binary data.
|
|
644
|
-
filter (viam.proto.app.data.Filter):
|
|
645
|
-
untagged.
|
|
1083
|
+
filter (~viam.proto.app.data.Filter): Specifies binary data to untag. If none is provided, removes tags from all data.
|
|
646
1084
|
|
|
647
1085
|
Raises:
|
|
648
1086
|
GRPCError: If no tags are provided.
|
|
@@ -650,7 +1088,7 @@ class DataClient:
|
|
|
650
1088
|
Returns:
|
|
651
1089
|
int: The number of tags removed.
|
|
652
1090
|
|
|
653
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1091
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#removetagsfrombinarydatabyfilter>`_.
|
|
654
1092
|
"""
|
|
655
1093
|
filter = filter if filter else Filter()
|
|
656
1094
|
request = RemoveTagsFromBinaryDataByFilterRequest(filter=filter, tags=tags)
|
|
@@ -670,13 +1108,12 @@ class DataClient:
|
|
|
670
1108
|
tags = await data_client.tags_by_filter(my_filter)
|
|
671
1109
|
|
|
672
1110
|
Args:
|
|
673
|
-
filter (viam.proto.app.data.Filter):
|
|
674
|
-
return.
|
|
1111
|
+
filter (~viam.proto.app.data.Filter): Specifies subset ofdata to retrieve tags from. If none is provided, returns all tags.
|
|
675
1112
|
|
|
676
1113
|
Returns:
|
|
677
1114
|
List[str]: The list of tags.
|
|
678
1115
|
|
|
679
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1116
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#tagsbyfilter>`_.
|
|
680
1117
|
"""
|
|
681
1118
|
filter = filter if filter else Filter()
|
|
682
1119
|
request = TagsByFilterRequest(filter=filter)
|
|
@@ -685,7 +1122,7 @@ class DataClient:
|
|
|
685
1122
|
|
|
686
1123
|
async def add_bounding_box_to_image_by_id(
|
|
687
1124
|
self,
|
|
688
|
-
binary_id: BinaryID,
|
|
1125
|
+
binary_id: Union[BinaryID, str],
|
|
689
1126
|
label: str,
|
|
690
1127
|
x_min_normalized: float,
|
|
691
1128
|
y_min_normalized: float,
|
|
@@ -696,16 +1133,8 @@ class DataClient:
|
|
|
696
1133
|
|
|
697
1134
|
::
|
|
698
1135
|
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
MY_BINARY_ID = BinaryID(
|
|
702
|
-
file_id=your-file_id,
|
|
703
|
-
organization_id=your-org-id,
|
|
704
|
-
location_id=your-location-id
|
|
705
|
-
)
|
|
706
|
-
|
|
707
|
-
bbox_label = await data_client.add_bounding_box_to_image_by_id(
|
|
708
|
-
binary_id=MY_BINARY_ID,
|
|
1136
|
+
bbox_id = await data_client.add_bounding_box_to_image_by_id(
|
|
1137
|
+
binary_id="<YOUR-BINARY-DATA-ID>",
|
|
709
1138
|
label="label",
|
|
710
1139
|
x_min_normalized=0,
|
|
711
1140
|
y_min_normalized=.1,
|
|
@@ -713,10 +1142,12 @@ class DataClient:
|
|
|
713
1142
|
y_max_normalized=.3
|
|
714
1143
|
)
|
|
715
1144
|
|
|
716
|
-
print(
|
|
1145
|
+
print(bbox_id)
|
|
717
1146
|
|
|
718
1147
|
Args:
|
|
719
|
-
binary_id (viam.proto.app.data.BinaryID): The ID of the image to add the bounding
|
|
1148
|
+
binary_id (Union[~viam.proto.app.data.BinaryID, str]): The binary data ID or :class:`BinaryID` of the image to add the bounding
|
|
1149
|
+
box to. *DEPRECATED:* :class:`BinaryID` *is deprecated and will be removed in a future release. Instead, pass binary data IDs as a
|
|
1150
|
+
list of strings.*
|
|
720
1151
|
label (str): A label for the bounding box.
|
|
721
1152
|
x_min_normalized (float): Min X value of the bounding box normalized from 0 to 1.
|
|
722
1153
|
y_min_normalized (float): Min Y value of the bounding box normalized from 0 to 1.
|
|
@@ -729,44 +1160,55 @@ class DataClient:
|
|
|
729
1160
|
Returns:
|
|
730
1161
|
str: The bounding box ID.
|
|
731
1162
|
|
|
732
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1163
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#addboundingboxtoimagebyid>`_.
|
|
733
1164
|
"""
|
|
734
|
-
request = AddBoundingBoxToImageByIDRequest(
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
1165
|
+
request = AddBoundingBoxToImageByIDRequest()
|
|
1166
|
+
if isinstance(binary_id, str):
|
|
1167
|
+
request = AddBoundingBoxToImageByIDRequest(
|
|
1168
|
+
binary_data_id=binary_id,
|
|
1169
|
+
label=label,
|
|
1170
|
+
x_max_normalized=x_max_normalized,
|
|
1171
|
+
x_min_normalized=x_min_normalized,
|
|
1172
|
+
y_max_normalized=y_max_normalized,
|
|
1173
|
+
y_min_normalized=y_min_normalized,
|
|
1174
|
+
)
|
|
1175
|
+
else:
|
|
1176
|
+
request = AddBoundingBoxToImageByIDRequest(
|
|
1177
|
+
binary_id=binary_id,
|
|
1178
|
+
label=label,
|
|
1179
|
+
x_max_normalized=x_max_normalized,
|
|
1180
|
+
x_min_normalized=x_min_normalized,
|
|
1181
|
+
y_max_normalized=y_max_normalized,
|
|
1182
|
+
y_min_normalized=y_min_normalized,
|
|
1183
|
+
)
|
|
742
1184
|
response: AddBoundingBoxToImageByIDResponse = await self._data_client.AddBoundingBoxToImageByID(request, metadata=self._metadata)
|
|
743
1185
|
return response.bbox_id
|
|
744
1186
|
|
|
745
|
-
async def remove_bounding_box_from_image_by_id(self, bbox_id: str, binary_id: BinaryID) -> None:
|
|
1187
|
+
async def remove_bounding_box_from_image_by_id(self, bbox_id: str, binary_id: Union[BinaryID, str]) -> None:
|
|
746
1188
|
"""Removes a bounding box from an image.
|
|
747
1189
|
|
|
748
1190
|
::
|
|
749
1191
|
|
|
750
|
-
from viam.proto.app.data import BinaryID
|
|
751
|
-
|
|
752
|
-
MY_BINARY_ID = BinaryID(
|
|
753
|
-
file_id=your-file_id,
|
|
754
|
-
organization_id=your-org-id,
|
|
755
|
-
location_id=your-location-id
|
|
756
|
-
)
|
|
757
|
-
|
|
758
1192
|
await data_client.remove_bounding_box_from_image_by_id(
|
|
759
|
-
binary_id=
|
|
1193
|
+
binary_id="<YOUR-BINARY-DATA-ID>",
|
|
760
1194
|
bbox_id="your-bounding-box-id-to-delete"
|
|
761
1195
|
)
|
|
762
1196
|
|
|
763
1197
|
Args:
|
|
764
1198
|
bbox_id (str): The ID of the bounding box to remove.
|
|
765
|
-
binary_id (viam.proto.
|
|
1199
|
+
binary_id (Union[~viam.proto.app.data.BinaryID, str]): The binary data ID or :class:`BinaryID` of the image to remove the
|
|
1200
|
+
bounding box from.
|
|
1201
|
+
*DEPRECATED:* :class:`BinaryID` *is deprecated and will be removed in a future release. Instead, pass binary data IDs as a
|
|
1202
|
+
list of strings.*
|
|
766
1203
|
|
|
767
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1204
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#removeboundingboxfromimagebyid>`_.
|
|
768
1205
|
"""
|
|
769
|
-
request = RemoveBoundingBoxFromImageByIDRequest(
|
|
1206
|
+
request = RemoveBoundingBoxFromImageByIDRequest()
|
|
1207
|
+
if isinstance(binary_id, str):
|
|
1208
|
+
request = RemoveBoundingBoxFromImageByIDRequest(binary_data_id=binary_id, bbox_id=bbox_id)
|
|
1209
|
+
else:
|
|
1210
|
+
request = RemoveBoundingBoxFromImageByIDRequest(binary_id=binary_id, bbox_id=bbox_id)
|
|
1211
|
+
|
|
770
1212
|
await self._data_client.RemoveBoundingBoxFromImageByID(request, metadata=self._metadata)
|
|
771
1213
|
|
|
772
1214
|
async def bounding_box_labels_by_filter(self, filter: Optional[Filter] = None) -> List[str]:
|
|
@@ -780,14 +1222,16 @@ class DataClient:
|
|
|
780
1222
|
bounding_box_labels = await data_client.bounding_box_labels_by_filter(
|
|
781
1223
|
my_filter)
|
|
782
1224
|
|
|
1225
|
+
print(bounding_box_labels)
|
|
1226
|
+
|
|
783
1227
|
Args:
|
|
784
|
-
filter (viam.proto.app.data.Filter):
|
|
785
|
-
|
|
1228
|
+
filter (~viam.proto.app.data.Filter): Specifies data to retrieve bounding box labels from. If none is provided, returns labels
|
|
1229
|
+
from all data.
|
|
786
1230
|
|
|
787
1231
|
Returns:
|
|
788
1232
|
List[str]: The list of bounding box labels.
|
|
789
1233
|
|
|
790
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1234
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#boundingboxlabelsbyfilter>`_.
|
|
791
1235
|
"""
|
|
792
1236
|
filter = filter if filter else Filter()
|
|
793
1237
|
request = BoundingBoxLabelsByFilterRequest(filter=filter)
|
|
@@ -799,16 +1243,16 @@ class DataClient:
|
|
|
799
1243
|
|
|
800
1244
|
::
|
|
801
1245
|
|
|
802
|
-
data_client.get_database_connection(
|
|
1246
|
+
hostname = await data_client.get_database_connection(organization_id="<YOUR-ORG-ID>")
|
|
803
1247
|
|
|
804
1248
|
Args:
|
|
805
|
-
organization_id (str):
|
|
806
|
-
|
|
1249
|
+
organization_id (str): The ID of the organization you'd like to connect to.
|
|
1250
|
+
To find your organization ID, visit the organization settings page.
|
|
807
1251
|
|
|
808
1252
|
Returns:
|
|
809
1253
|
str: The hostname of the federated database.
|
|
810
1254
|
|
|
811
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1255
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#getdatabaseconnection>`_.
|
|
812
1256
|
"""
|
|
813
1257
|
request = GetDatabaseConnectionRequest(organization_id=organization_id)
|
|
814
1258
|
response: GetDatabaseConnectionResponse = await self._data_client.GetDatabaseConnection(request, metadata=self._metadata)
|
|
@@ -821,16 +1265,16 @@ class DataClient:
|
|
|
821
1265
|
::
|
|
822
1266
|
|
|
823
1267
|
await data_client.configure_database_user(
|
|
824
|
-
organization_id="<
|
|
825
|
-
password="
|
|
1268
|
+
organization_id="<YOUR-ORG-ID>",
|
|
1269
|
+
password="Your_Password@1234"
|
|
826
1270
|
)
|
|
827
1271
|
|
|
828
1272
|
Args:
|
|
829
|
-
organization_id (str): The ID of the organization.
|
|
830
|
-
|
|
1273
|
+
organization_id (str): The ID of the organization you'd like to configure a database user for.
|
|
1274
|
+
To find your organization ID, visit the organization settings page.
|
|
831
1275
|
password (str): The password of the user.
|
|
832
1276
|
|
|
833
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1277
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#configuredatabaseuser>`_.
|
|
834
1278
|
"""
|
|
835
1279
|
request = ConfigureDatabaseUserRequest(organization_id=organization_id, password=password)
|
|
836
1280
|
await self._data_client.ConfigureDatabaseUser(request, metadata=self._metadata)
|
|
@@ -840,45 +1284,74 @@ class DataClient:
|
|
|
840
1284
|
|
|
841
1285
|
::
|
|
842
1286
|
|
|
843
|
-
|
|
844
|
-
name="<
|
|
845
|
-
organization_id="<
|
|
1287
|
+
dataset_id = await data_client.create_dataset(
|
|
1288
|
+
name="<DATASET-NAME>",
|
|
1289
|
+
organization_id="<YOUR-ORG-ID>"
|
|
846
1290
|
)
|
|
847
|
-
print(
|
|
1291
|
+
print(dataset_id)
|
|
848
1292
|
|
|
849
1293
|
Args:
|
|
850
1294
|
name (str): The name of the dataset being created.
|
|
851
1295
|
organization_id (str): The ID of the organization where the dataset is being created.
|
|
852
|
-
|
|
1296
|
+
To find your organization ID, visit the organization settings page.
|
|
853
1297
|
|
|
854
1298
|
Returns:
|
|
855
1299
|
str: The dataset ID of the created dataset.
|
|
856
1300
|
|
|
857
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1301
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#createdataset>`_.
|
|
858
1302
|
"""
|
|
859
1303
|
request = CreateDatasetRequest(name=name, organization_id=organization_id)
|
|
860
1304
|
response: CreateDatasetResponse = await self._dataset_client.CreateDataset(request, metadata=self._metadata)
|
|
861
1305
|
return response.id
|
|
862
1306
|
|
|
1307
|
+
async def merge_datasets(self, name: str, organization_id: str, dataset_ids: List[str]) -> str:
|
|
1308
|
+
"""Merge multiple datasets into a new dataset.
|
|
1309
|
+
|
|
1310
|
+
::
|
|
1311
|
+
|
|
1312
|
+
dataset_id = await data_client.merge_datasets(
|
|
1313
|
+
name="<DATASET-NAME>",
|
|
1314
|
+
organization_id="<YOUR-ORG-ID>",
|
|
1315
|
+
dataset_ids=["<YOUR-DATASET-ID-1>", "<YOUR-DATASET-ID-2>"]
|
|
1316
|
+
)
|
|
1317
|
+
print(dataset_id)
|
|
1318
|
+
|
|
1319
|
+
Args:
|
|
1320
|
+
name (str): The name of the dataset being created.
|
|
1321
|
+
organization_id (str): The ID of the organization where the dataset is being created.
|
|
1322
|
+
To find your organization ID, visit the organization settings page.
|
|
1323
|
+
dataset_ids (List[str]): The IDs of the datasets that you would like to merge.
|
|
1324
|
+
Returns:
|
|
1325
|
+
str: The dataset ID of the created dataset.
|
|
1326
|
+
|
|
1327
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#mergedatasets>`_.
|
|
1328
|
+
"""
|
|
1329
|
+
request = MergeDatasetsRequest(name=name, organization_id=organization_id, dataset_ids=dataset_ids)
|
|
1330
|
+
response: MergeDatasetsResponse = await self._dataset_client.MergeDatasets(request, metadata=self._metadata)
|
|
1331
|
+
return response.dataset_id
|
|
1332
|
+
|
|
863
1333
|
async def list_dataset_by_ids(self, ids: List[str]) -> Sequence[Dataset]:
|
|
864
1334
|
"""Get a list of datasets using their IDs.
|
|
865
1335
|
|
|
866
1336
|
::
|
|
867
1337
|
|
|
868
1338
|
datasets = await data_client.list_dataset_by_ids(
|
|
869
|
-
ids=["
|
|
1339
|
+
ids=["<YOUR-DATASET-ID-1>, <YOUR-DATASET-ID-2>"]
|
|
870
1340
|
)
|
|
871
1341
|
print(datasets)
|
|
872
1342
|
|
|
873
1343
|
Args:
|
|
874
|
-
ids (List[str]): The IDs of the datasets
|
|
875
|
-
|
|
876
|
-
|
|
1344
|
+
ids (List[str]): The IDs of the datasets that you would like to retrieve information about. To retrieve a dataset ID:
|
|
1345
|
+
|
|
1346
|
+
- Navigate to the **DATASETS** tab of the **DATA** page.
|
|
1347
|
+
- Click on the dataset.
|
|
1348
|
+
- Click the **...** menu.
|
|
1349
|
+
- Select **Copy dataset ID**.
|
|
877
1350
|
|
|
878
1351
|
Returns:
|
|
879
1352
|
Sequence[Dataset]: The list of datasets.
|
|
880
1353
|
|
|
881
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1354
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#listdatasetsbyids>`_.
|
|
882
1355
|
"""
|
|
883
1356
|
request = ListDatasetsByIDsRequest(ids=ids)
|
|
884
1357
|
response: ListDatasetsByIDsResponse = await self._dataset_client.ListDatasetsByIDs(request, metadata=self._metadata)
|
|
@@ -890,19 +1363,19 @@ class DataClient:
|
|
|
890
1363
|
|
|
891
1364
|
::
|
|
892
1365
|
|
|
893
|
-
datasets = await data_client.
|
|
894
|
-
organization_id=
|
|
1366
|
+
datasets = await data_client.list_datasets_by_organization_id(
|
|
1367
|
+
organization_id="<YOUR-ORG-ID>"
|
|
895
1368
|
)
|
|
896
1369
|
print(datasets)
|
|
897
1370
|
|
|
898
1371
|
Args:
|
|
899
|
-
organization_id (str): The ID of the organization.
|
|
900
|
-
|
|
1372
|
+
organization_id (str): The ID of the organization you'd like to retrieve datasets from.
|
|
1373
|
+
To find your organization ID, visit the organization settings page.
|
|
901
1374
|
|
|
902
1375
|
Returns:
|
|
903
1376
|
Sequence[Dataset]: The list of datasets in the organization.
|
|
904
1377
|
|
|
905
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1378
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#listdatasetsbyorganizationid>`_.
|
|
906
1379
|
"""
|
|
907
1380
|
request = ListDatasetsByOrganizationIDRequest(organization_id=organization_id)
|
|
908
1381
|
response: ListDatasetsByOrganizationIDResponse = await self._dataset_client.ListDatasetsByOrganizationID(
|
|
@@ -917,15 +1390,20 @@ class DataClient:
|
|
|
917
1390
|
::
|
|
918
1391
|
|
|
919
1392
|
await data_client.rename_dataset(
|
|
920
|
-
id="
|
|
921
|
-
name="
|
|
1393
|
+
id="<YOUR-DATASET-ID>",
|
|
1394
|
+
name="MyDataset"
|
|
922
1395
|
)
|
|
923
1396
|
|
|
924
1397
|
Args:
|
|
925
|
-
id (str): The ID of the dataset.
|
|
1398
|
+
id (str): The ID of the dataset. To retrieve the dataset ID:
|
|
1399
|
+
|
|
1400
|
+
- Navigate to the **DATASETS** tab of the **DATA** page.
|
|
1401
|
+
- Click on the dataset.
|
|
1402
|
+
- Click the **...** menu.
|
|
1403
|
+
- Select **Copy dataset ID**.
|
|
926
1404
|
name (str): The new name of the dataset.
|
|
927
1405
|
|
|
928
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1406
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#renamedataset>`_.
|
|
929
1407
|
"""
|
|
930
1408
|
request = RenameDatasetRequest(id=id, name=name)
|
|
931
1409
|
await self._dataset_client.RenameDataset(request, metadata=self._metadata)
|
|
@@ -936,95 +1414,110 @@ class DataClient:
|
|
|
936
1414
|
::
|
|
937
1415
|
|
|
938
1416
|
await data_client.delete_dataset(
|
|
939
|
-
id="
|
|
1417
|
+
id="<YOUR-DATASET-ID>"
|
|
940
1418
|
)
|
|
941
1419
|
|
|
942
1420
|
Args:
|
|
943
|
-
id (str): The ID of the dataset.
|
|
1421
|
+
id (str): The ID of the dataset. To retrieve the dataset ID:
|
|
944
1422
|
|
|
945
|
-
|
|
1423
|
+
- Navigate to the **DATASETS** tab of the **DATA** page.
|
|
1424
|
+
- Click on the dataset.
|
|
1425
|
+
- Click the **...** menu.
|
|
1426
|
+
- Select **Copy dataset ID**.
|
|
1427
|
+
|
|
1428
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#deletedataset>`_.
|
|
946
1429
|
"""
|
|
947
1430
|
request = DeleteDatasetRequest(id=id)
|
|
948
1431
|
await self._dataset_client.DeleteDataset(request, metadata=self._metadata)
|
|
949
1432
|
|
|
950
|
-
async def add_binary_data_to_dataset_by_ids(self, binary_ids: List[BinaryID], dataset_id: str) -> None:
|
|
1433
|
+
async def add_binary_data_to_dataset_by_ids(self, binary_ids: Union[List[BinaryID], List[str]], dataset_id: str) -> None:
|
|
951
1434
|
"""Add the BinaryData to the provided dataset.
|
|
952
1435
|
|
|
953
1436
|
This BinaryData will be tagged with the VIAM_DATASET_{id} label.
|
|
954
1437
|
|
|
955
1438
|
::
|
|
956
1439
|
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
binary_metadata = await data_client.binary_data_by_filter(
|
|
960
|
-
include_file_data=False
|
|
1440
|
+
binary_metadata, count, last = await data_client.binary_data_by_filter(
|
|
1441
|
+
include_binary_data=False
|
|
961
1442
|
)
|
|
962
1443
|
|
|
963
|
-
|
|
1444
|
+
my_binary_data_ids = []
|
|
964
1445
|
|
|
965
1446
|
for obj in binary_metadata:
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
file_id=obj.metadata.id,
|
|
969
|
-
organization_id=obj.metadata.capture_metadata.organization_id,
|
|
970
|
-
location_id=obj.metadata.capture_metadata.location_id
|
|
971
|
-
)
|
|
1447
|
+
my_binary_data_ids.append(
|
|
1448
|
+
obj.metadata.binary_data_id
|
|
972
1449
|
)
|
|
973
1450
|
|
|
974
1451
|
await data_client.add_binary_data_to_dataset_by_ids(
|
|
975
|
-
binary_ids=
|
|
1452
|
+
binary_ids=my_binary_data_ids,
|
|
976
1453
|
dataset_id="abcd-1234xyz-8765z-123abc"
|
|
977
1454
|
)
|
|
978
1455
|
|
|
979
1456
|
Args:
|
|
980
|
-
binary_ids (List[BinaryID]):
|
|
981
|
-
navigate to
|
|
982
|
-
|
|
983
|
-
dataset_id (str): The ID of the dataset to be added to.
|
|
1457
|
+
binary_ids (List[~viam.proto.app.data.BinaryID]): Unique identifiers for binary data to add to the dataset. To retrieve these IDs,
|
|
1458
|
+
navigate to the DATA page, click on an image, and copy its Binary Data ID from the details tab.
|
|
1459
|
+
dataset_id (str): The ID of the dataset to be added to. To retrieve the dataset ID:
|
|
984
1460
|
|
|
985
|
-
|
|
1461
|
+
- Navigate to the **DATASETS** tab of the **DATA** page.
|
|
1462
|
+
- Click on the dataset.
|
|
1463
|
+
- Click the **...** menu.
|
|
1464
|
+
- Select **Copy dataset ID**.
|
|
1465
|
+
|
|
1466
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#addbinarydatatodatasetbyids>`_.
|
|
986
1467
|
"""
|
|
987
|
-
request = AddBinaryDataToDatasetByIDsRequest(
|
|
1468
|
+
request = AddBinaryDataToDatasetByIDsRequest()
|
|
1469
|
+
if len(binary_ids) > 0 and isinstance(binary_ids[0], str):
|
|
1470
|
+
binary_data_ids = cast(List[str], binary_ids)
|
|
1471
|
+
request = AddBinaryDataToDatasetByIDsRequest(binary_data_ids=binary_data_ids, dataset_id=dataset_id)
|
|
1472
|
+
else:
|
|
1473
|
+
bin_ids = cast(List[BinaryID], binary_ids)
|
|
1474
|
+
request = AddBinaryDataToDatasetByIDsRequest(binary_ids=bin_ids, dataset_id=dataset_id)
|
|
988
1475
|
await self._data_client.AddBinaryDataToDatasetByIDs(request, metadata=self._metadata)
|
|
989
1476
|
|
|
990
|
-
async def remove_binary_data_from_dataset_by_ids(self, binary_ids: List[BinaryID], dataset_id: str) -> None:
|
|
1477
|
+
async def remove_binary_data_from_dataset_by_ids(self, binary_ids: Union[List[BinaryID], List[str]], dataset_id: str) -> None:
|
|
991
1478
|
"""Remove the BinaryData from the provided dataset.
|
|
992
1479
|
|
|
993
1480
|
This BinaryData will lose the VIAM_DATASET_{id} tag.
|
|
994
1481
|
|
|
995
1482
|
::
|
|
996
1483
|
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
binary_metadata = await data_client.binary_data_by_filter(
|
|
1000
|
-
include_file_data=False
|
|
1484
|
+
binary_metadata, count, last = await data_client.binary_data_by_filter(
|
|
1485
|
+
include_binary_data=False
|
|
1001
1486
|
)
|
|
1002
1487
|
|
|
1003
|
-
|
|
1488
|
+
my_binary_data_ids = []
|
|
1004
1489
|
|
|
1005
1490
|
for obj in binary_metadata:
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
file_id=obj.metadata.id,
|
|
1009
|
-
organization_id=obj.metadata.capture_metadata.organization_id,
|
|
1010
|
-
location_id=obj.metadata.capture_metadata.location_id
|
|
1011
|
-
)
|
|
1491
|
+
my_binary_data_ids.append(
|
|
1492
|
+
obj.metadata.binary_data_id
|
|
1012
1493
|
)
|
|
1013
1494
|
|
|
1014
1495
|
await data_client.remove_binary_data_from_dataset_by_ids(
|
|
1015
|
-
binary_ids=
|
|
1496
|
+
binary_ids=my_binary_data_ids,
|
|
1016
1497
|
dataset_id="abcd-1234xyz-8765z-123abc"
|
|
1017
1498
|
)
|
|
1018
1499
|
|
|
1019
1500
|
Args:
|
|
1020
|
-
binary_ids (List[BinaryID]):
|
|
1021
|
-
navigate to
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1501
|
+
binary_ids (Union[List[~viam.proto.app.data.BinaryID], List[str]]): Unique identifiers for the binary data to remove from the dataset. To retrieve these IDs,
|
|
1502
|
+
navigate to the DATA page, click on an image and copy its Binary Data ID from the details tab.
|
|
1503
|
+
*DEPRECATED:* :class:`BinaryID` *is deprecated and will be removed in a future release. Instead, pass binary data IDs as a
|
|
1504
|
+
list of strings.*
|
|
1505
|
+
dataset_id (str): The ID of the dataset to be removed from. To retrieve the dataset ID:
|
|
1506
|
+
|
|
1507
|
+
- Navigate to the **DATASETS** tab of the **DATA** page.
|
|
1508
|
+
- Click on the dataset.
|
|
1509
|
+
- Click the **...** menu.
|
|
1510
|
+
- Select **Copy dataset ID**.
|
|
1511
|
+
|
|
1512
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#removebinarydatafromdatasetbyids>`_.
|
|
1026
1513
|
"""
|
|
1027
|
-
request = RemoveBinaryDataFromDatasetByIDsRequest(
|
|
1514
|
+
request = RemoveBinaryDataFromDatasetByIDsRequest()
|
|
1515
|
+
if len(binary_ids) > 0 and isinstance(binary_ids[0], str):
|
|
1516
|
+
binary_data_ids = cast(List[str], binary_ids)
|
|
1517
|
+
request = RemoveBinaryDataFromDatasetByIDsRequest(binary_data_ids=binary_data_ids, dataset_id=dataset_id)
|
|
1518
|
+
else:
|
|
1519
|
+
bin_ids = cast(List[BinaryID], binary_ids)
|
|
1520
|
+
request = RemoveBinaryDataFromDatasetByIDsRequest(binary_ids=bin_ids, dataset_id=dataset_id)
|
|
1028
1521
|
await self._data_client.RemoveBinaryDataFromDatasetByIDs(request, metadata=self._metadata)
|
|
1029
1522
|
|
|
1030
1523
|
async def binary_data_capture_upload(
|
|
@@ -1037,12 +1530,13 @@ class DataClient:
|
|
|
1037
1530
|
file_extension: str,
|
|
1038
1531
|
method_parameters: Optional[Mapping[str, Any]] = None,
|
|
1039
1532
|
tags: Optional[List[str]] = None,
|
|
1533
|
+
dataset_ids: Optional[List[str]] = None,
|
|
1040
1534
|
data_request_times: Optional[Tuple[datetime, datetime]] = None,
|
|
1041
1535
|
) -> str:
|
|
1042
1536
|
"""Upload binary sensor data.
|
|
1043
1537
|
|
|
1044
|
-
Upload binary data collected on a robot through a specific component (for example, a motor) along with the relevant metadata
|
|
1045
|
-
|
|
1538
|
+
Upload binary data collected on a robot through a specific component (for example, a motor), along with the relevant metadata.
|
|
1539
|
+
Binary data can be found on the **DATA** page.
|
|
1046
1540
|
|
|
1047
1541
|
::
|
|
1048
1542
|
|
|
@@ -1058,7 +1552,8 @@ class DataClient:
|
|
|
1058
1552
|
tags=["tag_1", "tag_2"],
|
|
1059
1553
|
data_request_times=[time_requested, time_received],
|
|
1060
1554
|
file_extension=".jpg",
|
|
1061
|
-
binary_data=b"Encoded image bytes"
|
|
1555
|
+
binary_data=b"Encoded image bytes",
|
|
1556
|
+
dataset_ids=["dataset_1", "dataset_2"]
|
|
1062
1557
|
)
|
|
1063
1558
|
|
|
1064
1559
|
Args:
|
|
@@ -1067,21 +1562,22 @@ class DataClient:
|
|
|
1067
1562
|
component_type (str): Type of the component used to capture the data (for example, "movement_sensor").
|
|
1068
1563
|
component_name (str): Name of the component used to capture the data.
|
|
1069
1564
|
method_name (str): Name of the method used to capture the data.
|
|
1070
|
-
file_extension (str): The file extension of binary data including the period
|
|
1071
|
-
The backend
|
|
1072
|
-
or
|
|
1565
|
+
file_extension (str): The file extension of binary data, *including the period*, for example ``.jpg``, ``.png``, ``.pcd``.
|
|
1566
|
+
The backend routes the binary to its corresponding mime type based on this extension. Files with a ``.jpeg``, ``.jpg``,
|
|
1567
|
+
or ``.png`` extension will appear in the **Images** tab.
|
|
1073
1568
|
method_parameters (Optional[Mapping[str, Any]]): Optional dictionary of method parameters. No longer in active use.
|
|
1074
1569
|
tags (Optional[List[str]]): Optional list of tags to allow for tag-based data filtering when retrieving data.
|
|
1570
|
+
dataset_ids (Optional[List[str]]): Optional list of datasets to add the data to.
|
|
1075
1571
|
data_request_times (Optional[Tuple[datetime.datetime, datetime.datetime]]): Optional tuple containing datetime objects
|
|
1076
|
-
denoting the times this data was requested[0] by the robot and received[1] from the appropriate sensor.
|
|
1572
|
+
denoting the times this data was requested ``[0]`` by the robot and received ``[1]`` from the appropriate sensor.
|
|
1077
1573
|
|
|
1078
1574
|
Raises:
|
|
1079
1575
|
GRPCError: If an invalid part ID is passed.
|
|
1080
1576
|
|
|
1081
1577
|
Returns:
|
|
1082
|
-
str: The
|
|
1578
|
+
str: The binary data ID of the uploaded data.
|
|
1083
1579
|
|
|
1084
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1580
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#binarydatacaptureupload>`_.
|
|
1085
1581
|
"""
|
|
1086
1582
|
sensor_contents = SensorData(
|
|
1087
1583
|
metadata=(
|
|
@@ -1103,11 +1599,12 @@ class DataClient:
|
|
|
1103
1599
|
type=DataType.DATA_TYPE_BINARY_SENSOR,
|
|
1104
1600
|
method_parameters=method_parameters,
|
|
1105
1601
|
tags=tags,
|
|
1602
|
+
dataset_ids=dataset_ids,
|
|
1106
1603
|
)
|
|
1107
1604
|
if file_extension:
|
|
1108
1605
|
metadata.file_extension = file_extension if file_extension[0] == "." else f".{file_extension}"
|
|
1109
1606
|
response = await self._data_capture_upload(metadata=metadata, sensor_contents=[sensor_contents])
|
|
1110
|
-
return response.
|
|
1607
|
+
return response.binary_data_id
|
|
1111
1608
|
|
|
1112
1609
|
async def tabular_data_capture_upload(
|
|
1113
1610
|
self,
|
|
@@ -1116,57 +1613,62 @@ class DataClient:
|
|
|
1116
1613
|
component_type: str,
|
|
1117
1614
|
component_name: str,
|
|
1118
1615
|
method_name: str,
|
|
1616
|
+
data_request_times: List[Tuple[datetime, datetime]],
|
|
1119
1617
|
method_parameters: Optional[Mapping[str, Any]] = None,
|
|
1120
1618
|
tags: Optional[List[str]] = None,
|
|
1121
|
-
data_request_times: Optional[List[Tuple[datetime, datetime]]] = None,
|
|
1122
1619
|
) -> str:
|
|
1123
1620
|
"""Upload tabular sensor data.
|
|
1124
1621
|
|
|
1125
|
-
Upload tabular data collected on a robot through a specific component (for example, a motor) along with the relevant metadata
|
|
1126
|
-
|
|
1622
|
+
Upload tabular data collected on a robot through a specific component (for example, a motor), along with the relevant metadata.
|
|
1623
|
+
Tabular data can be found under the **Sensors** tab of the **DATA** page.
|
|
1127
1624
|
|
|
1128
1625
|
::
|
|
1129
1626
|
|
|
1627
|
+
from datetime import datetime
|
|
1628
|
+
|
|
1130
1629
|
time_requested = datetime(2023, 6, 5, 11)
|
|
1131
1630
|
time_received = datetime(2023, 6, 5, 11, 0, 3)
|
|
1132
|
-
|
|
1133
1631
|
file_id = await data_client.tabular_data_capture_upload(
|
|
1134
1632
|
part_id="INSERT YOUR PART ID",
|
|
1135
|
-
component_type='
|
|
1136
|
-
component_name='
|
|
1137
|
-
method_name='
|
|
1138
|
-
tags=["
|
|
1633
|
+
component_type='rdk:component:movement_sensor',
|
|
1634
|
+
component_name='my_movement_sensor',
|
|
1635
|
+
method_name='Readings',
|
|
1636
|
+
tags=["sensor_data"],
|
|
1139
1637
|
data_request_times=[(time_requested, time_received)],
|
|
1140
|
-
tabular_data=[{
|
|
1638
|
+
tabular_data=[{
|
|
1639
|
+
'readings': {
|
|
1640
|
+
'linear_velocity': {'x': 0.5, 'y': 0.0, 'z': 0.0},
|
|
1641
|
+
'angular_velocity': {'x': 0.0, 'y': 0.0, 'z': 0.1}
|
|
1642
|
+
}
|
|
1643
|
+
}]
|
|
1141
1644
|
)
|
|
1142
1645
|
|
|
1143
1646
|
Args:
|
|
1144
1647
|
tabular_data (List[Mapping[str, Any]]): List of the data to be uploaded, represented tabularly as a collection of dictionaries.
|
|
1648
|
+
Must include the key ``readings`` for sensors.
|
|
1145
1649
|
part_id (str): Part ID of the component used to capture the data.
|
|
1146
|
-
component_type (str): Type of the component used to capture the data (for example,
|
|
1650
|
+
component_type (str): Type of the component used to capture the data (for example, ``rdk:component:movement_sensor``).
|
|
1147
1651
|
component_name (str): Name of the component used to capture the data.
|
|
1148
1652
|
method_name (str): Name of the method used to capture the data.
|
|
1653
|
+
data_request_times (List[Tuple[datetime.datetime, datetime.datetime]]): List of tuples, each containing ``datetime`` objects
|
|
1654
|
+
denoting the times this data was requested ``[0]`` by the robot and received ``[1]`` from the appropriate sensor.
|
|
1655
|
+
Pass a list of tabular data and timestamps with length ``n > 1`` to upload ``n`` datapoints, all with the same metadata.
|
|
1149
1656
|
method_parameters (Optional[Mapping[str, Any]]): Optional dictionary of method parameters. No longer in active use.
|
|
1150
1657
|
tags (Optional[List[str]]): Optional list of tags to allow for tag-based data filtering when retrieving data.
|
|
1151
|
-
data_request_times (Optional[List[Tuple[datetime.datetime, datetime.datetime]]]): Optional list of tuples, each containing
|
|
1152
|
-
`datetime` objects denoting the times this data was requested[0] by the robot and received[1] from the appropriate sensor.
|
|
1153
|
-
Passing a list of tabular data and Timestamps with length n > 1 will result in n datapoints being uploaded, all tied to the
|
|
1154
|
-
same metadata.
|
|
1155
1658
|
|
|
1156
1659
|
Raises:
|
|
1157
1660
|
GRPCError: If an invalid part ID is passed.
|
|
1158
|
-
ValueError: If
|
|
1661
|
+
ValueError: If the provided list of `Timestamp` objects has a length that does not match the length of the list of tabular
|
|
1159
1662
|
data.
|
|
1160
1663
|
|
|
1161
1664
|
Returns:
|
|
1162
|
-
str: The
|
|
1665
|
+
str: The file ID of the uploaded data.
|
|
1163
1666
|
|
|
1164
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1667
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#tabulardatacaptureupload>`_.
|
|
1165
1668
|
"""
|
|
1166
1669
|
sensor_contents = []
|
|
1167
|
-
if data_request_times:
|
|
1168
|
-
|
|
1169
|
-
raise ValueError("data_request_times and tabular_data lengths must be equal.")
|
|
1670
|
+
if len(data_request_times) != len(tabular_data):
|
|
1671
|
+
raise ValueError("data_request_times and tabular_data lengths must be equal.")
|
|
1170
1672
|
|
|
1171
1673
|
for idx, tab in enumerate(tabular_data):
|
|
1172
1674
|
s = Struct()
|
|
@@ -1215,6 +1717,7 @@ class DataClient:
|
|
|
1215
1717
|
method_parameters: Optional[Mapping[str, Any]] = None,
|
|
1216
1718
|
data_request_times: Optional[Tuple[datetime, datetime]] = None,
|
|
1217
1719
|
tags: Optional[List[str]] = None,
|
|
1720
|
+
dataset_ids: Optional[List[str]] = None,
|
|
1218
1721
|
) -> str:
|
|
1219
1722
|
"""Uploads the metadata and contents of streaming binary data.
|
|
1220
1723
|
|
|
@@ -1230,29 +1733,31 @@ class DataClient:
|
|
|
1230
1733
|
component_type='motor',
|
|
1231
1734
|
component_name='left_motor',
|
|
1232
1735
|
method_name='IsPowered',
|
|
1233
|
-
data_request_times=[
|
|
1234
|
-
tags=["tag_1", "tag_2"]
|
|
1736
|
+
data_request_times=[time_requested, time_received],
|
|
1737
|
+
tags=["tag_1", "tag_2"],
|
|
1738
|
+
dataset_ids=["dataset_1", "dataset_2"]
|
|
1235
1739
|
)
|
|
1236
1740
|
|
|
1237
1741
|
Args:
|
|
1238
|
-
data (bytes):
|
|
1742
|
+
data (bytes): The data to be uploaded.
|
|
1239
1743
|
part_id (str): Part ID of the resource associated with the file.
|
|
1240
|
-
file_ext (str):
|
|
1744
|
+
file_ext (str): File extension type for the data. required for determining MIME type.
|
|
1241
1745
|
component_type (Optional[str]): Optional type of the component associated with the file (for example, "movement_sensor").
|
|
1242
1746
|
component_name (Optional[str]): Optional name of the component associated with the file.
|
|
1243
1747
|
method_name (Optional[str]): Optional name of the method associated with the file.
|
|
1244
1748
|
method_parameters (Optional[str]): Optional dictionary of the method parameters. No longer in active use.
|
|
1245
1749
|
data_request_times (Optional[Tuple[datetime.datetime, datetime.datetime]]): Optional tuple containing datetime objects
|
|
1246
|
-
denoting the times this data was requested[0] by the robot and received[1] from the appropriate sensor.
|
|
1750
|
+
denoting the times this data was requested ``[0]`` by the robot and received ``[1]`` from the appropriate sensor.
|
|
1247
1751
|
tags (Optional[List[str]]): Optional list of tags to allow for tag-based filtering when retrieving data.
|
|
1752
|
+
dataset_ids (Optional[List[str]]): Optional list of datasets to add the data to.
|
|
1248
1753
|
|
|
1249
1754
|
Raises:
|
|
1250
1755
|
GRPCError: If an invalid part ID is passed.
|
|
1251
1756
|
|
|
1252
1757
|
Returns:
|
|
1253
|
-
str: The
|
|
1758
|
+
str: The binary data ID of the uploaded data.
|
|
1254
1759
|
|
|
1255
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1760
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#streamingdatacaptureupload>`_.
|
|
1256
1761
|
"""
|
|
1257
1762
|
|
|
1258
1763
|
upload_metadata = UploadMetadata(
|
|
@@ -1264,6 +1769,7 @@ class DataClient:
|
|
|
1264
1769
|
type=DataType.DATA_TYPE_BINARY_SENSOR,
|
|
1265
1770
|
file_extension=file_ext if file_ext[0] == "." else f".{file_ext}",
|
|
1266
1771
|
tags=tags,
|
|
1772
|
+
dataset_ids=dataset_ids,
|
|
1267
1773
|
)
|
|
1268
1774
|
sensor_metadata = SensorMetadata(
|
|
1269
1775
|
time_requested=datetime_to_timestamp(data_request_times[0]) if data_request_times else None,
|
|
@@ -1279,7 +1785,7 @@ class DataClient:
|
|
|
1279
1785
|
if not response:
|
|
1280
1786
|
await stream.recv_trailing_metadata() # causes us to throw appropriate gRPC error
|
|
1281
1787
|
raise TypeError("Response cannot be empty")
|
|
1282
|
-
return response.
|
|
1788
|
+
return response.binary_data_id
|
|
1283
1789
|
|
|
1284
1790
|
async def file_upload(
|
|
1285
1791
|
self,
|
|
@@ -1292,11 +1798,12 @@ class DataClient:
|
|
|
1292
1798
|
method_parameters: Optional[Mapping[str, Any]] = None,
|
|
1293
1799
|
file_extension: Optional[str] = None,
|
|
1294
1800
|
tags: Optional[List[str]] = None,
|
|
1801
|
+
dataset_ids: Optional[List[str]] = None,
|
|
1295
1802
|
) -> str:
|
|
1296
1803
|
"""Upload arbitrary file data.
|
|
1297
1804
|
|
|
1298
|
-
Upload file data that may be stored on a robot along with the relevant metadata
|
|
1299
|
-
|
|
1805
|
+
Upload file data that may be stored on a robot along with the relevant metadata. File data can be found in the
|
|
1806
|
+
**Files** tab of the **DATA** page.
|
|
1300
1807
|
|
|
1301
1808
|
::
|
|
1302
1809
|
|
|
@@ -1305,7 +1812,8 @@ class DataClient:
|
|
|
1305
1812
|
part_id="INSERT YOUR PART ID",
|
|
1306
1813
|
tags=["tag_1", "tag_2"],
|
|
1307
1814
|
file_name="your-file",
|
|
1308
|
-
file_extension=".txt"
|
|
1815
|
+
file_extension=".txt",
|
|
1816
|
+
dataset_ids=["dataset_1", "dataset_2"]
|
|
1309
1817
|
)
|
|
1310
1818
|
|
|
1311
1819
|
Args:
|
|
@@ -1314,20 +1822,21 @@ class DataClient:
|
|
|
1314
1822
|
component_type (Optional[str]): Optional type of the component associated with the file (for example, "movement_sensor").
|
|
1315
1823
|
component_name (Optional[str]): Optional name of the component associated with the file.
|
|
1316
1824
|
method_name (Optional[str]): Optional name of the method associated with the file.
|
|
1317
|
-
file_name (Optional[str]): Optional name of the file. The empty string "" will be assigned as the file name if one isn't
|
|
1825
|
+
file_name (Optional[str]): Optional name of the file. The empty string ``""`` will be assigned as the file name if one isn't
|
|
1318
1826
|
provided.
|
|
1319
1827
|
method_parameters (Optional[str]): Optional dictionary of the method parameters. No longer in active use.
|
|
1320
|
-
file_extension (Optional[str]): Optional file extension. The empty string "" will be assigned as the file extension if one
|
|
1321
|
-
provided. Files with a
|
|
1828
|
+
file_extension (Optional[str]): Optional file extension. The empty string ``""`` will be assigned as the file extension if one
|
|
1829
|
+
isn't provided. Files with a ``.jpeg``, ``.jpg``, or ``.png`` extension will be saved to the **Images** tab.
|
|
1322
1830
|
tags (Optional[List[str]]): Optional list of tags to allow for tag-based filtering when retrieving data.
|
|
1831
|
+
dataset_ids (Optional[List[str]]): Optional list of datasets to add the data to.
|
|
1323
1832
|
|
|
1324
1833
|
Raises:
|
|
1325
1834
|
GRPCError: If an invalid part ID is passed.
|
|
1326
1835
|
|
|
1327
1836
|
Returns:
|
|
1328
|
-
str: ID of the new file.
|
|
1837
|
+
str: Binary data ID of the new file.
|
|
1329
1838
|
|
|
1330
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1839
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#fileupload>`_.
|
|
1331
1840
|
"""
|
|
1332
1841
|
metadata = UploadMetadata(
|
|
1333
1842
|
part_id=part_id,
|
|
@@ -1339,9 +1848,10 @@ class DataClient:
|
|
|
1339
1848
|
method_parameters=method_parameters,
|
|
1340
1849
|
file_extension=file_extension if file_extension else "",
|
|
1341
1850
|
tags=tags,
|
|
1851
|
+
dataset_ids=dataset_ids,
|
|
1342
1852
|
)
|
|
1343
1853
|
response: FileUploadResponse = await self._file_upload(metadata=metadata, file_contents=FileData(data=data))
|
|
1344
|
-
return response.
|
|
1854
|
+
return response.binary_data_id
|
|
1345
1855
|
|
|
1346
1856
|
async def file_upload_from_path(
|
|
1347
1857
|
self,
|
|
@@ -1352,17 +1862,19 @@ class DataClient:
|
|
|
1352
1862
|
method_name: Optional[str] = None,
|
|
1353
1863
|
method_parameters: Optional[Mapping[str, Any]] = None,
|
|
1354
1864
|
tags: Optional[List[str]] = None,
|
|
1865
|
+
dataset_ids: Optional[List[str]] = None,
|
|
1355
1866
|
) -> str:
|
|
1356
1867
|
"""Upload arbitrary file data.
|
|
1357
1868
|
|
|
1358
|
-
Upload file data that may be stored on a robot along with the relevant metadata
|
|
1359
|
-
|
|
1869
|
+
Upload file data that may be stored on a robot along with the relevant metadata. File data can be found in the
|
|
1870
|
+
**Files** tab of the **DATA** page.
|
|
1360
1871
|
|
|
1361
1872
|
::
|
|
1362
1873
|
|
|
1363
1874
|
file_id = await data_client.file_upload_from_path(
|
|
1364
1875
|
part_id="INSERT YOUR PART ID",
|
|
1365
1876
|
tags=["tag_1", "tag_2"],
|
|
1877
|
+
dataset_ids=["dataset_1", "dataset_2"],
|
|
1366
1878
|
filepath="/Users/<your-username>/<your-directory>/<your-file.txt>"
|
|
1367
1879
|
)
|
|
1368
1880
|
|
|
@@ -1374,23 +1886,22 @@ class DataClient:
|
|
|
1374
1886
|
method_name (Optional[str]): Optional name of the method associated with the file.
|
|
1375
1887
|
method_parameters (Optional[str]): Optional dictionary of the method parameters. No longer in active use.
|
|
1376
1888
|
tags (Optional[List[str]]): Optional list of tags to allow for tag-based filtering when retrieving data.
|
|
1377
|
-
|
|
1889
|
+
dataset_ids (Optional[List[str]]): Optional list of datasets to add the data to.
|
|
1378
1890
|
|
|
1379
1891
|
Raises:
|
|
1380
1892
|
GRPCError: If an invalid part ID is passed.
|
|
1381
1893
|
FileNotFoundError: If the provided filepath is not found.
|
|
1382
1894
|
|
|
1383
1895
|
Returns:
|
|
1384
|
-
str: ID of the new file.
|
|
1896
|
+
str: Binary data ID of the new file.
|
|
1385
1897
|
|
|
1386
|
-
For more information, see `Data Client API <https://docs.viam.com/
|
|
1898
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#fileuploadfrompath>`_.
|
|
1387
1899
|
"""
|
|
1388
1900
|
path = Path(filepath)
|
|
1389
1901
|
file_name = path.stem
|
|
1390
1902
|
file_extension = path.suffix if path.suffix != "" else None
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
f.close()
|
|
1903
|
+
with open(filepath, "rb") as f:
|
|
1904
|
+
data = f.read()
|
|
1394
1905
|
|
|
1395
1906
|
metadata = UploadMetadata(
|
|
1396
1907
|
part_id=part_id,
|
|
@@ -1402,9 +1913,10 @@ class DataClient:
|
|
|
1402
1913
|
method_parameters=method_parameters,
|
|
1403
1914
|
file_extension=file_extension if file_extension else "",
|
|
1404
1915
|
tags=tags,
|
|
1916
|
+
dataset_ids=dataset_ids,
|
|
1405
1917
|
)
|
|
1406
1918
|
response: FileUploadResponse = await self._file_upload(metadata=metadata, file_contents=FileData(data=data if data else bytes()))
|
|
1407
|
-
return response.
|
|
1919
|
+
return response.binary_data_id
|
|
1408
1920
|
|
|
1409
1921
|
async def _file_upload(self, metadata: UploadMetadata, file_contents: FileData) -> FileUploadResponse:
|
|
1410
1922
|
request_metadata = FileUploadRequest(metadata=metadata)
|
|
@@ -1419,6 +1931,265 @@ class DataClient:
|
|
|
1419
1931
|
raise TypeError("Response cannot be empty")
|
|
1420
1932
|
return response
|
|
1421
1933
|
|
|
1934
|
+
async def get_data_pipeline(self, id: str) -> DataPipeline:
|
|
1935
|
+
"""Get a data pipeline by its ID.
|
|
1936
|
+
|
|
1937
|
+
::
|
|
1938
|
+
|
|
1939
|
+
data_pipeline = await data_client.get_data_pipeline(id="<YOUR-DATA-PIPELINE-ID>")
|
|
1940
|
+
|
|
1941
|
+
Args:
|
|
1942
|
+
id (str): The ID of the data pipeline to get.
|
|
1943
|
+
|
|
1944
|
+
Returns:
|
|
1945
|
+
DataPipeline: The data pipeline with the given ID.
|
|
1946
|
+
"""
|
|
1947
|
+
request = GetDataPipelineRequest(id=id)
|
|
1948
|
+
response: GetDataPipelineResponse = await self._data_pipelines_client.GetDataPipeline(request, metadata=self._metadata)
|
|
1949
|
+
return DataClient.DataPipeline.from_proto(response.data_pipeline)
|
|
1950
|
+
|
|
1951
|
+
async def list_data_pipelines(self, organization_id: str) -> List[DataPipeline]:
|
|
1952
|
+
"""List all of the data pipelines for an organization.
|
|
1953
|
+
|
|
1954
|
+
::
|
|
1955
|
+
|
|
1956
|
+
data_pipelines = await data_client.list_data_pipelines(organization_id="<YOUR-ORGANIZATION-ID>")
|
|
1957
|
+
|
|
1958
|
+
Args:
|
|
1959
|
+
organization_id (str): The ID of the organization that owns the pipelines.
|
|
1960
|
+
You can obtain your organization ID from the organization settings page.
|
|
1961
|
+
|
|
1962
|
+
Returns:
|
|
1963
|
+
List[DataPipeline]: A list of all of the data pipelines for the given organization.
|
|
1964
|
+
"""
|
|
1965
|
+
request = ListDataPipelinesRequest(organization_id=organization_id)
|
|
1966
|
+
response: ListDataPipelinesResponse = await self._data_pipelines_client.ListDataPipelines(request, metadata=self._metadata)
|
|
1967
|
+
return [DataClient.DataPipeline.from_proto(pipeline) for pipeline in response.data_pipelines]
|
|
1968
|
+
|
|
1969
|
+
async def create_data_pipeline(
|
|
1970
|
+
self,
|
|
1971
|
+
organization_id: str,
|
|
1972
|
+
name: str,
|
|
1973
|
+
mql_binary: List[Dict[str, Any]],
|
|
1974
|
+
schedule: str,
|
|
1975
|
+
enable_backfill: bool,
|
|
1976
|
+
data_source_type: TabularDataSourceType.ValueType = TabularDataSourceType.TABULAR_DATA_SOURCE_TYPE_STANDARD,
|
|
1977
|
+
) -> str:
|
|
1978
|
+
"""Create a new data pipeline.
|
|
1979
|
+
|
|
1980
|
+
::
|
|
1981
|
+
|
|
1982
|
+
data_pipeline_id = await data_client.create_data_pipeline(
|
|
1983
|
+
organization_id="<YOUR-ORGANIZATION-ID>",
|
|
1984
|
+
name="<YOUR-PIPELINE-NAME>",
|
|
1985
|
+
mql_binary=[<YOUR-MQL-PIPELINE-AGGREGATION>],
|
|
1986
|
+
schedule="<YOUR-SCHEDULE>",
|
|
1987
|
+
enable_backfill=False,
|
|
1988
|
+
data_source_type=TabularDataSourceType.TABULAR_DATA_SOURCE_TYPE_STANDARD,
|
|
1989
|
+
)
|
|
1990
|
+
|
|
1991
|
+
Args:
|
|
1992
|
+
organization_id (str): The ID of the organization that will own the pipeline.
|
|
1993
|
+
You can obtain your organization ID from the organization settings page.
|
|
1994
|
+
name (str): The name of the pipeline.
|
|
1995
|
+
mql_binary (List[Dict[str, Any]]):The MQL pipeline to run, as a list of MongoDB aggregation pipeline stages.
|
|
1996
|
+
schedule (str): A cron expression representing the expected execution schedule in UTC (note this also
|
|
1997
|
+
defines the input time window; an hourly schedule would process 1 hour of data at a time).
|
|
1998
|
+
enable_backfill (bool): When true, pipeline runs will be scheduled for the organization's past data.
|
|
1999
|
+
data_source_type (TabularDataSourceType): The type of data source to use for the pipeline.
|
|
2000
|
+
Defaults to TabularDataSourceType.TABULAR_DATA_SOURCE_TYPE_STANDARD.
|
|
2001
|
+
|
|
2002
|
+
Returns:
|
|
2003
|
+
str: The ID of the newly created pipeline.
|
|
2004
|
+
"""
|
|
2005
|
+
binary: List[bytes] = [bson.encode(query) for query in mql_binary]
|
|
2006
|
+
request = CreateDataPipelineRequest(
|
|
2007
|
+
organization_id=organization_id,
|
|
2008
|
+
name=name,
|
|
2009
|
+
mql_binary=binary,
|
|
2010
|
+
schedule=schedule,
|
|
2011
|
+
enable_backfill=enable_backfill,
|
|
2012
|
+
data_source_type=data_source_type,
|
|
2013
|
+
)
|
|
2014
|
+
response: CreateDataPipelineResponse = await self._data_pipelines_client.CreateDataPipeline(request, metadata=self._metadata)
|
|
2015
|
+
return response.id
|
|
2016
|
+
|
|
2017
|
+
async def rename_data_pipeline(self, id: str, name: str) -> None:
|
|
2018
|
+
"""Rename a data pipeline by its ID.
|
|
2019
|
+
::
|
|
2020
|
+
|
|
2021
|
+
await data_client.rename_data_pipeline(id="<YOUR-DATA-PIPELINE-ID>", name="<YOUR-NEW-NAME>")
|
|
2022
|
+
|
|
2023
|
+
Args:
|
|
2024
|
+
id (str): The ID of the data pipeline to rename.
|
|
2025
|
+
name (str): The new name of the data pipeline.
|
|
2026
|
+
"""
|
|
2027
|
+
if not id or not name:
|
|
2028
|
+
raise ValueError("id and name are required")
|
|
2029
|
+
request = RenameDataPipelineRequest(id=id, name=name)
|
|
2030
|
+
await self._data_pipelines_client.RenameDataPipeline(request, metadata=self._metadata)
|
|
2031
|
+
|
|
2032
|
+
async def delete_data_pipeline(self, id: str) -> None:
|
|
2033
|
+
"""Delete a data pipeline by its ID.
|
|
2034
|
+
|
|
2035
|
+
::
|
|
2036
|
+
|
|
2037
|
+
await data_client.delete_data_pipeline(id="<YOUR-DATA-PIPELINE-ID>")
|
|
2038
|
+
|
|
2039
|
+
Args:
|
|
2040
|
+
id (str): The ID of the data pipeline to delete.
|
|
2041
|
+
"""
|
|
2042
|
+
request = DeleteDataPipelineRequest(id=id)
|
|
2043
|
+
await self._data_pipelines_client.DeleteDataPipeline(request, metadata=self._metadata)
|
|
2044
|
+
|
|
2045
|
+
async def list_data_pipeline_runs(self, id: str, page_size: int = 10) -> DataPipelineRunsPage:
|
|
2046
|
+
"""List all of the data pipeline runs for a data pipeline.
|
|
2047
|
+
|
|
2048
|
+
::
|
|
2049
|
+
|
|
2050
|
+
data_pipeline_runs = await data_client.list_data_pipeline_runs(id="<YOUR-DATA-PIPELINE-ID>")
|
|
2051
|
+
while len(data_pipeline_runs.runs) > 0:
|
|
2052
|
+
data_pipeline_runs = await data_pipeline_runs.next_page()
|
|
2053
|
+
|
|
2054
|
+
Args:
|
|
2055
|
+
id (str): The ID of the pipeline to list runs for
|
|
2056
|
+
page_size (int): The number of runs to return per page. Defaults to 10.
|
|
2057
|
+
|
|
2058
|
+
Returns:
|
|
2059
|
+
DataPipelineRunsPage: A page of data pipeline runs with pagination support
|
|
2060
|
+
"""
|
|
2061
|
+
return await self._list_data_pipeline_runs(id, page_size)
|
|
2062
|
+
|
|
2063
|
+
async def _list_data_pipeline_runs(self, id: str, page_size: int, page_token: str = "") -> DataPipelineRunsPage:
|
|
2064
|
+
"""Internal method to list data pipeline runs with pagination.
|
|
2065
|
+
|
|
2066
|
+
Args:
|
|
2067
|
+
id (str): The ID of the pipeline to list runs for
|
|
2068
|
+
page_size (int): The number of runs to return per page
|
|
2069
|
+
page_token (str): The token to use to get the next page of results
|
|
2070
|
+
|
|
2071
|
+
Returns:
|
|
2072
|
+
DataPipelineRunsPage: A page of data pipeline runs with pagination support
|
|
2073
|
+
"""
|
|
2074
|
+
request = ListDataPipelineRunsRequest(id=id, page_size=page_size, page_token=page_token)
|
|
2075
|
+
response: ListDataPipelineRunsResponse = await self._data_pipelines_client.ListDataPipelineRuns(request, metadata=self._metadata)
|
|
2076
|
+
return DataClient.DataPipelineRunsPage.from_proto(response, self, page_size)
|
|
2077
|
+
|
|
2078
|
+
async def create_index(
|
|
2079
|
+
self,
|
|
2080
|
+
organization_id: str,
|
|
2081
|
+
collection_type: IndexableCollection.ValueType,
|
|
2082
|
+
index_spec: Dict[str, Any],
|
|
2083
|
+
pipeline_name: Optional[str] = None,
|
|
2084
|
+
) -> None:
|
|
2085
|
+
"""Starts a custom index build.
|
|
2086
|
+
|
|
2087
|
+
Args:
|
|
2088
|
+
organization_id (str): The ID of the organization that owns the data.
|
|
2089
|
+
To find your organization ID, visit the organization settings page.
|
|
2090
|
+
collection_type (IndexableCollection.ValueType): The type of collection the index is on.
|
|
2091
|
+
index_spec (List[Dict[str, Any]]): The MongoDB index specification defined in JSON format.
|
|
2092
|
+
pipeline_name (Optional[str]): The name of the pipeline if the collection type is PIPELINE_SINK.
|
|
2093
|
+
|
|
2094
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#createindex>`_.
|
|
2095
|
+
"""
|
|
2096
|
+
index_spec_bytes = [bson.encode(index_spec)]
|
|
2097
|
+
request = CreateIndexRequest(
|
|
2098
|
+
organization_id=organization_id,
|
|
2099
|
+
collection_type=collection_type,
|
|
2100
|
+
index_spec=index_spec_bytes,
|
|
2101
|
+
pipeline_name=pipeline_name,
|
|
2102
|
+
)
|
|
2103
|
+
await self._data_client.CreateIndex(request, metadata=self._metadata)
|
|
2104
|
+
|
|
2105
|
+
async def list_indexes(
|
|
2106
|
+
self,
|
|
2107
|
+
organization_id: str,
|
|
2108
|
+
collection_type: IndexableCollection.ValueType,
|
|
2109
|
+
pipeline_name: Optional[str] = None,
|
|
2110
|
+
) -> Sequence[Index]:
|
|
2111
|
+
"""Returns all the indexes for a given collection.
|
|
2112
|
+
|
|
2113
|
+
Args:
|
|
2114
|
+
organization_id (str): The ID of the organization that owns the data.
|
|
2115
|
+
To find your organization ID, visit the organization settings page.
|
|
2116
|
+
collection_type (IndexableCollection.ValueType): The type of collection the index is on.
|
|
2117
|
+
pipeline_name (Optional[str]): The name of the pipeline if the collection type is PIPELINE_SINK.
|
|
2118
|
+
|
|
2119
|
+
Returns:
|
|
2120
|
+
List[Index]: A list of indexes.
|
|
2121
|
+
|
|
2122
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#listindexes>`_.
|
|
2123
|
+
"""
|
|
2124
|
+
request = ListIndexesRequest(
|
|
2125
|
+
organization_id=organization_id,
|
|
2126
|
+
collection_type=collection_type,
|
|
2127
|
+
pipeline_name=pipeline_name,
|
|
2128
|
+
)
|
|
2129
|
+
response: ListIndexesResponse = await self._data_client.ListIndexes(request, metadata=self._metadata)
|
|
2130
|
+
return response.indexes
|
|
2131
|
+
|
|
2132
|
+
async def delete_index(
|
|
2133
|
+
self,
|
|
2134
|
+
organization_id: str,
|
|
2135
|
+
collection_type: IndexableCollection.ValueType,
|
|
2136
|
+
index_name: str,
|
|
2137
|
+
pipeline_name: Optional[str] = None,
|
|
2138
|
+
) -> None:
|
|
2139
|
+
"""Drops the specified custom index from a collection.
|
|
2140
|
+
|
|
2141
|
+
Args:
|
|
2142
|
+
organization_id (str): The ID of the organization that owns the data.
|
|
2143
|
+
To find your organization ID, visit the organization settings page.
|
|
2144
|
+
collection_type (IndexableCollection.ValueType): The type of collection the index is on.
|
|
2145
|
+
index_name (str): The name of the index to delete.
|
|
2146
|
+
pipeline_name (Optional[str]): The name of the pipeline if the collection type is PIPELINE_SINK.
|
|
2147
|
+
|
|
2148
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#deleteindex>`_.
|
|
2149
|
+
"""
|
|
2150
|
+
request = DeleteIndexRequest(
|
|
2151
|
+
organization_id=organization_id,
|
|
2152
|
+
collection_type=collection_type,
|
|
2153
|
+
index_name=index_name,
|
|
2154
|
+
pipeline_name=pipeline_name,
|
|
2155
|
+
)
|
|
2156
|
+
await self._data_client.DeleteIndex(request, metadata=self._metadata)
|
|
2157
|
+
|
|
2158
|
+
async def create_binary_data_signed_url(
|
|
2159
|
+
self,
|
|
2160
|
+
binary_data_id: str,
|
|
2161
|
+
expiration_minutes: Optional[int] = None,
|
|
2162
|
+
) -> Tuple[str, datetime]:
|
|
2163
|
+
"""Create a signed URL for binary data.
|
|
2164
|
+
|
|
2165
|
+
::
|
|
2166
|
+
|
|
2167
|
+
signed_url, expires_at = await data_client.create_binary_data_signed_url(
|
|
2168
|
+
binary_data_id="<YOUR-BINARY-DATA-ID>",
|
|
2169
|
+
expiration_minutes=60
|
|
2170
|
+
)
|
|
2171
|
+
|
|
2172
|
+
print(f"Signed URL: {signed_url}")
|
|
2173
|
+
print(f"Expires at: {expires_at}")
|
|
2174
|
+
|
|
2175
|
+
Args:
|
|
2176
|
+
binary_data_id (str): The binary data ID of the file to create a signed URL for.
|
|
2177
|
+
expiration_minutes (Optional[int]): Expiration time in minutes. Defaults to 15 minutes if not specified.
|
|
2178
|
+
Maximum allowed is 10080 minutes (7 days).
|
|
2179
|
+
|
|
2180
|
+
Returns:
|
|
2181
|
+
Tuple[str, datetime]: A tuple containing:
|
|
2182
|
+
- ``signed_url`` (*str*): The signed URL for the binary data file.
|
|
2183
|
+
- ``expires_at`` (*datetime*): The expiration time of the signed URL token.
|
|
2184
|
+
|
|
2185
|
+
For more information, see `Data Client API <https://docs.viam.com/dev/reference/apis/data-client/#createbinarydatasignedurl>`_.
|
|
2186
|
+
"""
|
|
2187
|
+
request = CreateBinaryDataSignedURLRequest(binary_data_id=binary_data_id)
|
|
2188
|
+
if expiration_minutes is not None:
|
|
2189
|
+
request.expiration_minutes = expiration_minutes
|
|
2190
|
+
response: CreateBinaryDataSignedURLResponse = await self._data_client.CreateBinaryDataSignedURL(request, metadata=self._metadata)
|
|
2191
|
+
return response.signed_url, response.expires_at.ToDatetime()
|
|
2192
|
+
|
|
1422
2193
|
@staticmethod
|
|
1423
2194
|
def create_filter(
|
|
1424
2195
|
component_name: Optional[str] = None,
|