viam-sdk 0.41.1__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.

Files changed (225) hide show
  1. viam/app/app_client.py +225 -51
  2. viam/app/billing_client.py +47 -5
  3. viam/app/data_client.py +771 -234
  4. viam/app/ml_training_client.py +3 -5
  5. viam/app/provisioning_client.py +3 -5
  6. viam/app/viam_client.py +58 -11
  7. viam/components/arm/arm.py +1 -1
  8. viam/components/arm/service.py +1 -1
  9. viam/components/audio_in/__init__.py +24 -0
  10. viam/components/audio_in/audio_in.py +74 -0
  11. viam/components/audio_in/client.py +76 -0
  12. viam/components/audio_in/service.py +83 -0
  13. viam/components/audio_out/__init__.py +21 -0
  14. viam/components/audio_out/audio_out.py +72 -0
  15. viam/components/audio_out/client.py +67 -0
  16. viam/components/audio_out/service.py +63 -0
  17. viam/components/base/base.py +1 -1
  18. viam/components/board/board.py +8 -2
  19. viam/components/board/client.py +2 -1
  20. viam/components/board/service.py +1 -0
  21. viam/components/button/__init__.py +10 -0
  22. viam/components/button/button.py +41 -0
  23. viam/components/button/client.py +52 -0
  24. viam/components/button/service.py +46 -0
  25. viam/components/camera/camera.py +15 -30
  26. viam/components/camera/client.py +10 -21
  27. viam/components/camera/service.py +15 -28
  28. viam/components/component_base.py +2 -2
  29. viam/components/gantry/client.py +17 -2
  30. viam/components/gantry/gantry.py +32 -1
  31. viam/components/gantry/service.py +21 -5
  32. viam/components/gripper/__init__.py +2 -0
  33. viam/components/gripper/client.py +25 -2
  34. viam/components/gripper/gripper.py +76 -1
  35. viam/components/gripper/service.py +32 -3
  36. viam/components/input/input.py +1 -1
  37. viam/components/motor/motor.py +1 -1
  38. viam/components/power_sensor/power_sensor.py +1 -1
  39. viam/components/switch/__init__.py +10 -0
  40. viam/components/switch/client.py +83 -0
  41. viam/components/switch/service.py +72 -0
  42. viam/components/switch/switch.py +98 -0
  43. viam/gen/app/agent/v1/agent_pb2.py +1 -1
  44. viam/gen/app/cloudslam/v1/cloud_slam_pb2.py +1 -1
  45. viam/gen/app/data/v1/data_grpc.py +74 -2
  46. viam/gen/app/data/v1/data_pb2.py +198 -104
  47. viam/gen/app/data/v1/data_pb2.pyi +563 -31
  48. viam/gen/app/datapipelines/__init__.py +0 -0
  49. viam/gen/app/datapipelines/v1/__init__.py +0 -0
  50. viam/gen/app/datapipelines/v1/data_pipelines_grpc.py +84 -0
  51. viam/gen/app/datapipelines/v1/data_pipelines_pb2.py +57 -0
  52. viam/gen/app/datapipelines/v1/data_pipelines_pb2.pyi +387 -0
  53. viam/gen/app/dataset/v1/dataset_grpc.py +10 -2
  54. viam/gen/app/dataset/v1/dataset_pb2.py +8 -4
  55. viam/gen/app/dataset/v1/dataset_pb2.pyi +36 -1
  56. viam/gen/app/datasync/v1/data_sync_pb2.py +39 -35
  57. viam/gen/app/datasync/v1/data_sync_pb2.pyi +21 -8
  58. viam/gen/app/mlinference/v1/ml_inference_pb2.py +7 -7
  59. viam/gen/app/mlinference/v1/ml_inference_pb2.pyi +4 -2
  60. viam/gen/app/mltraining/v1/ml_training_grpc.py +10 -2
  61. viam/gen/app/mltraining/v1/ml_training_pb2.py +63 -43
  62. viam/gen/app/mltraining/v1/ml_training_pb2.pyi +112 -7
  63. viam/gen/app/packages/v1/packages_pb2.py +1 -1
  64. viam/gen/app/v1/app_grpc.py +74 -3
  65. viam/gen/app/v1/app_pb2.py +600 -545
  66. viam/gen/app/v1/app_pb2.pyi +1108 -258
  67. viam/gen/app/v1/billing_grpc.py +26 -2
  68. viam/gen/app/v1/billing_pb2.py +52 -36
  69. viam/gen/app/v1/billing_pb2.pyi +158 -4
  70. viam/gen/app/v1/end_user_pb2.py +1 -1
  71. viam/gen/app/v1/robot_pb2.py +95 -89
  72. viam/gen/app/v1/robot_pb2.pyi +121 -9
  73. viam/gen/common/v1/common_pb2.py +76 -58
  74. viam/gen/common/v1/common_pb2.pyi +186 -17
  75. viam/gen/component/arm/v1/arm_grpc.py +10 -2
  76. viam/gen/component/arm/v1/arm_pb2.py +5 -3
  77. viam/gen/component/audioin/__init__.py +0 -0
  78. viam/gen/component/audioin/v1/__init__.py +0 -0
  79. viam/gen/component/audioin/v1/audioin_grpc.py +54 -0
  80. viam/gen/component/audioin/v1/audioin_pb2.py +34 -0
  81. viam/gen/component/audioin/v1/audioin_pb2.pyi +94 -0
  82. viam/gen/component/audioinput/v1/audioinput_pb2.py +1 -1
  83. viam/gen/component/audioout/__init__.py +0 -0
  84. viam/gen/component/audioout/v1/__init__.py +0 -0
  85. viam/gen/component/audioout/v1/audioout_grpc.py +54 -0
  86. viam/gen/component/audioout/v1/audioout_pb2.py +32 -0
  87. viam/gen/component/audioout/v1/audioout_pb2.pyi +47 -0
  88. viam/gen/component/base/v1/base_pb2.py +1 -1
  89. viam/gen/component/board/v1/board_pb2.py +1 -1
  90. viam/gen/component/button/v1/button_pb2.py +1 -1
  91. viam/gen/component/camera/v1/camera_grpc.py +1 -0
  92. viam/gen/component/camera/v1/camera_pb2.py +37 -36
  93. viam/gen/component/camera/v1/camera_pb2.pyi +31 -4
  94. viam/gen/component/encoder/v1/encoder_pb2.py +1 -1
  95. viam/gen/component/gantry/v1/gantry_grpc.py +9 -1
  96. viam/gen/component/gantry/v1/gantry_pb2.py +5 -3
  97. viam/gen/component/generic/v1/generic_pb2.py +1 -1
  98. viam/gen/component/gripper/v1/gripper_grpc.py +18 -2
  99. viam/gen/component/gripper/v1/gripper_pb2.py +12 -4
  100. viam/gen/component/gripper/v1/gripper_pb2.pyi +43 -1
  101. viam/gen/component/inputcontroller/v1/input_controller_pb2.py +1 -1
  102. viam/gen/component/motor/v1/motor_pb2.py +1 -1
  103. viam/gen/component/movementsensor/v1/movementsensor_pb2.py +1 -1
  104. viam/gen/component/posetracker/v1/pose_tracker_pb2.py +1 -1
  105. viam/gen/component/powersensor/v1/powersensor_pb2.py +1 -1
  106. viam/gen/component/sensor/v1/sensor_pb2.py +1 -1
  107. viam/gen/component/servo/v1/servo_pb2.py +1 -1
  108. viam/gen/component/switch/v1/switch_pb2.py +5 -5
  109. viam/gen/component/switch/v1/switch_pb2.pyi +9 -2
  110. viam/gen/component/testecho/v1/testecho_pb2.py +1 -1
  111. viam/gen/module/v1/module_pb2.py +5 -5
  112. viam/gen/module/v1/module_pb2.pyi +7 -2
  113. viam/gen/opentelemetry/__init__.py +0 -0
  114. viam/gen/opentelemetry/proto/__init__.py +0 -0
  115. viam/gen/opentelemetry/proto/common/__init__.py +0 -0
  116. viam/gen/opentelemetry/proto/common/v1/__init__.py +0 -0
  117. viam/gen/opentelemetry/proto/common/v1/common_grpc.py +0 -0
  118. viam/gen/opentelemetry/proto/common/v1/common_pb2.py +27 -0
  119. viam/gen/opentelemetry/proto/common/v1/common_pb2.pyi +208 -0
  120. viam/gen/opentelemetry/proto/resource/__init__.py +0 -0
  121. viam/gen/opentelemetry/proto/resource/v1/__init__.py +0 -0
  122. viam/gen/opentelemetry/proto/resource/v1/resource_grpc.py +0 -0
  123. viam/gen/opentelemetry/proto/resource/v1/resource_pb2.py +18 -0
  124. viam/gen/opentelemetry/proto/resource/v1/resource_pb2.pyi +59 -0
  125. viam/gen/opentelemetry/proto/trace/__init__.py +0 -0
  126. viam/gen/opentelemetry/proto/trace/v1/__init__.py +0 -0
  127. viam/gen/opentelemetry/proto/trace/v1/trace_grpc.py +0 -0
  128. viam/gen/opentelemetry/proto/trace/v1/trace_pb2.py +37 -0
  129. viam/gen/opentelemetry/proto/trace/v1/trace_pb2.pyi +402 -0
  130. viam/gen/proto/rpc/examples/echo/v1/echo_pb2.py +1 -1
  131. viam/gen/proto/rpc/examples/echoresource/v1/echoresource_pb2.py +1 -1
  132. viam/gen/proto/rpc/v1/auth_pb2.py +1 -1
  133. viam/gen/proto/rpc/webrtc/v1/grpc_pb2.py +1 -1
  134. viam/gen/proto/rpc/webrtc/v1/signaling_pb2.py +1 -1
  135. viam/gen/provisioning/v1/provisioning_grpc.py +10 -2
  136. viam/gen/provisioning/v1/provisioning_pb2.py +32 -26
  137. viam/gen/provisioning/v1/provisioning_pb2.pyi +46 -5
  138. viam/gen/robot/v1/robot_grpc.py +51 -34
  139. viam/gen/robot/v1/robot_pb2.py +147 -142
  140. viam/gen/robot/v1/robot_pb2.pyi +153 -86
  141. viam/gen/service/datamanager/v1/data_manager_grpc.py +11 -2
  142. viam/gen/service/datamanager/v1/data_manager_pb2.py +15 -8
  143. viam/gen/service/datamanager/v1/data_manager_pb2.pyi +47 -1
  144. viam/gen/service/discovery/v1/discovery_pb2.py +1 -1
  145. viam/gen/service/generic/v1/generic_pb2.py +1 -1
  146. viam/gen/service/mlmodel/v1/mlmodel_pb2.py +1 -1
  147. viam/gen/service/motion/v1/motion_pb2.py +92 -62
  148. viam/gen/service/motion/v1/motion_pb2.pyi +130 -68
  149. viam/gen/service/navigation/v1/navigation_pb2.py +1 -1
  150. viam/gen/service/sensors/v1/sensors_pb2.py +1 -1
  151. viam/gen/service/shell/v1/shell_pb2.py +1 -1
  152. viam/gen/service/slam/v1/slam_pb2.py +1 -1
  153. viam/gen/service/slam/v1/slam_pb2.pyi +1 -1
  154. viam/gen/service/video/__init__.py +0 -0
  155. viam/gen/service/video/v1/__init__.py +0 -0
  156. viam/gen/service/video/v1/video_grpc.py +39 -0
  157. viam/gen/service/video/v1/video_pb2.py +29 -0
  158. viam/gen/service/video/v1/video_pb2.pyi +72 -0
  159. viam/gen/service/vision/v1/vision_pb2.py +27 -27
  160. viam/gen/service/vision/v1/vision_pb2.pyi +28 -3
  161. viam/gen/service/worldstatestore/__init__.py +0 -0
  162. viam/gen/service/worldstatestore/v1/__init__.py +0 -0
  163. viam/gen/service/worldstatestore/v1/world_state_store_grpc.py +55 -0
  164. viam/gen/service/worldstatestore/v1/world_state_store_pb2.py +39 -0
  165. viam/gen/service/worldstatestore/v1/world_state_store_pb2.pyi +171 -0
  166. viam/gen/stream/v1/stream_pb2.py +1 -1
  167. viam/gen/tagger/v1/tagger_pb2.py +1 -1
  168. viam/logging.py +9 -8
  169. viam/media/audio.py +22 -10
  170. viam/media/utils/pil/__init__.py +5 -1
  171. viam/media/video.py +54 -40
  172. viam/module/module.py +85 -16
  173. viam/module/resource_data_consumer.py +41 -0
  174. viam/module/service.py +9 -1
  175. viam/proto/app/__init__.py +68 -0
  176. viam/proto/app/billing.py +16 -0
  177. viam/proto/app/data/__init__.py +48 -0
  178. viam/proto/app/datapipelines/__init__.py +56 -0
  179. viam/proto/app/dataset/__init__.py +4 -0
  180. viam/proto/app/mltraining/__init__.py +6 -0
  181. viam/proto/app/robot.py +6 -0
  182. viam/proto/common/__init__.py +14 -0
  183. viam/proto/component/audioin/__init__.py +16 -0
  184. viam/proto/component/audioout/__init__.py +15 -0
  185. viam/proto/component/camera/__init__.py +0 -2
  186. viam/proto/component/gripper/__init__.py +4 -0
  187. viam/proto/opentelemetry/__init__.py +0 -0
  188. viam/proto/opentelemetry/proto/__init__.py +0 -0
  189. viam/proto/opentelemetry/proto/common/__init__.py +15 -0
  190. viam/proto/opentelemetry/proto/resource/__init__.py +10 -0
  191. viam/proto/opentelemetry/proto/trace/__init__.py +15 -0
  192. viam/proto/provisioning/__init__.py +6 -0
  193. viam/proto/robot/__init__.py +16 -8
  194. viam/proto/service/datamanager/__init__.py +8 -1
  195. viam/proto/service/motion/__init__.py +2 -0
  196. viam/proto/service/video/__init__.py +15 -0
  197. viam/proto/service/worldstatestore/__init__.py +32 -0
  198. viam/resource/easy_resource.py +5 -9
  199. viam/resource/manager.py +4 -3
  200. viam/resource/registry.py +2 -2
  201. viam/resource/types.py +2 -2
  202. viam/robot/client.py +38 -59
  203. viam/rpc/dial.py +48 -5
  204. viam/rpc/libviam_rust_utils.so +0 -0
  205. viam/rpc/server.py +24 -10
  206. viam/services/motion/client.py +8 -9
  207. viam/services/motion/motion.py +48 -46
  208. viam/services/navigation/navigation.py +2 -2
  209. viam/services/vision/client.py +1 -1
  210. viam/services/vision/service.py +5 -8
  211. viam/services/vision/vision.py +5 -3
  212. viam/services/worldstatestore/__init__.py +18 -0
  213. viam/services/worldstatestore/client.py +94 -0
  214. viam/services/worldstatestore/service.py +55 -0
  215. viam/services/worldstatestore/worldstatestore.py +90 -0
  216. viam/sessions_client.py +115 -46
  217. viam/version_metadata.py +2 -2
  218. {viam_sdk-0.41.1.dist-info → viam_sdk-0.66.0.dist-info}/METADATA +10 -6
  219. {viam_sdk-0.41.1.dist-info → viam_sdk-0.66.0.dist-info}/RECORD +221 -152
  220. {viam_sdk-0.41.1.dist-info → viam_sdk-0.66.0.dist-info}/WHEEL +1 -1
  221. viam/components/audio_input/__init__.py +0 -18
  222. viam/components/audio_input/audio_input.py +0 -81
  223. viam/components/audio_input/client.py +0 -70
  224. viam/components/audio_input/service.py +0 -114
  225. {viam_sdk-0.41.1.dist-info → viam_sdk-0.66.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,18 +0,0 @@
1
- from viam.resource.registry import Registry, ResourceRegistration
2
-
3
- from .audio_input import AudioInput
4
- from .client import AudioInputClient
5
- from .service import AudioInputRPCService
6
-
7
- __all__ = [
8
- "AudioInput",
9
- ]
10
-
11
-
12
- Registry.register_api(
13
- ResourceRegistration(
14
- AudioInput,
15
- AudioInputRPCService,
16
- lambda name, channel: AudioInputClient(name, channel),
17
- )
18
- )
@@ -1,81 +0,0 @@
1
- import abc
2
- from dataclasses import dataclass
3
- from datetime import timedelta
4
- from typing import Final, Optional
5
-
6
- from google.protobuf.duration_pb2 import Duration
7
- from typing_extensions import Self
8
-
9
- from viam.media.audio import Audio, AudioStream
10
- from viam.proto.component.audioinput import PropertiesResponse
11
- from viam.resource.types import API, RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT
12
- from viam.streams import StreamSource
13
-
14
- from ..component_base import ComponentBase
15
-
16
-
17
- class AudioInput(ComponentBase, StreamSource[Audio]):
18
- """AudioInput represents a component that can capture audio.
19
-
20
- This acts as an abstract base class for any drivers representing specific
21
- audio input implementations. This cannot be used on its own. If the ``__init__()`` function is
22
- overridden, it must call the ``super().__init__()`` function.
23
- """
24
-
25
- API: Final = API( # pyright: ignore [reportIncompatibleVariableOverride]
26
- RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT, "audio_input"
27
- )
28
-
29
- @dataclass
30
- class Properties:
31
- channel_count: int
32
- latency: timedelta
33
- sample_rate: int
34
- sample_size: int
35
- is_big_endian: bool
36
- is_float: bool
37
- is_interleaved: bool
38
-
39
- @property
40
- def proto(self) -> PropertiesResponse:
41
- latency = Duration()
42
- latency.FromTimedelta(self.latency)
43
- return PropertiesResponse(
44
- channel_count=self.channel_count,
45
- latency=latency,
46
- sample_rate=self.sample_rate,
47
- sample_size=self.sample_size,
48
- is_big_endian=self.is_big_endian,
49
- is_float=self.is_float,
50
- is_interleaved=self.is_interleaved,
51
- )
52
-
53
- @classmethod
54
- def from_proto(cls, proto: PropertiesResponse) -> Self:
55
- return cls(
56
- channel_count=proto.channel_count,
57
- latency=proto.latency.ToTimedelta(),
58
- sample_rate=proto.sample_rate,
59
- sample_size=proto.sample_size,
60
- is_big_endian=proto.is_big_endian,
61
- is_float=proto.is_float,
62
- is_interleaved=proto.is_interleaved,
63
- )
64
-
65
- @abc.abstractmethod
66
- async def stream(self, *, timeout: Optional[float] = None, **kwargs) -> AudioStream:
67
- """Stream audio samples from the audio input of the underlying robot
68
-
69
- Returns:
70
- Stream[Audio]: The stream of audio chunks
71
- """
72
- ...
73
-
74
- @abc.abstractmethod
75
- async def get_properties(self, *, timeout: Optional[float] = None, **kwargs) -> Properties:
76
- """Get the properties of the audio input of the underlying robot
77
-
78
- Returns:
79
- Properties: The audio input properties
80
- """
81
- ...
@@ -1,70 +0,0 @@
1
- from typing import Any, AsyncIterator, Dict, List, Mapping, Optional, Union
2
-
3
- from grpclib.client import Channel
4
-
5
- from viam.media.audio import Audio
6
- from viam.proto.common import DoCommandRequest, DoCommandResponse, Geometry
7
- from viam.proto.component.audioinput import (
8
- AudioInputServiceStub,
9
- ChunksRequest,
10
- ChunksResponse,
11
- PropertiesRequest,
12
- PropertiesResponse,
13
- SampleFormat,
14
- )
15
- from viam.resource.rpc_client_base import ReconfigurableResourceRPCClientBase
16
- from viam.streams import Stream, StreamWithIterator
17
- from viam.utils import ValueTypes, dict_to_struct, get_geometries, struct_to_dict
18
-
19
- from .audio_input import AudioInput
20
-
21
-
22
- class AudioInputClient(AudioInput, ReconfigurableResourceRPCClientBase):
23
- """
24
- gRPC client for the AudioInput component.
25
- """
26
-
27
- def __init__(self, name: str, channel: Channel):
28
- self.channel = channel
29
- self.client = AudioInputServiceStub(channel)
30
- super().__init__(name)
31
-
32
- async def stream(self, *, timeout: Optional[float] = None, **kwargs) -> Stream[Audio]:
33
- async def read() -> AsyncIterator[Audio]:
34
- md = kwargs.get("metadata", self.Metadata()).proto
35
- async with self.client.Chunks.open(timeout=timeout, metadata=md) as chunks_stream:
36
- await chunks_stream.send_message(
37
- ChunksRequest(name=self.name, sample_format=SampleFormat.SAMPLE_FORMAT_FLOAT32_INTERLEAVED), end=True
38
- )
39
- response: Union[ChunksResponse, None] = await chunks_stream.recv_message()
40
- if not response:
41
- await chunks_stream.recv_trailing_metadata() # causes us to throw appropriate gRPC error.
42
- raise TypeError("Response cannot be empty") # we should never get here, but for typechecking
43
- assert response.HasField("info")
44
- info = response.info
45
-
46
- while True:
47
- response = await chunks_stream.recv_message()
48
- if response is None:
49
- break
50
- assert response.HasField("chunk")
51
- audio = Audio(info=info, chunk=response.chunk)
52
- yield audio
53
-
54
- return StreamWithIterator(read())
55
-
56
- async def get_properties(self, *, timeout: Optional[float] = None, **kwargs) -> AudioInput.Properties:
57
- md = kwargs.get("metadata", self.Metadata()).proto
58
- request = PropertiesRequest(name=self.name)
59
- response: PropertiesResponse = await self.client.Properties(request, timeout=timeout, metadata=md)
60
- return AudioInput.Properties.from_proto(response)
61
-
62
- async def do_command(self, command: Mapping[str, ValueTypes], *, timeout: Optional[float] = None, **kwargs) -> Mapping[str, ValueTypes]:
63
- md = kwargs.get("metadata", self.Metadata()).proto
64
- request = DoCommandRequest(name=self.name, command=dict_to_struct(command))
65
- response: DoCommandResponse = await self.client.DoCommand(request, timeout=timeout, metadata=md)
66
- return struct_to_dict(response.result)
67
-
68
- async def get_geometries(self, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None, **kwargs) -> List[Geometry]:
69
- md = kwargs.get("metadata", self.Metadata())
70
- return await get_geometries(self.client, self.name, extra, timeout, md)
@@ -1,114 +0,0 @@
1
- import wave
2
- from datetime import timedelta
3
- from io import BytesIO
4
-
5
- from google.api.httpbody_pb2 import HttpBody # type: ignore
6
- from grpclib import GRPCError, Status
7
- from grpclib.server import Stream
8
-
9
- from viam.errors import NotSupportedError
10
- from viam.proto.common import DoCommandRequest, DoCommandResponse, GetGeometriesRequest, GetGeometriesResponse
11
- from viam.proto.component.audioinput import (
12
- AudioInputServiceBase,
13
- ChunksRequest,
14
- ChunksResponse,
15
- PropertiesRequest,
16
- PropertiesResponse,
17
- RecordRequest,
18
- SampleFormat,
19
- )
20
- from viam.resource.rpc_service_base import ResourceRPCServiceBase
21
- from viam.utils import dict_to_struct, struct_to_dict
22
-
23
- from .audio_input import AudioInput
24
-
25
-
26
- class AudioInputRPCService(AudioInputServiceBase, ResourceRPCServiceBase[AudioInput]):
27
- """
28
- gRPC Service for a generic AudioInput
29
- """
30
-
31
- RESOURCE_TYPE = AudioInput
32
-
33
- async def Chunks(self, stream: Stream[ChunksRequest, ChunksResponse]) -> None:
34
- request = await stream.recv_message()
35
- assert request is not None
36
- audio_input = self.get_resource(request.name)
37
- timeout = stream.deadline.time_remaining() if stream.deadline else None
38
- audio_stream = await audio_input.stream(timeout=timeout, metadata=stream.metadata)
39
- first_chunk = await audio_stream.__anext__()
40
- await stream.send_message(ChunksResponse(info=first_chunk.info))
41
- await stream.send_message(ChunksResponse(chunk=first_chunk.chunk))
42
-
43
- async for audio in audio_stream:
44
- await stream.send_message(ChunksResponse(chunk=audio.chunk))
45
-
46
- async def Properties(self, stream: Stream[PropertiesRequest, PropertiesResponse]) -> None:
47
- request = await stream.recv_message()
48
- assert request is not None
49
- audio_input = self.get_resource(request.name)
50
- timeout = stream.deadline.time_remaining() if stream.deadline else None
51
- response = (await audio_input.get_properties(timeout=timeout, metadata=stream.metadata)).proto
52
- await stream.send_message(response)
53
-
54
- async def Record(self, stream: Stream[RecordRequest, HttpBody]) -> None: # pyright: ignore [reportInvalidTypeForm]
55
- raise NotSupportedError("Recording audio input is not supported").grpc_error
56
-
57
- # TODO: Eventually implement recording
58
- request = await stream.recv_message()
59
- assert request is not None
60
- duration = request.duration.ToTimedelta()
61
- if duration.total_seconds() == 0:
62
- duration = timedelta(seconds=1)
63
- if duration.total_seconds() > 5:
64
- raise GRPCError(Status.INVALID_ARGUMENT, "Can only record up to 5 seconds")
65
-
66
- audio_input = self.get_resource(request.name)
67
- audio_stream = await audio_input.stream()
68
- first_chunk = await audio_stream.__anext__()
69
- num_chunks = int(duration.total_seconds() * float(first_chunk.info.sampling_rate / first_chunk.chunk.length))
70
-
71
- sample_width: int
72
- if first_chunk.info.sample_format == SampleFormat.SAMPLE_FORMAT_INT16_INTERLEAVED:
73
- sample_width = 2
74
- elif first_chunk.info.sample_format == SampleFormat.SAMPLE_FORMAT_FLOAT32_INTERLEAVED:
75
- sample_width = 4
76
- else:
77
- raise GRPCError(Status.INVALID_ARGUMENT, "Unspecified type of audio buffer")
78
-
79
- output = BytesIO()
80
- wav_file = wave.open(output, "w")
81
- wav_file.setnchannels(first_chunk.info.channels)
82
- wav_file.setframerate(first_chunk.info.sampling_rate)
83
- wav_file.setsampwidth(sample_width)
84
- try:
85
- wav_file.writeframes(first_chunk.chunk.data)
86
- for _ in range(num_chunks - 1):
87
- chunk = await audio_stream.__anext__()
88
- wav_file.writeframes(chunk.chunk.data)
89
- finally:
90
- wav_file.close()
91
- output.close()
92
-
93
- output.seek(0)
94
- response = HttpBody(data=output.read(), content_type="audio/wav")
95
-
96
- await stream.send_message(response)
97
-
98
- async def DoCommand(self, stream: Stream[DoCommandRequest, DoCommandResponse]) -> None:
99
- request = await stream.recv_message()
100
- assert request is not None
101
- audio_input = self.get_resource(request.name)
102
- timeout = stream.deadline.time_remaining() if stream.deadline else None
103
- result = await audio_input.do_command(command=struct_to_dict(request.command), timeout=timeout, metadata=stream.metadata)
104
- response = DoCommandResponse(result=dict_to_struct(result))
105
- await stream.send_message(response)
106
-
107
- async def GetGeometries(self, stream: Stream[GetGeometriesRequest, GetGeometriesResponse]) -> None:
108
- request = await stream.recv_message()
109
- assert request is not None
110
- audio_input = self.get_resource(request.name)
111
- timeout = stream.deadline.time_remaining() if stream.deadline else None
112
- geometries = await audio_input.get_geometries(extra=struct_to_dict(request.extra), timeout=timeout)
113
- response = GetGeometriesResponse(geometries=geometries)
114
- await stream.send_message(response)