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.
Potentially problematic release.
This version of viam-sdk might be problematic. Click here for more details.
- 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/module/module.py
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
import io
|
|
3
3
|
import logging as pylogging
|
|
4
|
+
import os
|
|
4
5
|
import sys
|
|
6
|
+
from collections.abc import Iterable
|
|
5
7
|
from inspect import iscoroutinefunction
|
|
6
8
|
from threading import Lock
|
|
7
9
|
from typing import List, Mapping, Optional, Sequence, Tuple
|
|
8
10
|
|
|
11
|
+
from grpclib.metadata import Deadline
|
|
9
12
|
from grpclib.utils import _service_name
|
|
10
13
|
from typing_extensions import Self
|
|
11
14
|
|
|
12
15
|
from viam import logging
|
|
13
16
|
from viam.errors import ResourceNotFoundError, ValidationError
|
|
17
|
+
from viam.logging import update_log_level
|
|
14
18
|
from viam.proto.app.robot import ComponentConfig
|
|
15
19
|
from viam.proto.module import (
|
|
16
20
|
AddResourceRequest,
|
|
@@ -26,15 +30,40 @@ from viam.proto.module import (
|
|
|
26
30
|
from viam.proto.robot import ResourceRPCSubtype
|
|
27
31
|
from viam.resource.base import ResourceBase
|
|
28
32
|
from viam.resource.registry import Registry
|
|
29
|
-
from viam.resource.types import RESOURCE_TYPE_COMPONENT, RESOURCE_TYPE_SERVICE, Model, ResourceName,
|
|
33
|
+
from viam.resource.types import API, RESOURCE_TYPE_COMPONENT, RESOURCE_TYPE_SERVICE, Model, ResourceName, resource_name_from_string
|
|
30
34
|
from viam.robot.client import RobotClient
|
|
31
|
-
from viam.rpc.dial import DialOptions
|
|
35
|
+
from viam.rpc.dial import DialOptions, _host_port_from_url
|
|
32
36
|
from viam.rpc.server import Server
|
|
33
37
|
|
|
38
|
+
# These imports are required to register built-in resources with the registry
|
|
39
|
+
from ..components.arm import Arm # noqa: F401
|
|
40
|
+
from ..components.audio_input import AudioInput # noqa: F401
|
|
41
|
+
from ..components.base import Base # noqa: F401
|
|
42
|
+
from ..components.board import Board # noqa: F401
|
|
43
|
+
from ..components.button import Button # noqa: F401
|
|
44
|
+
from ..components.camera import Camera # noqa: F401
|
|
45
|
+
from ..components.encoder import Encoder # noqa: F401
|
|
46
|
+
from ..components.gantry import Gantry # noqa: F401
|
|
47
|
+
from ..components.generic import Generic as GenericComponent # noqa: F401
|
|
48
|
+
from ..components.gripper import Gripper # noqa: F401
|
|
49
|
+
from ..components.input import Controller # noqa: F401
|
|
50
|
+
from ..components.motor import Motor # noqa: F401
|
|
51
|
+
from ..components.movement_sensor import MovementSensor # noqa: F401
|
|
52
|
+
from ..components.pose_tracker import PoseTracker # noqa: F401
|
|
53
|
+
from ..components.power_sensor import PowerSensor # noqa: F401
|
|
54
|
+
from ..components.sensor import Sensor # noqa: F401
|
|
55
|
+
from ..components.servo import Servo # noqa: F401
|
|
56
|
+
from ..components.switch import Switch # noqa: F401
|
|
57
|
+
from ..services.discovery import Discovery # noqa: F401
|
|
58
|
+
from ..services.generic import Generic as GenericService # noqa: F401
|
|
59
|
+
from ..services.motion import Motion # noqa: F401
|
|
60
|
+
from ..services.navigation import Navigation # noqa: F401
|
|
61
|
+
from ..services.slam import SLAM # noqa: F401
|
|
62
|
+
from ..services.vision import Vision # noqa: F401
|
|
34
63
|
from .service import ModuleRPCService
|
|
35
64
|
from .types import Reconfigurable, Stoppable
|
|
36
65
|
|
|
37
|
-
|
|
66
|
+
NO_MODULE_PARENT = os.environ.get("VIAM_NO_MODULE_PARENT", "").lower() == "true"
|
|
38
67
|
|
|
39
68
|
|
|
40
69
|
def _parse_module_args() -> argparse.Namespace:
|
|
@@ -44,7 +73,8 @@ def _parse_module_args() -> argparse.Namespace:
|
|
|
44
73
|
p = argparse.ArgumentParser(description="Start this viam python module")
|
|
45
74
|
p.add_argument("socket_path", help="path where this module will serve a unix socket")
|
|
46
75
|
p.add_argument("--log-level", type=lambda name: pylogging._nameToLevel[name.upper()], default=logging.INFO)
|
|
47
|
-
|
|
76
|
+
p.add_argument("--tcp-mode", action="store_true")
|
|
77
|
+
return p.parse_known_args()[0]
|
|
48
78
|
|
|
49
79
|
|
|
50
80
|
class Module:
|
|
@@ -53,8 +83,10 @@ class Module:
|
|
|
53
83
|
_ready: bool
|
|
54
84
|
_log_level: int
|
|
55
85
|
_lock: Lock
|
|
86
|
+
_tcp_mode: bool
|
|
56
87
|
parent: Optional[RobotClient] = None
|
|
57
88
|
server: Server
|
|
89
|
+
logger: pylogging.Logger
|
|
58
90
|
|
|
59
91
|
@classmethod
|
|
60
92
|
def from_args(cls) -> Self:
|
|
@@ -70,7 +102,7 @@ class Module:
|
|
|
70
102
|
Module: a new Module instance
|
|
71
103
|
"""
|
|
72
104
|
args = _parse_module_args()
|
|
73
|
-
return cls(args.socket_path, log_level=args.log_level)
|
|
105
|
+
return cls(args.socket_path, log_level=args.log_level, tcp_mode=args.tcp_mode)
|
|
74
106
|
|
|
75
107
|
@classmethod
|
|
76
108
|
async def run_with_models(cls, *models: ResourceBase):
|
|
@@ -82,7 +114,7 @@ class Module:
|
|
|
82
114
|
for model in models:
|
|
83
115
|
if not hasattr(model, "MODEL"):
|
|
84
116
|
raise TypeError(f"missing MODEL field on {model}. Resource implementations must define MODEL")
|
|
85
|
-
module.add_model_from_registry(model.
|
|
117
|
+
module.add_model_from_registry(model.API, model.MODEL) # pyright: ignore [reportAttributeAccessIssue]
|
|
86
118
|
await module.start()
|
|
87
119
|
|
|
88
120
|
@classmethod
|
|
@@ -102,7 +134,7 @@ class Module:
|
|
|
102
134
|
module.add_model_from_registry(*key.split("/")) # pyright: ignore [reportArgumentType]
|
|
103
135
|
await module.start()
|
|
104
136
|
|
|
105
|
-
def __init__(self, address: str, *, log_level: int = logging.INFO) -> None:
|
|
137
|
+
def __init__(self, address: str, *, log_level: int = logging.INFO, tcp_mode: bool = False) -> None:
|
|
106
138
|
# When a module is launched by viam-server, its stdout is not connected to a tty. In
|
|
107
139
|
# response, python disables line buffering, which prevents `print` statements from being
|
|
108
140
|
# immediately flushed to viam-server. This behavior can be confusing, interfere with
|
|
@@ -113,12 +145,21 @@ class Module:
|
|
|
113
145
|
if isinstance(sys.stderr, io.TextIOWrapper):
|
|
114
146
|
sys.stderr.reconfigure(line_buffering=True)
|
|
115
147
|
self._address = address
|
|
148
|
+
self._tcp_mode = tcp_mode
|
|
116
149
|
self.server = Server(resources=[], module_service=ModuleRPCService(self))
|
|
117
150
|
self._log_level = log_level
|
|
151
|
+
|
|
152
|
+
module_name = os.environ.get("VIAM_MODULE_NAME")
|
|
153
|
+
# this can happen if the user is running an old version of viam-server that doesn't set `VIAM_MODULE_NAME`
|
|
154
|
+
if module_name is None:
|
|
155
|
+
module_name = __name__
|
|
156
|
+
self.logger = logging.getLogger(module_name)
|
|
118
157
|
self._ready = True
|
|
119
158
|
self._lock = Lock()
|
|
120
159
|
|
|
121
160
|
async def _connect_to_parent(self):
|
|
161
|
+
if NO_MODULE_PARENT:
|
|
162
|
+
return
|
|
122
163
|
if self.parent is None:
|
|
123
164
|
if self._parent_address is None:
|
|
124
165
|
raise ValueError("Parent address not found")
|
|
@@ -129,7 +170,7 @@ class Module:
|
|
|
129
170
|
log_level=self._log_level,
|
|
130
171
|
),
|
|
131
172
|
)
|
|
132
|
-
|
|
173
|
+
self.logger.debug("Starting module logging")
|
|
133
174
|
logging.setParent(self.parent)
|
|
134
175
|
|
|
135
176
|
async def _get_resource(self, name: ResourceName) -> ResourceBase:
|
|
@@ -152,18 +193,23 @@ class Module:
|
|
|
152
193
|
async def start(self):
|
|
153
194
|
"""Start the module service and gRPC server"""
|
|
154
195
|
try:
|
|
155
|
-
|
|
196
|
+
if self._tcp_mode:
|
|
197
|
+
host, port = _host_port_from_url(self._address)
|
|
198
|
+
await self.server.serve(log_level=self._log_level, host=host, port=port)
|
|
199
|
+
else:
|
|
200
|
+
await self.server.serve(log_level=self._log_level, path=self._address)
|
|
156
201
|
finally:
|
|
157
202
|
await self.stop()
|
|
158
203
|
|
|
159
204
|
async def stop(self):
|
|
160
205
|
"""Stop the module service and gRPC server"""
|
|
161
|
-
|
|
206
|
+
self.logger.debug("Shutting down module")
|
|
162
207
|
try:
|
|
208
|
+
logging.shutdown()
|
|
163
209
|
if self.parent is not None:
|
|
164
210
|
await self.parent.close()
|
|
165
211
|
except Exception as e:
|
|
166
|
-
|
|
212
|
+
self.logger.error("Encountered error while shutting down module", exc_info=e)
|
|
167
213
|
|
|
168
214
|
def set_ready(self, ready: bool):
|
|
169
215
|
"""Set the module's ready state. The module automatically sets to READY on load. Setting to False can be useful
|
|
@@ -175,21 +221,24 @@ class Module:
|
|
|
175
221
|
with self._lock:
|
|
176
222
|
self._ready = ready
|
|
177
223
|
|
|
178
|
-
async def add_resource(self, request: AddResourceRequest):
|
|
224
|
+
async def add_resource(self, request: AddResourceRequest, *, deadline: Optional[Deadline] = None):
|
|
179
225
|
dependencies = await self._get_dependencies(request.dependencies)
|
|
180
226
|
config: ComponentConfig = request.config
|
|
181
|
-
|
|
227
|
+
api = API.from_string(config.api)
|
|
182
228
|
model = Model.from_string(config.model, ignore_errors=True)
|
|
183
|
-
creator = Registry.lookup_resource_creator(
|
|
229
|
+
creator = Registry.lookup_resource_creator(api, model)
|
|
184
230
|
resource = creator(config, dependencies)
|
|
231
|
+
if deadline is not None and deadline.time_remaining() <= 0:
|
|
232
|
+
raise TimeoutError("Deadline expired")
|
|
233
|
+
update_log_level(resource.logger, config.log_configuration.level.upper())
|
|
185
234
|
self.server.register(resource)
|
|
186
235
|
|
|
187
236
|
async def reconfigure_resource(self, request: ReconfigureResourceRequest):
|
|
188
237
|
dependencies = await self._get_dependencies(request.dependencies)
|
|
189
238
|
config: ComponentConfig = request.config
|
|
190
|
-
|
|
239
|
+
api = API.from_string(config.api)
|
|
191
240
|
name = config.name
|
|
192
|
-
rn = ResourceName(namespace=
|
|
241
|
+
rn = ResourceName(namespace=api.namespace, type=api.resource_type, subtype=api.resource_subtype, name=name)
|
|
193
242
|
resource = self.server.get_resource(ResourceBase, rn)
|
|
194
243
|
if isinstance(resource, Reconfigurable):
|
|
195
244
|
resource.reconfigure(config, dependencies)
|
|
@@ -207,38 +256,41 @@ class Module:
|
|
|
207
256
|
rn = resource_name_from_string(request.name)
|
|
208
257
|
resource = self.server.get_resource(ResourceBase, rn)
|
|
209
258
|
if isinstance(resource, Stoppable):
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
259
|
+
try:
|
|
260
|
+
if iscoroutinefunction(resource.stop):
|
|
261
|
+
await resource.stop()
|
|
262
|
+
else:
|
|
263
|
+
resource.stop()
|
|
264
|
+
except Exception as e:
|
|
265
|
+
self.logger.warning(f"Could not remove resource named {resource.name}", exc_info=e)
|
|
214
266
|
await self.server.remove_resource(rn)
|
|
215
267
|
|
|
216
268
|
async def ready(self, request: ReadyRequest) -> ReadyResponse:
|
|
217
269
|
self._parent_address = request.parent_address
|
|
218
270
|
await self._connect_to_parent()
|
|
219
271
|
|
|
220
|
-
svcname_to_models: Mapping[Tuple[str,
|
|
221
|
-
for
|
|
222
|
-
|
|
223
|
-
|
|
272
|
+
svcname_to_models: Mapping[Tuple[str, API], List[Model]] = {}
|
|
273
|
+
for api_model_str in Registry.REGISTERED_RESOURCE_CREATORS().keys():
|
|
274
|
+
api_str, model_str = api_model_str.split("/")
|
|
275
|
+
api = API.from_string(api_str)
|
|
224
276
|
model = Model.from_string(model_str)
|
|
225
277
|
|
|
226
|
-
registration = Registry.
|
|
278
|
+
registration = Registry.lookup_api(api)
|
|
227
279
|
service = registration.rpc_service(self.server)
|
|
228
280
|
service_name = _service_name(service)
|
|
229
281
|
|
|
230
|
-
models = svcname_to_models.get((service_name,
|
|
282
|
+
models = svcname_to_models.get((service_name, api), [])
|
|
231
283
|
models.append(model)
|
|
232
|
-
svcname_to_models[(service_name,
|
|
284
|
+
svcname_to_models[(service_name, api)] = models
|
|
233
285
|
|
|
234
286
|
handlers: List[HandlerDefinition] = []
|
|
235
287
|
for key, value in svcname_to_models.items():
|
|
236
|
-
svc_name,
|
|
288
|
+
svc_name, api = key
|
|
237
289
|
rpc_subtype = ResourceRPCSubtype(
|
|
238
290
|
subtype=ResourceName(
|
|
239
|
-
namespace=
|
|
240
|
-
type=
|
|
241
|
-
subtype=
|
|
291
|
+
namespace=api.namespace,
|
|
292
|
+
type=api.resource_type,
|
|
293
|
+
subtype=api.resource_subtype,
|
|
242
294
|
name="",
|
|
243
295
|
),
|
|
244
296
|
proto_service=svc_name,
|
|
@@ -248,22 +300,43 @@ class Module:
|
|
|
248
300
|
|
|
249
301
|
return ReadyResponse(ready=self._ready, handlermap=HandlerMap(handlers=handlers))
|
|
250
302
|
|
|
251
|
-
def add_model_from_registry(self,
|
|
303
|
+
def add_model_from_registry(self, api: API, model: Model):
|
|
252
304
|
"""Add a pre-registered model to this Module"""
|
|
253
305
|
|
|
254
306
|
# All we need to do is double check that the model has already been registered
|
|
255
307
|
try:
|
|
256
|
-
Registry.lookup_resource_creator(
|
|
308
|
+
Registry.lookup_resource_creator(api, model)
|
|
257
309
|
except ResourceNotFoundError:
|
|
258
|
-
raise ValueError(f"Cannot add model because it has not been registered.
|
|
310
|
+
raise ValueError(f"Cannot add model because it has not been registered. API: {api}. Model: {model}")
|
|
259
311
|
|
|
260
312
|
async def validate_config(self, request: ValidateConfigRequest) -> ValidateConfigResponse:
|
|
261
313
|
config: ComponentConfig = request.config
|
|
262
|
-
|
|
314
|
+
api = API.from_string(config.api)
|
|
263
315
|
model = Model.from_string(config.model)
|
|
264
|
-
validator = Registry.lookup_validator(
|
|
316
|
+
validator = Registry.lookup_validator(api, model)
|
|
265
317
|
try:
|
|
266
|
-
|
|
267
|
-
|
|
318
|
+
# backwards compatibility. Support both ([], []) or [] with deprecation warning.
|
|
319
|
+
# If user's validate returns [str], it will be treated as required dependencies only.
|
|
320
|
+
# Incorect formats, e.g. int, will raise ValidationError.
|
|
321
|
+
_validator_return_test = validator(config)
|
|
322
|
+
if not (isinstance(_validator_return_test, tuple) and len(_validator_return_test) == 2):
|
|
323
|
+
msg = f"Your validate function {validator.__name__} did not return \
|
|
324
|
+
type tuple[Sequence[str], Sequence[str]]. Got {_validator_return_test}."
|
|
325
|
+
self.logger.warning(msg)
|
|
326
|
+
if (isinstance(_validator_return_test, Iterable) and not isinstance(_validator_return_test, str)) and all(
|
|
327
|
+
isinstance(e, str)
|
|
328
|
+
for e in _validator_return_test # type: ignore
|
|
329
|
+
):
|
|
330
|
+
self.logger.warning(
|
|
331
|
+
f"Detected deprecated validate function signature. \
|
|
332
|
+
Treating all dependencies {_validator_return_test} as required dependencies. \
|
|
333
|
+
Please update to new signature Tuple[Sequence[str], Sequence[str]] soon."
|
|
334
|
+
)
|
|
335
|
+
return ValidateConfigResponse(dependencies=_validator_return_test)
|
|
336
|
+
else:
|
|
337
|
+
raise ValidationError(msg)
|
|
338
|
+
|
|
339
|
+
dependencies, optional_dependencies = _validator_return_test
|
|
340
|
+
return ValidateConfigResponse(dependencies=dependencies, optional_dependencies=optional_dependencies)
|
|
268
341
|
except Exception as e:
|
|
269
342
|
raise ValidationError(f"{type(Exception)}: {e}").grpc_error
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import datetime
|
|
2
|
+
import os
|
|
3
|
+
from typing import Any, Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
from viam.app.viam_client import ViamClient
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ResourceDataConsumer:
|
|
9
|
+
"""Client for retrieving historical module data from app.
|
|
10
|
+
|
|
11
|
+
Inherit from this class in a module to get access to historical module data.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
@classmethod
|
|
15
|
+
def construct_query(cls, part_id: str, resource_name: str, time_back: datetime.timedelta) -> List[Dict[str, Any]]:
|
|
16
|
+
return [
|
|
17
|
+
{
|
|
18
|
+
"$match": {
|
|
19
|
+
"part_id": part_id,
|
|
20
|
+
"component_name": resource_name,
|
|
21
|
+
"time_received": {"$gte": datetime.datetime.now() - time_back},
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
async def query_tabular_data(
|
|
28
|
+
cls, resource_name: str, time_back: datetime.timedelta, additional_stages: Optional[List[Dict[str, Any]]] = None, **kwargs
|
|
29
|
+
) -> List[Dict[str, Any]]:
|
|
30
|
+
"""Return historical data for this module, queried with MQL."""
|
|
31
|
+
viam_client = await ViamClient.create_from_env_vars()
|
|
32
|
+
|
|
33
|
+
org_id = os.environ["VIAM_PRIMARY_ORG_ID"]
|
|
34
|
+
part_id = os.environ["VIAM_MACHINE_PART_ID"]
|
|
35
|
+
|
|
36
|
+
query = cls.construct_query(part_id=part_id, resource_name=resource_name, time_back=time_back)
|
|
37
|
+
|
|
38
|
+
if additional_stages is not None:
|
|
39
|
+
query += additional_stages
|
|
40
|
+
|
|
41
|
+
return await viam_client.data_client.tabular_data_by_mql(org_id, query)
|
viam/module/service.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
|
+
from grpclib import Status
|
|
3
4
|
from grpclib.server import Stream
|
|
4
5
|
|
|
6
|
+
from viam.errors import ViamGRPCError
|
|
5
7
|
from viam.proto.module import (
|
|
6
8
|
AddResourceRequest,
|
|
7
9
|
AddResourceResponse,
|
|
@@ -29,7 +31,13 @@ class ModuleRPCService(ModuleServiceBase):
|
|
|
29
31
|
async def AddResource(self, stream: Stream[AddResourceRequest, AddResourceResponse]) -> None:
|
|
30
32
|
request = await stream.recv_message()
|
|
31
33
|
assert request is not None
|
|
32
|
-
|
|
34
|
+
try:
|
|
35
|
+
await self._module.add_resource(request, deadline=stream.deadline)
|
|
36
|
+
except TimeoutError:
|
|
37
|
+
raise ViamGRPCError(
|
|
38
|
+
message="Timeout while adding resource",
|
|
39
|
+
grpc_code=Status.DEADLINE_EXCEEDED,
|
|
40
|
+
)
|
|
33
41
|
await stream.send_message(AddResourceResponse())
|
|
34
42
|
|
|
35
43
|
async def ReconfigureResource(self, stream: Stream[ReconfigureResourceRequest, ReconfigureResourceResponse]) -> None:
|
viam/module/types.py
CHANGED
|
@@ -9,8 +9,7 @@ from viam.resource.base import ResourceBase
|
|
|
9
9
|
class Reconfigurable(Protocol):
|
|
10
10
|
"""The Reconfigurable protocol defines the requirements for making a resource Reconfigurable"""
|
|
11
11
|
|
|
12
|
-
def reconfigure(self, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase]):
|
|
13
|
-
...
|
|
12
|
+
def reconfigure(self, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase]): ...
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
@runtime_checkable
|
|
@@ -21,5 +20,4 @@ class Stoppable(Protocol):
|
|
|
21
20
|
All resources that physically move should be Stoppable.
|
|
22
21
|
"""
|
|
23
22
|
|
|
24
|
-
def stop(self, *, extra: Optional[Mapping[str, Any]] = None, timeout: Optional[float] = None, **kwargs):
|
|
25
|
-
...
|
|
23
|
+
def stop(self, *, extra: Optional[Mapping[str, Any]] = None, timeout: Optional[float] = None, **kwargs): ...
|