viam-sdk 0.45.2__py3-none-win_amd64.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 (476) hide show
  1. viam/__init__.py +71 -0
  2. viam/app/__init__.py +0 -0
  3. viam/app/_logs.py +34 -0
  4. viam/app/app_client.py +2525 -0
  5. viam/app/billing_client.py +143 -0
  6. viam/app/data_client.py +1715 -0
  7. viam/app/ml_training_client.py +251 -0
  8. viam/app/provisioning_client.py +95 -0
  9. viam/app/viam_client.py +260 -0
  10. viam/components/__init__.py +0 -0
  11. viam/components/arm/__init__.py +16 -0
  12. viam/components/arm/arm.py +223 -0
  13. viam/components/arm/client.py +124 -0
  14. viam/components/arm/service.py +123 -0
  15. viam/components/audio_input/__init__.py +18 -0
  16. viam/components/audio_input/audio_input.py +81 -0
  17. viam/components/audio_input/client.py +70 -0
  18. viam/components/audio_input/service.py +114 -0
  19. viam/components/base/__init__.py +13 -0
  20. viam/components/base/base.py +260 -0
  21. viam/components/base/client.py +153 -0
  22. viam/components/base/service.py +138 -0
  23. viam/components/board/__init__.py +9 -0
  24. viam/components/board/board.py +414 -0
  25. viam/components/board/client.py +241 -0
  26. viam/components/board/service.py +223 -0
  27. viam/components/button/__init__.py +10 -0
  28. viam/components/button/button.py +41 -0
  29. viam/components/button/client.py +52 -0
  30. viam/components/button/service.py +46 -0
  31. viam/components/camera/__init__.py +22 -0
  32. viam/components/camera/camera.py +138 -0
  33. viam/components/camera/client.py +98 -0
  34. viam/components/camera/service.py +105 -0
  35. viam/components/component_base.py +65 -0
  36. viam/components/encoder/__init__.py +18 -0
  37. viam/components/encoder/client.py +83 -0
  38. viam/components/encoder/encoder.py +118 -0
  39. viam/components/encoder/service.py +72 -0
  40. viam/components/gantry/__init__.py +11 -0
  41. viam/components/gantry/client.py +115 -0
  42. viam/components/gantry/gantry.py +156 -0
  43. viam/components/gantry/service.py +113 -0
  44. viam/components/generic/__init__.py +18 -0
  45. viam/components/generic/client.py +62 -0
  46. viam/components/generic/generic.py +76 -0
  47. viam/components/generic/service.py +40 -0
  48. viam/components/gripper/__init__.py +11 -0
  49. viam/components/gripper/client.py +85 -0
  50. viam/components/gripper/gripper.py +114 -0
  51. viam/components/gripper/service.py +81 -0
  52. viam/components/input/__init__.py +15 -0
  53. viam/components/input/client.py +194 -0
  54. viam/components/input/input.py +297 -0
  55. viam/components/input/service.py +175 -0
  56. viam/components/motor/__init__.py +11 -0
  57. viam/components/motor/client.py +168 -0
  58. viam/components/motor/motor.py +301 -0
  59. viam/components/motor/service.py +150 -0
  60. viam/components/movement_sensor/__init__.py +21 -0
  61. viam/components/movement_sensor/client.py +161 -0
  62. viam/components/movement_sensor/movement_sensor.py +253 -0
  63. viam/components/movement_sensor/service.py +146 -0
  64. viam/components/pose_tracker/__init__.py +17 -0
  65. viam/components/pose_tracker/client.py +50 -0
  66. viam/components/pose_tracker/pose_tracker.py +40 -0
  67. viam/components/pose_tracker/service.py +45 -0
  68. viam/components/power_sensor/__init__.py +17 -0
  69. viam/components/power_sensor/client.py +86 -0
  70. viam/components/power_sensor/power_sensor.py +104 -0
  71. viam/components/power_sensor/service.py +72 -0
  72. viam/components/sensor/__init__.py +18 -0
  73. viam/components/sensor/client.py +49 -0
  74. viam/components/sensor/sensor.py +48 -0
  75. viam/components/sensor/service.py +51 -0
  76. viam/components/servo/__init__.py +11 -0
  77. viam/components/servo/client.py +86 -0
  78. viam/components/servo/service.py +80 -0
  79. viam/components/servo/servo.py +114 -0
  80. viam/components/switch/__init__.py +10 -0
  81. viam/components/switch/client.py +83 -0
  82. viam/components/switch/service.py +72 -0
  83. viam/components/switch/switch.py +95 -0
  84. viam/errors.py +105 -0
  85. viam/gen/__init__.py +0 -0
  86. viam/gen/app/__init__.py +0 -0
  87. viam/gen/app/agent/__init__.py +0 -0
  88. viam/gen/app/agent/v1/__init__.py +0 -0
  89. viam/gen/app/agent/v1/agent_grpc.py +29 -0
  90. viam/gen/app/agent/v1/agent_pb2.py +47 -0
  91. viam/gen/app/agent/v1/agent_pb2.pyi +280 -0
  92. viam/gen/app/cloudslam/__init__.py +0 -0
  93. viam/gen/app/cloudslam/v1/__init__.py +0 -0
  94. viam/gen/app/cloudslam/v1/cloud_slam_grpc.py +70 -0
  95. viam/gen/app/cloudslam/v1/cloud_slam_pb2.py +54 -0
  96. viam/gen/app/cloudslam/v1/cloud_slam_pb2.pyi +384 -0
  97. viam/gen/app/data/__init__.py +0 -0
  98. viam/gen/app/data/v1/__init__.py +0 -0
  99. viam/gen/app/data/v1/data_grpc.py +206 -0
  100. viam/gen/app/data/v1/data_pb2.py +178 -0
  101. viam/gen/app/data/v1/data_pb2.pyi +1485 -0
  102. viam/gen/app/datapipelines/__init__.py +0 -0
  103. viam/gen/app/datapipelines/v1/__init__.py +0 -0
  104. viam/gen/app/datapipelines/v1/data_pipelines_grpc.py +84 -0
  105. viam/gen/app/datapipelines/v1/data_pipelines_pb2.py +56 -0
  106. viam/gen/app/datapipelines/v1/data_pipelines_pb2.pyi +370 -0
  107. viam/gen/app/dataset/__init__.py +0 -0
  108. viam/gen/app/dataset/v1/__init__.py +0 -0
  109. viam/gen/app/dataset/v1/dataset_grpc.py +60 -0
  110. viam/gen/app/dataset/v1/dataset_pb2.py +40 -0
  111. viam/gen/app/dataset/v1/dataset_pb2.pyi +179 -0
  112. viam/gen/app/datasync/__init__.py +0 -0
  113. viam/gen/app/datasync/v1/__init__.py +0 -0
  114. viam/gen/app/datasync/v1/data_sync_grpc.py +47 -0
  115. viam/gen/app/datasync/v1/data_sync_pb2.py +70 -0
  116. viam/gen/app/datasync/v1/data_sync_pb2.pyi +425 -0
  117. viam/gen/app/mlinference/__init__.py +0 -0
  118. viam/gen/app/mlinference/v1/__init__.py +0 -0
  119. viam/gen/app/mlinference/v1/ml_inference_grpc.py +28 -0
  120. viam/gen/app/mlinference/v1/ml_inference_pb2.py +23 -0
  121. viam/gen/app/mlinference/v1/ml_inference_pb2.pyi +63 -0
  122. viam/gen/app/mltraining/__init__.py +0 -0
  123. viam/gen/app/mltraining/v1/__init__.py +0 -0
  124. viam/gen/app/mltraining/v1/ml_training_grpc.py +78 -0
  125. viam/gen/app/mltraining/v1/ml_training_pb2.py +124 -0
  126. viam/gen/app/mltraining/v1/ml_training_pb2.pyi +415 -0
  127. viam/gen/app/packages/__init__.py +0 -0
  128. viam/gen/app/packages/v1/__init__.py +0 -0
  129. viam/gen/app/packages/v1/packages_grpc.py +54 -0
  130. viam/gen/app/packages/v1/packages_pb2.py +52 -0
  131. viam/gen/app/packages/v1/packages_pb2.pyi +311 -0
  132. viam/gen/app/v1/__init__.py +0 -0
  133. viam/gen/app/v1/app_grpc.py +863 -0
  134. viam/gen/app/v1/app_pb2.py +649 -0
  135. viam/gen/app/v1/app_pb2.pyi +5279 -0
  136. viam/gen/app/v1/billing_grpc.py +76 -0
  137. viam/gen/app/v1/billing_pb2.py +92 -0
  138. viam/gen/app/v1/billing_pb2.pyi +463 -0
  139. viam/gen/app/v1/end_user_grpc.py +59 -0
  140. viam/gen/app/v1/end_user_pb2.py +55 -0
  141. viam/gen/app/v1/end_user_pb2.pyi +181 -0
  142. viam/gen/app/v1/robot_grpc.py +55 -0
  143. viam/gen/app/v1/robot_pb2.py +127 -0
  144. viam/gen/app/v1/robot_pb2.pyi +1202 -0
  145. viam/gen/common/__init__.py +0 -0
  146. viam/gen/common/v1/__init__.py +0 -0
  147. viam/gen/common/v1/common_grpc.py +0 -0
  148. viam/gen/common/v1/common_pb2.py +78 -0
  149. viam/gen/common/v1/common_pb2.pyi +687 -0
  150. viam/gen/component/__init__.py +0 -0
  151. viam/gen/component/arm/__init__.py +0 -0
  152. viam/gen/component/arm/v1/__init__.py +0 -0
  153. viam/gen/component/arm/v1/arm_grpc.py +102 -0
  154. viam/gen/component/arm/v1/arm_pb2.py +74 -0
  155. viam/gen/component/arm/v1/arm_pb2.pyi +344 -0
  156. viam/gen/component/audioinput/__init__.py +0 -0
  157. viam/gen/component/audioinput/v1/__init__.py +0 -0
  158. viam/gen/component/audioinput/v1/audioinput_grpc.py +63 -0
  159. viam/gen/component/audioinput/v1/audioinput_pb2.py +45 -0
  160. viam/gen/component/audioinput/v1/audioinput_pb2.pyi +179 -0
  161. viam/gen/component/base/__init__.py +0 -0
  162. viam/gen/component/base/v1/__init__.py +0 -0
  163. viam/gen/component/base/v1/base_grpc.py +94 -0
  164. viam/gen/component/base/v1/base_pb2.py +66 -0
  165. viam/gen/component/base/v1/base_pb2.pyi +258 -0
  166. viam/gen/component/board/__init__.py +0 -0
  167. viam/gen/component/board/v1/__init__.py +0 -0
  168. viam/gen/component/board/v1/board_grpc.py +127 -0
  169. viam/gen/component/board/v1/board_pb2.py +103 -0
  170. viam/gen/component/board/v1/board_pb2.pyi +496 -0
  171. viam/gen/component/button/__init__.py +0 -0
  172. viam/gen/component/button/v1/__init__.py +0 -0
  173. viam/gen/component/button/v1/button_grpc.py +38 -0
  174. viam/gen/component/button/v1/button_pb2.py +28 -0
  175. viam/gen/component/button/v1/button_pb2.pyi +39 -0
  176. viam/gen/component/camera/__init__.py +0 -0
  177. viam/gen/component/camera/v1/__init__.py +0 -0
  178. viam/gen/component/camera/v1/camera_grpc.py +79 -0
  179. viam/gen/component/camera/v1/camera_pb2.py +67 -0
  180. viam/gen/component/camera/v1/camera_pb2.pyi +373 -0
  181. viam/gen/component/encoder/__init__.py +0 -0
  182. viam/gen/component/encoder/v1/__init__.py +0 -0
  183. viam/gen/component/encoder/v1/encoder_grpc.py +62 -0
  184. viam/gen/component/encoder/v1/encoder_pb2.py +44 -0
  185. viam/gen/component/encoder/v1/encoder_pb2.pyi +147 -0
  186. viam/gen/component/gantry/__init__.py +0 -0
  187. viam/gen/component/gantry/v1/__init__.py +0 -0
  188. viam/gen/component/gantry/v1/gantry_grpc.py +86 -0
  189. viam/gen/component/gantry/v1/gantry_pb2.py +62 -0
  190. viam/gen/component/gantry/v1/gantry_pb2.pyi +239 -0
  191. viam/gen/component/generic/__init__.py +0 -0
  192. viam/gen/component/generic/v1/__init__.py +0 -0
  193. viam/gen/component/generic/v1/generic_grpc.py +37 -0
  194. viam/gen/component/generic/v1/generic_pb2.py +23 -0
  195. viam/gen/component/generic/v1/generic_pb2.pyi +6 -0
  196. viam/gen/component/gripper/__init__.py +0 -0
  197. viam/gen/component/gripper/v1/__init__.py +0 -0
  198. viam/gen/component/gripper/v1/gripper_grpc.py +70 -0
  199. viam/gen/component/gripper/v1/gripper_pb2.py +48 -0
  200. viam/gen/component/gripper/v1/gripper_pb2.pyi +137 -0
  201. viam/gen/component/inputcontroller/__init__.py +0 -0
  202. viam/gen/component/inputcontroller/v1/__init__.py +0 -0
  203. viam/gen/component/inputcontroller/v1/input_controller_grpc.py +71 -0
  204. viam/gen/component/inputcontroller/v1/input_controller_pb2.py +55 -0
  205. viam/gen/component/inputcontroller/v1/input_controller_pb2.pyi +243 -0
  206. viam/gen/component/motor/__init__.py +0 -0
  207. viam/gen/component/motor/v1/__init__.py +0 -0
  208. viam/gen/component/motor/v1/motor_grpc.py +118 -0
  209. viam/gen/component/motor/v1/motor_pb2.py +86 -0
  210. viam/gen/component/motor/v1/motor_pb2.pyi +368 -0
  211. viam/gen/component/movementsensor/__init__.py +0 -0
  212. viam/gen/component/movementsensor/v1/__init__.py +0 -0
  213. viam/gen/component/movementsensor/v1/movementsensor_grpc.py +110 -0
  214. viam/gen/component/movementsensor/v1/movementsensor_pb2.py +78 -0
  215. viam/gen/component/movementsensor/v1/movementsensor_pb2.pyi +384 -0
  216. viam/gen/component/posetracker/__init__.py +0 -0
  217. viam/gen/component/posetracker/v1/__init__.py +0 -0
  218. viam/gen/component/posetracker/v1/pose_tracker_grpc.py +46 -0
  219. viam/gen/component/posetracker/v1/pose_tracker_pb2.py +34 -0
  220. viam/gen/component/posetracker/v1/pose_tracker_pb2.pyi +79 -0
  221. viam/gen/component/powersensor/__init__.py +0 -0
  222. viam/gen/component/powersensor/v1/__init__.py +0 -0
  223. viam/gen/component/powersensor/v1/powersensor_grpc.py +62 -0
  224. viam/gen/component/powersensor/v1/powersensor_pb2.py +42 -0
  225. viam/gen/component/powersensor/v1/powersensor_pb2.pyi +124 -0
  226. viam/gen/component/sensor/__init__.py +0 -0
  227. viam/gen/component/sensor/v1/__init__.py +0 -0
  228. viam/gen/component/sensor/v1/sensor_grpc.py +45 -0
  229. viam/gen/component/sensor/v1/sensor_pb2.py +25 -0
  230. viam/gen/component/sensor/v1/sensor_pb2.pyi +6 -0
  231. viam/gen/component/servo/__init__.py +0 -0
  232. viam/gen/component/servo/v1/__init__.py +0 -0
  233. viam/gen/component/servo/v1/servo_grpc.py +70 -0
  234. viam/gen/component/servo/v1/servo_pb2.py +50 -0
  235. viam/gen/component/servo/v1/servo_pb2.pyi +150 -0
  236. viam/gen/component/switch/__init__.py +0 -0
  237. viam/gen/component/switch/v1/__init__.py +0 -0
  238. viam/gen/component/switch/v1/switch_grpc.py +54 -0
  239. viam/gen/component/switch/v1/switch_pb2.py +40 -0
  240. viam/gen/component/switch/v1/switch_pb2.pyi +109 -0
  241. viam/gen/component/testecho/__init__.py +0 -0
  242. viam/gen/component/testecho/v1/__init__.py +0 -0
  243. viam/gen/component/testecho/v1/testecho_grpc.py +52 -0
  244. viam/gen/component/testecho/v1/testecho_pb2.py +36 -0
  245. viam/gen/component/testecho/v1/testecho_pb2.pyi +114 -0
  246. viam/gen/module/__init__.py +0 -0
  247. viam/gen/module/v1/__init__.py +0 -0
  248. viam/gen/module/v1/module_grpc.py +61 -0
  249. viam/gen/module/v1/module_pb2.py +43 -0
  250. viam/gen/module/v1/module_pb2.pyi +211 -0
  251. viam/gen/proto/__init__.py +0 -0
  252. viam/gen/proto/rpc/__init__.py +0 -0
  253. viam/gen/proto/rpc/examples/__init__.py +0 -0
  254. viam/gen/proto/rpc/examples/echo/__init__.py +0 -0
  255. viam/gen/proto/rpc/examples/echo/v1/__init__.py +0 -0
  256. viam/gen/proto/rpc/examples/echo/v1/echo_grpc.py +44 -0
  257. viam/gen/proto/rpc/examples/echo/v1/echo_pb2.py +32 -0
  258. viam/gen/proto/rpc/examples/echo/v1/echo_pb2.pyi +87 -0
  259. viam/gen/proto/rpc/examples/echoresource/__init__.py +0 -0
  260. viam/gen/proto/rpc/examples/echoresource/v1/__init__.py +0 -0
  261. viam/gen/proto/rpc/examples/echoresource/v1/echoresource_grpc.py +43 -0
  262. viam/gen/proto/rpc/examples/echoresource/v1/echoresource_pb2.py +29 -0
  263. viam/gen/proto/rpc/examples/echoresource/v1/echoresource_pb2.pyi +93 -0
  264. viam/gen/proto/rpc/v1/__init__.py +0 -0
  265. viam/gen/proto/rpc/v1/auth_grpc.py +47 -0
  266. viam/gen/proto/rpc/v1/auth_pb2.py +34 -0
  267. viam/gen/proto/rpc/v1/auth_pb2.pyi +92 -0
  268. viam/gen/proto/rpc/webrtc/__init__.py +0 -0
  269. viam/gen/proto/rpc/webrtc/v1/__init__.py +0 -0
  270. viam/gen/proto/rpc/webrtc/v1/grpc_grpc.py +0 -0
  271. viam/gen/proto/rpc/webrtc/v1/grpc_pb2.py +43 -0
  272. viam/gen/proto/rpc/webrtc/v1/grpc_pb2.pyi +304 -0
  273. viam/gen/proto/rpc/webrtc/v1/signaling_grpc.py +54 -0
  274. viam/gen/proto/rpc/webrtc/v1/signaling_pb2.py +70 -0
  275. viam/gen/proto/rpc/webrtc/v1/signaling_pb2.pyi +496 -0
  276. viam/gen/provisioning/__init__.py +0 -0
  277. viam/gen/provisioning/v1/__init__.py +0 -0
  278. viam/gen/provisioning/v1/provisioning_grpc.py +51 -0
  279. viam/gen/provisioning/v1/provisioning_pb2.py +39 -0
  280. viam/gen/provisioning/v1/provisioning_pb2.pyi +188 -0
  281. viam/gen/robot/__init__.py +0 -0
  282. viam/gen/robot/v1/__init__.py +0 -0
  283. viam/gen/robot/v1/robot_grpc.py +208 -0
  284. viam/gen/robot/v1/robot_pb2.py +188 -0
  285. viam/gen/robot/v1/robot_pb2.pyi +1020 -0
  286. viam/gen/service/__init__.py +0 -0
  287. viam/gen/service/datamanager/__init__.py +0 -0
  288. viam/gen/service/datamanager/v1/__init__.py +0 -0
  289. viam/gen/service/datamanager/v1/data_manager_grpc.py +38 -0
  290. viam/gen/service/datamanager/v1/data_manager_pb2.py +28 -0
  291. viam/gen/service/datamanager/v1/data_manager_pb2.pyi +39 -0
  292. viam/gen/service/discovery/__init__.py +0 -0
  293. viam/gen/service/discovery/v1/__init__.py +0 -0
  294. viam/gen/service/discovery/v1/discovery_grpc.py +39 -0
  295. viam/gen/service/discovery/v1/discovery_pb2.py +29 -0
  296. viam/gen/service/discovery/v1/discovery_pb2.pyi +51 -0
  297. viam/gen/service/generic/__init__.py +0 -0
  298. viam/gen/service/generic/v1/__init__.py +0 -0
  299. viam/gen/service/generic/v1/generic_grpc.py +29 -0
  300. viam/gen/service/generic/v1/generic_pb2.py +21 -0
  301. viam/gen/service/generic/v1/generic_pb2.pyi +6 -0
  302. viam/gen/service/mlmodel/__init__.py +0 -0
  303. viam/gen/service/mlmodel/v1/__init__.py +0 -0
  304. viam/gen/service/mlmodel/v1/mlmodel_grpc.py +37 -0
  305. viam/gen/service/mlmodel/v1/mlmodel_pb2.py +83 -0
  306. viam/gen/service/mlmodel/v1/mlmodel_pb2.pyi +480 -0
  307. viam/gen/service/motion/__init__.py +0 -0
  308. viam/gen/service/motion/v1/__init__.py +0 -0
  309. viam/gen/service/motion/v1/motion_grpc.py +87 -0
  310. viam/gen/service/motion/v1/motion_pb2.py +97 -0
  311. viam/gen/service/motion/v1/motion_pb2.pyi +838 -0
  312. viam/gen/service/navigation/__init__.py +0 -0
  313. viam/gen/service/navigation/v1/__init__.py +0 -0
  314. viam/gen/service/navigation/v1/navigation_grpc.py +102 -0
  315. viam/gen/service/navigation/v1/navigation_pb2.py +84 -0
  316. viam/gen/service/navigation/v1/navigation_pb2.pyi +419 -0
  317. viam/gen/service/sensors/__init__.py +0 -0
  318. viam/gen/service/sensors/v1/__init__.py +0 -0
  319. viam/gen/service/sensors/v1/sensors_grpc.py +46 -0
  320. viam/gen/service/sensors/v1/sensors_pb2.py +68 -0
  321. viam/gen/service/sensors/v1/sensors_pb2.pyi +137 -0
  322. viam/gen/service/shell/__init__.py +0 -0
  323. viam/gen/service/shell/v1/__init__.py +0 -0
  324. viam/gen/service/shell/v1/shell_grpc.py +55 -0
  325. viam/gen/service/shell/v1/shell_pb2.py +45 -0
  326. viam/gen/service/shell/v1/shell_pb2.pyi +307 -0
  327. viam/gen/service/slam/__init__.py +0 -0
  328. viam/gen/service/slam/v1/__init__.py +0 -0
  329. viam/gen/service/slam/v1/slam_grpc.py +61 -0
  330. viam/gen/service/slam/v1/slam_pb2.py +51 -0
  331. viam/gen/service/slam/v1/slam_pb2.pyi +213 -0
  332. viam/gen/service/vision/__init__.py +0 -0
  333. viam/gen/service/vision/v1/__init__.py +0 -0
  334. viam/gen/service/vision/v1/vision_grpc.py +87 -0
  335. viam/gen/service/vision/v1/vision_pb2.py +69 -0
  336. viam/gen/service/vision/v1/vision_pb2.pyi +454 -0
  337. viam/gen/stream/__init__.py +0 -0
  338. viam/gen/stream/v1/__init__.py +0 -0
  339. viam/gen/stream/v1/stream_grpc.py +59 -0
  340. viam/gen/stream/v1/stream_pb2.py +39 -0
  341. viam/gen/stream/v1/stream_pb2.pyi +161 -0
  342. viam/gen/tagger/__init__.py +0 -0
  343. viam/gen/tagger/v1/__init__.py +0 -0
  344. viam/gen/tagger/v1/tagger_grpc.py +0 -0
  345. viam/gen/tagger/v1/tagger_pb2.py +16 -0
  346. viam/gen/tagger/v1/tagger_pb2.pyi +15 -0
  347. viam/logging.py +216 -0
  348. viam/media/__init__.py +0 -0
  349. viam/media/audio.py +16 -0
  350. viam/media/utils/__init__.py +0 -0
  351. viam/media/utils/pil/__init__.py +51 -0
  352. viam/media/utils/pil/viam_rgba_plugin.py +73 -0
  353. viam/media/viam_rgba.py +10 -0
  354. viam/media/video.py +217 -0
  355. viam/module/__init__.py +5 -0
  356. viam/module/module.py +281 -0
  357. viam/module/service.py +66 -0
  358. viam/module/types.py +23 -0
  359. viam/operations.py +124 -0
  360. viam/proto/__init__.py +0 -0
  361. viam/proto/app/__init__.py +554 -0
  362. viam/proto/app/agent/__init__.py +28 -0
  363. viam/proto/app/billing.py +58 -0
  364. viam/proto/app/cloudslam/__init__.py +48 -0
  365. viam/proto/app/data/__init__.py +138 -0
  366. viam/proto/app/datapipelines/__init__.py +56 -0
  367. viam/proto/app/dataset/__init__.py +36 -0
  368. viam/proto/app/datasync/__init__.py +44 -0
  369. viam/proto/app/end_user.py +34 -0
  370. viam/proto/app/mlinference/__init__.py +15 -0
  371. viam/proto/app/mltraining/__init__.py +52 -0
  372. viam/proto/app/packages/__init__.py +38 -0
  373. viam/proto/app/robot.py +84 -0
  374. viam/proto/common/__init__.py +66 -0
  375. viam/proto/component/__init__.py +0 -0
  376. viam/proto/component/arm/__init__.py +48 -0
  377. viam/proto/component/audioinput/__init__.py +30 -0
  378. viam/proto/component/base/__init__.py +42 -0
  379. viam/proto/component/board/__init__.py +62 -0
  380. viam/proto/component/button/__init__.py +15 -0
  381. viam/proto/component/camera/__init__.py +46 -0
  382. viam/proto/component/encoder/__init__.py +28 -0
  383. viam/proto/component/gantry/__init__.py +40 -0
  384. viam/proto/component/generic/__init__.py +12 -0
  385. viam/proto/component/gripper/__init__.py +30 -0
  386. viam/proto/component/inputcontroller/__init__.py +38 -0
  387. viam/proto/component/motor/__init__.py +56 -0
  388. viam/proto/component/movementsensor/__init__.py +50 -0
  389. viam/proto/component/posetracker/__init__.py +19 -0
  390. viam/proto/component/powersensor/__init__.py +30 -0
  391. viam/proto/component/sensor/__init__.py +12 -0
  392. viam/proto/component/servo/__init__.py +32 -0
  393. viam/proto/component/switch/__init__.py +26 -0
  394. viam/proto/component/testecho/__init__.py +30 -0
  395. viam/proto/module/__init__.py +38 -0
  396. viam/proto/provisioning/__init__.py +36 -0
  397. viam/proto/robot/__init__.py +130 -0
  398. viam/proto/rpc/__init__.py +0 -0
  399. viam/proto/rpc/auth.py +34 -0
  400. viam/proto/rpc/examples/__init__.py +0 -0
  401. viam/proto/rpc/examples/echo/__init__.py +26 -0
  402. viam/proto/rpc/examples/echoresource/__init__.py +30 -0
  403. viam/proto/rpc/webrtc/__init__.py +0 -0
  404. viam/proto/rpc/webrtc/grpc.py +36 -0
  405. viam/proto/rpc/webrtc/signaling.py +58 -0
  406. viam/proto/service/__init__.py +0 -0
  407. viam/proto/service/datamanager/__init__.py +19 -0
  408. viam/proto/service/discovery/__init__.py +15 -0
  409. viam/proto/service/generic/__init__.py +12 -0
  410. viam/proto/service/mlmodel/__init__.py +54 -0
  411. viam/proto/service/motion/__init__.py +68 -0
  412. viam/proto/service/navigation/__init__.py +58 -0
  413. viam/proto/service/sensors/__init__.py +18 -0
  414. viam/proto/service/shell/__init__.py +36 -0
  415. viam/proto/service/slam/__init__.py +36 -0
  416. viam/proto/service/vision/__init__.py +46 -0
  417. viam/proto/stream/__init__.py +36 -0
  418. viam/proto/tagger/__init__.py +6 -0
  419. viam/py.typed +0 -0
  420. viam/resource/__init__.py +0 -0
  421. viam/resource/base.py +123 -0
  422. viam/resource/easy_resource.py +153 -0
  423. viam/resource/manager.py +126 -0
  424. viam/resource/registry.py +199 -0
  425. viam/resource/rpc_client_base.py +65 -0
  426. viam/resource/rpc_service_base.py +48 -0
  427. viam/resource/types.py +213 -0
  428. viam/robot/__init__.py +0 -0
  429. viam/robot/client.py +909 -0
  430. viam/robot/service.py +69 -0
  431. viam/rpc/__init__.py +0 -0
  432. viam/rpc/dial.py +420 -0
  433. viam/rpc/libviam_rust_utils.dll +0 -0
  434. viam/rpc/server.py +201 -0
  435. viam/rpc/signaling.py +29 -0
  436. viam/rpc/types.py +22 -0
  437. viam/services/__init__.py +0 -0
  438. viam/services/discovery/__init__.py +12 -0
  439. viam/services/discovery/client.py +55 -0
  440. viam/services/discovery/discovery.py +52 -0
  441. viam/services/discovery/service.py +43 -0
  442. viam/services/generic/__init__.py +18 -0
  443. viam/services/generic/client.py +58 -0
  444. viam/services/generic/generic.py +58 -0
  445. viam/services/generic/service.py +29 -0
  446. viam/services/mlmodel/__init__.py +24 -0
  447. viam/services/mlmodel/client.py +37 -0
  448. viam/services/mlmodel/mlmodel.py +78 -0
  449. viam/services/mlmodel/service.py +38 -0
  450. viam/services/mlmodel/utils.py +101 -0
  451. viam/services/motion/__init__.py +17 -0
  452. viam/services/motion/client.py +215 -0
  453. viam/services/motion/motion.py +378 -0
  454. viam/services/motion/service.py +132 -0
  455. viam/services/navigation/__init__.py +11 -0
  456. viam/services/navigation/client.py +99 -0
  457. viam/services/navigation/navigation.py +250 -0
  458. viam/services/navigation/service.py +137 -0
  459. viam/services/service_base.py +78 -0
  460. viam/services/service_client_base.py +46 -0
  461. viam/services/slam/__init__.py +17 -0
  462. viam/services/slam/client.py +62 -0
  463. viam/services/slam/service.py +75 -0
  464. viam/services/slam/slam.py +111 -0
  465. viam/services/vision/__init__.py +15 -0
  466. viam/services/vision/client.py +206 -0
  467. viam/services/vision/service.py +146 -0
  468. viam/services/vision/vision.py +315 -0
  469. viam/sessions_client.py +245 -0
  470. viam/streams.py +44 -0
  471. viam/utils.py +365 -0
  472. viam/version_metadata.py +4 -0
  473. viam_sdk-0.45.2.dist-info/METADATA +157 -0
  474. viam_sdk-0.45.2.dist-info/RECORD +476 -0
  475. viam_sdk-0.45.2.dist-info/WHEEL +4 -0
  476. viam_sdk-0.45.2.dist-info/licenses/LICENSE +202 -0
viam/rpc/signaling.py ADDED
@@ -0,0 +1,29 @@
1
+ from grpclib.const import Status
2
+ from grpclib.exceptions import GRPCError
3
+ from grpclib.server import Stream
4
+
5
+ from viam.proto.rpc.webrtc.signaling import (
6
+ AnswerRequest,
7
+ AnswerResponse,
8
+ CallRequest,
9
+ CallResponse,
10
+ CallUpdateRequest,
11
+ CallUpdateResponse,
12
+ OptionalWebRTCConfigRequest,
13
+ OptionalWebRTCConfigResponse,
14
+ SignalingServiceBase,
15
+ )
16
+
17
+
18
+ class SignalingService(SignalingServiceBase):
19
+ async def Call(self, stream: Stream[CallRequest, CallResponse]) -> None:
20
+ raise GRPCError(Status.UNIMPLEMENTED, "SignalingService is unimplemented")
21
+
22
+ async def CallUpdate(self, stream: Stream[CallUpdateRequest, CallUpdateResponse]) -> None:
23
+ raise GRPCError(Status.UNIMPLEMENTED, "SignalingService is unimplemented")
24
+
25
+ async def Answer(self, stream: Stream[AnswerResponse, AnswerRequest]) -> None:
26
+ raise GRPCError(Status.UNIMPLEMENTED, "SignalingService is unimplemented")
27
+
28
+ async def OptionalWebRTCConfig(self, stream: Stream[OptionalWebRTCConfigRequest, OptionalWebRTCConfigResponse]) -> None:
29
+ raise GRPCError(Status.UNIMPLEMENTED, "SignalingService is unimplemented")
viam/rpc/types.py ADDED
@@ -0,0 +1,22 @@
1
+ from abc import abstractmethod
2
+ from typing import Mapping, Protocol, runtime_checkable
3
+
4
+ import grpclib
5
+ from grpclib._typing import IServable
6
+ from grpclib.client import Channel
7
+
8
+
9
+ class RPCServiceBase(IServable):
10
+ """The base requirements for an RPC Service.
11
+
12
+ An RPC Service is a service that can handle incoming RPC requests.
13
+ Services that implement the service bases generated by grpclib will automatically conform to this protocol.
14
+ """
15
+
16
+ @abstractmethod
17
+ def __mapping__(self) -> Mapping[str, grpclib.const.Handler]: ...
18
+
19
+
20
+ @runtime_checkable
21
+ class RPCServiceStubBase(Protocol):
22
+ def __init__(self, channel: Channel) -> None: ...
File without changes
@@ -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)))
@@ -0,0 +1,18 @@
1
+ import viam.gen.service.generic.v1.generic_pb2 # Need this import for Generic service descriptors to resolve
2
+ from viam.resource.registry import Registry, ResourceRegistration
3
+
4
+ from .client import GenericClient
5
+ from .generic import Generic
6
+ from .service import GenericRPCService
7
+
8
+ __all__ = [
9
+ "Generic",
10
+ ]
11
+
12
+ Registry.register_api(
13
+ ResourceRegistration(
14
+ Generic,
15
+ GenericRPCService,
16
+ lambda name, channel: GenericClient(name, channel),
17
+ )
18
+ )
@@ -0,0 +1,58 @@
1
+ from typing import Any, Mapping, Optional
2
+
3
+ from grpclib import GRPCError, Status
4
+ from grpclib.client import Channel
5
+
6
+ from viam.proto.common import DoCommandRequest, DoCommandResponse
7
+ from viam.proto.service.generic import GenericServiceStub
8
+ from viam.resource.rpc_client_base import ReconfigurableResourceRPCClientBase, ResourceRPCClientBase
9
+ from viam.utils import ValueTypes, dict_to_struct, struct_to_dict
10
+
11
+ from .generic import Generic
12
+
13
+
14
+ class GenericClient(Generic, ReconfigurableResourceRPCClientBase):
15
+ """
16
+ gRPC client for the Generic service.
17
+ """
18
+
19
+ def __init__(self, name: str, channel: Channel):
20
+ self.channel = channel
21
+ self.client = GenericServiceStub(channel)
22
+ super().__init__(name)
23
+
24
+ async def do_command(
25
+ self,
26
+ command: Mapping[str, Any],
27
+ *,
28
+ timeout: Optional[float] = None,
29
+ **kwargs,
30
+ ) -> Mapping[str, Any]:
31
+ md = kwargs.get("metadata", self.Metadata()).proto
32
+ request = DoCommandRequest(name=self.name, command=dict_to_struct(command))
33
+ try:
34
+ response: DoCommandResponse = await self.client.DoCommand(request, timeout=timeout, metadata=md)
35
+ except GRPCError as e:
36
+ if e.status == Status.UNIMPLEMENTED:
37
+ raise NotImplementedError()
38
+ raise e
39
+
40
+ return struct_to_dict(response.result)
41
+
42
+
43
+ async def do_command(
44
+ channel: Channel, name: str, command: Mapping[str, ValueTypes], *, timeout: Optional[float] = None, **kwargs
45
+ ) -> Mapping[str, ValueTypes]:
46
+ """Convenience method to allow service clients to execute ``do_command`` functions
47
+
48
+ Args:
49
+ channel (Channel): A gRPC channel
50
+ name (str): The name of the component
51
+ command (Dict[str, Any]): The command to execute
52
+
53
+ Returns:
54
+ Dict[str, Any]: The result of the executed command
55
+ """
56
+ md = kwargs.get("metadata", ResourceRPCClientBase.Metadata()).proto
57
+ client = GenericClient(name, channel)
58
+ return await client.do_command(command, timeout=timeout, metadata=md)
@@ -0,0 +1,58 @@
1
+ from typing import Final
2
+
3
+ from viam.resource.types import API, RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_SERVICE
4
+
5
+ from ..service_base import ServiceBase
6
+
7
+
8
+ class Generic(ServiceBase):
9
+ """
10
+ Generic service, which represents any type of service that can execute arbitrary commands
11
+
12
+ This acts as an abstract base class for any drivers representing generic services.
13
+ This cannot be used on its own. If the ``__init__()`` function is overridden, it must call the ``super().__init__()`` function.
14
+
15
+ To create a Generic service (an arbitrary service that can process commands), this ``Generic`` service should be subclassed
16
+ and the ``do_command`` function implemented.
17
+
18
+ Example::
19
+
20
+ class ComplexService(Generic):
21
+
22
+ async def do_command(
23
+ self,
24
+ command: Mapping[str, ValueTypes],
25
+ *,
26
+ timeout: Optional[float] = None,
27
+ **kwargs
28
+ ) -> Mapping[str, ValueTypes]:
29
+ result = {key: False for key in command.keys()}
30
+ for (name, args) in command.items():
31
+ if name == 'set_val':
32
+ self.set_val(*args)
33
+ result[name] = True
34
+ if name == 'get_val':
35
+ result[name] = self.val
36
+ if name == 'complex_command':
37
+ self.complex_command(*args)
38
+ result[name] = True
39
+ return result
40
+
41
+ def set_val(self, val: int):
42
+ self.val = val
43
+
44
+ def complex_command(self, arg1, arg2, arg3):
45
+ ...
46
+
47
+ To execute commands, simply call the ``do_command`` function with the appropriate parameters.
48
+ ::
49
+
50
+ await service.do_command({'set_val': 10})
51
+ service.val # 10
52
+ await service.do_command({'set_val': 5})
53
+ service.val # 5
54
+ """
55
+
56
+ API: Final = API( # pyright: ignore [reportIncompatibleVariableOverride]
57
+ RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_SERVICE, "generic"
58
+ )
@@ -0,0 +1,29 @@
1
+ from grpclib import GRPCError, Status
2
+ from grpclib.server import Stream
3
+
4
+ from viam.proto.common import DoCommandRequest, DoCommandResponse
5
+ from viam.proto.service.generic import GenericServiceBase
6
+ from viam.resource.rpc_service_base import ResourceRPCServiceBase
7
+ from viam.services.service_base import ServiceBase
8
+ from viam.utils import dict_to_struct, struct_to_dict
9
+
10
+
11
+ class GenericRPCService(GenericServiceBase, ResourceRPCServiceBase):
12
+ """
13
+ gRPC Service for a Generic service
14
+ """
15
+
16
+ RESOURCE_TYPE = ServiceBase
17
+
18
+ async def DoCommand(self, stream: Stream[DoCommandRequest, DoCommandResponse]) -> None:
19
+ request = await stream.recv_message()
20
+ assert request is not None
21
+ name = request.name
22
+ service = self.get_resource(name)
23
+ try:
24
+ timeout = stream.deadline.time_remaining() if stream.deadline else None
25
+ result = await service.do_command(struct_to_dict(request.command), timeout=timeout, metadata=stream.metadata)
26
+ except NotImplementedError:
27
+ raise GRPCError(Status.UNIMPLEMENTED, f"``DO`` command is unimplemented for service named: {name}")
28
+ response = DoCommandResponse(result=dict_to_struct(result))
29
+ await stream.send_message(response)
@@ -0,0 +1,24 @@
1
+ try:
2
+ import numpy
3
+ except ImportError:
4
+ import warnings
5
+
6
+ warnings.warn(
7
+ (
8
+ """MLModel support in the Viam Python SDK requires the installation of an
9
+ additional dependency: numpy. Update your package using the extra [mlmodel]
10
+ for example `pip install viam-sdk[mlmodel]` or the equivalent update in your dependency manager."""
11
+ ),
12
+ )
13
+ raise
14
+
15
+ from viam.proto.service.mlmodel import File, LabelType, Metadata, TensorInfo
16
+ from viam.resource.registry import Registry, ResourceRegistration
17
+
18
+ from .client import MLModelClient
19
+ from .mlmodel import MLModel
20
+ from .service import MLModelRPCService
21
+
22
+ __all__ = ["File", "LabelType", "Metadata", "MLModel", "MLModelClient", "TensorInfo"]
23
+
24
+ Registry.register_api(ResourceRegistration(MLModel, MLModelRPCService, lambda name, channel: MLModelClient(name, channel)))
@@ -0,0 +1,37 @@
1
+ from typing import Dict, Mapping, Optional
2
+
3
+ from grpclib.client import Channel
4
+ from numpy.typing import NDArray
5
+
6
+ from viam.proto.service.mlmodel import InferRequest, InferResponse, MetadataRequest, MetadataResponse, MLModelServiceStub
7
+ from viam.resource.rpc_client_base import ReconfigurableResourceRPCClientBase
8
+ from viam.services.mlmodel.utils import flat_tensors_to_ndarrays, ndarrays_to_flat_tensors
9
+ from viam.utils import ValueTypes, dict_to_struct
10
+
11
+ from .mlmodel import Metadata, MLModel
12
+
13
+
14
+ class MLModelClient(MLModel, ReconfigurableResourceRPCClientBase):
15
+ def __init__(self, name: str, channel: Channel):
16
+ self.channel = channel
17
+ self.client = MLModelServiceStub(channel)
18
+ super().__init__(name)
19
+
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)
31
+ return flat_tensors_to_ndarrays(response.output_tensors)
32
+
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)
37
+ return response.metadata
@@ -0,0 +1,78 @@
1
+ import abc
2
+ from typing import Dict, Final, Mapping, Optional
3
+
4
+ from numpy.typing import NDArray
5
+
6
+ from viam.proto.service.mlmodel import Metadata
7
+ from viam.resource.types import API, RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_SERVICE
8
+ from viam.utils import ValueTypes
9
+
10
+ from ..service_base import ServiceBase
11
+
12
+
13
+ class MLModel(ServiceBase):
14
+ """
15
+ MLModel represents a Machine Learning Model service.
16
+
17
+ This acts as an abstract base class for any drivers representing specific
18
+ arm implementations. This cannot be used on its own. If the ``__init__()`` function is
19
+ overridden, it must call the ``super().__init__()`` function.
20
+
21
+ For more information, see `ML model service <https://docs.viam.com/dev/reference/apis/services/ml/>`_.
22
+ """
23
+
24
+ API: Final = API( # pyright: ignore [reportIncompatibleVariableOverride]
25
+ RESOURCE_NAMESPACE_RDK, RESOURCE_TYPE_SERVICE, "mlmodel"
26
+ )
27
+
28
+ @abc.abstractmethod
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]:
36
+ """Take an already ordered input tensor as an array, make an inference on the model, and return an output tensor map.
37
+
38
+ ::
39
+
40
+ import numpy as np
41
+
42
+ my_mlmodel = MLModelClient.from_robot(robot=machine, name="my_mlmodel_service")
43
+
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
+ }
50
+
51
+ output_tensors = await my_mlmodel.infer(input_tensors)
52
+
53
+ Args:
54
+ input_tensors (Dict[str, NDArray]): A dictionary of input flat tensors as specified in the metadata
55
+
56
+ Returns:
57
+ Dict[str, NDArray]: A dictionary of output flat tensors as specified in the metadata
58
+
59
+ For more information, see `ML model service <https://docs.viam.com/dev/reference/apis/services/ml/#infer>`_.
60
+ """
61
+ ...
62
+
63
+ @abc.abstractmethod
64
+ async def metadata(self, *, extra: Optional[Mapping[str, ValueTypes]] = None, timeout: Optional[float] = None) -> Metadata:
65
+ """Get the metadata (such as name, type, expected tensor/array shape, inputs, and outputs) associated with the ML model.
66
+
67
+ ::
68
+
69
+ my_mlmodel = MLModelClient.from_robot(robot=machine, name="my_mlmodel_service")
70
+
71
+ metadata = await my_mlmodel.metadata()
72
+
73
+ Returns:
74
+ Metadata: The metadata
75
+
76
+ For more information, see `ML model service <https://docs.viam.com/dev/reference/apis/services/ml/#metadata>`_.
77
+ """
78
+ ...
@@ -0,0 +1,38 @@
1
+ from grpclib.server import Stream
2
+
3
+ from viam.proto.service.mlmodel import InferRequest, InferResponse, MetadataRequest, MetadataResponse, MLModelServiceBase
4
+ from viam.resource.rpc_service_base import ResourceRPCServiceBase
5
+ from viam.services.mlmodel.utils import flat_tensors_to_ndarrays, ndarrays_to_flat_tensors
6
+ from viam.utils import struct_to_dict
7
+
8
+ from .mlmodel import MLModel
9
+
10
+
11
+ class MLModelRPCService(MLModelServiceBase, ResourceRPCServiceBase):
12
+ """
13
+ gRPC service for a ML Model service
14
+ """
15
+
16
+ RESOURCE_TYPE = MLModel
17
+
18
+ async def Infer(self, stream: Stream[InferRequest, InferResponse]) -> None:
19
+ request = await stream.recv_message()
20
+ assert request is not None
21
+ name = request.name
22
+ mlmodel = self.get_resource(name)
23
+ extra = struct_to_dict(request.extra)
24
+ timeout = stream.deadline.time_remaining() if stream.deadline else None
25
+ output_tensors = await mlmodel.infer(input_tensors=flat_tensors_to_ndarrays(request.input_tensors), extra=extra, timeout=timeout)
26
+ response = InferResponse(output_tensors=ndarrays_to_flat_tensors(output_tensors))
27
+ await stream.send_message(response)
28
+
29
+ async def Metadata(self, stream: Stream[MetadataRequest, MetadataResponse]) -> None:
30
+ request = await stream.recv_message()
31
+ assert request is not None
32
+ name = request.name
33
+ mlmodel = self.get_resource(name)
34
+ extra = struct_to_dict(request.extra)
35
+ timeout = stream.deadline.time_remaining() if stream.deadline else None
36
+ metadata = await mlmodel.metadata(extra=extra, timeout=timeout)
37
+ response = MetadataResponse(metadata=metadata)
38
+ await stream.send_message(response)
@@ -0,0 +1,101 @@
1
+ from typing import Dict
2
+
3
+ import numpy as np
4
+ from numpy.typing import NDArray
5
+ from packaging.version import Version
6
+
7
+ from viam.proto.service.mlmodel import (
8
+ FlatTensor,
9
+ FlatTensorDataDouble,
10
+ FlatTensorDataFloat,
11
+ FlatTensorDataInt8,
12
+ FlatTensorDataInt16,
13
+ FlatTensorDataInt32,
14
+ FlatTensorDataInt64,
15
+ FlatTensorDataUInt8,
16
+ FlatTensorDataUInt16,
17
+ FlatTensorDataUInt32,
18
+ FlatTensorDataUInt64,
19
+ FlatTensors,
20
+ )
21
+
22
+
23
+ def flat_tensors_to_ndarrays(flat_tensors: FlatTensors) -> Dict[str, NDArray]:
24
+ property_name_to_dtype = {
25
+ "float_tensor": np.float32,
26
+ "double_tensor": np.float64,
27
+ "int8_tensor": np.int8,
28
+ "int16_tensor": np.int16,
29
+ "int32_tensor": np.int32,
30
+ "int64_tensor": np.int64,
31
+ "uint8_tensor": np.uint8,
32
+ "uint16_tensor": np.uint16,
33
+ "uint32_tensor": np.uint32,
34
+ "uint64_tensor": np.uint64,
35
+ }
36
+
37
+ def make_ndarray(flat_data, dtype, shape):
38
+ """Takes flat data (protobuf RepeatedScalarFieldContainer | bytes) to output an ndarray
39
+ of appropriate dtype and shape"""
40
+ make_array = np.frombuffer if dtype == np.int8 or dtype == np.uint8 else np.array
41
+ # As per proto, int16 and uint16 are stored as uint32. As of numpy v2, this creates
42
+ # some strange interactions with negative values for int16. Specifically, we end up
43
+ # trying to create an np.Int16 value with an out of bounds int due to rollover.
44
+ # Creating our array as a uint32 array initially and then casting to int16 solves this.
45
+ if Version(np.__version__) >= Version("2") and dtype == np.int16:
46
+ arr = np.astype(make_array(flat_data, np.uint32), np.int16) # pyright: ignore [reportAttributeAccessIssue]
47
+
48
+ else:
49
+ arr = make_array(flat_data, dtype)
50
+ return arr.reshape(shape)
51
+
52
+ ndarrays: Dict[str, NDArray] = dict()
53
+ for name, flat_tensor in flat_tensors.tensors.items():
54
+ property_name = flat_tensor.WhichOneof("tensor") or flat_tensor.WhichOneof(b"tensor")
55
+ if property_name:
56
+ tensor_data = getattr(flat_tensor, property_name)
57
+ flat_data, dtype, shape = tensor_data.data, property_name_to_dtype[property_name], flat_tensor.shape
58
+ ndarrays[name] = make_ndarray(flat_data, dtype, shape)
59
+ return ndarrays
60
+
61
+
62
+ def ndarrays_to_flat_tensors(ndarrays: Dict[str, NDArray]) -> FlatTensors:
63
+ dtype_name_to_tensor_data_class = {
64
+ "float32": FlatTensorDataFloat,
65
+ "float64": FlatTensorDataDouble,
66
+ "int8": FlatTensorDataInt8,
67
+ "int16": FlatTensorDataInt16,
68
+ "int32": FlatTensorDataInt32,
69
+ "int64": FlatTensorDataInt64,
70
+ "uint8": FlatTensorDataUInt8,
71
+ "uint16": FlatTensorDataUInt16,
72
+ "uint32": FlatTensorDataUInt32,
73
+ "uint64": FlatTensorDataUInt64,
74
+ }
75
+
76
+ def get_tensor_data(ndarray: NDArray):
77
+ """Takes an ndarray and returns the corresponding tensor data class instance
78
+ for example FlatTensorDataInt8, FlatTensorDataUInt8 etc."""
79
+ tensor_data_class = dtype_name_to_tensor_data_class[ndarray.dtype.name]
80
+ data = ndarray.flatten()
81
+ if tensor_data_class == FlatTensorDataInt8 or tensor_data_class == FlatTensorDataUInt8:
82
+ data = data.tobytes() # as per the proto, int8 and uint8 are stored as bytes
83
+ elif tensor_data_class == FlatTensorDataInt16 or tensor_data_class == FlatTensorDataUInt16:
84
+ data = data.astype(np.uint32) # as per the proto, int16 and uint16 are stored as uint32
85
+ tensor_data = tensor_data_class(data=data)
86
+ return tensor_data
87
+
88
+ def get_tensor_data_type(ndarray: NDArray):
89
+ """Takes ndarray and returns a FlatTensor datatype property to be set
90
+ for example "float_tensor", "uint32_tensor" etc."""
91
+ if ndarray.dtype == np.float32:
92
+ return "float_tensor"
93
+ elif ndarray.dtype == np.float64:
94
+ return "double_tensor"
95
+ return f"{ndarray.dtype.name}_tensor"
96
+
97
+ tensors_mapping: Dict[str, FlatTensor] = dict()
98
+ for name, ndarray in ndarrays.items():
99
+ prop_name, prop_value = get_tensor_data_type(ndarray), get_tensor_data(ndarray)
100
+ tensors_mapping[name] = FlatTensor(shape=ndarray.shape, **{prop_name: prop_value})
101
+ return FlatTensors(tensors=tensors_mapping)