viam-sdk 0.3.0__py3-none-linux_armv6l.whl → 0.66.0__py3-none-linux_armv6l.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.
Potentially problematic release.
This version of viam-sdk might be problematic. Click here for more details.
- viam/__init__.py +29 -2
- viam/app/_logs.py +34 -0
- viam/app/app_client.py +2696 -0
- viam/app/billing_client.py +185 -0
- viam/app/data_client.py +2231 -0
- viam/app/ml_training_client.py +249 -0
- viam/app/provisioning_client.py +93 -0
- viam/app/viam_client.py +275 -0
- viam/components/arm/__init__.py +3 -26
- viam/components/arm/arm.py +123 -8
- viam/components/arm/client.py +37 -24
- viam/components/arm/service.py +35 -32
- 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_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 +6 -11
- viam/components/base/base.py +134 -8
- viam/components/base/client.py +51 -23
- viam/components/base/service.py +33 -30
- viam/components/board/__init__.py +3 -12
- viam/components/board/board.py +247 -91
- viam/components/board/client.py +149 -83
- viam/components/board/service.py +63 -33
- 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 +3 -3
- viam/components/camera/camera.py +62 -27
- viam/components/camera/client.py +59 -27
- viam/components/camera/service.py +42 -65
- viam/components/component_base.py +28 -5
- viam/components/encoder/__init__.py +1 -1
- viam/components/encoder/client.py +25 -14
- viam/components/encoder/encoder.py +48 -10
- viam/components/encoder/service.py +14 -18
- viam/components/gantry/__init__.py +1 -13
- viam/components/gantry/client.py +80 -25
- viam/components/gantry/gantry.py +123 -9
- viam/components/gantry/service.py +51 -29
- viam/components/generic/__init__.py +1 -1
- viam/components/generic/client.py +21 -8
- viam/components/generic/generic.py +10 -2
- viam/components/generic/service.py +12 -7
- viam/components/gripper/__init__.py +3 -13
- viam/components/gripper/client.py +69 -21
- viam/components/gripper/gripper.py +123 -3
- viam/components/gripper/service.py +44 -22
- viam/components/input/__init__.py +1 -14
- viam/components/input/client.py +55 -23
- viam/components/input/input.py +106 -3
- viam/components/input/service.py +16 -21
- viam/components/motor/__init__.py +1 -21
- viam/components/motor/client.py +56 -33
- viam/components/motor/motor.py +127 -4
- viam/components/motor/service.py +33 -44
- viam/components/movement_sensor/__init__.py +1 -1
- viam/components/movement_sensor/client.py +102 -45
- viam/components/movement_sensor/movement_sensor.py +130 -61
- viam/components/movement_sensor/service.py +38 -41
- viam/components/pose_tracker/__init__.py +1 -1
- viam/components/pose_tracker/client.py +18 -7
- viam/components/pose_tracker/pose_tracker.py +4 -2
- viam/components/pose_tracker/service.py +12 -10
- viam/components/power_sensor/__init__.py +17 -0
- viam/components/power_sensor/client.py +86 -0
- viam/components/power_sensor/power_sensor.py +104 -0
- viam/components/power_sensor/service.py +72 -0
- viam/components/sensor/__init__.py +2 -1
- viam/components/sensor/client.py +26 -10
- viam/components/sensor/sensor.py +22 -4
- viam/components/sensor/service.py +20 -11
- viam/components/servo/__init__.py +1 -13
- viam/components/servo/client.py +47 -21
- viam/components/servo/service.py +15 -22
- viam/components/servo/servo.py +61 -2
- 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 +98 -0
- viam/errors.py +10 -0
- viam/gen/app/agent/v1/agent_grpc.py +29 -0
- viam/gen/app/agent/v1/agent_pb2.py +47 -0
- viam/gen/app/agent/v1/agent_pb2.pyi +280 -0
- viam/gen/app/cloudslam/v1/__init__.py +0 -0
- viam/gen/app/cloudslam/v1/cloud_slam_grpc.py +70 -0
- viam/gen/app/cloudslam/v1/cloud_slam_pb2.py +54 -0
- viam/gen/app/cloudslam/v1/cloud_slam_pb2.pyi +384 -0
- viam/gen/app/data/v1/data_grpc.py +197 -8
- viam/gen/app/data/v1/data_pb2.py +238 -99
- viam/gen/app/data/v1/data_pb2.pyi +1222 -259
- viam/gen/app/datapipelines/__init__.py +0 -0
- viam/gen/app/datapipelines/v1/__init__.py +0 -0
- 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/__init__.py +0 -0
- viam/gen/app/dataset/v1/__init__.py +0 -0
- viam/gen/app/dataset/v1/dataset_grpc.py +68 -0
- viam/gen/app/dataset/v1/dataset_pb2.py +44 -0
- viam/gen/app/dataset/v1/dataset_pb2.pyi +214 -0
- viam/gen/app/datasync/v1/data_sync_grpc.py +21 -4
- viam/gen/app/datasync/v1/data_sync_pb2.py +62 -128
- viam/gen/app/datasync/v1/data_sync_pb2.pyi +156 -199
- 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 +51 -3
- viam/gen/app/mltraining/v1/ml_training_pb2.py +135 -58
- viam/gen/app/mltraining/v1/ml_training_pb2.pyi +328 -39
- viam/gen/app/packages/v1/packages_grpc.py +15 -1
- viam/gen/app/packages/v1/packages_pb2.py +44 -64
- viam/gen/app/packages/v1/packages_pb2.pyi +75 -85
- viam/gen/app/v1/app_grpc.py +644 -3
- viam/gen/app/v1/app_pb2.py +695 -295
- viam/gen/app/v1/app_pb2.pyi +4488 -635
- viam/gen/app/v1/billing_grpc.py +53 -11
- viam/gen/app/v1/billing_pb2.py +94 -39
- viam/gen/app/v1/billing_pb2.pyi +391 -191
- viam/gen/app/v1/end_user_grpc.py +59 -0
- viam/gen/app/v1/end_user_pb2.py +55 -0
- viam/gen/app/v1/end_user_pb2.pyi +181 -0
- viam/gen/app/v1/robot_grpc.py +16 -1
- viam/gen/app/v1/robot_pb2.py +122 -94
- viam/gen/app/v1/robot_pb2.pyi +463 -123
- viam/gen/common/v1/common_pb2.py +87 -58
- viam/gen/common/v1/common_pb2.pyi +456 -149
- viam/gen/component/arm/v1/arm_grpc.py +58 -2
- viam/gen/component/arm/v1/arm_pb2.py +68 -51
- viam/gen/component/arm/v1/arm_pb2.pyi +108 -42
- 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_grpc.py +25 -2
- viam/gen/component/audioinput/v1/audioinput_pb2.py +36 -31
- viam/gen/component/audioinput/v1/audioinput_pb2.pyi +22 -22
- 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_grpc.py +42 -2
- viam/gen/component/base/v1/base_pb2.py +58 -47
- viam/gen/component/base/v1/base_pb2.pyi +65 -30
- viam/gen/component/board/v1/board_grpc.py +59 -7
- viam/gen/component/board/v1/board_pb2.py +94 -73
- viam/gen/component/board/v1/board_pb2.pyi +165 -68
- 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_grpc.py +38 -2
- viam/gen/component/camera/v1/camera_pb2.py +60 -43
- viam/gen/component/camera/v1/camera_pb2.pyi +191 -37
- viam/gen/component/encoder/v1/encoder_grpc.py +25 -2
- viam/gen/component/encoder/v1/encoder_pb2.py +36 -31
- viam/gen/component/encoder/v1/encoder_pb2.pyi +15 -15
- viam/gen/component/gantry/v1/gantry_grpc.py +47 -2
- viam/gen/component/gantry/v1/gantry_pb2.py +56 -43
- viam/gen/component/gantry/v1/gantry_pb2.pyi +67 -31
- viam/gen/component/generic/v1/generic_grpc.py +16 -2
- viam/gen/component/generic/v1/generic_pb2.py +16 -11
- viam/gen/component/gripper/v1/gripper_grpc.py +44 -2
- viam/gen/component/gripper/v1/gripper_pb2.py +48 -35
- viam/gen/component/gripper/v1/gripper_pb2.pyi +62 -24
- viam/gen/component/inputcontroller/v1/input_controller_grpc.py +28 -2
- viam/gen/component/inputcontroller/v1/input_controller_pb2.py +46 -41
- viam/gen/component/inputcontroller/v1/input_controller_pb2.pyi +32 -36
- viam/gen/component/motor/v1/motor_grpc.py +51 -2
- viam/gen/component/motor/v1/motor_pb2.py +78 -67
- viam/gen/component/motor/v1/motor_pb2.pyi +75 -46
- viam/gen/component/movementsensor/v1/movementsensor_grpc.py +48 -2
- viam/gen/component/movementsensor/v1/movementsensor_pb2.py +70 -63
- viam/gen/component/movementsensor/v1/movementsensor_pb2.pyi +84 -57
- viam/gen/component/posetracker/v1/pose_tracker_grpc.py +19 -2
- viam/gen/component/posetracker/v1/pose_tracker_pb2.py +26 -21
- viam/gen/component/posetracker/v1/pose_tracker_pb2.pyi +9 -13
- viam/gen/component/powersensor/__init__.py +0 -0
- viam/gen/component/powersensor/v1/__init__.py +0 -0
- viam/gen/component/powersensor/v1/powersensor_grpc.py +62 -0
- viam/gen/component/powersensor/v1/powersensor_pb2.py +42 -0
- viam/gen/component/powersensor/v1/powersensor_pb2.pyi +124 -0
- viam/gen/component/sensor/v1/sensor_grpc.py +21 -5
- viam/gen/component/sensor/v1/sensor_pb2.py +18 -22
- viam/gen/component/sensor/v1/sensor_pb2.pyi +1 -69
- viam/gen/component/servo/v1/servo_grpc.py +28 -2
- viam/gen/component/servo/v1/servo_pb2.py +42 -37
- viam/gen/component/servo/v1/servo_pb2.pyi +22 -26
- 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_grpc.py +15 -0
- viam/gen/component/testecho/v1/testecho_pb2.py +29 -26
- viam/gen/component/testecho/v1/testecho_pb2.pyi +16 -20
- viam/gen/module/v1/module_grpc.py +18 -0
- viam/gen/module/v1/module_pb2.py +36 -33
- viam/gen/module/v1/module_pb2.pyi +39 -34
- viam/gen/opentelemetry/__init__.py +0 -0
- viam/gen/opentelemetry/proto/__init__.py +0 -0
- viam/gen/opentelemetry/proto/common/__init__.py +0 -0
- viam/gen/opentelemetry/proto/common/v1/__init__.py +0 -0
- viam/gen/opentelemetry/proto/common/v1/common_grpc.py +0 -0
- viam/gen/opentelemetry/proto/common/v1/common_pb2.py +27 -0
- viam/gen/opentelemetry/proto/common/v1/common_pb2.pyi +208 -0
- viam/gen/opentelemetry/proto/resource/__init__.py +0 -0
- viam/gen/opentelemetry/proto/resource/v1/__init__.py +0 -0
- viam/gen/opentelemetry/proto/resource/v1/resource_grpc.py +0 -0
- viam/gen/opentelemetry/proto/resource/v1/resource_pb2.py +18 -0
- viam/gen/opentelemetry/proto/resource/v1/resource_pb2.pyi +59 -0
- viam/gen/opentelemetry/proto/trace/__init__.py +0 -0
- viam/gen/opentelemetry/proto/trace/v1/__init__.py +0 -0
- viam/gen/opentelemetry/proto/trace/v1/trace_grpc.py +0 -0
- viam/gen/opentelemetry/proto/trace/v1/trace_pb2.py +37 -0
- viam/gen/opentelemetry/proto/trace/v1/trace_pb2.pyi +402 -0
- viam/gen/proto/rpc/examples/echo/v1/echo_grpc.py +12 -0
- viam/gen/proto/rpc/examples/echo/v1/echo_pb2.py +25 -22
- viam/gen/proto/rpc/examples/echo/v1/echo_pb2.pyi +13 -17
- viam/gen/proto/rpc/examples/echoresource/v1/echoresource_grpc.py +12 -0
- viam/gen/proto/rpc/examples/echoresource/v1/echoresource_pb2.py +23 -20
- viam/gen/proto/rpc/examples/echoresource/v1/echoresource_pb2.pyi +13 -17
- viam/gen/proto/rpc/v1/auth_grpc.py +11 -0
- viam/gen/proto/rpc/v1/auth_pb2.py +27 -24
- viam/gen/proto/rpc/v1/auth_pb2.pyi +12 -16
- viam/gen/proto/rpc/webrtc/v1/grpc_pb2.py +35 -32
- viam/gen/proto/rpc/webrtc/v1/grpc_pb2.pyi +37 -41
- viam/gen/proto/rpc/webrtc/v1/signaling_grpc.py +15 -0
- viam/gen/proto/rpc/webrtc/v1/signaling_pb2.py +62 -57
- viam/gen/proto/rpc/webrtc/v1/signaling_pb2.pyi +78 -69
- viam/gen/provisioning/__init__.py +0 -0
- viam/gen/provisioning/v1/__init__.py +0 -0
- viam/gen/provisioning/v1/provisioning_grpc.py +59 -0
- viam/gen/provisioning/v1/provisioning_pb2.py +45 -0
- viam/gen/provisioning/v1/provisioning_pb2.pyi +229 -0
- viam/gen/robot/v1/robot_grpc.py +144 -15
- viam/gen/robot/v1/robot_pb2.py +193 -119
- viam/gen/robot/v1/robot_pb2.pyi +565 -137
- viam/gen/service/datamanager/v1/data_manager_grpc.py +20 -2
- viam/gen/service/datamanager/v1/data_manager_pb2.py +27 -17
- viam/gen/service/datamanager/v1/data_manager_pb2.pyi +52 -10
- 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/__init__.py +0 -0
- viam/gen/service/generic/v1/__init__.py +0 -0
- viam/gen/service/generic/v1/generic_grpc.py +29 -0
- viam/gen/service/generic/v1/generic_pb2.py +21 -0
- viam/gen/service/generic/v1/generic_pb2.pyi +6 -0
- viam/gen/service/mlmodel/v1/mlmodel_grpc.py +9 -0
- viam/gen/service/mlmodel/v1/mlmodel_pb2.py +76 -29
- viam/gen/service/mlmodel/v1/mlmodel_pb2.pyi +307 -28
- viam/gen/service/motion/v1/motion_grpc.py +42 -4
- viam/gen/service/motion/v1/motion_pb2.py +119 -51
- viam/gen/service/motion/v1/motion_pb2.pyi +595 -120
- viam/gen/service/navigation/v1/navigation_grpc.py +49 -1
- viam/gen/service/navigation/v1/navigation_pb2.py +76 -51
- viam/gen/service/navigation/v1/navigation_pb2.pyi +188 -33
- viam/gen/service/sensors/v1/sensors_grpc.py +12 -0
- viam/gen/service/sensors/v1/sensors_pb2.py +60 -29
- viam/gen/service/sensors/v1/sensors_pb2.pyi +18 -21
- viam/gen/service/shell/v1/shell_grpc.py +27 -1
- viam/gen/service/shell/v1/shell_pb2.py +37 -15
- viam/gen/service/shell/v1/shell_pb2.pyi +260 -7
- viam/gen/service/slam/v1/slam_grpc.py +24 -2
- viam/gen/service/slam/v1/slam_pb2.py +44 -30
- viam/gen/service/slam/v1/slam_pb2.pyi +128 -27
- 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_grpc.py +39 -1
- viam/gen/service/vision/v1/vision_pb2.py +61 -45
- viam/gen/service/vision/v1/vision_pb2.pyi +180 -41
- 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/__init__.py +0 -0
- viam/gen/stream/v1/__init__.py +0 -0
- viam/gen/stream/v1/stream_grpc.py +59 -0
- viam/gen/stream/v1/stream_pb2.py +39 -0
- viam/gen/stream/v1/stream_pb2.pyi +161 -0
- viam/gen/tagger/v1/tagger_pb2.py +9 -8
- viam/logging.py +160 -17
- viam/media/__init__.py +0 -9
- viam/media/audio.py +22 -10
- viam/media/utils/__init__.py +0 -0
- viam/media/utils/pil/__init__.py +55 -0
- viam/media/{viam_rgba_plugin.py → utils/pil/viam_rgba_plugin.py} +10 -16
- viam/media/viam_rgba.py +10 -0
- viam/media/video.py +197 -73
- viam/module/module.py +191 -44
- viam/module/resource_data_consumer.py +41 -0
- viam/module/service.py +9 -1
- viam/module/types.py +4 -5
- viam/operations.py +4 -3
- viam/proto/app/__init__.py +361 -5
- viam/proto/app/agent/__init__.py +28 -0
- viam/proto/app/billing.py +51 -27
- viam/proto/app/cloudslam/__init__.py +48 -0
- viam/proto/app/data/__init__.py +103 -17
- viam/proto/app/datapipelines/__init__.py +56 -0
- viam/proto/app/dataset/__init__.py +40 -0
- viam/proto/app/datasync/__init__.py +11 -5
- viam/proto/app/end_user.py +34 -0
- viam/proto/app/mlinference/__init__.py +15 -0
- viam/proto/app/mltraining/__init__.py +25 -1
- viam/proto/app/packages/__init__.py +3 -3
- viam/proto/app/robot.py +19 -1
- viam/proto/common/__init__.py +35 -8
- viam/proto/component/arm/__init__.py +9 -1
- viam/proto/component/audioin/__init__.py +16 -0
- viam/proto/component/audioinput/__init__.py +3 -1
- viam/proto/component/audioout/__init__.py +15 -0
- viam/proto/component/base/__init__.py +7 -1
- viam/proto/component/board/__init__.py +13 -5
- viam/proto/component/button/__init__.py +15 -0
- viam/proto/component/camera/__init__.py +9 -1
- viam/proto/component/encoder/__init__.py +3 -1
- viam/proto/component/gantry/__init__.py +7 -1
- viam/proto/component/generic/__init__.py +3 -1
- viam/proto/component/gripper/__init__.py +7 -1
- viam/proto/component/inputcontroller/__init__.py +7 -1
- viam/proto/component/motor/__init__.py +7 -1
- viam/proto/component/movementsensor/__init__.py +7 -1
- viam/proto/component/posetracker/__init__.py +7 -1
- viam/proto/component/powersensor/__init__.py +30 -0
- viam/proto/component/sensor/__init__.py +3 -4
- viam/proto/component/servo/__init__.py +3 -1
- viam/proto/component/switch/__init__.py +26 -0
- viam/proto/component/testecho/__init__.py +3 -1
- viam/proto/module/__init__.py +3 -1
- viam/proto/opentelemetry/__init__.py +0 -0
- viam/proto/opentelemetry/proto/__init__.py +0 -0
- viam/proto/opentelemetry/proto/common/__init__.py +15 -0
- viam/proto/opentelemetry/proto/resource/__init__.py +10 -0
- viam/proto/opentelemetry/proto/trace/__init__.py +15 -0
- viam/proto/provisioning/__init__.py +42 -0
- viam/proto/robot/__init__.py +57 -9
- viam/proto/rpc/auth.py +11 -1
- viam/proto/rpc/examples/echo/__init__.py +3 -1
- viam/proto/rpc/examples/echoresource/__init__.py +7 -1
- viam/proto/rpc/webrtc/grpc.py +3 -1
- viam/proto/rpc/webrtc/signaling.py +5 -1
- viam/proto/service/datamanager/__init__.py +15 -2
- viam/proto/service/discovery/__init__.py +15 -0
- viam/proto/service/generic/__init__.py +12 -0
- viam/proto/service/mlmodel/__init__.py +27 -1
- viam/proto/service/motion/__init__.py +35 -5
- viam/proto/service/navigation/__init__.py +19 -1
- viam/proto/service/sensors/__init__.py +3 -1
- viam/proto/service/shell/__init__.py +25 -2
- viam/proto/service/slam/__init__.py +13 -1
- viam/proto/service/video/__init__.py +15 -0
- viam/proto/service/vision/__init__.py +11 -1
- viam/proto/service/worldstatestore/__init__.py +32 -0
- viam/proto/stream/__init__.py +36 -0
- viam/py.typed +0 -0
- viam/resource/base.py +45 -8
- viam/resource/easy_resource.py +149 -0
- viam/resource/manager.py +35 -14
- viam/resource/registry.py +40 -52
- viam/resource/rpc_client_base.py +33 -1
- viam/resource/rpc_service_base.py +15 -8
- viam/resource/types.py +39 -26
- viam/robot/client.py +458 -91
- viam/robot/service.py +13 -107
- viam/rpc/dial.py +133 -15
- viam/rpc/libviam_rust_utils.so +0 -0
- viam/rpc/server.py +59 -15
- 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 +18 -0
- viam/services/generic/client.py +58 -0
- viam/services/generic/generic.py +58 -0
- viam/services/generic/service.py +29 -0
- viam/services/mlmodel/__init__.py +15 -1
- viam/services/mlmodel/client.py +20 -15
- viam/services/mlmodel/mlmodel.py +44 -7
- viam/services/mlmodel/service.py +9 -13
- viam/services/mlmodel/utils.py +101 -0
- viam/services/motion/__init__.py +15 -3
- viam/services/motion/client.py +109 -150
- viam/services/motion/motion.py +380 -0
- viam/services/motion/service.py +132 -0
- viam/services/navigation/__init__.py +11 -0
- viam/services/navigation/client.py +99 -0
- viam/services/navigation/navigation.py +250 -0
- viam/services/navigation/service.py +137 -0
- viam/services/service_base.py +43 -4
- viam/services/service_client_base.py +4 -4
- viam/services/slam/__init__.py +4 -1
- viam/services/slam/client.py +21 -11
- viam/services/slam/service.py +16 -19
- viam/services/slam/slam.py +66 -5
- viam/services/vision/__init__.py +8 -0
- viam/services/vision/client.py +115 -111
- viam/services/vision/service.py +143 -0
- viam/services/vision/vision.py +317 -0
- 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 +254 -0
- viam/streams.py +44 -0
- viam/utils.py +143 -15
- viam/version_metadata.py +4 -0
- viam_sdk-0.66.0.dist-info/METADATA +157 -0
- viam_sdk-0.66.0.dist-info/RECORD +531 -0
- {viam_sdk-0.3.0.dist-info → viam_sdk-0.66.0.dist-info}/WHEEL +1 -1
- viam/components/audio_input/__init__.py +0 -18
- viam/components/audio_input/audio_input.py +0 -79
- viam/components/audio_input/client.py +0 -60
- viam/components/audio_input/service.py +0 -118
- viam/components/types.py +0 -5
- viam/gen/app/model/v1/model_grpc.py +0 -39
- viam/gen/app/model/v1/model_pb2.py +0 -71
- viam/gen/app/model/v1/model_pb2.pyi +0 -285
- viam/gen/proto/rpc/examples/fileupload/v1/fileupload_grpc.py +0 -21
- viam/gen/proto/rpc/examples/fileupload/v1/fileupload_pb2.py +0 -18
- viam/gen/proto/rpc/examples/fileupload/v1/fileupload_pb2.pyi +0 -49
- viam/media/media.py +0 -53
- viam/proto/app/model/__init__.py +0 -40
- viam/proto/rpc/examples/fileupload/__init__.py +0 -13
- viam/services/sensors/__init__.py +0 -5
- viam/services/sensors/client.py +0 -63
- viam_sdk-0.3.0.dist-info/LICENSE +0 -202
- viam_sdk-0.3.0.dist-info/METADATA +0 -122
- viam_sdk-0.3.0.dist-info/RECORD +0 -372
- /viam/{gen/app/model → app}/__init__.py +0 -0
- /viam/gen/app/{model/v1 → agent}/__init__.py +0 -0
- /viam/gen/{proto/rpc/examples/fileupload → app/agent/v1}/__init__.py +0 -0
- /viam/gen/{proto/rpc/examples/fileupload/v1 → app/cloudslam}/__init__.py +0 -0
- /LICENSE → /viam_sdk-0.66.0.dist-info/licenses/LICENSE +0 -0
viam/robot/service.py
CHANGED
|
@@ -1,78 +1,37 @@
|
|
|
1
|
-
import
|
|
2
|
-
from typing import Any, Dict, Iterable, List
|
|
1
|
+
from typing import Any, Dict, List, Set
|
|
3
2
|
|
|
4
3
|
from grpclib.server import Stream
|
|
5
4
|
|
|
6
5
|
from viam import logging
|
|
7
|
-
from viam.
|
|
6
|
+
from viam.components.movement_sensor import MovementSensor
|
|
7
|
+
from viam.components.sensor import Sensor
|
|
8
|
+
from viam.errors import ViamGRPCError
|
|
8
9
|
from viam.proto.common import ResourceName
|
|
9
10
|
from viam.proto.robot import (
|
|
10
|
-
BlockForOperationRequest,
|
|
11
|
-
BlockForOperationResponse,
|
|
12
|
-
CancelOperationRequest,
|
|
13
|
-
CancelOperationResponse,
|
|
14
|
-
DiscoverComponentsRequest,
|
|
15
|
-
DiscoverComponentsResponse,
|
|
16
|
-
FrameSystemConfigRequest,
|
|
17
|
-
FrameSystemConfigResponse,
|
|
18
|
-
GetOperationsRequest,
|
|
19
|
-
GetOperationsResponse,
|
|
20
|
-
GetSessionsRequest,
|
|
21
|
-
GetSessionsResponse,
|
|
22
|
-
GetStatusRequest,
|
|
23
|
-
GetStatusResponse,
|
|
24
11
|
ResourceNamesRequest,
|
|
25
12
|
ResourceNamesResponse,
|
|
26
|
-
ResourceRPCSubtypesRequest,
|
|
27
|
-
ResourceRPCSubtypesResponse,
|
|
28
|
-
RobotServiceBase,
|
|
29
|
-
SendSessionHeartbeatRequest,
|
|
30
|
-
SendSessionHeartbeatResponse,
|
|
31
|
-
StartSessionRequest,
|
|
32
|
-
StartSessionResponse,
|
|
33
|
-
Status,
|
|
34
13
|
StopAllRequest,
|
|
35
14
|
StopAllResponse,
|
|
36
|
-
|
|
37
|
-
StreamStatusResponse,
|
|
38
|
-
TransformPCDRequest,
|
|
39
|
-
TransformPCDResponse,
|
|
40
|
-
TransformPoseRequest,
|
|
41
|
-
TransformPoseResponse,
|
|
15
|
+
UnimplementedRobotServiceBase,
|
|
42
16
|
)
|
|
43
|
-
from viam.resource.registry import Registry
|
|
44
17
|
from viam.resource.rpc_service_base import ResourceRPCServiceBase
|
|
45
18
|
from viam.utils import resource_names_for_resource, struct_to_dict
|
|
46
19
|
|
|
47
20
|
LOGGER = logging.getLogger(__name__)
|
|
48
21
|
|
|
49
22
|
|
|
50
|
-
class RobotService(
|
|
23
|
+
class RobotService(UnimplementedRobotServiceBase, ResourceRPCServiceBase):
|
|
51
24
|
def _generate_metadata(self) -> List[ResourceName]:
|
|
52
|
-
md:
|
|
25
|
+
md: Set[ResourceName] = set()
|
|
53
26
|
|
|
54
|
-
for
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
async def _generate_status(self, resource_names: Iterable[ResourceName]) -> List[Status]:
|
|
60
|
-
statuses: List[Status] = []
|
|
27
|
+
for resource in self.manager.resources.values():
|
|
28
|
+
# If the resource is a MovementSensor, DO NOT include Sensor as well (it will get added via MovementSensor)
|
|
29
|
+
if resource.API == Sensor.API and MovementSensor.get_resource_name(resource.name) in self.manager.resources:
|
|
30
|
+
continue
|
|
61
31
|
|
|
62
|
-
|
|
63
|
-
for registration in Registry.REGISTERED_SUBTYPES().values():
|
|
64
|
-
if isinstance(component, registration.resource_type):
|
|
65
|
-
if resource_names and component.get_resource_name(component.name) not in resource_names:
|
|
66
|
-
continue
|
|
67
|
-
try:
|
|
68
|
-
status = await registration.create_status(component)
|
|
69
|
-
statuses.append(status)
|
|
70
|
-
except ViamGRPCError as e:
|
|
71
|
-
raise e.grpc_error
|
|
32
|
+
md.update(resource_names_for_resource(resource))
|
|
72
33
|
|
|
73
|
-
|
|
74
|
-
statuses = [s for s in statuses if s.name in resource_names]
|
|
75
|
-
return statuses
|
|
34
|
+
return list(md)
|
|
76
35
|
|
|
77
36
|
async def ResourceNames(self, stream: Stream[ResourceNamesRequest, ResourceNamesResponse]) -> None:
|
|
78
37
|
request = await stream.recv_message()
|
|
@@ -81,47 +40,6 @@ class RobotService(RobotServiceBase, ResourceRPCServiceBase):
|
|
|
81
40
|
response = ResourceNamesResponse(resources=metadata)
|
|
82
41
|
await stream.send_message(response)
|
|
83
42
|
|
|
84
|
-
async def GetStatus(self, stream: Stream[GetStatusRequest, GetStatusResponse]) -> None:
|
|
85
|
-
request = await stream.recv_message()
|
|
86
|
-
assert request is not None
|
|
87
|
-
status = await self._generate_status(request.resource_names)
|
|
88
|
-
response = GetStatusResponse(status=status)
|
|
89
|
-
await stream.send_message(response)
|
|
90
|
-
|
|
91
|
-
async def StreamStatus(self, stream: Stream[StreamStatusRequest, StreamStatusResponse]) -> None:
|
|
92
|
-
request = await stream.recv_message()
|
|
93
|
-
assert request is not None
|
|
94
|
-
interval = 1
|
|
95
|
-
every = request.every.ToSeconds()
|
|
96
|
-
if every > 0:
|
|
97
|
-
interval = every
|
|
98
|
-
while True:
|
|
99
|
-
status = await self._generate_status(request.resource_names)
|
|
100
|
-
response = StreamStatusResponse(status=status)
|
|
101
|
-
await stream.send_message(response)
|
|
102
|
-
await asyncio.sleep(interval)
|
|
103
|
-
|
|
104
|
-
async def GetOperations(self, stream: Stream[GetOperationsRequest, GetOperationsResponse]) -> None:
|
|
105
|
-
raise MethodNotImplementedError("GetOperations").grpc_error
|
|
106
|
-
|
|
107
|
-
async def ResourceRPCSubtypes(self, stream: Stream[ResourceRPCSubtypesRequest, ResourceRPCSubtypesResponse]) -> None:
|
|
108
|
-
raise MethodNotImplementedError("ResourceRPCSubtypes").grpc_error
|
|
109
|
-
|
|
110
|
-
async def CancelOperation(self, stream: Stream[CancelOperationRequest, CancelOperationResponse]) -> None:
|
|
111
|
-
raise MethodNotImplementedError("CancelOperation").grpc_error
|
|
112
|
-
|
|
113
|
-
async def BlockForOperation(self, stream: Stream[BlockForOperationRequest, BlockForOperationResponse]) -> None:
|
|
114
|
-
raise MethodNotImplementedError("BlockForOperation").grpc_error
|
|
115
|
-
|
|
116
|
-
async def FrameSystemConfig(self, stream: Stream[FrameSystemConfigRequest, FrameSystemConfigResponse]) -> None:
|
|
117
|
-
raise MethodNotImplementedError("FrameSystemConfig").grpc_error
|
|
118
|
-
|
|
119
|
-
async def TransformPose(self, stream: Stream[TransformPoseRequest, TransformPoseResponse]) -> None:
|
|
120
|
-
raise MethodNotImplementedError("TransformPose").grpc_error
|
|
121
|
-
|
|
122
|
-
async def DiscoverComponents(self, stream: Stream[DiscoverComponentsRequest, DiscoverComponentsResponse]) -> None:
|
|
123
|
-
raise MethodNotImplementedError("DiscoverComponents").grpc_error
|
|
124
|
-
|
|
125
43
|
async def StopAll(self, stream: Stream[StopAllRequest, StopAllResponse]) -> None:
|
|
126
44
|
request = await stream.recv_message()
|
|
127
45
|
assert request is not None
|
|
@@ -149,15 +67,3 @@ class RobotService(RobotServiceBase, ResourceRPCServiceBase):
|
|
|
149
67
|
if errors:
|
|
150
68
|
raise ViamGRPCError(f'Failed to stop components named {", ".join(errors)}')
|
|
151
69
|
await stream.send_message(StopAllResponse())
|
|
152
|
-
|
|
153
|
-
async def GetSessions(self, stream: Stream[GetSessionsRequest, GetSessionsResponse]) -> None:
|
|
154
|
-
raise MethodNotImplementedError("GetSessions").grpc_error
|
|
155
|
-
|
|
156
|
-
async def StartSession(self, stream: Stream[StartSessionRequest, StartSessionResponse]) -> None:
|
|
157
|
-
raise MethodNotImplementedError("StartSession").grpc_error
|
|
158
|
-
|
|
159
|
-
async def SendSessionHeartbeat(self, stream: Stream[SendSessionHeartbeatRequest, SendSessionHeartbeatResponse]) -> None:
|
|
160
|
-
raise MethodNotImplementedError("SendSessionHeartbeat").grpc_error
|
|
161
|
-
|
|
162
|
-
async def TransformPCD(self, stream: Stream[TransformPCDRequest, TransformPCDResponse]) -> None:
|
|
163
|
-
raise MethodNotImplementedError("TransformPCD").grpc_error
|
viam/rpc/dial.py
CHANGED
|
@@ -4,33 +4,34 @@ import re
|
|
|
4
4
|
import socket
|
|
5
5
|
import ssl
|
|
6
6
|
import sys
|
|
7
|
+
import uuid
|
|
7
8
|
import warnings
|
|
8
9
|
from dataclasses import dataclass
|
|
9
10
|
from typing import Callable, Literal, Optional, Tuple, Type, Union
|
|
10
11
|
|
|
11
12
|
from grpclib.client import Channel, Stream
|
|
12
13
|
from grpclib.const import Cardinality
|
|
14
|
+
from grpclib.events import SendRequest, listen
|
|
13
15
|
from grpclib.metadata import Deadline, _MetadataLike
|
|
14
16
|
from grpclib.protocol import H2Protocol
|
|
15
17
|
from grpclib.stream import _RecvType, _SendType
|
|
18
|
+
from typing_extensions import Self
|
|
16
19
|
|
|
17
20
|
from viam import logging
|
|
18
21
|
from viam.errors import InsecureConnectionError, ViamError
|
|
19
22
|
from viam.proto.rpc.auth import AuthenticateRequest, AuthServiceStub
|
|
20
23
|
from viam.proto.rpc.auth import Credentials as PBCredentials
|
|
21
24
|
from viam.utils import to_thread
|
|
25
|
+
from viam.version_metadata import API_VERSION, SDK_VERSION
|
|
22
26
|
|
|
23
27
|
LOGGER = logging.getLogger(__name__)
|
|
24
28
|
|
|
25
29
|
|
|
26
30
|
@dataclass
|
|
27
31
|
class Credentials:
|
|
28
|
-
"""Credentials to connect to the
|
|
32
|
+
"""Credentials to connect to the machine and app.viam.com."""
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
"""
|
|
32
|
-
|
|
33
|
-
type: Literal["robot-location-secret"]
|
|
34
|
+
type: Union[Literal["robot-secret"], Literal["api-key"]]
|
|
34
35
|
"""The type of credential
|
|
35
36
|
"""
|
|
36
37
|
|
|
@@ -66,14 +67,34 @@ class DialOptions:
|
|
|
66
67
|
if detected, even with credentials present. This is generally
|
|
67
68
|
unsafe to use, but can be requested."""
|
|
68
69
|
|
|
70
|
+
max_reconnect_attempts: int = 3
|
|
71
|
+
"""Max number of times the client attempts to reconnect when connection is lost"""
|
|
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
|
+
|
|
81
|
+
timeout: float = 20
|
|
82
|
+
"""Number of seconds before the dial connection times out
|
|
83
|
+
Set to 20sec to match _defaultOfferDeadline in goutils/rpc/wrtc_call_queue.go"""
|
|
84
|
+
|
|
69
85
|
def __init__(
|
|
70
86
|
self,
|
|
87
|
+
*,
|
|
71
88
|
disable_webrtc: bool = False,
|
|
72
89
|
auth_entity: Optional[str] = None,
|
|
73
90
|
credentials: Optional[Credentials] = None,
|
|
74
91
|
insecure: bool = False,
|
|
75
92
|
allow_insecure_downgrade: bool = False,
|
|
76
93
|
allow_insecure_with_creds_downgrade: bool = False,
|
|
94
|
+
max_reconnect_attempts: int = 3,
|
|
95
|
+
timeout: float = 20,
|
|
96
|
+
initial_connection_attempts: int = 3,
|
|
97
|
+
initial_connection_attempt_timeout: Optional[float] = None,
|
|
77
98
|
) -> None:
|
|
78
99
|
self.disable_webrtc = disable_webrtc
|
|
79
100
|
self.auth_entity = auth_entity
|
|
@@ -81,6 +102,32 @@ class DialOptions:
|
|
|
81
102
|
self.insecure = insecure
|
|
82
103
|
self.allow_insecure_downgrade = allow_insecure_downgrade
|
|
83
104
|
self.allow_insecure_with_creds_downgrade = allow_insecure_with_creds_downgrade
|
|
105
|
+
self.max_reconnect_attempts = max_reconnect_attempts
|
|
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
|
|
109
|
+
|
|
110
|
+
@classmethod
|
|
111
|
+
def with_api_key(cls, api_key: str, api_key_id: str) -> Self:
|
|
112
|
+
"""Create DialOptions with an API key for credentials and default values for other arguments.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
api_key (str): your API key
|
|
116
|
+
api_key_id (str): your API key ID. Must be a valid UUID
|
|
117
|
+
|
|
118
|
+
Raises:
|
|
119
|
+
ValueError: Raised if the api_key_id is not a valid UUID
|
|
120
|
+
|
|
121
|
+
Returns:
|
|
122
|
+
Self: the DialOptions
|
|
123
|
+
"""
|
|
124
|
+
try:
|
|
125
|
+
uuid.UUID(api_key_id)
|
|
126
|
+
except ValueError:
|
|
127
|
+
raise ValueError(f"{api_key_id} is not a valid UUID")
|
|
128
|
+
|
|
129
|
+
credentials = Credentials(type="api-key", payload=api_key)
|
|
130
|
+
return cls(credentials=credentials, auth_entity=api_key_id)
|
|
84
131
|
|
|
85
132
|
|
|
86
133
|
def _host_port_from_url(url) -> Tuple[Optional[str], Optional[int]]:
|
|
@@ -160,6 +207,12 @@ class ViamChannel:
|
|
|
160
207
|
if not self._closed:
|
|
161
208
|
try:
|
|
162
209
|
self.channel.close()
|
|
210
|
+
except RuntimeError as e:
|
|
211
|
+
# ignore event loop is closed errors - robot is getting shutdown
|
|
212
|
+
if len(e.args) > 0 and e.args[0] == "Event loop is closed":
|
|
213
|
+
LOGGER.debug("ViamChannel might not have shut down cleanly - Event loop was closed")
|
|
214
|
+
return
|
|
215
|
+
raise
|
|
163
216
|
finally:
|
|
164
217
|
self.release()
|
|
165
218
|
self._closed = True
|
|
@@ -179,13 +232,22 @@ class _Runtime:
|
|
|
179
232
|
_ptr: ctypes.c_void_p
|
|
180
233
|
|
|
181
234
|
def __init__(self) -> None:
|
|
235
|
+
suffix = "dylib" if sys.platform == "darwin" else "so" if "linux" in sys.platform else "dll"
|
|
182
236
|
LOGGER.debug("Creating new viam-rust-utils runtime")
|
|
183
|
-
libname = pathlib.Path(__file__).parent.absolute() / f"libviam_rust_utils.{
|
|
237
|
+
libname = pathlib.Path(__file__).parent.absolute() / f"libviam_rust_utils.{suffix}"
|
|
184
238
|
self._lib = ctypes.CDLL(libname.__str__())
|
|
185
239
|
self._lib.init_rust_runtime.argtypes = ()
|
|
186
240
|
self._lib.init_rust_runtime.restype = ctypes.c_void_p
|
|
187
241
|
|
|
188
|
-
self._lib.dial.argtypes = (
|
|
242
|
+
self._lib.dial.argtypes = (
|
|
243
|
+
ctypes.c_char_p,
|
|
244
|
+
ctypes.c_char_p,
|
|
245
|
+
ctypes.c_char_p,
|
|
246
|
+
ctypes.c_char_p,
|
|
247
|
+
ctypes.c_bool,
|
|
248
|
+
ctypes.c_float,
|
|
249
|
+
ctypes.c_void_p,
|
|
250
|
+
)
|
|
189
251
|
self._lib.dial.restype = ctypes.c_void_p
|
|
190
252
|
|
|
191
253
|
self._lib.free_rust_runtime.argtypes = (ctypes.c_void_p,)
|
|
@@ -197,20 +259,27 @@ class _Runtime:
|
|
|
197
259
|
self._ptr = self._lib.init_rust_runtime()
|
|
198
260
|
|
|
199
261
|
async def dial(self, address: str, options: DialOptions) -> Tuple[Optional[str], ctypes.c_void_p]:
|
|
200
|
-
|
|
201
|
-
|
|
262
|
+
type = options.credentials.type if options.credentials else ""
|
|
263
|
+
payload = options.credentials.payload if options.credentials else ""
|
|
264
|
+
insecure = (
|
|
265
|
+
options.insecure
|
|
266
|
+
or options.allow_insecure_with_creds_downgrade
|
|
267
|
+
or (not type and not payload and options.allow_insecure_downgrade)
|
|
268
|
+
)
|
|
202
269
|
|
|
203
270
|
LOGGER.debug(f"Dialing {address} using viam-rust-utils library")
|
|
204
271
|
path_ptr = await to_thread(
|
|
205
272
|
self._lib.dial,
|
|
206
273
|
address.encode("utf-8"),
|
|
207
|
-
|
|
274
|
+
options.auth_entity.encode("utf-8") if options.auth_entity else None,
|
|
275
|
+
type.encode("utf-8") if type else None,
|
|
276
|
+
payload.encode("utf-8") if payload else None,
|
|
208
277
|
insecure,
|
|
278
|
+
ctypes.c_float(options.timeout),
|
|
209
279
|
self._ptr,
|
|
210
280
|
)
|
|
211
281
|
path = ctypes.cast(path_ptr, ctypes.c_char_p).value
|
|
212
282
|
path = path.decode("utf-8") if path else ""
|
|
213
|
-
|
|
214
283
|
return (path, path_ptr)
|
|
215
284
|
|
|
216
285
|
def release(self):
|
|
@@ -223,15 +292,50 @@ class _Runtime:
|
|
|
223
292
|
|
|
224
293
|
|
|
225
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
|
+
|
|
226
328
|
opts = options if options else DialOptions()
|
|
227
329
|
if opts.disable_webrtc:
|
|
228
330
|
channel = await _dial_direct(address, options)
|
|
331
|
+
listen(channel, SendRequest, send_request)
|
|
229
332
|
return ViamChannel(channel, lambda: None)
|
|
230
333
|
runtime = _Runtime()
|
|
231
334
|
path, path_ptr = await runtime.dial(address, opts)
|
|
232
335
|
if path:
|
|
233
336
|
LOGGER.info(f"Connecting to socket: {path}")
|
|
234
|
-
chan =
|
|
337
|
+
chan = _create_chan(path)
|
|
338
|
+
listen(chan, SendRequest, send_request)
|
|
235
339
|
|
|
236
340
|
def release():
|
|
237
341
|
runtime.free_str(path_ptr)
|
|
@@ -259,17 +363,27 @@ async def _dial_direct(address: str, options: Optional[DialOptions] = None) -> C
|
|
|
259
363
|
if insecure:
|
|
260
364
|
ctx = None
|
|
261
365
|
else:
|
|
262
|
-
|
|
366
|
+
is_local_host = host is not None and (host.startswith("localhost") or host.startswith("0.0.0.0") or host.startswith("127."))
|
|
367
|
+
if is_local_host:
|
|
368
|
+
ctx = ssl._create_unverified_context(purpose=ssl.Purpose.SERVER_AUTH)
|
|
369
|
+
else:
|
|
370
|
+
ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
|
|
263
371
|
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
|
|
264
372
|
ctx.set_ciphers("ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20")
|
|
265
373
|
ctx.set_alpn_protocols(["h2"])
|
|
266
374
|
|
|
267
|
-
if
|
|
375
|
+
if (
|
|
376
|
+
options is not None
|
|
377
|
+
and options.auth_entity
|
|
378
|
+
and host != options.auth_entity
|
|
379
|
+
and options.credentials is not None
|
|
380
|
+
and options.credentials.type != "api-key"
|
|
381
|
+
):
|
|
268
382
|
server_hostname = options.auth_entity
|
|
269
383
|
|
|
270
384
|
# Test if downgrade is required.
|
|
271
385
|
downgrade = False
|
|
272
|
-
with socket.create_connection((host, port)) as sock:
|
|
386
|
+
with socket.create_connection((host, port), timeout=opts.timeout) as sock:
|
|
273
387
|
try:
|
|
274
388
|
with ctx.wrap_socket(sock, server_hostname=server_hostname) as ssock:
|
|
275
389
|
_ = ssock.version()
|
|
@@ -300,3 +414,7 @@ async def _dial_direct(address: str, options: Optional[DialOptions] = None) -> C
|
|
|
300
414
|
async def dial_direct(address: str, options: Optional[DialOptions] = None) -> Channel:
|
|
301
415
|
warnings.warn("dial_direct is deprecated. Use rpc.dial.dial instead.", DeprecationWarning, stacklevel=2)
|
|
302
416
|
return await _dial_direct(address, options)
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
async def _dial_app(app_url: str) -> Channel:
|
|
420
|
+
return await _dial_direct(app_url)
|
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
|
|
@@ -6,6 +7,7 @@ from grpclib.const import Handler
|
|
|
6
7
|
from grpclib.events import RecvRequest, listen
|
|
7
8
|
from grpclib.reflection.service import ServerReflection
|
|
8
9
|
from grpclib.server import Server as GRPCServer
|
|
10
|
+
from grpclib.server import Stream
|
|
9
11
|
from grpclib.utils import graceful_exit
|
|
10
12
|
|
|
11
13
|
from viam import logging
|
|
@@ -40,7 +42,7 @@ class Server(ResourceManager):
|
|
|
40
42
|
super().__init__(resources)
|
|
41
43
|
|
|
42
44
|
services = [SignalingService(), RobotService(manager=self)]
|
|
43
|
-
for registration in Registry.
|
|
45
|
+
for registration in Registry.REGISTERED_APIS().values():
|
|
44
46
|
if issubclass(registration.rpc_service, ResourceRPCServiceBase):
|
|
45
47
|
services.append(registration.rpc_service(manager=self))
|
|
46
48
|
else:
|
|
@@ -53,15 +55,51 @@ class Server(ResourceManager):
|
|
|
53
55
|
|
|
54
56
|
self._server = GRPCServer(services)
|
|
55
57
|
|
|
56
|
-
async def
|
|
58
|
+
async def _grpc_recvrequest_handler(self, event: RecvRequest):
|
|
57
59
|
host = None
|
|
58
60
|
port = None
|
|
59
61
|
address = event.peer.addr()
|
|
60
62
|
if address:
|
|
61
63
|
host = address[0]
|
|
62
64
|
port = address[1]
|
|
63
|
-
|
|
64
|
-
|
|
65
|
+
method_func = event.method_func
|
|
66
|
+
|
|
67
|
+
async def log_resource_name(stream: Stream):
|
|
68
|
+
recv_msg = stream.recv_message
|
|
69
|
+
|
|
70
|
+
async def rcv_and_log_msg():
|
|
71
|
+
msg = await recv_msg()
|
|
72
|
+
log_msg = f"[gRPC] Received message from {host or 'xxxx'}:{port or 'xxxx'} - {event.method_name}"
|
|
73
|
+
if msg and hasattr(msg, "name"):
|
|
74
|
+
log_msg += f" for resource named: {msg.name}"
|
|
75
|
+
LOGGER.debug(log_msg)
|
|
76
|
+
return msg
|
|
77
|
+
|
|
78
|
+
stream.recv_message = rcv_and_log_msg
|
|
79
|
+
try:
|
|
80
|
+
return await method_func(stream)
|
|
81
|
+
finally:
|
|
82
|
+
LOGGER.debug(f"[gRPC] Finished call from {host or 'xxxx'}:{port or 'xxxx'} - {event.method_name}")
|
|
83
|
+
|
|
84
|
+
event.method_func = log_resource_name
|
|
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")
|
|
65
103
|
|
|
66
104
|
async def serve(
|
|
67
105
|
self,
|
|
@@ -84,17 +122,13 @@ class Server(ResourceManager):
|
|
|
84
122
|
logging.silence()
|
|
85
123
|
else:
|
|
86
124
|
logging.setLevel(log_level)
|
|
87
|
-
listen(self._server, RecvRequest, self.
|
|
125
|
+
listen(self._server, RecvRequest, self._grpc_recvrequest_handler)
|
|
88
126
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
await self.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
await self._server.start(host, port)
|
|
95
|
-
LOGGER.info(f"Serving on {host}:{port}")
|
|
96
|
-
await self._server.wait_closed()
|
|
97
|
-
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)
|
|
98
132
|
|
|
99
133
|
@classmethod
|
|
100
134
|
async def create_and_serve(
|
|
@@ -142,7 +176,17 @@ def _grpc_error_wrapper(func: Callable):
|
|
|
142
176
|
except ViamGRPCError as e:
|
|
143
177
|
raise e.grpc_error
|
|
144
178
|
except Exception as e:
|
|
145
|
-
|
|
179
|
+
tb = e.__traceback__
|
|
180
|
+
file_name = None
|
|
181
|
+
func_name = None
|
|
182
|
+
line_num = None
|
|
183
|
+
# only print the last entry in the stacktrace - not perfect but gives users a starting point
|
|
184
|
+
while tb is not None:
|
|
185
|
+
file_name = tb.tb_frame.f_code.co_filename
|
|
186
|
+
func_name = tb.tb_frame.f_code.co_name
|
|
187
|
+
line_num = tb.tb_lineno
|
|
188
|
+
tb = tb.tb_next
|
|
189
|
+
raise GRPCError(Status.UNKNOWN, f"{e.__class__.__name__} - {e} - {file_name=} {func_name=} {line_num=}")
|
|
146
190
|
|
|
147
191
|
return interceptor
|
|
148
192
|
|
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
|
+
...
|