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/robot/service.py
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
from typing import Any, Dict, Iterable, List, Set
|
|
1
|
+
from typing import Any, Dict, List, Set
|
|
3
2
|
|
|
4
3
|
from grpclib.server import Stream
|
|
5
4
|
|
|
@@ -9,18 +8,12 @@ from viam.components.sensor import Sensor
|
|
|
9
8
|
from viam.errors import ViamGRPCError
|
|
10
9
|
from viam.proto.common import ResourceName
|
|
11
10
|
from viam.proto.robot import (
|
|
12
|
-
GetStatusRequest,
|
|
13
|
-
GetStatusResponse,
|
|
14
11
|
ResourceNamesRequest,
|
|
15
12
|
ResourceNamesResponse,
|
|
16
|
-
Status,
|
|
17
13
|
StopAllRequest,
|
|
18
14
|
StopAllResponse,
|
|
19
|
-
StreamStatusRequest,
|
|
20
|
-
StreamStatusResponse,
|
|
21
15
|
UnimplementedRobotServiceBase,
|
|
22
16
|
)
|
|
23
|
-
from viam.resource.registry import Registry
|
|
24
17
|
from viam.resource.rpc_service_base import ResourceRPCServiceBase
|
|
25
18
|
from viam.utils import resource_names_for_resource, struct_to_dict
|
|
26
19
|
|
|
@@ -33,34 +26,13 @@ class RobotService(UnimplementedRobotServiceBase, ResourceRPCServiceBase):
|
|
|
33
26
|
|
|
34
27
|
for resource in self.manager.resources.values():
|
|
35
28
|
# If the resource is a MovementSensor, DO NOT include Sensor as well (it will get added via MovementSensor)
|
|
36
|
-
if resource.
|
|
29
|
+
if resource.API == Sensor.API and MovementSensor.get_resource_name(resource.name) in self.manager.resources:
|
|
37
30
|
continue
|
|
38
31
|
|
|
39
32
|
md.update(resource_names_for_resource(resource))
|
|
40
33
|
|
|
41
34
|
return list(md)
|
|
42
35
|
|
|
43
|
-
async def _generate_status(self, resource_names: Iterable[ResourceName]) -> List[Status]:
|
|
44
|
-
statuses: List[Status] = []
|
|
45
|
-
seen_resource_names: Set[ResourceName] = set()
|
|
46
|
-
|
|
47
|
-
for resource in self.manager.resources.values():
|
|
48
|
-
for registration in Registry.REGISTERED_SUBTYPES().values():
|
|
49
|
-
if isinstance(resource, registration.resource_type):
|
|
50
|
-
if resource_names and resource.get_resource_name(resource.name) not in resource_names:
|
|
51
|
-
continue
|
|
52
|
-
try:
|
|
53
|
-
status = await registration.create_status(resource)
|
|
54
|
-
if status.name not in seen_resource_names:
|
|
55
|
-
seen_resource_names.add(status.name)
|
|
56
|
-
statuses.append(status)
|
|
57
|
-
except ViamGRPCError as e:
|
|
58
|
-
raise e.grpc_error
|
|
59
|
-
|
|
60
|
-
if resource_names:
|
|
61
|
-
statuses = [s for s in statuses if s.name in resource_names]
|
|
62
|
-
return statuses
|
|
63
|
-
|
|
64
36
|
async def ResourceNames(self, stream: Stream[ResourceNamesRequest, ResourceNamesResponse]) -> None:
|
|
65
37
|
request = await stream.recv_message()
|
|
66
38
|
assert request is not None
|
|
@@ -68,26 +40,6 @@ class RobotService(UnimplementedRobotServiceBase, ResourceRPCServiceBase):
|
|
|
68
40
|
response = ResourceNamesResponse(resources=metadata)
|
|
69
41
|
await stream.send_message(response)
|
|
70
42
|
|
|
71
|
-
async def GetStatus(self, stream: Stream[GetStatusRequest, GetStatusResponse]) -> None:
|
|
72
|
-
request = await stream.recv_message()
|
|
73
|
-
assert request is not None
|
|
74
|
-
status = await self._generate_status(request.resource_names)
|
|
75
|
-
response = GetStatusResponse(status=status)
|
|
76
|
-
await stream.send_message(response)
|
|
77
|
-
|
|
78
|
-
async def StreamStatus(self, stream: Stream[StreamStatusRequest, StreamStatusResponse]) -> None:
|
|
79
|
-
request = await stream.recv_message()
|
|
80
|
-
assert request is not None
|
|
81
|
-
interval = 1
|
|
82
|
-
every = request.every.ToSeconds()
|
|
83
|
-
if every > 0:
|
|
84
|
-
interval = every
|
|
85
|
-
while True:
|
|
86
|
-
status = await self._generate_status(request.resource_names)
|
|
87
|
-
response = StreamStatusResponse(status=status)
|
|
88
|
-
await stream.send_message(response)
|
|
89
|
-
await asyncio.sleep(interval)
|
|
90
|
-
|
|
91
43
|
async def StopAll(self, stream: Stream[StopAllRequest, StopAllResponse]) -> None:
|
|
92
44
|
request = await stream.recv_message()
|
|
93
45
|
assert request is not None
|
viam/rpc/dial.py
CHANGED
|
@@ -11,6 +11,7 @@ from typing import Callable, Literal, Optional, Tuple, Type, Union
|
|
|
11
11
|
|
|
12
12
|
from grpclib.client import Channel, Stream
|
|
13
13
|
from grpclib.const import Cardinality
|
|
14
|
+
from grpclib.events import SendRequest, listen
|
|
14
15
|
from grpclib.metadata import Deadline, _MetadataLike
|
|
15
16
|
from grpclib.protocol import H2Protocol
|
|
16
17
|
from grpclib.stream import _RecvType, _SendType
|
|
@@ -21,15 +22,16 @@ from viam.errors import InsecureConnectionError, ViamError
|
|
|
21
22
|
from viam.proto.rpc.auth import AuthenticateRequest, AuthServiceStub
|
|
22
23
|
from viam.proto.rpc.auth import Credentials as PBCredentials
|
|
23
24
|
from viam.utils import to_thread
|
|
25
|
+
from viam.version_metadata import API_VERSION, SDK_VERSION
|
|
24
26
|
|
|
25
27
|
LOGGER = logging.getLogger(__name__)
|
|
26
28
|
|
|
27
29
|
|
|
28
30
|
@dataclass
|
|
29
31
|
class Credentials:
|
|
30
|
-
"""Credentials to connect to the
|
|
32
|
+
"""Credentials to connect to the machine and app.viam.com."""
|
|
31
33
|
|
|
32
|
-
type: Union[Literal["robot-
|
|
34
|
+
type: Union[Literal["robot-secret"], Literal["api-key"]]
|
|
33
35
|
"""The type of credential
|
|
34
36
|
"""
|
|
35
37
|
|
|
@@ -68,6 +70,14 @@ class DialOptions:
|
|
|
68
70
|
max_reconnect_attempts: int = 3
|
|
69
71
|
"""Max number of times the client attempts to reconnect when connection is lost"""
|
|
70
72
|
|
|
73
|
+
initial_connection_attempts: int = 3
|
|
74
|
+
"""Max number of times the client will attempt to establish an initial connection
|
|
75
|
+
If set to a non-positive integer, then there will be no limit to initial connection attempts"""
|
|
76
|
+
|
|
77
|
+
initial_connection_attempt_timeout: float
|
|
78
|
+
"""Number of seconds before dial connection times out on initial connection attempts
|
|
79
|
+
Defaults to whatever value is set in the `timeout` field"""
|
|
80
|
+
|
|
71
81
|
timeout: float = 20
|
|
72
82
|
"""Number of seconds before the dial connection times out
|
|
73
83
|
Set to 20sec to match _defaultOfferDeadline in goutils/rpc/wrtc_call_queue.go"""
|
|
@@ -83,6 +93,8 @@ class DialOptions:
|
|
|
83
93
|
allow_insecure_with_creds_downgrade: bool = False,
|
|
84
94
|
max_reconnect_attempts: int = 3,
|
|
85
95
|
timeout: float = 20,
|
|
96
|
+
initial_connection_attempts: int = 3,
|
|
97
|
+
initial_connection_attempt_timeout: Optional[float] = None,
|
|
86
98
|
) -> None:
|
|
87
99
|
self.disable_webrtc = disable_webrtc
|
|
88
100
|
self.auth_entity = auth_entity
|
|
@@ -92,6 +104,8 @@ class DialOptions:
|
|
|
92
104
|
self.allow_insecure_with_creds_downgrade = allow_insecure_with_creds_downgrade
|
|
93
105
|
self.max_reconnect_attempts = max_reconnect_attempts
|
|
94
106
|
self.timeout = timeout
|
|
107
|
+
self.initial_connection_attempts = initial_connection_attempts
|
|
108
|
+
self.initial_connection_attempt_timeout = initial_connection_attempt_timeout if initial_connection_attempt_timeout else timeout
|
|
95
109
|
|
|
96
110
|
@classmethod
|
|
97
111
|
def with_api_key(cls, api_key: str, api_key_id: str) -> Self:
|
|
@@ -218,8 +232,9 @@ class _Runtime:
|
|
|
218
232
|
_ptr: ctypes.c_void_p
|
|
219
233
|
|
|
220
234
|
def __init__(self) -> None:
|
|
235
|
+
suffix = "dylib" if sys.platform == "darwin" else "so" if "linux" in sys.platform else "dll"
|
|
221
236
|
LOGGER.debug("Creating new viam-rust-utils runtime")
|
|
222
|
-
libname = pathlib.Path(__file__).parent.absolute() / f"libviam_rust_utils.{
|
|
237
|
+
libname = pathlib.Path(__file__).parent.absolute() / f"libviam_rust_utils.{suffix}"
|
|
223
238
|
self._lib = ctypes.CDLL(libname.__str__())
|
|
224
239
|
self._lib.init_rust_runtime.argtypes = ()
|
|
225
240
|
self._lib.init_rust_runtime.restype = ctypes.c_void_p
|
|
@@ -277,15 +292,50 @@ class _Runtime:
|
|
|
277
292
|
|
|
278
293
|
|
|
279
294
|
async def dial(address: str, options: Optional[DialOptions] = None) -> ViamChannel:
|
|
295
|
+
options = options if options else DialOptions()
|
|
296
|
+
timeout = options.timeout
|
|
297
|
+
options.timeout = options.initial_connection_attempt_timeout
|
|
298
|
+
if options.initial_connection_attempts == 0:
|
|
299
|
+
options.initial_connection_attempts = -1
|
|
300
|
+
attempt_countdown = options.initial_connection_attempts
|
|
301
|
+
exception: Exception
|
|
302
|
+
while attempt_countdown != 0:
|
|
303
|
+
try:
|
|
304
|
+
chan = await _dial_inner(address, options)
|
|
305
|
+
options.timeout = timeout
|
|
306
|
+
return chan
|
|
307
|
+
except Exception as e:
|
|
308
|
+
exception = e
|
|
309
|
+
attempt_countdown -= 1
|
|
310
|
+
# the only way we could get here is if we failed at least once which means we've set the
|
|
311
|
+
# exception, so typechecker concerns about a possibly unbounded variable are unfounded
|
|
312
|
+
raise exception # type: ignore
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def _create_chan(path: str) -> Channel:
|
|
316
|
+
if sys.platform == "win32" or sys.platform == "cygwin":
|
|
317
|
+
# we have to use a TCP connection, so we want a host and port for our channel.
|
|
318
|
+
host, port = _host_port_from_url(path)
|
|
319
|
+
return Channel(host=host, port=port, ssl=None)
|
|
320
|
+
# we're not on windows and so can use a UDS
|
|
321
|
+
return Channel(path=path, ssl=None)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
async def _dial_inner(address: str, options: Optional[DialOptions] = None) -> ViamChannel:
|
|
325
|
+
async def send_request(event: SendRequest):
|
|
326
|
+
event.metadata["viam-client"] = f"python;v{SDK_VERSION};v{API_VERSION}"
|
|
327
|
+
|
|
280
328
|
opts = options if options else DialOptions()
|
|
281
329
|
if opts.disable_webrtc:
|
|
282
330
|
channel = await _dial_direct(address, options)
|
|
331
|
+
listen(channel, SendRequest, send_request)
|
|
283
332
|
return ViamChannel(channel, lambda: None)
|
|
284
333
|
runtime = _Runtime()
|
|
285
334
|
path, path_ptr = await runtime.dial(address, opts)
|
|
286
335
|
if path:
|
|
287
336
|
LOGGER.info(f"Connecting to socket: {path}")
|
|
288
|
-
chan =
|
|
337
|
+
chan = _create_chan(path)
|
|
338
|
+
listen(chan, SendRequest, send_request)
|
|
289
339
|
|
|
290
340
|
def release():
|
|
291
341
|
runtime.free_str(path_ptr)
|
viam/rpc/libviam_rust_utils.so
CHANGED
|
Binary file
|
viam/rpc/server.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import sys
|
|
1
2
|
from typing import TYPE_CHECKING, Callable, List, Optional
|
|
2
3
|
|
|
3
4
|
from grpclib import GRPCError, Status
|
|
@@ -41,7 +42,7 @@ class Server(ResourceManager):
|
|
|
41
42
|
super().__init__(resources)
|
|
42
43
|
|
|
43
44
|
services = [SignalingService(), RobotService(manager=self)]
|
|
44
|
-
for registration in Registry.
|
|
45
|
+
for registration in Registry.REGISTERED_APIS().values():
|
|
45
46
|
if issubclass(registration.rpc_service, ResourceRPCServiceBase):
|
|
46
47
|
services.append(registration.rpc_service(manager=self))
|
|
47
48
|
else:
|
|
@@ -82,6 +83,24 @@ class Server(ResourceManager):
|
|
|
82
83
|
|
|
83
84
|
event.method_func = log_resource_name
|
|
84
85
|
|
|
86
|
+
async def _serve(
|
|
87
|
+
self,
|
|
88
|
+
host: Optional[str] = "localhost",
|
|
89
|
+
port: Optional[int] = 9090,
|
|
90
|
+
log_level: Optional[int] = logging.INFO,
|
|
91
|
+
*,
|
|
92
|
+
path: Optional[str] = None,
|
|
93
|
+
):
|
|
94
|
+
if path:
|
|
95
|
+
await self._server.start(path=path)
|
|
96
|
+
LOGGER.info(f"Serving on {path}")
|
|
97
|
+
else:
|
|
98
|
+
await self._server.start(host, port)
|
|
99
|
+
LOGGER.info(f"Serving on {host}:{port}")
|
|
100
|
+
await self._server.wait_closed()
|
|
101
|
+
await self.close()
|
|
102
|
+
LOGGER.debug("gRPC server closed")
|
|
103
|
+
|
|
85
104
|
async def serve(
|
|
86
105
|
self,
|
|
87
106
|
host: Optional[str] = "localhost",
|
|
@@ -105,16 +124,11 @@ class Server(ResourceManager):
|
|
|
105
124
|
logging.setLevel(log_level)
|
|
106
125
|
listen(self._server, RecvRequest, self._grpc_recvrequest_handler)
|
|
107
126
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
await self.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
await self._server.start(host, port)
|
|
114
|
-
LOGGER.info(f"Serving on {host}:{port}")
|
|
115
|
-
await self._server.wait_closed()
|
|
116
|
-
await self.close()
|
|
117
|
-
LOGGER.debug("gRPC server closed")
|
|
127
|
+
if sys.platform != "win32":
|
|
128
|
+
with graceful_exit([self._server]):
|
|
129
|
+
await self._serve(host=host, port=port, log_level=log_level, path=path)
|
|
130
|
+
else:
|
|
131
|
+
await self._serve(host=host, port=port, log_level=log_level, path=path)
|
|
118
132
|
|
|
119
133
|
@classmethod
|
|
120
134
|
async def create_and_serve(
|
viam/rpc/types.py
CHANGED
|
@@ -14,11 +14,9 @@ class RPCServiceBase(IServable):
|
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
@abstractmethod
|
|
17
|
-
def __mapping__(self) -> Mapping[str, grpclib.const.Handler]:
|
|
18
|
-
...
|
|
17
|
+
def __mapping__(self) -> Mapping[str, grpclib.const.Handler]: ...
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
@runtime_checkable
|
|
22
21
|
class RPCServiceStubBase(Protocol):
|
|
23
|
-
def __init__(self, channel: Channel) -> None:
|
|
24
|
-
...
|
|
22
|
+
def __init__(self, channel: Channel) -> None: ...
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from viam.resource.registry import Registry, ResourceRegistration
|
|
2
|
+
from viam.services.discovery.service import DiscoveryRPCService
|
|
3
|
+
|
|
4
|
+
from .client import DiscoveryClient
|
|
5
|
+
from .discovery import Discovery
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"DiscoveryClient",
|
|
9
|
+
"Discovery",
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
Registry.register_api(ResourceRegistration(Discovery, DiscoveryRPCService, lambda name, channel: DiscoveryClient(name, channel)))
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from typing import Any, List, Mapping, Optional
|
|
2
|
+
|
|
3
|
+
from grpclib.client import Channel
|
|
4
|
+
|
|
5
|
+
from viam.proto.app.robot import ComponentConfig
|
|
6
|
+
from viam.proto.common import DoCommandRequest, DoCommandResponse
|
|
7
|
+
from viam.proto.service.discovery import (
|
|
8
|
+
DiscoverResourcesRequest,
|
|
9
|
+
DiscoverResourcesResponse,
|
|
10
|
+
DiscoveryServiceStub,
|
|
11
|
+
)
|
|
12
|
+
from viam.resource.rpc_client_base import ReconfigurableResourceRPCClientBase
|
|
13
|
+
from viam.utils import ValueTypes, dict_to_struct, struct_to_dict
|
|
14
|
+
|
|
15
|
+
from .discovery import Discovery
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class DiscoveryClient(Discovery, ReconfigurableResourceRPCClientBase):
|
|
19
|
+
"""
|
|
20
|
+
Connect to the Discovery service, which allows you to discover resources on a machine.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
client: DiscoveryServiceStub
|
|
24
|
+
|
|
25
|
+
def __init__(self, name: str, channel: Channel):
|
|
26
|
+
super().__init__(name)
|
|
27
|
+
self.channel = channel
|
|
28
|
+
self.client = DiscoveryServiceStub(channel)
|
|
29
|
+
|
|
30
|
+
async def discover_resources(
|
|
31
|
+
self,
|
|
32
|
+
*,
|
|
33
|
+
extra: Optional[Mapping[str, Any]] = None,
|
|
34
|
+
timeout: Optional[float] = None,
|
|
35
|
+
**kwargs,
|
|
36
|
+
) -> List[ComponentConfig]:
|
|
37
|
+
md = kwargs.get("metadata", self.Metadata()).proto
|
|
38
|
+
request = DiscoverResourcesRequest(
|
|
39
|
+
name=self.name,
|
|
40
|
+
extra=dict_to_struct(extra),
|
|
41
|
+
)
|
|
42
|
+
response: DiscoverResourcesResponse = await self.client.DiscoverResources(request, timeout=timeout, metadata=md)
|
|
43
|
+
return list(response.discoveries)
|
|
44
|
+
|
|
45
|
+
async def do_command(
|
|
46
|
+
self,
|
|
47
|
+
command: Mapping[str, ValueTypes],
|
|
48
|
+
*,
|
|
49
|
+
timeout: Optional[float] = None,
|
|
50
|
+
**kwargs,
|
|
51
|
+
) -> Mapping[str, ValueTypes]:
|
|
52
|
+
md = kwargs.get("metadata", self.Metadata()).proto
|
|
53
|
+
request = DoCommandRequest(name=self.name, command=dict_to_struct(command))
|
|
54
|
+
response: DoCommandResponse = await self.client.DoCommand(request, timeout=timeout, metadata=md)
|
|
55
|
+
return struct_to_dict(response.result)
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import abc
|
|
2
|
+
from typing import Final, List, Mapping, Optional
|
|
3
|
+
|
|
4
|
+
from viam.proto.app.robot import ComponentConfig
|
|
5
|
+
from viam.resource.types import API, RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_SERVICE
|
|
6
|
+
from viam.utils import ValueTypes
|
|
7
|
+
|
|
8
|
+
from ..service_base import ServiceBase
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Discovery(ServiceBase):
|
|
12
|
+
"""
|
|
13
|
+
Discovery represents a Discovery service.
|
|
14
|
+
|
|
15
|
+
This acts as an abstract base class for any drivers representing specific
|
|
16
|
+
discovery implementations. This cannot be used on its own. If the ``__init__()`` function is
|
|
17
|
+
overridden, it must call the ``super().__init__()`` function.
|
|
18
|
+
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
API: Final = API( # pyright: ignore [reportIncompatibleVariableOverride]
|
|
22
|
+
RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_SERVICE, "discovery"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
@abc.abstractmethod
|
|
26
|
+
async def discover_resources(
|
|
27
|
+
self,
|
|
28
|
+
*,
|
|
29
|
+
extra: Optional[Mapping[str, ValueTypes]] = None,
|
|
30
|
+
timeout: Optional[float] = None,
|
|
31
|
+
) -> List[ComponentConfig]:
|
|
32
|
+
"""Get all component configs of discovered resources on a machine
|
|
33
|
+
|
|
34
|
+
::
|
|
35
|
+
|
|
36
|
+
my_discovery = DiscoveryClient.from_robot(machine, "my_discovery")
|
|
37
|
+
|
|
38
|
+
# Get the discovered resources
|
|
39
|
+
result = await my_discovery.discover_resources(
|
|
40
|
+
"my_discovery",
|
|
41
|
+
)
|
|
42
|
+
discoveries = result.discoveries
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
name (str): The name of the discover service
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
List[ComponentConfig]: A list of ComponentConfigs that describe
|
|
49
|
+
the components found by a discover service
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
...
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
from grpclib.server import Stream
|
|
2
|
+
|
|
3
|
+
from viam.proto.common import DoCommandRequest, DoCommandResponse
|
|
4
|
+
from viam.proto.service.discovery import (
|
|
5
|
+
DiscoverResourcesRequest,
|
|
6
|
+
DiscoverResourcesResponse,
|
|
7
|
+
UnimplementedDiscoveryServiceBase,
|
|
8
|
+
)
|
|
9
|
+
from viam.resource.rpc_service_base import ResourceRPCServiceBase
|
|
10
|
+
from viam.utils import dict_to_struct, struct_to_dict
|
|
11
|
+
|
|
12
|
+
from .discovery import Discovery
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class DiscoveryRPCService(UnimplementedDiscoveryServiceBase, ResourceRPCServiceBase):
|
|
16
|
+
"""
|
|
17
|
+
gRPC service for a Discovery service
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
RESOURCE_TYPE = Discovery
|
|
21
|
+
|
|
22
|
+
async def DiscoverResources(self, stream: Stream[DiscoverResourcesRequest, DiscoverResourcesResponse]) -> None:
|
|
23
|
+
request = await stream.recv_message()
|
|
24
|
+
assert request is not None
|
|
25
|
+
discovery = self.get_resource(request.name)
|
|
26
|
+
extra = struct_to_dict(request.extra)
|
|
27
|
+
timeout = stream.deadline.time_remaining() if stream.deadline else None
|
|
28
|
+
result = await discovery.discover_resources(
|
|
29
|
+
extra=extra,
|
|
30
|
+
timeout=timeout,
|
|
31
|
+
)
|
|
32
|
+
response = DiscoverResourcesResponse(
|
|
33
|
+
discoveries=result,
|
|
34
|
+
)
|
|
35
|
+
await stream.send_message(response)
|
|
36
|
+
|
|
37
|
+
async def DoCommand(self, stream: Stream[DoCommandRequest, DoCommandResponse]) -> None:
|
|
38
|
+
request = await stream.recv_message()
|
|
39
|
+
assert request is not None
|
|
40
|
+
discovery = self.get_resource(request.name)
|
|
41
|
+
timeout = stream.deadline.time_remaining() if stream.deadline else None
|
|
42
|
+
result = await discovery.do_command(struct_to_dict(request.command), timeout=timeout)
|
|
43
|
+
await stream.send_message(DoCommandResponse(result=dict_to_struct(result)))
|
viam/services/generic/client.py
CHANGED
|
@@ -5,7 +5,7 @@ from grpclib.client import Channel
|
|
|
5
5
|
|
|
6
6
|
from viam.proto.common import DoCommandRequest, DoCommandResponse
|
|
7
7
|
from viam.proto.service.generic import GenericServiceStub
|
|
8
|
-
from viam.resource.rpc_client_base import ReconfigurableResourceRPCClientBase
|
|
8
|
+
from viam.resource.rpc_client_base import ReconfigurableResourceRPCClientBase, ResourceRPCClientBase
|
|
9
9
|
from viam.utils import ValueTypes, dict_to_struct, struct_to_dict
|
|
10
10
|
|
|
11
11
|
from .generic import Generic
|
|
@@ -17,6 +17,7 @@ class GenericClient(Generic, ReconfigurableResourceRPCClientBase):
|
|
|
17
17
|
"""
|
|
18
18
|
|
|
19
19
|
def __init__(self, name: str, channel: Channel):
|
|
20
|
+
self.channel = channel
|
|
20
21
|
self.client = GenericServiceStub(channel)
|
|
21
22
|
super().__init__(name)
|
|
22
23
|
|
|
@@ -25,11 +26,12 @@ class GenericClient(Generic, ReconfigurableResourceRPCClientBase):
|
|
|
25
26
|
command: Mapping[str, Any],
|
|
26
27
|
*,
|
|
27
28
|
timeout: Optional[float] = None,
|
|
28
|
-
**
|
|
29
|
+
**kwargs,
|
|
29
30
|
) -> Mapping[str, Any]:
|
|
31
|
+
md = kwargs.get("metadata", self.Metadata()).proto
|
|
30
32
|
request = DoCommandRequest(name=self.name, command=dict_to_struct(command))
|
|
31
33
|
try:
|
|
32
|
-
response: DoCommandResponse = await self.client.DoCommand(request, timeout=timeout)
|
|
34
|
+
response: DoCommandResponse = await self.client.DoCommand(request, timeout=timeout, metadata=md)
|
|
33
35
|
except GRPCError as e:
|
|
34
36
|
if e.status == Status.UNIMPLEMENTED:
|
|
35
37
|
raise NotImplementedError()
|
|
@@ -39,7 +41,7 @@ class GenericClient(Generic, ReconfigurableResourceRPCClientBase):
|
|
|
39
41
|
|
|
40
42
|
|
|
41
43
|
async def do_command(
|
|
42
|
-
channel: Channel, name: str, command: Mapping[str, ValueTypes], *, timeout: Optional[float] = None
|
|
44
|
+
channel: Channel, name: str, command: Mapping[str, ValueTypes], *, timeout: Optional[float] = None, **kwargs
|
|
43
45
|
) -> Mapping[str, ValueTypes]:
|
|
44
46
|
"""Convenience method to allow service clients to execute ``do_command`` functions
|
|
45
47
|
|
|
@@ -51,5 +53,6 @@ async def do_command(
|
|
|
51
53
|
Returns:
|
|
52
54
|
Dict[str, Any]: The result of the executed command
|
|
53
55
|
"""
|
|
56
|
+
md = kwargs.get("metadata", ResourceRPCClientBase.Metadata()).proto
|
|
54
57
|
client = GenericClient(name, channel)
|
|
55
|
-
return await client.do_command(command, timeout=timeout)
|
|
58
|
+
return await client.do_command(command, timeout=timeout, metadata=md)
|
viam/services/generic/generic.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from typing import Final
|
|
2
2
|
|
|
3
|
-
from viam.resource.types import RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_SERVICE
|
|
3
|
+
from viam.resource.types import API, RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_SERVICE
|
|
4
4
|
|
|
5
5
|
from ..service_base import ServiceBase
|
|
6
6
|
|
|
@@ -53,6 +53,6 @@ class Generic(ServiceBase):
|
|
|
53
53
|
service.val # 5
|
|
54
54
|
"""
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
API: Final = API( # pyright: ignore [reportIncompatibleVariableOverride]
|
|
57
57
|
RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_SERVICE, "generic"
|
|
58
58
|
)
|
|
@@ -21,4 +21,4 @@ from .service import MLModelRPCService
|
|
|
21
21
|
|
|
22
22
|
__all__ = ["File", "LabelType", "Metadata", "MLModel", "MLModelClient", "TensorInfo"]
|
|
23
23
|
|
|
24
|
-
Registry.
|
|
24
|
+
Registry.register_api(ResourceRegistration(MLModel, MLModelRPCService, lambda name, channel: MLModelClient(name, channel)))
|
viam/services/mlmodel/client.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
from typing import Dict, Optional
|
|
1
|
+
from typing import Dict, Mapping, Optional
|
|
2
2
|
|
|
3
3
|
from grpclib.client import Channel
|
|
4
4
|
from numpy.typing import NDArray
|
|
@@ -6,6 +6,7 @@ from numpy.typing import NDArray
|
|
|
6
6
|
from viam.proto.service.mlmodel import InferRequest, InferResponse, MetadataRequest, MetadataResponse, MLModelServiceStub
|
|
7
7
|
from viam.resource.rpc_client_base import ReconfigurableResourceRPCClientBase
|
|
8
8
|
from viam.services.mlmodel.utils import flat_tensors_to_ndarrays, ndarrays_to_flat_tensors
|
|
9
|
+
from viam.utils import ValueTypes, dict_to_struct
|
|
9
10
|
|
|
10
11
|
from .mlmodel import Metadata, MLModel
|
|
11
12
|
|
|
@@ -16,12 +17,21 @@ class MLModelClient(MLModel, ReconfigurableResourceRPCClientBase):
|
|
|
16
17
|
self.client = MLModelServiceStub(channel)
|
|
17
18
|
super().__init__(name)
|
|
18
19
|
|
|
19
|
-
async def infer(
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
async def infer(
|
|
21
|
+
self,
|
|
22
|
+
input_tensors: Dict[str, NDArray],
|
|
23
|
+
*,
|
|
24
|
+
extra: Optional[Mapping[str, ValueTypes]] = None,
|
|
25
|
+
timeout: Optional[float] = None,
|
|
26
|
+
**kwargs,
|
|
27
|
+
) -> Dict[str, NDArray]:
|
|
28
|
+
md = kwargs.get("metadata", self.Metadata()).proto
|
|
29
|
+
request = InferRequest(name=self.name, input_tensors=ndarrays_to_flat_tensors(input_tensors), extra=dict_to_struct(extra))
|
|
30
|
+
response: InferResponse = await self.client.Infer(request, timeout=timeout, metadata=md)
|
|
22
31
|
return flat_tensors_to_ndarrays(response.output_tensors)
|
|
23
32
|
|
|
24
|
-
async def metadata(self, *, timeout: Optional[float] = None) -> Metadata:
|
|
25
|
-
|
|
26
|
-
|
|
33
|
+
async def metadata(self, *, extra: Optional[Mapping[str, ValueTypes]] = None, timeout: Optional[float] = None, **kwargs) -> Metadata:
|
|
34
|
+
md = kwargs.get("metadata", self.Metadata()).proto
|
|
35
|
+
request = MetadataRequest(name=self.name, extra=dict_to_struct(extra))
|
|
36
|
+
response: MetadataResponse = await self.client.Metadata(request, timeout=timeout, metadata=md)
|
|
27
37
|
return response.metadata
|
viam/services/mlmodel/mlmodel.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import abc
|
|
2
|
-
from typing import Dict, Final, Optional
|
|
2
|
+
from typing import Dict, Final, Mapping, Optional
|
|
3
3
|
|
|
4
4
|
from numpy.typing import NDArray
|
|
5
5
|
|
|
6
6
|
from viam.proto.service.mlmodel import Metadata
|
|
7
|
-
from viam.resource.types import RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_SERVICE
|
|
7
|
+
from viam.resource.types import API, RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_SERVICE
|
|
8
|
+
from viam.utils import ValueTypes
|
|
8
9
|
|
|
9
10
|
from ..service_base import ServiceBase
|
|
10
11
|
|
|
@@ -17,25 +18,35 @@ class MLModel(ServiceBase):
|
|
|
17
18
|
arm implementations. This cannot be used on its own. If the ``__init__()`` function is
|
|
18
19
|
overridden, it must call the ``super().__init__()`` function.
|
|
19
20
|
|
|
20
|
-
For more information, see `ML model service <https://docs.viam.com/services/ml
|
|
21
|
+
For more information, see `ML model service <https://docs.viam.com/dev/reference/apis/services/ml/>`_.
|
|
21
22
|
"""
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
API: Final = API( # pyright: ignore [reportIncompatibleVariableOverride]
|
|
24
25
|
RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_SERVICE, "mlmodel"
|
|
25
26
|
)
|
|
26
27
|
|
|
27
28
|
@abc.abstractmethod
|
|
28
|
-
async def infer(
|
|
29
|
+
async def infer(
|
|
30
|
+
self,
|
|
31
|
+
input_tensors: Dict[str, NDArray],
|
|
32
|
+
*,
|
|
33
|
+
extra: Optional[Mapping[str, ValueTypes]] = None,
|
|
34
|
+
timeout: Optional[float] = None,
|
|
35
|
+
) -> Dict[str, NDArray]:
|
|
29
36
|
"""Take an already ordered input tensor as an array, make an inference on the model, and return an output tensor map.
|
|
30
37
|
|
|
31
38
|
::
|
|
32
39
|
|
|
33
40
|
import numpy as np
|
|
34
41
|
|
|
35
|
-
my_mlmodel = MLModelClient.from_robot(robot=
|
|
42
|
+
my_mlmodel = MLModelClient.from_robot(robot=machine, name="my_mlmodel_service")
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
44
|
+
image_data = np.zeros((1, 384, 384, 3), dtype=np.uint8)
|
|
45
|
+
|
|
46
|
+
# Create the input tensors dictionary
|
|
47
|
+
input_tensors = {
|
|
48
|
+
"image": image_data
|
|
49
|
+
}
|
|
39
50
|
|
|
40
51
|
output_tensors = await my_mlmodel.infer(input_tensors)
|
|
41
52
|
|
|
@@ -45,23 +56,23 @@ class MLModel(ServiceBase):
|
|
|
45
56
|
Returns:
|
|
46
57
|
Dict[str, NDArray]: A dictionary of output flat tensors as specified in the metadata
|
|
47
58
|
|
|
48
|
-
For more information, see `ML model service <https://docs.viam.com/services/ml
|
|
59
|
+
For more information, see `ML model service <https://docs.viam.com/dev/reference/apis/services/ml/#infer>`_.
|
|
49
60
|
"""
|
|
50
61
|
...
|
|
51
62
|
|
|
52
63
|
@abc.abstractmethod
|
|
53
|
-
async def metadata(self, *, timeout: Optional[float]) -> Metadata:
|
|
64
|
+
async def metadata(self, *, extra: Optional[Mapping[str, ValueTypes]] = None, timeout: Optional[float] = None) -> Metadata:
|
|
54
65
|
"""Get the metadata (such as name, type, expected tensor/array shape, inputs, and outputs) associated with the ML model.
|
|
55
66
|
|
|
56
67
|
::
|
|
57
68
|
|
|
58
|
-
my_mlmodel = MLModelClient.from_robot(robot=
|
|
69
|
+
my_mlmodel = MLModelClient.from_robot(robot=machine, name="my_mlmodel_service")
|
|
59
70
|
|
|
60
71
|
metadata = await my_mlmodel.metadata()
|
|
61
72
|
|
|
62
73
|
Returns:
|
|
63
74
|
Metadata: The metadata
|
|
64
75
|
|
|
65
|
-
For more information, see `ML model service <https://docs.viam.com/services/ml
|
|
76
|
+
For more information, see `ML model service <https://docs.viam.com/dev/reference/apis/services/ml/#metadata>`_.
|
|
66
77
|
"""
|
|
67
78
|
...
|