viam-sdk 0.3.0__py3-none-linux_armv6l.whl → 0.66.0__py3-none-linux_armv6l.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of viam-sdk might be problematic. Click here for more details.

Files changed (452) hide show
  1. viam/__init__.py +29 -2
  2. viam/app/_logs.py +34 -0
  3. viam/app/app_client.py +2696 -0
  4. viam/app/billing_client.py +185 -0
  5. viam/app/data_client.py +2231 -0
  6. viam/app/ml_training_client.py +249 -0
  7. viam/app/provisioning_client.py +93 -0
  8. viam/app/viam_client.py +275 -0
  9. viam/components/arm/__init__.py +3 -26
  10. viam/components/arm/arm.py +123 -8
  11. viam/components/arm/client.py +37 -24
  12. viam/components/arm/service.py +35 -32
  13. viam/components/audio_in/__init__.py +24 -0
  14. viam/components/audio_in/audio_in.py +74 -0
  15. viam/components/audio_in/client.py +76 -0
  16. viam/components/audio_in/service.py +83 -0
  17. viam/components/audio_out/__init__.py +21 -0
  18. viam/components/audio_out/audio_out.py +72 -0
  19. viam/components/audio_out/client.py +67 -0
  20. viam/components/audio_out/service.py +63 -0
  21. viam/components/base/__init__.py +6 -11
  22. viam/components/base/base.py +134 -8
  23. viam/components/base/client.py +51 -23
  24. viam/components/base/service.py +33 -30
  25. viam/components/board/__init__.py +3 -12
  26. viam/components/board/board.py +247 -91
  27. viam/components/board/client.py +149 -83
  28. viam/components/board/service.py +63 -33
  29. viam/components/button/__init__.py +10 -0
  30. viam/components/button/button.py +41 -0
  31. viam/components/button/client.py +52 -0
  32. viam/components/button/service.py +46 -0
  33. viam/components/camera/__init__.py +3 -3
  34. viam/components/camera/camera.py +62 -27
  35. viam/components/camera/client.py +59 -27
  36. viam/components/camera/service.py +42 -65
  37. viam/components/component_base.py +28 -5
  38. viam/components/encoder/__init__.py +1 -1
  39. viam/components/encoder/client.py +25 -14
  40. viam/components/encoder/encoder.py +48 -10
  41. viam/components/encoder/service.py +14 -18
  42. viam/components/gantry/__init__.py +1 -13
  43. viam/components/gantry/client.py +80 -25
  44. viam/components/gantry/gantry.py +123 -9
  45. viam/components/gantry/service.py +51 -29
  46. viam/components/generic/__init__.py +1 -1
  47. viam/components/generic/client.py +21 -8
  48. viam/components/generic/generic.py +10 -2
  49. viam/components/generic/service.py +12 -7
  50. viam/components/gripper/__init__.py +3 -13
  51. viam/components/gripper/client.py +69 -21
  52. viam/components/gripper/gripper.py +123 -3
  53. viam/components/gripper/service.py +44 -22
  54. viam/components/input/__init__.py +1 -14
  55. viam/components/input/client.py +55 -23
  56. viam/components/input/input.py +106 -3
  57. viam/components/input/service.py +16 -21
  58. viam/components/motor/__init__.py +1 -21
  59. viam/components/motor/client.py +56 -33
  60. viam/components/motor/motor.py +127 -4
  61. viam/components/motor/service.py +33 -44
  62. viam/components/movement_sensor/__init__.py +1 -1
  63. viam/components/movement_sensor/client.py +102 -45
  64. viam/components/movement_sensor/movement_sensor.py +130 -61
  65. viam/components/movement_sensor/service.py +38 -41
  66. viam/components/pose_tracker/__init__.py +1 -1
  67. viam/components/pose_tracker/client.py +18 -7
  68. viam/components/pose_tracker/pose_tracker.py +4 -2
  69. viam/components/pose_tracker/service.py +12 -10
  70. viam/components/power_sensor/__init__.py +17 -0
  71. viam/components/power_sensor/client.py +86 -0
  72. viam/components/power_sensor/power_sensor.py +104 -0
  73. viam/components/power_sensor/service.py +72 -0
  74. viam/components/sensor/__init__.py +2 -1
  75. viam/components/sensor/client.py +26 -10
  76. viam/components/sensor/sensor.py +22 -4
  77. viam/components/sensor/service.py +20 -11
  78. viam/components/servo/__init__.py +1 -13
  79. viam/components/servo/client.py +47 -21
  80. viam/components/servo/service.py +15 -22
  81. viam/components/servo/servo.py +61 -2
  82. viam/components/switch/__init__.py +10 -0
  83. viam/components/switch/client.py +83 -0
  84. viam/components/switch/service.py +72 -0
  85. viam/components/switch/switch.py +98 -0
  86. viam/errors.py +10 -0
  87. viam/gen/app/agent/v1/agent_grpc.py +29 -0
  88. viam/gen/app/agent/v1/agent_pb2.py +47 -0
  89. viam/gen/app/agent/v1/agent_pb2.pyi +280 -0
  90. viam/gen/app/cloudslam/v1/__init__.py +0 -0
  91. viam/gen/app/cloudslam/v1/cloud_slam_grpc.py +70 -0
  92. viam/gen/app/cloudslam/v1/cloud_slam_pb2.py +54 -0
  93. viam/gen/app/cloudslam/v1/cloud_slam_pb2.pyi +384 -0
  94. viam/gen/app/data/v1/data_grpc.py +197 -8
  95. viam/gen/app/data/v1/data_pb2.py +238 -99
  96. viam/gen/app/data/v1/data_pb2.pyi +1222 -259
  97. viam/gen/app/datapipelines/__init__.py +0 -0
  98. viam/gen/app/datapipelines/v1/__init__.py +0 -0
  99. viam/gen/app/datapipelines/v1/data_pipelines_grpc.py +84 -0
  100. viam/gen/app/datapipelines/v1/data_pipelines_pb2.py +57 -0
  101. viam/gen/app/datapipelines/v1/data_pipelines_pb2.pyi +387 -0
  102. viam/gen/app/dataset/__init__.py +0 -0
  103. viam/gen/app/dataset/v1/__init__.py +0 -0
  104. viam/gen/app/dataset/v1/dataset_grpc.py +68 -0
  105. viam/gen/app/dataset/v1/dataset_pb2.py +44 -0
  106. viam/gen/app/dataset/v1/dataset_pb2.pyi +214 -0
  107. viam/gen/app/datasync/v1/data_sync_grpc.py +21 -4
  108. viam/gen/app/datasync/v1/data_sync_pb2.py +62 -128
  109. viam/gen/app/datasync/v1/data_sync_pb2.pyi +156 -199
  110. viam/gen/app/mlinference/__init__.py +0 -0
  111. viam/gen/app/mlinference/v1/__init__.py +0 -0
  112. viam/gen/app/mlinference/v1/ml_inference_grpc.py +28 -0
  113. viam/gen/app/mlinference/v1/ml_inference_pb2.py +23 -0
  114. viam/gen/app/mlinference/v1/ml_inference_pb2.pyi +63 -0
  115. viam/gen/app/mltraining/v1/ml_training_grpc.py +51 -3
  116. viam/gen/app/mltraining/v1/ml_training_pb2.py +135 -58
  117. viam/gen/app/mltraining/v1/ml_training_pb2.pyi +328 -39
  118. viam/gen/app/packages/v1/packages_grpc.py +15 -1
  119. viam/gen/app/packages/v1/packages_pb2.py +44 -64
  120. viam/gen/app/packages/v1/packages_pb2.pyi +75 -85
  121. viam/gen/app/v1/app_grpc.py +644 -3
  122. viam/gen/app/v1/app_pb2.py +695 -295
  123. viam/gen/app/v1/app_pb2.pyi +4488 -635
  124. viam/gen/app/v1/billing_grpc.py +53 -11
  125. viam/gen/app/v1/billing_pb2.py +94 -39
  126. viam/gen/app/v1/billing_pb2.pyi +391 -191
  127. viam/gen/app/v1/end_user_grpc.py +59 -0
  128. viam/gen/app/v1/end_user_pb2.py +55 -0
  129. viam/gen/app/v1/end_user_pb2.pyi +181 -0
  130. viam/gen/app/v1/robot_grpc.py +16 -1
  131. viam/gen/app/v1/robot_pb2.py +122 -94
  132. viam/gen/app/v1/robot_pb2.pyi +463 -123
  133. viam/gen/common/v1/common_pb2.py +87 -58
  134. viam/gen/common/v1/common_pb2.pyi +456 -149
  135. viam/gen/component/arm/v1/arm_grpc.py +58 -2
  136. viam/gen/component/arm/v1/arm_pb2.py +68 -51
  137. viam/gen/component/arm/v1/arm_pb2.pyi +108 -42
  138. viam/gen/component/audioin/__init__.py +0 -0
  139. viam/gen/component/audioin/v1/__init__.py +0 -0
  140. viam/gen/component/audioin/v1/audioin_grpc.py +54 -0
  141. viam/gen/component/audioin/v1/audioin_pb2.py +34 -0
  142. viam/gen/component/audioin/v1/audioin_pb2.pyi +94 -0
  143. viam/gen/component/audioinput/v1/audioinput_grpc.py +25 -2
  144. viam/gen/component/audioinput/v1/audioinput_pb2.py +36 -31
  145. viam/gen/component/audioinput/v1/audioinput_pb2.pyi +22 -22
  146. viam/gen/component/audioout/__init__.py +0 -0
  147. viam/gen/component/audioout/v1/__init__.py +0 -0
  148. viam/gen/component/audioout/v1/audioout_grpc.py +54 -0
  149. viam/gen/component/audioout/v1/audioout_pb2.py +32 -0
  150. viam/gen/component/audioout/v1/audioout_pb2.pyi +47 -0
  151. viam/gen/component/base/v1/base_grpc.py +42 -2
  152. viam/gen/component/base/v1/base_pb2.py +58 -47
  153. viam/gen/component/base/v1/base_pb2.pyi +65 -30
  154. viam/gen/component/board/v1/board_grpc.py +59 -7
  155. viam/gen/component/board/v1/board_pb2.py +94 -73
  156. viam/gen/component/board/v1/board_pb2.pyi +165 -68
  157. viam/gen/component/button/__init__.py +0 -0
  158. viam/gen/component/button/v1/__init__.py +0 -0
  159. viam/gen/component/button/v1/button_grpc.py +38 -0
  160. viam/gen/component/button/v1/button_pb2.py +28 -0
  161. viam/gen/component/button/v1/button_pb2.pyi +39 -0
  162. viam/gen/component/camera/v1/camera_grpc.py +38 -2
  163. viam/gen/component/camera/v1/camera_pb2.py +60 -43
  164. viam/gen/component/camera/v1/camera_pb2.pyi +191 -37
  165. viam/gen/component/encoder/v1/encoder_grpc.py +25 -2
  166. viam/gen/component/encoder/v1/encoder_pb2.py +36 -31
  167. viam/gen/component/encoder/v1/encoder_pb2.pyi +15 -15
  168. viam/gen/component/gantry/v1/gantry_grpc.py +47 -2
  169. viam/gen/component/gantry/v1/gantry_pb2.py +56 -43
  170. viam/gen/component/gantry/v1/gantry_pb2.pyi +67 -31
  171. viam/gen/component/generic/v1/generic_grpc.py +16 -2
  172. viam/gen/component/generic/v1/generic_pb2.py +16 -11
  173. viam/gen/component/gripper/v1/gripper_grpc.py +44 -2
  174. viam/gen/component/gripper/v1/gripper_pb2.py +48 -35
  175. viam/gen/component/gripper/v1/gripper_pb2.pyi +62 -24
  176. viam/gen/component/inputcontroller/v1/input_controller_grpc.py +28 -2
  177. viam/gen/component/inputcontroller/v1/input_controller_pb2.py +46 -41
  178. viam/gen/component/inputcontroller/v1/input_controller_pb2.pyi +32 -36
  179. viam/gen/component/motor/v1/motor_grpc.py +51 -2
  180. viam/gen/component/motor/v1/motor_pb2.py +78 -67
  181. viam/gen/component/motor/v1/motor_pb2.pyi +75 -46
  182. viam/gen/component/movementsensor/v1/movementsensor_grpc.py +48 -2
  183. viam/gen/component/movementsensor/v1/movementsensor_pb2.py +70 -63
  184. viam/gen/component/movementsensor/v1/movementsensor_pb2.pyi +84 -57
  185. viam/gen/component/posetracker/v1/pose_tracker_grpc.py +19 -2
  186. viam/gen/component/posetracker/v1/pose_tracker_pb2.py +26 -21
  187. viam/gen/component/posetracker/v1/pose_tracker_pb2.pyi +9 -13
  188. viam/gen/component/powersensor/__init__.py +0 -0
  189. viam/gen/component/powersensor/v1/__init__.py +0 -0
  190. viam/gen/component/powersensor/v1/powersensor_grpc.py +62 -0
  191. viam/gen/component/powersensor/v1/powersensor_pb2.py +42 -0
  192. viam/gen/component/powersensor/v1/powersensor_pb2.pyi +124 -0
  193. viam/gen/component/sensor/v1/sensor_grpc.py +21 -5
  194. viam/gen/component/sensor/v1/sensor_pb2.py +18 -22
  195. viam/gen/component/sensor/v1/sensor_pb2.pyi +1 -69
  196. viam/gen/component/servo/v1/servo_grpc.py +28 -2
  197. viam/gen/component/servo/v1/servo_pb2.py +42 -37
  198. viam/gen/component/servo/v1/servo_pb2.pyi +22 -26
  199. viam/gen/component/switch/__init__.py +0 -0
  200. viam/gen/component/switch/v1/__init__.py +0 -0
  201. viam/gen/component/switch/v1/switch_grpc.py +54 -0
  202. viam/gen/component/switch/v1/switch_pb2.py +40 -0
  203. viam/gen/component/switch/v1/switch_pb2.pyi +116 -0
  204. viam/gen/component/testecho/v1/testecho_grpc.py +15 -0
  205. viam/gen/component/testecho/v1/testecho_pb2.py +29 -26
  206. viam/gen/component/testecho/v1/testecho_pb2.pyi +16 -20
  207. viam/gen/module/v1/module_grpc.py +18 -0
  208. viam/gen/module/v1/module_pb2.py +36 -33
  209. viam/gen/module/v1/module_pb2.pyi +39 -34
  210. viam/gen/opentelemetry/__init__.py +0 -0
  211. viam/gen/opentelemetry/proto/__init__.py +0 -0
  212. viam/gen/opentelemetry/proto/common/__init__.py +0 -0
  213. viam/gen/opentelemetry/proto/common/v1/__init__.py +0 -0
  214. viam/gen/opentelemetry/proto/common/v1/common_grpc.py +0 -0
  215. viam/gen/opentelemetry/proto/common/v1/common_pb2.py +27 -0
  216. viam/gen/opentelemetry/proto/common/v1/common_pb2.pyi +208 -0
  217. viam/gen/opentelemetry/proto/resource/__init__.py +0 -0
  218. viam/gen/opentelemetry/proto/resource/v1/__init__.py +0 -0
  219. viam/gen/opentelemetry/proto/resource/v1/resource_grpc.py +0 -0
  220. viam/gen/opentelemetry/proto/resource/v1/resource_pb2.py +18 -0
  221. viam/gen/opentelemetry/proto/resource/v1/resource_pb2.pyi +59 -0
  222. viam/gen/opentelemetry/proto/trace/__init__.py +0 -0
  223. viam/gen/opentelemetry/proto/trace/v1/__init__.py +0 -0
  224. viam/gen/opentelemetry/proto/trace/v1/trace_grpc.py +0 -0
  225. viam/gen/opentelemetry/proto/trace/v1/trace_pb2.py +37 -0
  226. viam/gen/opentelemetry/proto/trace/v1/trace_pb2.pyi +402 -0
  227. viam/gen/proto/rpc/examples/echo/v1/echo_grpc.py +12 -0
  228. viam/gen/proto/rpc/examples/echo/v1/echo_pb2.py +25 -22
  229. viam/gen/proto/rpc/examples/echo/v1/echo_pb2.pyi +13 -17
  230. viam/gen/proto/rpc/examples/echoresource/v1/echoresource_grpc.py +12 -0
  231. viam/gen/proto/rpc/examples/echoresource/v1/echoresource_pb2.py +23 -20
  232. viam/gen/proto/rpc/examples/echoresource/v1/echoresource_pb2.pyi +13 -17
  233. viam/gen/proto/rpc/v1/auth_grpc.py +11 -0
  234. viam/gen/proto/rpc/v1/auth_pb2.py +27 -24
  235. viam/gen/proto/rpc/v1/auth_pb2.pyi +12 -16
  236. viam/gen/proto/rpc/webrtc/v1/grpc_pb2.py +35 -32
  237. viam/gen/proto/rpc/webrtc/v1/grpc_pb2.pyi +37 -41
  238. viam/gen/proto/rpc/webrtc/v1/signaling_grpc.py +15 -0
  239. viam/gen/proto/rpc/webrtc/v1/signaling_pb2.py +62 -57
  240. viam/gen/proto/rpc/webrtc/v1/signaling_pb2.pyi +78 -69
  241. viam/gen/provisioning/__init__.py +0 -0
  242. viam/gen/provisioning/v1/__init__.py +0 -0
  243. viam/gen/provisioning/v1/provisioning_grpc.py +59 -0
  244. viam/gen/provisioning/v1/provisioning_pb2.py +45 -0
  245. viam/gen/provisioning/v1/provisioning_pb2.pyi +229 -0
  246. viam/gen/robot/v1/robot_grpc.py +144 -15
  247. viam/gen/robot/v1/robot_pb2.py +193 -119
  248. viam/gen/robot/v1/robot_pb2.pyi +565 -137
  249. viam/gen/service/datamanager/v1/data_manager_grpc.py +20 -2
  250. viam/gen/service/datamanager/v1/data_manager_pb2.py +27 -17
  251. viam/gen/service/datamanager/v1/data_manager_pb2.pyi +52 -10
  252. viam/gen/service/discovery/__init__.py +0 -0
  253. viam/gen/service/discovery/v1/__init__.py +0 -0
  254. viam/gen/service/discovery/v1/discovery_grpc.py +39 -0
  255. viam/gen/service/discovery/v1/discovery_pb2.py +29 -0
  256. viam/gen/service/discovery/v1/discovery_pb2.pyi +51 -0
  257. viam/gen/service/generic/__init__.py +0 -0
  258. viam/gen/service/generic/v1/__init__.py +0 -0
  259. viam/gen/service/generic/v1/generic_grpc.py +29 -0
  260. viam/gen/service/generic/v1/generic_pb2.py +21 -0
  261. viam/gen/service/generic/v1/generic_pb2.pyi +6 -0
  262. viam/gen/service/mlmodel/v1/mlmodel_grpc.py +9 -0
  263. viam/gen/service/mlmodel/v1/mlmodel_pb2.py +76 -29
  264. viam/gen/service/mlmodel/v1/mlmodel_pb2.pyi +307 -28
  265. viam/gen/service/motion/v1/motion_grpc.py +42 -4
  266. viam/gen/service/motion/v1/motion_pb2.py +119 -51
  267. viam/gen/service/motion/v1/motion_pb2.pyi +595 -120
  268. viam/gen/service/navigation/v1/navigation_grpc.py +49 -1
  269. viam/gen/service/navigation/v1/navigation_pb2.py +76 -51
  270. viam/gen/service/navigation/v1/navigation_pb2.pyi +188 -33
  271. viam/gen/service/sensors/v1/sensors_grpc.py +12 -0
  272. viam/gen/service/sensors/v1/sensors_pb2.py +60 -29
  273. viam/gen/service/sensors/v1/sensors_pb2.pyi +18 -21
  274. viam/gen/service/shell/v1/shell_grpc.py +27 -1
  275. viam/gen/service/shell/v1/shell_pb2.py +37 -15
  276. viam/gen/service/shell/v1/shell_pb2.pyi +260 -7
  277. viam/gen/service/slam/v1/slam_grpc.py +24 -2
  278. viam/gen/service/slam/v1/slam_pb2.py +44 -30
  279. viam/gen/service/slam/v1/slam_pb2.pyi +128 -27
  280. viam/gen/service/video/__init__.py +0 -0
  281. viam/gen/service/video/v1/__init__.py +0 -0
  282. viam/gen/service/video/v1/video_grpc.py +39 -0
  283. viam/gen/service/video/v1/video_pb2.py +29 -0
  284. viam/gen/service/video/v1/video_pb2.pyi +72 -0
  285. viam/gen/service/vision/v1/vision_grpc.py +39 -1
  286. viam/gen/service/vision/v1/vision_pb2.py +61 -45
  287. viam/gen/service/vision/v1/vision_pb2.pyi +180 -41
  288. viam/gen/service/worldstatestore/__init__.py +0 -0
  289. viam/gen/service/worldstatestore/v1/__init__.py +0 -0
  290. viam/gen/service/worldstatestore/v1/world_state_store_grpc.py +55 -0
  291. viam/gen/service/worldstatestore/v1/world_state_store_pb2.py +39 -0
  292. viam/gen/service/worldstatestore/v1/world_state_store_pb2.pyi +171 -0
  293. viam/gen/stream/__init__.py +0 -0
  294. viam/gen/stream/v1/__init__.py +0 -0
  295. viam/gen/stream/v1/stream_grpc.py +59 -0
  296. viam/gen/stream/v1/stream_pb2.py +39 -0
  297. viam/gen/stream/v1/stream_pb2.pyi +161 -0
  298. viam/gen/tagger/v1/tagger_pb2.py +9 -8
  299. viam/logging.py +160 -17
  300. viam/media/__init__.py +0 -9
  301. viam/media/audio.py +22 -10
  302. viam/media/utils/__init__.py +0 -0
  303. viam/media/utils/pil/__init__.py +55 -0
  304. viam/media/{viam_rgba_plugin.py → utils/pil/viam_rgba_plugin.py} +10 -16
  305. viam/media/viam_rgba.py +10 -0
  306. viam/media/video.py +197 -73
  307. viam/module/module.py +191 -44
  308. viam/module/resource_data_consumer.py +41 -0
  309. viam/module/service.py +9 -1
  310. viam/module/types.py +4 -5
  311. viam/operations.py +4 -3
  312. viam/proto/app/__init__.py +361 -5
  313. viam/proto/app/agent/__init__.py +28 -0
  314. viam/proto/app/billing.py +51 -27
  315. viam/proto/app/cloudslam/__init__.py +48 -0
  316. viam/proto/app/data/__init__.py +103 -17
  317. viam/proto/app/datapipelines/__init__.py +56 -0
  318. viam/proto/app/dataset/__init__.py +40 -0
  319. viam/proto/app/datasync/__init__.py +11 -5
  320. viam/proto/app/end_user.py +34 -0
  321. viam/proto/app/mlinference/__init__.py +15 -0
  322. viam/proto/app/mltraining/__init__.py +25 -1
  323. viam/proto/app/packages/__init__.py +3 -3
  324. viam/proto/app/robot.py +19 -1
  325. viam/proto/common/__init__.py +35 -8
  326. viam/proto/component/arm/__init__.py +9 -1
  327. viam/proto/component/audioin/__init__.py +16 -0
  328. viam/proto/component/audioinput/__init__.py +3 -1
  329. viam/proto/component/audioout/__init__.py +15 -0
  330. viam/proto/component/base/__init__.py +7 -1
  331. viam/proto/component/board/__init__.py +13 -5
  332. viam/proto/component/button/__init__.py +15 -0
  333. viam/proto/component/camera/__init__.py +9 -1
  334. viam/proto/component/encoder/__init__.py +3 -1
  335. viam/proto/component/gantry/__init__.py +7 -1
  336. viam/proto/component/generic/__init__.py +3 -1
  337. viam/proto/component/gripper/__init__.py +7 -1
  338. viam/proto/component/inputcontroller/__init__.py +7 -1
  339. viam/proto/component/motor/__init__.py +7 -1
  340. viam/proto/component/movementsensor/__init__.py +7 -1
  341. viam/proto/component/posetracker/__init__.py +7 -1
  342. viam/proto/component/powersensor/__init__.py +30 -0
  343. viam/proto/component/sensor/__init__.py +3 -4
  344. viam/proto/component/servo/__init__.py +3 -1
  345. viam/proto/component/switch/__init__.py +26 -0
  346. viam/proto/component/testecho/__init__.py +3 -1
  347. viam/proto/module/__init__.py +3 -1
  348. viam/proto/opentelemetry/__init__.py +0 -0
  349. viam/proto/opentelemetry/proto/__init__.py +0 -0
  350. viam/proto/opentelemetry/proto/common/__init__.py +15 -0
  351. viam/proto/opentelemetry/proto/resource/__init__.py +10 -0
  352. viam/proto/opentelemetry/proto/trace/__init__.py +15 -0
  353. viam/proto/provisioning/__init__.py +42 -0
  354. viam/proto/robot/__init__.py +57 -9
  355. viam/proto/rpc/auth.py +11 -1
  356. viam/proto/rpc/examples/echo/__init__.py +3 -1
  357. viam/proto/rpc/examples/echoresource/__init__.py +7 -1
  358. viam/proto/rpc/webrtc/grpc.py +3 -1
  359. viam/proto/rpc/webrtc/signaling.py +5 -1
  360. viam/proto/service/datamanager/__init__.py +15 -2
  361. viam/proto/service/discovery/__init__.py +15 -0
  362. viam/proto/service/generic/__init__.py +12 -0
  363. viam/proto/service/mlmodel/__init__.py +27 -1
  364. viam/proto/service/motion/__init__.py +35 -5
  365. viam/proto/service/navigation/__init__.py +19 -1
  366. viam/proto/service/sensors/__init__.py +3 -1
  367. viam/proto/service/shell/__init__.py +25 -2
  368. viam/proto/service/slam/__init__.py +13 -1
  369. viam/proto/service/video/__init__.py +15 -0
  370. viam/proto/service/vision/__init__.py +11 -1
  371. viam/proto/service/worldstatestore/__init__.py +32 -0
  372. viam/proto/stream/__init__.py +36 -0
  373. viam/py.typed +0 -0
  374. viam/resource/base.py +45 -8
  375. viam/resource/easy_resource.py +149 -0
  376. viam/resource/manager.py +35 -14
  377. viam/resource/registry.py +40 -52
  378. viam/resource/rpc_client_base.py +33 -1
  379. viam/resource/rpc_service_base.py +15 -8
  380. viam/resource/types.py +39 -26
  381. viam/robot/client.py +458 -91
  382. viam/robot/service.py +13 -107
  383. viam/rpc/dial.py +133 -15
  384. viam/rpc/libviam_rust_utils.so +0 -0
  385. viam/rpc/server.py +59 -15
  386. viam/rpc/types.py +2 -4
  387. viam/services/discovery/__init__.py +12 -0
  388. viam/services/discovery/client.py +55 -0
  389. viam/services/discovery/discovery.py +52 -0
  390. viam/services/discovery/service.py +43 -0
  391. viam/services/generic/__init__.py +18 -0
  392. viam/services/generic/client.py +58 -0
  393. viam/services/generic/generic.py +58 -0
  394. viam/services/generic/service.py +29 -0
  395. viam/services/mlmodel/__init__.py +15 -1
  396. viam/services/mlmodel/client.py +20 -15
  397. viam/services/mlmodel/mlmodel.py +44 -7
  398. viam/services/mlmodel/service.py +9 -13
  399. viam/services/mlmodel/utils.py +101 -0
  400. viam/services/motion/__init__.py +15 -3
  401. viam/services/motion/client.py +109 -150
  402. viam/services/motion/motion.py +380 -0
  403. viam/services/motion/service.py +132 -0
  404. viam/services/navigation/__init__.py +11 -0
  405. viam/services/navigation/client.py +99 -0
  406. viam/services/navigation/navigation.py +250 -0
  407. viam/services/navigation/service.py +137 -0
  408. viam/services/service_base.py +43 -4
  409. viam/services/service_client_base.py +4 -4
  410. viam/services/slam/__init__.py +4 -1
  411. viam/services/slam/client.py +21 -11
  412. viam/services/slam/service.py +16 -19
  413. viam/services/slam/slam.py +66 -5
  414. viam/services/vision/__init__.py +8 -0
  415. viam/services/vision/client.py +115 -111
  416. viam/services/vision/service.py +143 -0
  417. viam/services/vision/vision.py +317 -0
  418. viam/services/worldstatestore/__init__.py +18 -0
  419. viam/services/worldstatestore/client.py +94 -0
  420. viam/services/worldstatestore/service.py +55 -0
  421. viam/services/worldstatestore/worldstatestore.py +90 -0
  422. viam/sessions_client.py +254 -0
  423. viam/streams.py +44 -0
  424. viam/utils.py +143 -15
  425. viam/version_metadata.py +4 -0
  426. viam_sdk-0.66.0.dist-info/METADATA +157 -0
  427. viam_sdk-0.66.0.dist-info/RECORD +531 -0
  428. {viam_sdk-0.3.0.dist-info → viam_sdk-0.66.0.dist-info}/WHEEL +1 -1
  429. viam/components/audio_input/__init__.py +0 -18
  430. viam/components/audio_input/audio_input.py +0 -79
  431. viam/components/audio_input/client.py +0 -60
  432. viam/components/audio_input/service.py +0 -118
  433. viam/components/types.py +0 -5
  434. viam/gen/app/model/v1/model_grpc.py +0 -39
  435. viam/gen/app/model/v1/model_pb2.py +0 -71
  436. viam/gen/app/model/v1/model_pb2.pyi +0 -285
  437. viam/gen/proto/rpc/examples/fileupload/v1/fileupload_grpc.py +0 -21
  438. viam/gen/proto/rpc/examples/fileupload/v1/fileupload_pb2.py +0 -18
  439. viam/gen/proto/rpc/examples/fileupload/v1/fileupload_pb2.pyi +0 -49
  440. viam/media/media.py +0 -53
  441. viam/proto/app/model/__init__.py +0 -40
  442. viam/proto/rpc/examples/fileupload/__init__.py +0 -13
  443. viam/services/sensors/__init__.py +0 -5
  444. viam/services/sensors/client.py +0 -63
  445. viam_sdk-0.3.0.dist-info/LICENSE +0 -202
  446. viam_sdk-0.3.0.dist-info/METADATA +0 -122
  447. viam_sdk-0.3.0.dist-info/RECORD +0 -372
  448. /viam/{gen/app/model → app}/__init__.py +0 -0
  449. /viam/gen/app/{model/v1 → agent}/__init__.py +0 -0
  450. /viam/gen/{proto/rpc/examples/fileupload → app/agent/v1}/__init__.py +0 -0
  451. /viam/gen/{proto/rpc/examples/fileupload/v1 → app/cloudslam}/__init__.py +0 -0
  452. /LICENSE → /viam_sdk-0.66.0.dist-info/licenses/LICENSE +0 -0
viam/robot/service.py CHANGED
@@ -1,78 +1,37 @@
1
- import asyncio
2
- from typing import Any, Dict, Iterable, List
1
+ from typing import Any, Dict, List, Set
3
2
 
4
3
  from grpclib.server import Stream
5
4
 
6
5
  from viam import logging
7
- from viam.errors import MethodNotImplementedError, ViamGRPCError
6
+ from viam.components.movement_sensor import MovementSensor
7
+ from viam.components.sensor import Sensor
8
+ from viam.errors import ViamGRPCError
8
9
  from viam.proto.common import ResourceName
9
10
  from viam.proto.robot import (
10
- BlockForOperationRequest,
11
- BlockForOperationResponse,
12
- CancelOperationRequest,
13
- CancelOperationResponse,
14
- DiscoverComponentsRequest,
15
- DiscoverComponentsResponse,
16
- FrameSystemConfigRequest,
17
- FrameSystemConfigResponse,
18
- GetOperationsRequest,
19
- GetOperationsResponse,
20
- GetSessionsRequest,
21
- GetSessionsResponse,
22
- GetStatusRequest,
23
- GetStatusResponse,
24
11
  ResourceNamesRequest,
25
12
  ResourceNamesResponse,
26
- ResourceRPCSubtypesRequest,
27
- ResourceRPCSubtypesResponse,
28
- RobotServiceBase,
29
- SendSessionHeartbeatRequest,
30
- SendSessionHeartbeatResponse,
31
- StartSessionRequest,
32
- StartSessionResponse,
33
- Status,
34
13
  StopAllRequest,
35
14
  StopAllResponse,
36
- StreamStatusRequest,
37
- StreamStatusResponse,
38
- TransformPCDRequest,
39
- TransformPCDResponse,
40
- TransformPoseRequest,
41
- TransformPoseResponse,
15
+ UnimplementedRobotServiceBase,
42
16
  )
43
- from viam.resource.registry import Registry
44
17
  from viam.resource.rpc_service_base import ResourceRPCServiceBase
45
18
  from viam.utils import resource_names_for_resource, struct_to_dict
46
19
 
47
20
  LOGGER = logging.getLogger(__name__)
48
21
 
49
22
 
50
- class RobotService(RobotServiceBase, ResourceRPCServiceBase):
23
+ class RobotService(UnimplementedRobotServiceBase, ResourceRPCServiceBase):
51
24
  def _generate_metadata(self) -> List[ResourceName]:
52
- md: List[ResourceName] = []
25
+ md: Set[ResourceName] = set()
53
26
 
54
- for component in self.manager.resources.values():
55
- md.extend(resource_names_for_resource(component))
56
-
57
- return md
58
-
59
- async def _generate_status(self, resource_names: Iterable[ResourceName]) -> List[Status]:
60
- statuses: List[Status] = []
27
+ for resource in self.manager.resources.values():
28
+ # If the resource is a MovementSensor, DO NOT include Sensor as well (it will get added via MovementSensor)
29
+ if resource.API == Sensor.API and MovementSensor.get_resource_name(resource.name) in self.manager.resources:
30
+ continue
61
31
 
62
- for component in self.manager.resources.values():
63
- for registration in Registry.REGISTERED_SUBTYPES().values():
64
- if isinstance(component, registration.resource_type):
65
- if resource_names and component.get_resource_name(component.name) not in resource_names:
66
- continue
67
- try:
68
- status = await registration.create_status(component)
69
- statuses.append(status)
70
- except ViamGRPCError as e:
71
- raise e.grpc_error
32
+ md.update(resource_names_for_resource(resource))
72
33
 
73
- if resource_names:
74
- statuses = [s for s in statuses if s.name in resource_names]
75
- return statuses
34
+ return list(md)
76
35
 
77
36
  async def ResourceNames(self, stream: Stream[ResourceNamesRequest, ResourceNamesResponse]) -> None:
78
37
  request = await stream.recv_message()
@@ -81,47 +40,6 @@ class RobotService(RobotServiceBase, ResourceRPCServiceBase):
81
40
  response = ResourceNamesResponse(resources=metadata)
82
41
  await stream.send_message(response)
83
42
 
84
- async def GetStatus(self, stream: Stream[GetStatusRequest, GetStatusResponse]) -> None:
85
- request = await stream.recv_message()
86
- assert request is not None
87
- status = await self._generate_status(request.resource_names)
88
- response = GetStatusResponse(status=status)
89
- await stream.send_message(response)
90
-
91
- async def StreamStatus(self, stream: Stream[StreamStatusRequest, StreamStatusResponse]) -> None:
92
- request = await stream.recv_message()
93
- assert request is not None
94
- interval = 1
95
- every = request.every.ToSeconds()
96
- if every > 0:
97
- interval = every
98
- while True:
99
- status = await self._generate_status(request.resource_names)
100
- response = StreamStatusResponse(status=status)
101
- await stream.send_message(response)
102
- await asyncio.sleep(interval)
103
-
104
- async def GetOperations(self, stream: Stream[GetOperationsRequest, GetOperationsResponse]) -> None:
105
- raise MethodNotImplementedError("GetOperations").grpc_error
106
-
107
- async def ResourceRPCSubtypes(self, stream: Stream[ResourceRPCSubtypesRequest, ResourceRPCSubtypesResponse]) -> None:
108
- raise MethodNotImplementedError("ResourceRPCSubtypes").grpc_error
109
-
110
- async def CancelOperation(self, stream: Stream[CancelOperationRequest, CancelOperationResponse]) -> None:
111
- raise MethodNotImplementedError("CancelOperation").grpc_error
112
-
113
- async def BlockForOperation(self, stream: Stream[BlockForOperationRequest, BlockForOperationResponse]) -> None:
114
- raise MethodNotImplementedError("BlockForOperation").grpc_error
115
-
116
- async def FrameSystemConfig(self, stream: Stream[FrameSystemConfigRequest, FrameSystemConfigResponse]) -> None:
117
- raise MethodNotImplementedError("FrameSystemConfig").grpc_error
118
-
119
- async def TransformPose(self, stream: Stream[TransformPoseRequest, TransformPoseResponse]) -> None:
120
- raise MethodNotImplementedError("TransformPose").grpc_error
121
-
122
- async def DiscoverComponents(self, stream: Stream[DiscoverComponentsRequest, DiscoverComponentsResponse]) -> None:
123
- raise MethodNotImplementedError("DiscoverComponents").grpc_error
124
-
125
43
  async def StopAll(self, stream: Stream[StopAllRequest, StopAllResponse]) -> None:
126
44
  request = await stream.recv_message()
127
45
  assert request is not None
@@ -149,15 +67,3 @@ class RobotService(RobotServiceBase, ResourceRPCServiceBase):
149
67
  if errors:
150
68
  raise ViamGRPCError(f'Failed to stop components named {", ".join(errors)}')
151
69
  await stream.send_message(StopAllResponse())
152
-
153
- async def GetSessions(self, stream: Stream[GetSessionsRequest, GetSessionsResponse]) -> None:
154
- raise MethodNotImplementedError("GetSessions").grpc_error
155
-
156
- async def StartSession(self, stream: Stream[StartSessionRequest, StartSessionResponse]) -> None:
157
- raise MethodNotImplementedError("StartSession").grpc_error
158
-
159
- async def SendSessionHeartbeat(self, stream: Stream[SendSessionHeartbeatRequest, SendSessionHeartbeatResponse]) -> None:
160
- raise MethodNotImplementedError("SendSessionHeartbeat").grpc_error
161
-
162
- async def TransformPCD(self, stream: Stream[TransformPCDRequest, TransformPCDResponse]) -> None:
163
- raise MethodNotImplementedError("TransformPCD").grpc_error
viam/rpc/dial.py CHANGED
@@ -4,33 +4,34 @@ import re
4
4
  import socket
5
5
  import ssl
6
6
  import sys
7
+ import uuid
7
8
  import warnings
8
9
  from dataclasses import dataclass
9
10
  from typing import Callable, Literal, Optional, Tuple, Type, Union
10
11
 
11
12
  from grpclib.client import Channel, Stream
12
13
  from grpclib.const import Cardinality
14
+ from grpclib.events import SendRequest, listen
13
15
  from grpclib.metadata import Deadline, _MetadataLike
14
16
  from grpclib.protocol import H2Protocol
15
17
  from grpclib.stream import _RecvType, _SendType
18
+ from typing_extensions import Self
16
19
 
17
20
  from viam import logging
18
21
  from viam.errors import InsecureConnectionError, ViamError
19
22
  from viam.proto.rpc.auth import AuthenticateRequest, AuthServiceStub
20
23
  from viam.proto.rpc.auth import Credentials as PBCredentials
21
24
  from viam.utils import to_thread
25
+ from viam.version_metadata import API_VERSION, SDK_VERSION
22
26
 
23
27
  LOGGER = logging.getLogger(__name__)
24
28
 
25
29
 
26
30
  @dataclass
27
31
  class Credentials:
28
- """Credentials to connect to the robot.
32
+ """Credentials to connect to the machine and app.viam.com."""
29
33
 
30
- Currently only supports robot location secret.
31
- """
32
-
33
- type: Literal["robot-location-secret"]
34
+ type: Union[Literal["robot-secret"], Literal["api-key"]]
34
35
  """The type of credential
35
36
  """
36
37
 
@@ -66,14 +67,34 @@ class DialOptions:
66
67
  if detected, even with credentials present. This is generally
67
68
  unsafe to use, but can be requested."""
68
69
 
70
+ max_reconnect_attempts: int = 3
71
+ """Max number of times the client attempts to reconnect when connection is lost"""
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
+
81
+ timeout: float = 20
82
+ """Number of seconds before the dial connection times out
83
+ Set to 20sec to match _defaultOfferDeadline in goutils/rpc/wrtc_call_queue.go"""
84
+
69
85
  def __init__(
70
86
  self,
87
+ *,
71
88
  disable_webrtc: bool = False,
72
89
  auth_entity: Optional[str] = None,
73
90
  credentials: Optional[Credentials] = None,
74
91
  insecure: bool = False,
75
92
  allow_insecure_downgrade: bool = False,
76
93
  allow_insecure_with_creds_downgrade: bool = False,
94
+ max_reconnect_attempts: int = 3,
95
+ timeout: float = 20,
96
+ initial_connection_attempts: int = 3,
97
+ initial_connection_attempt_timeout: Optional[float] = None,
77
98
  ) -> None:
78
99
  self.disable_webrtc = disable_webrtc
79
100
  self.auth_entity = auth_entity
@@ -81,6 +102,32 @@ class DialOptions:
81
102
  self.insecure = insecure
82
103
  self.allow_insecure_downgrade = allow_insecure_downgrade
83
104
  self.allow_insecure_with_creds_downgrade = allow_insecure_with_creds_downgrade
105
+ self.max_reconnect_attempts = max_reconnect_attempts
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
109
+
110
+ @classmethod
111
+ def with_api_key(cls, api_key: str, api_key_id: str) -> Self:
112
+ """Create DialOptions with an API key for credentials and default values for other arguments.
113
+
114
+ Args:
115
+ api_key (str): your API key
116
+ api_key_id (str): your API key ID. Must be a valid UUID
117
+
118
+ Raises:
119
+ ValueError: Raised if the api_key_id is not a valid UUID
120
+
121
+ Returns:
122
+ Self: the DialOptions
123
+ """
124
+ try:
125
+ uuid.UUID(api_key_id)
126
+ except ValueError:
127
+ raise ValueError(f"{api_key_id} is not a valid UUID")
128
+
129
+ credentials = Credentials(type="api-key", payload=api_key)
130
+ return cls(credentials=credentials, auth_entity=api_key_id)
84
131
 
85
132
 
86
133
  def _host_port_from_url(url) -> Tuple[Optional[str], Optional[int]]:
@@ -160,6 +207,12 @@ class ViamChannel:
160
207
  if not self._closed:
161
208
  try:
162
209
  self.channel.close()
210
+ except RuntimeError as e:
211
+ # ignore event loop is closed errors - robot is getting shutdown
212
+ if len(e.args) > 0 and e.args[0] == "Event loop is closed":
213
+ LOGGER.debug("ViamChannel might not have shut down cleanly - Event loop was closed")
214
+ return
215
+ raise
163
216
  finally:
164
217
  self.release()
165
218
  self._closed = True
@@ -179,13 +232,22 @@ class _Runtime:
179
232
  _ptr: ctypes.c_void_p
180
233
 
181
234
  def __init__(self) -> None:
235
+ suffix = "dylib" if sys.platform == "darwin" else "so" if "linux" in sys.platform else "dll"
182
236
  LOGGER.debug("Creating new viam-rust-utils runtime")
183
- 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}"
184
238
  self._lib = ctypes.CDLL(libname.__str__())
185
239
  self._lib.init_rust_runtime.argtypes = ()
186
240
  self._lib.init_rust_runtime.restype = ctypes.c_void_p
187
241
 
188
- self._lib.dial.argtypes = (ctypes.c_char_p, ctypes.c_char_p, ctypes.c_bool, ctypes.c_void_p)
242
+ self._lib.dial.argtypes = (
243
+ ctypes.c_char_p,
244
+ ctypes.c_char_p,
245
+ ctypes.c_char_p,
246
+ ctypes.c_char_p,
247
+ ctypes.c_bool,
248
+ ctypes.c_float,
249
+ ctypes.c_void_p,
250
+ )
189
251
  self._lib.dial.restype = ctypes.c_void_p
190
252
 
191
253
  self._lib.free_rust_runtime.argtypes = (ctypes.c_void_p,)
@@ -197,20 +259,27 @@ class _Runtime:
197
259
  self._ptr = self._lib.init_rust_runtime()
198
260
 
199
261
  async def dial(self, address: str, options: DialOptions) -> Tuple[Optional[str], ctypes.c_void_p]:
200
- creds = options.credentials.payload if options.credentials else ""
201
- insecure = options.insecure or options.allow_insecure_with_creds_downgrade or (not creds and options.allow_insecure_downgrade)
262
+ type = options.credentials.type if options.credentials else ""
263
+ payload = options.credentials.payload if options.credentials else ""
264
+ insecure = (
265
+ options.insecure
266
+ or options.allow_insecure_with_creds_downgrade
267
+ or (not type and not payload and options.allow_insecure_downgrade)
268
+ )
202
269
 
203
270
  LOGGER.debug(f"Dialing {address} using viam-rust-utils library")
204
271
  path_ptr = await to_thread(
205
272
  self._lib.dial,
206
273
  address.encode("utf-8"),
207
- creds.encode("utf-8") if creds else None,
274
+ options.auth_entity.encode("utf-8") if options.auth_entity else None,
275
+ type.encode("utf-8") if type else None,
276
+ payload.encode("utf-8") if payload else None,
208
277
  insecure,
278
+ ctypes.c_float(options.timeout),
209
279
  self._ptr,
210
280
  )
211
281
  path = ctypes.cast(path_ptr, ctypes.c_char_p).value
212
282
  path = path.decode("utf-8") if path else ""
213
-
214
283
  return (path, path_ptr)
215
284
 
216
285
  def release(self):
@@ -223,15 +292,50 @@ class _Runtime:
223
292
 
224
293
 
225
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
+
226
328
  opts = options if options else DialOptions()
227
329
  if opts.disable_webrtc:
228
330
  channel = await _dial_direct(address, options)
331
+ listen(channel, SendRequest, send_request)
229
332
  return ViamChannel(channel, lambda: None)
230
333
  runtime = _Runtime()
231
334
  path, path_ptr = await runtime.dial(address, opts)
232
335
  if path:
233
336
  LOGGER.info(f"Connecting to socket: {path}")
234
- chan = Channel(path=path, ssl=None)
337
+ chan = _create_chan(path)
338
+ listen(chan, SendRequest, send_request)
235
339
 
236
340
  def release():
237
341
  runtime.free_str(path_ptr)
@@ -259,17 +363,27 @@ async def _dial_direct(address: str, options: Optional[DialOptions] = None) -> C
259
363
  if insecure:
260
364
  ctx = None
261
365
  else:
262
- ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
366
+ is_local_host = host is not None and (host.startswith("localhost") or host.startswith("0.0.0.0") or host.startswith("127."))
367
+ if is_local_host:
368
+ ctx = ssl._create_unverified_context(purpose=ssl.Purpose.SERVER_AUTH)
369
+ else:
370
+ ctx = ssl.create_default_context(purpose=ssl.Purpose.SERVER_AUTH)
263
371
  ctx.minimum_version = ssl.TLSVersion.TLSv1_2
264
372
  ctx.set_ciphers("ECDHE+AESGCM:ECDHE+CHACHA20:DHE+AESGCM:DHE+CHACHA20")
265
373
  ctx.set_alpn_protocols(["h2"])
266
374
 
267
- if options is not None and options.auth_entity and host != options.auth_entity:
375
+ if (
376
+ options is not None
377
+ and options.auth_entity
378
+ and host != options.auth_entity
379
+ and options.credentials is not None
380
+ and options.credentials.type != "api-key"
381
+ ):
268
382
  server_hostname = options.auth_entity
269
383
 
270
384
  # Test if downgrade is required.
271
385
  downgrade = False
272
- with socket.create_connection((host, port)) as sock:
386
+ with socket.create_connection((host, port), timeout=opts.timeout) as sock:
273
387
  try:
274
388
  with ctx.wrap_socket(sock, server_hostname=server_hostname) as ssock:
275
389
  _ = ssock.version()
@@ -300,3 +414,7 @@ async def _dial_direct(address: str, options: Optional[DialOptions] = None) -> C
300
414
  async def dial_direct(address: str, options: Optional[DialOptions] = None) -> Channel:
301
415
  warnings.warn("dial_direct is deprecated. Use rpc.dial.dial instead.", DeprecationWarning, stacklevel=2)
302
416
  return await _dial_direct(address, options)
417
+
418
+
419
+ async def _dial_app(app_url: str) -> Channel:
420
+ return await _dial_direct(app_url)
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
@@ -6,6 +7,7 @@ from grpclib.const import Handler
6
7
  from grpclib.events import RecvRequest, listen
7
8
  from grpclib.reflection.service import ServerReflection
8
9
  from grpclib.server import Server as GRPCServer
10
+ from grpclib.server import Stream
9
11
  from grpclib.utils import graceful_exit
10
12
 
11
13
  from viam import logging
@@ -40,7 +42,7 @@ class Server(ResourceManager):
40
42
  super().__init__(resources)
41
43
 
42
44
  services = [SignalingService(), RobotService(manager=self)]
43
- for registration in Registry.REGISTERED_SUBTYPES().values():
45
+ for registration in Registry.REGISTERED_APIS().values():
44
46
  if issubclass(registration.rpc_service, ResourceRPCServiceBase):
45
47
  services.append(registration.rpc_service(manager=self))
46
48
  else:
@@ -53,15 +55,51 @@ class Server(ResourceManager):
53
55
 
54
56
  self._server = GRPCServer(services)
55
57
 
56
- async def _grpc_event_handler(self, event: RecvRequest):
58
+ async def _grpc_recvrequest_handler(self, event: RecvRequest):
57
59
  host = None
58
60
  port = None
59
61
  address = event.peer.addr()
60
62
  if address:
61
63
  host = address[0]
62
64
  port = address[1]
63
- msg = f"[gRPC Request] {host or 'xxxx'}:{port or 'xxxx'} - {event.method_name}"
64
- LOGGER.debug(msg)
65
+ method_func = event.method_func
66
+
67
+ async def log_resource_name(stream: Stream):
68
+ recv_msg = stream.recv_message
69
+
70
+ async def rcv_and_log_msg():
71
+ msg = await recv_msg()
72
+ log_msg = f"[gRPC] Received message from {host or 'xxxx'}:{port or 'xxxx'} - {event.method_name}"
73
+ if msg and hasattr(msg, "name"):
74
+ log_msg += f" for resource named: {msg.name}"
75
+ LOGGER.debug(log_msg)
76
+ return msg
77
+
78
+ stream.recv_message = rcv_and_log_msg
79
+ try:
80
+ return await method_func(stream)
81
+ finally:
82
+ LOGGER.debug(f"[gRPC] Finished call from {host or 'xxxx'}:{port or 'xxxx'} - {event.method_name}")
83
+
84
+ event.method_func = log_resource_name
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")
65
103
 
66
104
  async def serve(
67
105
  self,
@@ -84,17 +122,13 @@ class Server(ResourceManager):
84
122
  logging.silence()
85
123
  else:
86
124
  logging.setLevel(log_level)
87
- listen(self._server, RecvRequest, self._grpc_event_handler)
125
+ listen(self._server, RecvRequest, self._grpc_recvrequest_handler)
88
126
 
89
- with graceful_exit([self._server]):
90
- if path:
91
- await self._server.start(path=path)
92
- LOGGER.info(f"Serving on {path}")
93
- else:
94
- await self._server.start(host, port)
95
- LOGGER.info(f"Serving on {host}:{port}")
96
- await self._server.wait_closed()
97
- 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)
98
132
 
99
133
  @classmethod
100
134
  async def create_and_serve(
@@ -142,7 +176,17 @@ def _grpc_error_wrapper(func: Callable):
142
176
  except ViamGRPCError as e:
143
177
  raise e.grpc_error
144
178
  except Exception as e:
145
- raise GRPCError(Status.UNKNOWN, f"{e.__class__.__name__} - {e}")
179
+ tb = e.__traceback__
180
+ file_name = None
181
+ func_name = None
182
+ line_num = None
183
+ # only print the last entry in the stacktrace - not perfect but gives users a starting point
184
+ while tb is not None:
185
+ file_name = tb.tb_frame.f_code.co_filename
186
+ func_name = tb.tb_frame.f_code.co_name
187
+ line_num = tb.tb_lineno
188
+ tb = tb.tb_next
189
+ raise GRPCError(Status.UNKNOWN, f"{e.__class__.__name__} - {e} - {file_name=} {func_name=} {line_num=}")
146
190
 
147
191
  return interceptor
148
192
 
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
+ ...