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.
Files changed (328) hide show
  1. viam/app/_logs.py +3 -6
  2. viam/app/app_client.py +606 -262
  3. viam/app/billing_client.py +60 -18
  4. viam/app/data_client.py +1086 -315
  5. viam/app/ml_training_client.py +51 -48
  6. viam/app/provisioning_client.py +3 -5
  7. viam/app/viam_client.py +105 -11
  8. viam/components/arm/__init__.py +1 -25
  9. viam/components/arm/arm.py +21 -22
  10. viam/components/arm/client.py +27 -30
  11. viam/components/arm/service.py +3 -3
  12. viam/components/audio_in/__init__.py +24 -0
  13. viam/components/audio_in/audio_in.py +74 -0
  14. viam/components/audio_in/client.py +76 -0
  15. viam/components/audio_in/service.py +83 -0
  16. viam/components/audio_input/__init__.py +1 -1
  17. viam/components/audio_input/audio_input.py +4 -3
  18. viam/components/audio_input/client.py +19 -8
  19. viam/components/audio_input/service.py +10 -0
  20. viam/components/audio_out/__init__.py +21 -0
  21. viam/components/audio_out/audio_out.py +72 -0
  22. viam/components/audio_out/client.py +67 -0
  23. viam/components/audio_out/service.py +63 -0
  24. viam/components/base/__init__.py +2 -10
  25. viam/components/base/base.py +20 -20
  26. viam/components/base/client.py +27 -30
  27. viam/components/board/__init__.py +2 -25
  28. viam/components/board/board.py +39 -77
  29. viam/components/board/client.py +39 -73
  30. viam/components/button/__init__.py +10 -0
  31. viam/components/button/button.py +41 -0
  32. viam/components/button/client.py +52 -0
  33. viam/components/button/service.py +46 -0
  34. viam/components/camera/__init__.py +1 -1
  35. viam/components/camera/camera.py +31 -22
  36. viam/components/camera/client.py +30 -20
  37. viam/components/camera/service.py +14 -12
  38. viam/components/component_base.py +10 -7
  39. viam/components/encoder/__init__.py +1 -1
  40. viam/components/encoder/client.py +15 -16
  41. viam/components/encoder/encoder.py +9 -9
  42. viam/components/gantry/__init__.py +1 -13
  43. viam/components/gantry/client.py +41 -28
  44. viam/components/gantry/gantry.py +48 -17
  45. viam/components/gantry/service.py +21 -5
  46. viam/components/generic/__init__.py +1 -1
  47. viam/components/generic/client.py +11 -7
  48. viam/components/generic/generic.py +3 -3
  49. viam/components/gripper/__init__.py +3 -12
  50. viam/components/gripper/client.py +43 -20
  51. viam/components/gripper/gripper.py +87 -12
  52. viam/components/gripper/service.py +32 -3
  53. viam/components/input/__init__.py +1 -14
  54. viam/components/input/client.py +22 -23
  55. viam/components/input/input.py +18 -12
  56. viam/components/motor/__init__.py +1 -21
  57. viam/components/motor/client.py +36 -42
  58. viam/components/motor/motor.py +24 -24
  59. viam/components/movement_sensor/__init__.py +1 -1
  60. viam/components/movement_sensor/client.py +33 -40
  61. viam/components/movement_sensor/movement_sensor.py +12 -12
  62. viam/components/pose_tracker/__init__.py +1 -1
  63. viam/components/pose_tracker/client.py +9 -8
  64. viam/components/pose_tracker/pose_tracker.py +2 -2
  65. viam/components/power_sensor/__init__.py +1 -1
  66. viam/components/power_sensor/client.py +15 -18
  67. viam/components/power_sensor/power_sensor.py +12 -12
  68. viam/components/sensor/__init__.py +1 -1
  69. viam/components/sensor/client.py +9 -8
  70. viam/components/sensor/sensor.py +5 -5
  71. viam/components/servo/__init__.py +1 -13
  72. viam/components/servo/client.py +18 -18
  73. viam/components/servo/servo.py +12 -12
  74. viam/components/switch/__init__.py +10 -0
  75. viam/components/switch/client.py +83 -0
  76. viam/components/switch/service.py +72 -0
  77. viam/components/switch/switch.py +95 -0
  78. viam/gen/app/agent/v1/agent_pb2.py +40 -29
  79. viam/gen/app/agent/v1/agent_pb2.pyi +73 -11
  80. viam/gen/app/cloudslam/v1/cloud_slam_pb2.py +45 -42
  81. viam/gen/app/data/v1/data_grpc.py +98 -2
  82. viam/gen/app/data/v1/data_pb2.py +238 -119
  83. viam/gen/app/data/v1/data_pb2.pyi +804 -34
  84. viam/gen/app/datapipelines/v1/data_pipelines_grpc.py +84 -0
  85. viam/gen/app/datapipelines/v1/data_pipelines_pb2.py +57 -0
  86. viam/gen/app/datapipelines/v1/data_pipelines_pb2.pyi +387 -0
  87. viam/gen/app/dataset/v1/dataset_grpc.py +10 -2
  88. viam/gen/app/dataset/v1/dataset_pb2.py +38 -31
  89. viam/gen/app/dataset/v1/dataset_pb2.pyi +36 -1
  90. viam/gen/app/datasync/v1/data_sync_grpc.py +1 -1
  91. viam/gen/app/datasync/v1/data_sync_pb2.py +61 -51
  92. viam/gen/app/datasync/v1/data_sync_pb2.pyi +52 -12
  93. viam/gen/app/mlinference/__init__.py +0 -0
  94. viam/gen/app/mlinference/v1/__init__.py +0 -0
  95. viam/gen/app/mlinference/v1/ml_inference_grpc.py +28 -0
  96. viam/gen/app/mlinference/v1/ml_inference_pb2.py +23 -0
  97. viam/gen/app/mlinference/v1/ml_inference_pb2.pyi +63 -0
  98. viam/gen/app/mltraining/v1/ml_training_grpc.py +18 -2
  99. viam/gen/app/mltraining/v1/ml_training_pb2.py +134 -101
  100. viam/gen/app/mltraining/v1/ml_training_pb2.pyi +193 -7
  101. viam/gen/app/packages/v1/packages_pb2.py +43 -40
  102. viam/gen/app/v1/app_grpc.py +290 -2
  103. viam/gen/app/v1/app_pb2.py +670 -453
  104. viam/gen/app/v1/app_pb2.pyi +3133 -947
  105. viam/gen/app/v1/billing_grpc.py +34 -2
  106. viam/gen/app/v1/billing_pb2.py +94 -35
  107. viam/gen/app/v1/billing_pb2.pyi +314 -61
  108. viam/gen/app/v1/end_user_pb2.py +50 -29
  109. viam/gen/app/v1/robot_pb2.py +120 -111
  110. viam/gen/app/v1/robot_pb2.pyi +137 -15
  111. viam/gen/common/v1/common_pb2.py +86 -66
  112. viam/gen/common/v1/common_pb2.pyi +184 -8
  113. viam/gen/component/arm/v1/arm_grpc.py +18 -2
  114. viam/gen/component/arm/v1/arm_pb2.py +68 -55
  115. viam/gen/component/arm/v1/arm_pb2.pyi +73 -3
  116. viam/gen/component/audioin/__init__.py +0 -0
  117. viam/gen/component/audioin/v1/__init__.py +0 -0
  118. viam/gen/component/audioin/v1/audioin_grpc.py +54 -0
  119. viam/gen/component/audioin/v1/audioin_pb2.py +34 -0
  120. viam/gen/component/audioin/v1/audioin_pb2.pyi +94 -0
  121. viam/gen/component/audioinput/v1/audioinput_pb2.py +35 -32
  122. viam/gen/component/audioout/__init__.py +0 -0
  123. viam/gen/component/audioout/v1/__init__.py +0 -0
  124. viam/gen/component/audioout/v1/audioout_grpc.py +54 -0
  125. viam/gen/component/audioout/v1/audioout_pb2.py +32 -0
  126. viam/gen/component/audioout/v1/audioout_pb2.pyi +47 -0
  127. viam/gen/component/base/v1/base_pb2.py +57 -54
  128. viam/gen/component/board/v1/board_pb2.py +93 -90
  129. viam/gen/component/button/__init__.py +0 -0
  130. viam/gen/component/button/v1/__init__.py +0 -0
  131. viam/gen/component/button/v1/button_grpc.py +38 -0
  132. viam/gen/component/button/v1/button_pb2.py +28 -0
  133. viam/gen/component/button/v1/button_pb2.pyi +39 -0
  134. viam/gen/component/camera/v1/camera_pb2.py +58 -55
  135. viam/gen/component/camera/v1/camera_pb2.pyi +31 -7
  136. viam/gen/component/encoder/v1/encoder_pb2.py +35 -32
  137. viam/gen/component/gantry/v1/gantry_grpc.py +9 -1
  138. viam/gen/component/gantry/v1/gantry_pb2.py +56 -51
  139. viam/gen/component/generic/v1/generic_pb2.py +15 -12
  140. viam/gen/component/gripper/v1/gripper_grpc.py +18 -2
  141. viam/gen/component/gripper/v1/gripper_pb2.py +48 -37
  142. viam/gen/component/gripper/v1/gripper_pb2.pyi +43 -1
  143. viam/gen/component/inputcontroller/v1/input_controller_pb2.py +45 -42
  144. viam/gen/component/motor/v1/motor_pb2.py +77 -74
  145. viam/gen/component/movementsensor/v1/movementsensor_pb2.py +69 -66
  146. viam/gen/component/posetracker/v1/pose_tracker_pb2.py +25 -22
  147. viam/gen/component/powersensor/v1/powersensor_pb2.py +33 -30
  148. viam/gen/component/sensor/v1/sensor_pb2.py +17 -14
  149. viam/gen/component/servo/v1/servo_pb2.py +41 -38
  150. viam/gen/component/switch/__init__.py +0 -0
  151. viam/gen/component/switch/v1/__init__.py +0 -0
  152. viam/gen/component/switch/v1/switch_grpc.py +54 -0
  153. viam/gen/component/switch/v1/switch_pb2.py +40 -0
  154. viam/gen/component/switch/v1/switch_pb2.pyi +116 -0
  155. viam/gen/component/testecho/v1/testecho_pb2.py +29 -26
  156. viam/gen/module/v1/module_pb2.py +36 -33
  157. viam/gen/module/v1/module_pb2.pyi +7 -2
  158. viam/gen/proto/rpc/examples/echo/v1/echo_pb2.py +26 -23
  159. viam/gen/proto/rpc/examples/echoresource/v1/echoresource_pb2.py +23 -20
  160. viam/gen/proto/rpc/v1/auth_pb2.py +27 -24
  161. viam/gen/proto/rpc/webrtc/v1/grpc_pb2.py +35 -32
  162. viam/gen/proto/rpc/webrtc/v1/signaling_pb2.py +62 -57
  163. viam/gen/proto/rpc/webrtc/v1/signaling_pb2.pyi +18 -4
  164. viam/gen/provisioning/v1/provisioning_grpc.py +10 -2
  165. viam/gen/provisioning/v1/provisioning_pb2.py +38 -31
  166. viam/gen/provisioning/v1/provisioning_pb2.pyi +20 -2
  167. viam/gen/robot/v1/robot_grpc.py +61 -29
  168. viam/gen/robot/v1/robot_pb2.py +186 -155
  169. viam/gen/robot/v1/robot_pb2.pyi +278 -59
  170. viam/gen/service/datamanager/v1/data_manager_grpc.py +11 -2
  171. viam/gen/service/datamanager/v1/data_manager_pb2.py +27 -17
  172. viam/gen/service/datamanager/v1/data_manager_pb2.pyi +47 -1
  173. viam/gen/service/discovery/__init__.py +0 -0
  174. viam/gen/service/discovery/v1/__init__.py +0 -0
  175. viam/gen/service/discovery/v1/discovery_grpc.py +39 -0
  176. viam/gen/service/discovery/v1/discovery_pb2.py +29 -0
  177. viam/gen/service/discovery/v1/discovery_pb2.pyi +51 -0
  178. viam/gen/service/generic/v1/generic_pb2.py +13 -10
  179. viam/gen/service/mlmodel/v1/mlmodel_pb2.py +75 -72
  180. viam/gen/service/motion/v1/motion_pb2.py +118 -85
  181. viam/gen/service/motion/v1/motion_pb2.pyi +130 -68
  182. viam/gen/service/navigation/v1/navigation_pb2.py +75 -72
  183. viam/gen/service/sensors/v1/sensors_pb2.py +59 -56
  184. viam/gen/service/shell/v1/shell_pb2.py +35 -32
  185. viam/gen/service/slam/v1/slam_pb2.py +43 -40
  186. viam/gen/service/slam/v1/slam_pb2.pyi +1 -1
  187. viam/gen/service/video/__init__.py +0 -0
  188. viam/gen/service/video/v1/__init__.py +0 -0
  189. viam/gen/service/video/v1/video_grpc.py +39 -0
  190. viam/gen/service/video/v1/video_pb2.py +29 -0
  191. viam/gen/service/video/v1/video_pb2.pyi +72 -0
  192. viam/gen/service/vision/v1/vision_pb2.py +60 -57
  193. viam/gen/service/vision/v1/vision_pb2.pyi +28 -3
  194. viam/gen/service/worldstatestore/__init__.py +0 -0
  195. viam/gen/service/worldstatestore/v1/__init__.py +0 -0
  196. viam/gen/service/worldstatestore/v1/world_state_store_grpc.py +55 -0
  197. viam/gen/service/worldstatestore/v1/world_state_store_pb2.py +39 -0
  198. viam/gen/service/worldstatestore/v1/world_state_store_pb2.pyi +171 -0
  199. viam/gen/stream/v1/stream_grpc.py +17 -1
  200. viam/gen/stream/v1/stream_pb2.py +34 -21
  201. viam/gen/stream/v1/stream_pb2.pyi +79 -1
  202. viam/gen/tagger/v1/tagger_pb2.py +9 -8
  203. viam/logging.py +77 -18
  204. viam/media/audio.py +28 -0
  205. viam/media/utils/pil/__init__.py +7 -3
  206. viam/media/video.py +80 -17
  207. viam/module/module.py +111 -38
  208. viam/module/resource_data_consumer.py +41 -0
  209. viam/module/service.py +9 -1
  210. viam/module/types.py +2 -4
  211. viam/proto/app/__init__.py +199 -0
  212. viam/proto/app/agent/__init__.py +5 -2
  213. viam/proto/app/billing.py +31 -4
  214. viam/proto/app/cloudslam/__init__.py +1 -0
  215. viam/proto/app/data/__init__.py +63 -0
  216. viam/proto/app/datapipelines/__init__.py +56 -0
  217. viam/proto/app/dataset/__init__.py +5 -0
  218. viam/proto/app/datasync/__init__.py +3 -0
  219. viam/proto/app/end_user.py +1 -0
  220. viam/proto/app/mlinference/__init__.py +15 -0
  221. viam/proto/app/mltraining/__init__.py +13 -0
  222. viam/proto/app/packages/__init__.py +1 -0
  223. viam/proto/app/robot.py +7 -0
  224. viam/proto/common/__init__.py +15 -0
  225. viam/proto/component/arm/__init__.py +7 -0
  226. viam/proto/component/audioin/__init__.py +16 -0
  227. viam/proto/component/audioinput/__init__.py +1 -0
  228. viam/proto/component/audioout/__init__.py +15 -0
  229. viam/proto/component/base/__init__.py +1 -0
  230. viam/proto/component/board/__init__.py +1 -0
  231. viam/proto/component/button/__init__.py +15 -0
  232. viam/proto/component/camera/__init__.py +1 -0
  233. viam/proto/component/encoder/__init__.py +1 -0
  234. viam/proto/component/gantry/__init__.py +1 -0
  235. viam/proto/component/generic/__init__.py +1 -0
  236. viam/proto/component/gripper/__init__.py +5 -0
  237. viam/proto/component/inputcontroller/__init__.py +1 -0
  238. viam/proto/component/motor/__init__.py +1 -0
  239. viam/proto/component/movementsensor/__init__.py +1 -0
  240. viam/proto/component/posetracker/__init__.py +1 -0
  241. viam/proto/component/powersensor/__init__.py +1 -0
  242. viam/proto/component/sensor/__init__.py +1 -0
  243. viam/proto/component/servo/__init__.py +1 -0
  244. viam/proto/component/switch/__init__.py +26 -0
  245. viam/proto/component/testecho/__init__.py +1 -0
  246. viam/proto/module/__init__.py +1 -0
  247. viam/proto/provisioning/__init__.py +5 -0
  248. viam/proto/robot/__init__.py +29 -8
  249. viam/proto/rpc/auth.py +1 -0
  250. viam/proto/rpc/examples/echo/__init__.py +1 -0
  251. viam/proto/rpc/examples/echoresource/__init__.py +1 -0
  252. viam/proto/rpc/webrtc/grpc.py +1 -0
  253. viam/proto/rpc/webrtc/signaling.py +3 -0
  254. viam/proto/service/datamanager/__init__.py +9 -1
  255. viam/proto/service/discovery/__init__.py +15 -0
  256. viam/proto/service/generic/__init__.py +1 -0
  257. viam/proto/service/mlmodel/__init__.py +1 -0
  258. viam/proto/service/motion/__init__.py +3 -0
  259. viam/proto/service/navigation/__init__.py +1 -0
  260. viam/proto/service/sensors/__init__.py +1 -0
  261. viam/proto/service/shell/__init__.py +1 -0
  262. viam/proto/service/slam/__init__.py +1 -0
  263. viam/proto/service/video/__init__.py +15 -0
  264. viam/proto/service/vision/__init__.py +1 -0
  265. viam/proto/service/worldstatestore/__init__.py +32 -0
  266. viam/proto/stream/__init__.py +11 -0
  267. viam/py.typed +0 -0
  268. viam/resource/base.py +12 -8
  269. viam/resource/easy_resource.py +24 -13
  270. viam/resource/manager.py +6 -5
  271. viam/resource/registry.py +39 -51
  272. viam/resource/rpc_client_base.py +33 -1
  273. viam/resource/types.py +13 -14
  274. viam/robot/client.py +190 -122
  275. viam/robot/service.py +2 -50
  276. viam/rpc/dial.py +54 -4
  277. viam/rpc/libviam_rust_utils.so +0 -0
  278. viam/rpc/server.py +25 -11
  279. viam/rpc/types.py +2 -4
  280. viam/services/discovery/__init__.py +12 -0
  281. viam/services/discovery/client.py +55 -0
  282. viam/services/discovery/discovery.py +52 -0
  283. viam/services/discovery/service.py +43 -0
  284. viam/services/generic/__init__.py +1 -1
  285. viam/services/generic/client.py +8 -5
  286. viam/services/generic/generic.py +2 -2
  287. viam/services/mlmodel/__init__.py +1 -1
  288. viam/services/mlmodel/client.py +17 -7
  289. viam/services/mlmodel/mlmodel.py +23 -12
  290. viam/services/mlmodel/service.py +5 -2
  291. viam/services/mlmodel/utils.py +11 -1
  292. viam/services/motion/__init__.py +2 -2
  293. viam/services/motion/client.py +32 -32
  294. viam/services/motion/motion.py +66 -62
  295. viam/services/navigation/__init__.py +1 -1
  296. viam/services/navigation/client.py +30 -20
  297. viam/services/navigation/navigation.py +23 -23
  298. viam/services/service_base.py +13 -9
  299. viam/services/service_client_base.py +3 -3
  300. viam/services/slam/__init__.py +1 -1
  301. viam/services/slam/client.py +15 -10
  302. viam/services/slam/slam.py +11 -11
  303. viam/services/vision/__init__.py +1 -1
  304. viam/services/vision/client.py +31 -24
  305. viam/services/vision/service.py +8 -8
  306. viam/services/vision/vision.py +36 -53
  307. viam/services/worldstatestore/__init__.py +18 -0
  308. viam/services/worldstatestore/client.py +94 -0
  309. viam/services/worldstatestore/service.py +55 -0
  310. viam/services/worldstatestore/worldstatestore.py +90 -0
  311. viam/sessions_client.py +115 -46
  312. viam/streams.py +3 -6
  313. viam/utils.py +44 -14
  314. viam/version_metadata.py +4 -0
  315. {viam_sdk-0.25.2.dist-info → viam_sdk-0.62.0.dist-info}/METADATA +27 -28
  316. viam_sdk-0.62.0.dist-info/RECORD +514 -0
  317. {viam_sdk-0.25.2.dist-info → viam_sdk-0.62.0.dist-info}/WHEEL +1 -1
  318. viam/gen/proto/rpc/examples/fileupload/v1/fileupload_grpc.py +0 -27
  319. viam/gen/proto/rpc/examples/fileupload/v1/fileupload_pb2.py +0 -18
  320. viam/gen/proto/rpc/examples/fileupload/v1/fileupload_pb2.pyi +0 -45
  321. viam/proto/rpc/examples/fileupload/__init__.py +0 -18
  322. viam/services/sensors/__init__.py +0 -5
  323. viam/services/sensors/client.py +0 -65
  324. viam_sdk-0.25.2.dist-info/LICENSE +0 -202
  325. viam_sdk-0.25.2.dist-info/RECORD +0 -442
  326. /viam/gen/{proto/rpc/examples/fileupload → app/datapipelines}/__init__.py +0 -0
  327. /viam/gen/{proto/rpc/examples/fileupload → app/datapipelines}/v1/__init__.py +0 -0
  328. /LICENSE → /viam_sdk-0.62.0.dist-info/licenses/LICENSE +0 -0
@@ -39,12 +39,11 @@ class ArmClient(Arm, ReconfigurableResourceRPCClientBase):
39
39
  *,
40
40
  extra: Optional[Dict[str, Any]] = None,
41
41
  timeout: Optional[float] = None,
42
- **__,
42
+ **kwargs,
43
43
  ) -> Pose:
44
- if extra is None:
45
- extra = {}
44
+ md = kwargs.get("metadata", self.Metadata()).proto
46
45
  request = GetEndPositionRequest(name=self.name, extra=dict_to_struct(extra))
47
- response: GetEndPositionResponse = await self.client.GetEndPosition(request, timeout=timeout)
46
+ response: GetEndPositionResponse = await self.client.GetEndPosition(request, timeout=timeout, metadata=md)
48
47
  return response.pose
49
48
 
50
49
  async def move_to_position(
@@ -53,24 +52,22 @@ class ArmClient(Arm, ReconfigurableResourceRPCClientBase):
53
52
  *,
54
53
  extra: Optional[Dict[str, Any]] = None,
55
54
  timeout: Optional[float] = None,
56
- **__,
55
+ **kwargs,
57
56
  ):
58
- if extra is None:
59
- extra = {}
57
+ md = kwargs.get("metadata", self.Metadata()).proto
60
58
  request = MoveToPositionRequest(name=self.name, to=pose, extra=dict_to_struct(extra))
61
- await self.client.MoveToPosition(request, timeout=timeout)
59
+ await self.client.MoveToPosition(request, timeout=timeout, metadata=md)
62
60
 
63
61
  async def get_joint_positions(
64
62
  self,
65
63
  *,
66
64
  extra: Optional[Dict[str, Any]] = None,
67
65
  timeout: Optional[float] = None,
68
- **__,
66
+ **kwargs,
69
67
  ) -> JointPositions:
70
- if extra is None:
71
- extra = {}
68
+ md = kwargs.get("metadata", self.Metadata()).proto
72
69
  request = GetJointPositionsRequest(name=self.name, extra=dict_to_struct(extra))
73
- response: GetJointPositionsResponse = await self.client.GetJointPositions(request, timeout=timeout)
70
+ response: GetJointPositionsResponse = await self.client.GetJointPositions(request, timeout=timeout, metadata=md)
74
71
  return response.positions
75
72
 
76
73
  async def move_to_joint_positions(
@@ -79,28 +76,27 @@ class ArmClient(Arm, ReconfigurableResourceRPCClientBase):
79
76
  *,
80
77
  extra: Optional[Dict[str, Any]] = None,
81
78
  timeout: Optional[float] = None,
82
- **__,
79
+ **kwargs,
83
80
  ):
84
- if extra is None:
85
- extra = {}
81
+ md = kwargs.get("metadata", self.Metadata()).proto
86
82
  request = MoveToJointPositionsRequest(name=self.name, positions=positions, extra=dict_to_struct(extra))
87
- await self.client.MoveToJointPositions(request, timeout=timeout)
83
+ await self.client.MoveToJointPositions(request, timeout=timeout, metadata=md)
88
84
 
89
85
  async def stop(
90
86
  self,
91
87
  *,
92
88
  extra: Optional[Dict[str, Any]] = None,
93
89
  timeout: Optional[float] = None,
94
- **__,
90
+ **kwargs,
95
91
  ):
96
- if extra is None:
97
- extra = {}
92
+ md = kwargs.get("metadata", self.Metadata()).proto
98
93
  request = StopRequest(name=self.name, extra=dict_to_struct(extra))
99
- await self.client.Stop(request, timeout=timeout)
94
+ await self.client.Stop(request, timeout=timeout, metadata=md)
100
95
 
101
- async def is_moving(self, *, timeout: Optional[float] = None) -> bool:
96
+ async def is_moving(self, *, timeout: Optional[float] = None, **kwargs) -> bool:
97
+ md = kwargs.get("metadata", self.Metadata()).proto
102
98
  request = IsMovingRequest(name=self.name)
103
- response: IsMovingResponse = await self.client.IsMoving(request, timeout=timeout)
99
+ response: IsMovingResponse = await self.client.IsMoving(request, timeout=timeout, metadata=md)
104
100
  return response.is_moving
105
101
 
106
102
  async def do_command(
@@ -108,20 +104,21 @@ class ArmClient(Arm, ReconfigurableResourceRPCClientBase):
108
104
  command: Mapping[str, Any],
109
105
  *,
110
106
  timeout: Optional[float] = None,
111
- **__,
107
+ **kwargs,
112
108
  ) -> Mapping[str, ValueTypes]:
109
+ md = kwargs.get("metadata", self.Metadata()).proto
113
110
  request = DoCommandRequest(name=self.name, command=dict_to_struct(command))
114
- response: DoCommandResponse = await self.client.DoCommand(request, timeout=timeout)
111
+ response: DoCommandResponse = await self.client.DoCommand(request, timeout=timeout, metadata=md)
115
112
  return struct_to_dict(response.result)
116
113
 
117
114
  async def get_kinematics(
118
- self, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None
115
+ self, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None, **kwargs
119
116
  ) -> Tuple[KinematicsFileFormat.ValueType, bytes]:
120
- if extra is None:
121
- extra = {}
117
+ md = kwargs.get("metadata", self.Metadata()).proto
122
118
  request = GetKinematicsRequest(name=self.name, extra=dict_to_struct(extra))
123
- response: GetKinematicsResponse = await self.client.GetKinematics(request, timeout=timeout)
119
+ response: GetKinematicsResponse = await self.client.GetKinematics(request, timeout=timeout, metadata=md)
124
120
  return (response.format, response.kinematics_data)
125
121
 
126
- async def get_geometries(self, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None) -> List[Geometry]:
127
- return await get_geometries(self.client, self.name, extra, timeout)
122
+ async def get_geometries(self, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None, **kwargs) -> List[Geometry]:
123
+ md = kwargs.get("metadata", self.Metadata())
124
+ return await get_geometries(self.client, self.name, extra, timeout, md)
@@ -9,7 +9,6 @@ from viam.proto.common import (
9
9
  GetKinematicsResponse,
10
10
  )
11
11
  from viam.proto.component.arm import (
12
- ArmServiceBase,
13
12
  GetEndPositionRequest,
14
13
  GetEndPositionResponse,
15
14
  GetJointPositionsRequest,
@@ -22,6 +21,7 @@ from viam.proto.component.arm import (
22
21
  MoveToPositionResponse,
23
22
  StopRequest,
24
23
  StopResponse,
24
+ UnimplementedArmServiceBase,
25
25
  )
26
26
  from viam.resource.rpc_service_base import ResourceRPCServiceBase
27
27
  from viam.utils import dict_to_struct, struct_to_dict
@@ -29,7 +29,7 @@ from viam.utils import dict_to_struct, struct_to_dict
29
29
  from .arm import Arm
30
30
 
31
31
 
32
- class ArmRPCService(ArmServiceBase, ResourceRPCServiceBase[Arm]):
32
+ class ArmRPCService(UnimplementedArmServiceBase, ResourceRPCServiceBase[Arm]):
33
33
  """
34
34
  gRPC Service for an Arm
35
35
  """
@@ -109,7 +109,7 @@ class ArmRPCService(ArmServiceBase, ResourceRPCServiceBase[Arm]):
109
109
  assert request is not None
110
110
  arm = self.get_resource(request.name)
111
111
  timeout = stream.deadline.time_remaining() if stream.deadline else None
112
- format, kinematics_data = await arm.get_kinematics(extra=struct_to_dict(request.extra), timeout=timeout)
112
+ format, kinematics_data = await arm.get_kinematics(extra=struct_to_dict(request.extra), timeout=timeout, metadata=stream.metadata)
113
113
  response = GetKinematicsResponse(format=format, kinematics_data=kinematics_data)
114
114
  await stream.send_message(response)
115
115
 
@@ -0,0 +1,24 @@
1
+ from viam.media.audio import AudioCodec
2
+ from viam.proto.common import AudioInfo
3
+ from viam.resource.registry import Registry, ResourceRegistration
4
+
5
+ from .audio_in import AudioIn
6
+ from .client import AudioInClient
7
+ from .service import AudioInRPCService
8
+
9
+ AudioResponse = AudioIn.AudioResponse
10
+
11
+ __all__ = [
12
+ "AudioIn",
13
+ "AudioResponse",
14
+ "AudioInfo",
15
+ "AudioCodec",
16
+ ]
17
+
18
+ Registry.register_api(
19
+ ResourceRegistration(
20
+ AudioIn,
21
+ AudioInRPCService,
22
+ lambda name, channel: AudioInClient(name, channel),
23
+ )
24
+ )
@@ -0,0 +1,74 @@
1
+ import abc
2
+ import sys
3
+ from typing import Final, Optional
4
+
5
+ from viam.proto.common import GetPropertiesResponse
6
+ from viam.proto.component.audioin import GetAudioResponse
7
+ from viam.resource.types import API, RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT
8
+ from viam.streams import Stream
9
+
10
+ from ..component_base import ComponentBase
11
+
12
+ if sys.version_info >= (3, 10):
13
+ from typing import TypeAlias
14
+ else:
15
+ from typing_extensions import TypeAlias
16
+
17
+
18
+ class AudioIn(ComponentBase):
19
+ """AudioIn represents a component that can capture audio.
20
+
21
+ This acts as an abstract base class for any drivers representing specific
22
+ audio input implementations. This cannot be used on its own. If the ``__init__()`` function is
23
+ overridden, it must call the ``super().__init__()`` function.
24
+ """
25
+
26
+ API: Final = API( # pyright: ignore [reportIncompatibleVariableOverride]
27
+ RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT, "audio_in"
28
+ )
29
+
30
+ Properties: "TypeAlias" = GetPropertiesResponse
31
+ AudioResponse: "TypeAlias" = GetAudioResponse
32
+ AudioStream = Stream[AudioResponse]
33
+
34
+ @abc.abstractmethod
35
+ async def get_audio(
36
+ self, codec: str, duration_seconds: float, previous_timestamp_ns: int, *, timeout: Optional[float] = None, **kwargs
37
+ ) -> AudioStream:
38
+ """
39
+ Get a stream of audio from the device
40
+
41
+ ::
42
+
43
+ my_audio_in = AudioIn.from_robot(robot=machine, name="my_audio_in")
44
+
45
+ stream = await my_audio_in.get_audio(
46
+ codec=AudioCodec.PCM16,
47
+ duration_seconds=10.0,
48
+ previous_timestamp_ns=0
49
+ )
50
+
51
+ Args:
52
+ codec (str): The desired codec of the returned audio data
53
+ duration_seconds (float): duration of the stream. 0 = indefinite stream
54
+ previous_timestamp_ns (int): starting timestamp in nanoseconds for recording continuity.
55
+ Set to 0 to begin recording from the current time.
56
+ Returns:
57
+ AudioStream: stream of audio chunks.
58
+ ...
59
+ """
60
+
61
+ @abc.abstractmethod
62
+ async def get_properties(self, *, timeout: Optional[float] = None, **kwargs) -> Properties:
63
+ """
64
+ Get the audio device's properties
65
+
66
+ ::
67
+
68
+ my_audio_in = AudioIn.from_robot(robot=machine, name="my_audio_in")
69
+ properties = await my_audio_in.get_properties()
70
+
71
+ Returns:
72
+ Properties: The properties of the audio in device.
73
+ ...
74
+ """
@@ -0,0 +1,76 @@
1
+ import uuid
2
+ from typing import Any, Dict, List, Mapping, Optional
3
+
4
+ from grpclib.client import Channel
5
+ from grpclib.client import Stream as ClientStream
6
+
7
+ from viam.proto.common import DoCommandRequest, DoCommandResponse, Geometry, GetPropertiesRequest
8
+ from viam.proto.component.audioin import AudioInServiceStub, GetAudioRequest, GetAudioResponse
9
+ from viam.resource.rpc_client_base import ReconfigurableResourceRPCClientBase
10
+ from viam.streams import StreamWithIterator
11
+ from viam.utils import ValueTypes, dict_to_struct, get_geometries, struct_to_dict
12
+
13
+ from .audio_in import AudioIn
14
+
15
+
16
+ class AudioInClient(AudioIn, ReconfigurableResourceRPCClientBase):
17
+ def __init__(self, name: str, channel: Channel) -> None:
18
+ self.channel = channel
19
+ self.client = AudioInServiceStub(channel)
20
+ super().__init__(name)
21
+
22
+ async def get_audio(
23
+ self,
24
+ codec: str,
25
+ duration_seconds: float,
26
+ previous_timestamp_ns: int,
27
+ *,
28
+ extra: Optional[Dict[str, Any]] = None,
29
+ **kwargs,
30
+ ):
31
+ request = GetAudioRequest(
32
+ name=self.name,
33
+ codec=codec,
34
+ duration_seconds=duration_seconds,
35
+ previous_timestamp_nanoseconds=previous_timestamp_ns,
36
+ request_id=str(uuid.uuid4()),
37
+ extra=dict_to_struct(extra),
38
+ )
39
+
40
+ async def read():
41
+ md = kwargs.get("metadata", self.Metadata()).proto
42
+ audio_stream: ClientStream[GetAudioRequest, GetAudioResponse]
43
+ async with self.client.GetAudio.open(metadata=md) as audio_stream:
44
+ try:
45
+ await audio_stream.send_message(request, end=True)
46
+ async for response in audio_stream:
47
+ yield response
48
+ except Exception as e:
49
+ raise (e)
50
+
51
+ return StreamWithIterator(read())
52
+
53
+ async def get_properties(
54
+ self,
55
+ *,
56
+ timeout: Optional[float] = None,
57
+ **kwargs,
58
+ ) -> AudioIn.Properties:
59
+ md = kwargs.get("metadata", self.Metadata()).proto
60
+ return await self.client.GetProperties(GetPropertiesRequest(name=self.name), timeout=timeout, metadata=md)
61
+
62
+ async def do_command(
63
+ self,
64
+ command: Mapping[str, ValueTypes],
65
+ *,
66
+ timeout: Optional[float] = None,
67
+ **kwargs,
68
+ ) -> Mapping[str, ValueTypes]:
69
+ md = kwargs.get("metadata", self.Metadata()).proto
70
+ request = DoCommandRequest(name=self.name, command=dict_to_struct(command))
71
+ response: DoCommandResponse = await self.client.DoCommand(request, timeout=timeout, metadata=md)
72
+ return struct_to_dict(response.result)
73
+
74
+ async def get_geometries(self, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None, **kwargs) -> List[Geometry]:
75
+ md = kwargs.get("metadata", self.Metadata())
76
+ return await get_geometries(self.client, self.name, extra, timeout, md)
@@ -0,0 +1,83 @@
1
+ from grpclib.server import Stream
2
+ from h2.exceptions import StreamClosedError
3
+
4
+ from viam.logging import getLogger
5
+ from viam.proto.common import (
6
+ DoCommandRequest,
7
+ DoCommandResponse,
8
+ GetGeometriesRequest,
9
+ GetGeometriesResponse,
10
+ GetPropertiesRequest,
11
+ GetPropertiesResponse,
12
+ )
13
+ from viam.proto.component.audioin import AudioInServiceBase, GetAudioRequest, GetAudioResponse
14
+ from viam.resource.rpc_service_base import ResourceRPCServiceBase
15
+ from viam.utils import dict_to_struct, struct_to_dict
16
+
17
+ from .audio_in import AudioIn
18
+
19
+ LOGGER = getLogger(__name__)
20
+
21
+
22
+ class AudioInRPCService(AudioInServiceBase, ResourceRPCServiceBase[AudioIn]):
23
+ """
24
+ gRPC Service for a generic audio in.
25
+ """
26
+
27
+ RESOURCE_TYPE = AudioIn
28
+
29
+ async def GetAudio(self, stream: Stream[GetAudioRequest, GetAudioResponse]) -> None:
30
+ request = await stream.recv_message()
31
+ assert request is not None
32
+ name = request.name
33
+ audio_in = self.get_resource(name)
34
+ audio_stream = await audio_in.get_audio(
35
+ codec=request.codec,
36
+ duration_seconds=request.duration_seconds,
37
+ previous_timestamp_ns=request.previous_timestamp_nanoseconds,
38
+ metadata=stream.metadata,
39
+ )
40
+ async for response in audio_stream:
41
+ try:
42
+ response.request_id = request.request_id
43
+ await stream.send_message(response)
44
+ except StreamClosedError:
45
+ return
46
+ except Exception as e:
47
+ LOGGER.error(e)
48
+ return
49
+
50
+ async def GetProperties(self, stream: Stream[GetPropertiesRequest, GetPropertiesResponse]) -> None:
51
+ request = await stream.recv_message()
52
+ assert request is not None
53
+ name = request.name
54
+ audio_in = self.get_resource(name)
55
+ timeout = stream.deadline.time_remaining() if stream.deadline else None
56
+ properties = await audio_in.get_properties(
57
+ timeout=timeout,
58
+ metadata=stream.metadata,
59
+ )
60
+ await stream.send_message(properties)
61
+
62
+ async def DoCommand(self, stream: Stream[DoCommandRequest, DoCommandResponse]) -> None:
63
+ request = await stream.recv_message()
64
+ assert request is not None
65
+ name = request.name
66
+ audio_in = self.get_resource(name)
67
+ timeout = stream.deadline.time_remaining() if stream.deadline else None
68
+ result = await audio_in.do_command(
69
+ command=struct_to_dict(request.command),
70
+ timeout=timeout,
71
+ metadata=stream.metadata,
72
+ )
73
+ response = DoCommandResponse(result=dict_to_struct(result))
74
+ await stream.send_message(response)
75
+
76
+ async def GetGeometries(self, stream: Stream[GetGeometriesRequest, GetGeometriesResponse]) -> None:
77
+ request = await stream.recv_message()
78
+ assert request is not None
79
+ arm = self.get_resource(request.name)
80
+ timeout = stream.deadline.time_remaining() if stream.deadline else None
81
+ geometries = await arm.get_geometries(extra=struct_to_dict(request.extra), timeout=timeout)
82
+ response = GetGeometriesResponse(geometries=geometries)
83
+ await stream.send_message(response)
@@ -9,7 +9,7 @@ __all__ = [
9
9
  ]
10
10
 
11
11
 
12
- Registry.register_subtype(
12
+ Registry.register_api(
13
13
  ResourceRegistration(
14
14
  AudioInput,
15
15
  AudioInputRPCService,
@@ -8,21 +8,22 @@ from typing_extensions import Self
8
8
 
9
9
  from viam.media.audio import Audio, AudioStream
10
10
  from viam.proto.component.audioinput import PropertiesResponse
11
- from viam.resource.types import RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT, Subtype
11
+ from viam.resource.types import API, RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT
12
12
  from viam.streams import StreamSource
13
13
 
14
14
  from ..component_base import ComponentBase
15
15
 
16
16
 
17
17
  class AudioInput(ComponentBase, StreamSource[Audio]):
18
- """AudioInput represents a component that can capture audio.
18
+ """DEPRECATED: AudioInput is deprecated, use AudioIn instead
19
+ AudioInput represents a component that can capture audio.
19
20
 
20
21
  This acts as an abstract base class for any drivers representing specific
21
22
  audio input implementations. This cannot be used on its own. If the ``__init__()`` function is
22
23
  overridden, it must call the ``super().__init__()`` function.
23
24
  """
24
25
 
25
- SUBTYPE: Final = Subtype( # pyright: ignore [reportIncompatibleVariableOverride]
26
+ API: Final = API( # pyright: ignore [reportIncompatibleVariableOverride]
26
27
  RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT, "audio_input"
27
28
  )
28
29
 
@@ -1,3 +1,4 @@
1
+ import warnings
1
2
  from typing import Any, AsyncIterator, Dict, List, Mapping, Optional, Union
2
3
 
3
4
  from grpclib.client import Channel
@@ -21,17 +22,24 @@ from .audio_input import AudioInput
21
22
 
22
23
  class AudioInputClient(AudioInput, ReconfigurableResourceRPCClientBase):
23
24
  """
25
+ DEPRECATED: AudioInput is deprecated, use AudioIn instead.
24
26
  gRPC client for the AudioInput component.
25
27
  """
26
28
 
27
29
  def __init__(self, name: str, channel: Channel):
30
+ warnings.warn(
31
+ "AudioInputClient is deprecated and will be removed in a future release. " "Use AudioIn instead.",
32
+ DeprecationWarning,
33
+ stacklevel=2,
34
+ )
28
35
  self.channel = channel
29
36
  self.client = AudioInputServiceStub(channel)
30
37
  super().__init__(name)
31
38
 
32
- async def stream(self, *, timeout: Optional[float] = None, **__) -> Stream[Audio]:
39
+ async def stream(self, *, timeout: Optional[float] = None, **kwargs) -> Stream[Audio]:
33
40
  async def read() -> AsyncIterator[Audio]:
34
- async with self.client.Chunks.open(timeout=timeout) as chunks_stream:
41
+ md = kwargs.get("metadata", self.Metadata()).proto
42
+ async with self.client.Chunks.open(timeout=timeout, metadata=md) as chunks_stream:
35
43
  await chunks_stream.send_message(
36
44
  ChunksRequest(name=self.name, sample_format=SampleFormat.SAMPLE_FORMAT_FLOAT32_INTERLEAVED), end=True
37
45
  )
@@ -52,15 +60,18 @@ class AudioInputClient(AudioInput, ReconfigurableResourceRPCClientBase):
52
60
 
53
61
  return StreamWithIterator(read())
54
62
 
55
- async def get_properties(self, *, timeout: Optional[float] = None, **__) -> AudioInput.Properties:
63
+ async def get_properties(self, *, timeout: Optional[float] = None, **kwargs) -> AudioInput.Properties:
64
+ md = kwargs.get("metadata", self.Metadata()).proto
56
65
  request = PropertiesRequest(name=self.name)
57
- response: PropertiesResponse = await self.client.Properties(request, timeout=timeout)
66
+ response: PropertiesResponse = await self.client.Properties(request, timeout=timeout, metadata=md)
58
67
  return AudioInput.Properties.from_proto(response)
59
68
 
60
- async def do_command(self, command: Mapping[str, ValueTypes], *, timeout: Optional[float] = None, **__) -> Mapping[str, ValueTypes]:
69
+ async def do_command(self, command: Mapping[str, ValueTypes], *, timeout: Optional[float] = None, **kwargs) -> Mapping[str, ValueTypes]:
70
+ md = kwargs.get("metadata", self.Metadata()).proto
61
71
  request = DoCommandRequest(name=self.name, command=dict_to_struct(command))
62
- response: DoCommandResponse = await self.client.DoCommand(request, timeout=timeout)
72
+ response: DoCommandResponse = await self.client.DoCommand(request, timeout=timeout, metadata=md)
63
73
  return struct_to_dict(response.result)
64
74
 
65
- async def get_geometries(self, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None) -> List[Geometry]:
66
- return await get_geometries(self.client, self.name, extra, timeout)
75
+ async def get_geometries(self, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None, **kwargs) -> List[Geometry]:
76
+ md = kwargs.get("metadata", self.Metadata())
77
+ return await get_geometries(self.client, self.name, extra, timeout, md)
@@ -1,3 +1,4 @@
1
+ import warnings
1
2
  import wave
2
3
  from datetime import timedelta
3
4
  from io import BytesIO
@@ -25,9 +26,18 @@ from .audio_input import AudioInput
25
26
 
26
27
  class AudioInputRPCService(AudioInputServiceBase, ResourceRPCServiceBase[AudioInput]):
27
28
  """
29
+ DEPRECATED: AudioInput is deprecated, use AudioIn instead.
28
30
  gRPC Service for a generic AudioInput
29
31
  """
30
32
 
33
+ def __init__(self, *args, **kwargs):
34
+ warnings.warn(
35
+ "AudioInput is deprecated and will be removed in a future release. " "Use AudioIn instead.",
36
+ DeprecationWarning,
37
+ stacklevel=2,
38
+ )
39
+ super().__init__(*args, **kwargs)
40
+
31
41
  RESOURCE_TYPE = AudioInput
32
42
 
33
43
  async def Chunks(self, stream: Stream[ChunksRequest, ChunksResponse]) -> None:
@@ -0,0 +1,21 @@
1
+ from viam.media.audio import AudioCodec
2
+ from viam.proto.common import AudioInfo
3
+ from viam.resource.registry import Registry, ResourceRegistration
4
+
5
+ from .audio_out import AudioOut
6
+ from .client import AudioOutClient
7
+ from .service import AudioOutRPCService
8
+
9
+ __all__ = [
10
+ "AudioOut",
11
+ "AudioInfo",
12
+ "AudioCodec",
13
+ ]
14
+
15
+ Registry.register_api(
16
+ ResourceRegistration(
17
+ AudioOut,
18
+ AudioOutRPCService,
19
+ lambda name, channel: AudioOutClient(name, channel),
20
+ )
21
+ )
@@ -0,0 +1,72 @@
1
+ import abc
2
+ import sys
3
+ from typing import Any, Dict, Final, Optional
4
+
5
+ from viam.proto.common import GetPropertiesResponse
6
+ from viam.resource.types import API, RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_COMPONENT
7
+
8
+ from ..component_base import ComponentBase
9
+ from . import AudioInfo
10
+
11
+ if sys.version_info >= (3, 10):
12
+ from typing import TypeAlias
13
+ else:
14
+ from typing_extensions import TypeAlias
15
+
16
+
17
+ class AudioOut(ComponentBase):
18
+ """AudioOut represents a component that can play audio.
19
+
20
+ This acts as an abstract base class for any drivers representing specific
21
+ audio output 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_out"
27
+ )
28
+
29
+ Properties: "TypeAlias" = GetPropertiesResponse
30
+
31
+ @abc.abstractmethod
32
+ async def play(
33
+ self,
34
+ data: bytes,
35
+ info: Optional[AudioInfo] = None,
36
+ *,
37
+ extra: Optional[Dict[str, Any]] = None,
38
+ timeout: Optional[float] = None,
39
+ **kwargs,
40
+ ) -> None:
41
+ """
42
+ Play the given audio data.
43
+
44
+ ::
45
+
46
+ my_audio_out = AudioOut.from_robot(robot=machine, name="my_audio_out")
47
+
48
+ # With audio info
49
+ audio_info = AudioInfo(codec=AudioCodec.PCM16, sample_rate_hz=44100, num_channels=2)
50
+ await my_audio_out.play(audio_data, audio_info)
51
+
52
+ # Without audio info (when codec encodes information within audio_data)
53
+ await my_audio_out.play(audio_data)
54
+
55
+ Args:
56
+ data: audio bytes to play
57
+ info: (optional) information about the audio data such as codec, sample rate, and channel count
58
+ """
59
+
60
+ @abc.abstractmethod
61
+ async def get_properties(self, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None, **kwargs) -> Properties:
62
+ """
63
+ Get the audio output device's properties.
64
+
65
+ ::
66
+
67
+ my_audio_out = AudioOut.from_robot(robot=machine, name="my_audio_out")
68
+ properties = await my_audio_out.get_properties()
69
+
70
+ Returns:
71
+ Properties: The properties of the audio output device
72
+ """