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