viam-sdk 0.25.2__py3-none-linux_armv7l.whl → 0.62.0__py3-none-linux_armv7l.whl

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

Potentially problematic release.


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

Files changed (328) hide show
  1. viam/app/_logs.py +3 -6
  2. viam/app/app_client.py +606 -262
  3. viam/app/billing_client.py +60 -18
  4. viam/app/data_client.py +1086 -315
  5. viam/app/ml_training_client.py +51 -48
  6. viam/app/provisioning_client.py +3 -5
  7. viam/app/viam_client.py +105 -11
  8. viam/components/arm/__init__.py +1 -25
  9. viam/components/arm/arm.py +21 -22
  10. viam/components/arm/client.py +27 -30
  11. viam/components/arm/service.py +3 -3
  12. viam/components/audio_in/__init__.py +24 -0
  13. viam/components/audio_in/audio_in.py +74 -0
  14. viam/components/audio_in/client.py +76 -0
  15. viam/components/audio_in/service.py +83 -0
  16. viam/components/audio_input/__init__.py +1 -1
  17. viam/components/audio_input/audio_input.py +4 -3
  18. viam/components/audio_input/client.py +19 -8
  19. viam/components/audio_input/service.py +10 -0
  20. viam/components/audio_out/__init__.py +21 -0
  21. viam/components/audio_out/audio_out.py +72 -0
  22. viam/components/audio_out/client.py +67 -0
  23. viam/components/audio_out/service.py +63 -0
  24. viam/components/base/__init__.py +2 -10
  25. viam/components/base/base.py +20 -20
  26. viam/components/base/client.py +27 -30
  27. viam/components/board/__init__.py +2 -25
  28. viam/components/board/board.py +39 -77
  29. viam/components/board/client.py +39 -73
  30. viam/components/button/__init__.py +10 -0
  31. viam/components/button/button.py +41 -0
  32. viam/components/button/client.py +52 -0
  33. viam/components/button/service.py +46 -0
  34. viam/components/camera/__init__.py +1 -1
  35. viam/components/camera/camera.py +31 -22
  36. viam/components/camera/client.py +30 -20
  37. viam/components/camera/service.py +14 -12
  38. viam/components/component_base.py +10 -7
  39. viam/components/encoder/__init__.py +1 -1
  40. viam/components/encoder/client.py +15 -16
  41. viam/components/encoder/encoder.py +9 -9
  42. viam/components/gantry/__init__.py +1 -13
  43. viam/components/gantry/client.py +41 -28
  44. viam/components/gantry/gantry.py +48 -17
  45. viam/components/gantry/service.py +21 -5
  46. viam/components/generic/__init__.py +1 -1
  47. viam/components/generic/client.py +11 -7
  48. viam/components/generic/generic.py +3 -3
  49. viam/components/gripper/__init__.py +3 -12
  50. viam/components/gripper/client.py +43 -20
  51. viam/components/gripper/gripper.py +87 -12
  52. viam/components/gripper/service.py +32 -3
  53. viam/components/input/__init__.py +1 -14
  54. viam/components/input/client.py +22 -23
  55. viam/components/input/input.py +18 -12
  56. viam/components/motor/__init__.py +1 -21
  57. viam/components/motor/client.py +36 -42
  58. viam/components/motor/motor.py +24 -24
  59. viam/components/movement_sensor/__init__.py +1 -1
  60. viam/components/movement_sensor/client.py +33 -40
  61. viam/components/movement_sensor/movement_sensor.py +12 -12
  62. viam/components/pose_tracker/__init__.py +1 -1
  63. viam/components/pose_tracker/client.py +9 -8
  64. viam/components/pose_tracker/pose_tracker.py +2 -2
  65. viam/components/power_sensor/__init__.py +1 -1
  66. viam/components/power_sensor/client.py +15 -18
  67. viam/components/power_sensor/power_sensor.py +12 -12
  68. viam/components/sensor/__init__.py +1 -1
  69. viam/components/sensor/client.py +9 -8
  70. viam/components/sensor/sensor.py +5 -5
  71. viam/components/servo/__init__.py +1 -13
  72. viam/components/servo/client.py +18 -18
  73. viam/components/servo/servo.py +12 -12
  74. viam/components/switch/__init__.py +10 -0
  75. viam/components/switch/client.py +83 -0
  76. viam/components/switch/service.py +72 -0
  77. viam/components/switch/switch.py +95 -0
  78. viam/gen/app/agent/v1/agent_pb2.py +40 -29
  79. viam/gen/app/agent/v1/agent_pb2.pyi +73 -11
  80. viam/gen/app/cloudslam/v1/cloud_slam_pb2.py +45 -42
  81. viam/gen/app/data/v1/data_grpc.py +98 -2
  82. viam/gen/app/data/v1/data_pb2.py +238 -119
  83. viam/gen/app/data/v1/data_pb2.pyi +804 -34
  84. viam/gen/app/datapipelines/v1/data_pipelines_grpc.py +84 -0
  85. viam/gen/app/datapipelines/v1/data_pipelines_pb2.py +57 -0
  86. viam/gen/app/datapipelines/v1/data_pipelines_pb2.pyi +387 -0
  87. viam/gen/app/dataset/v1/dataset_grpc.py +10 -2
  88. viam/gen/app/dataset/v1/dataset_pb2.py +38 -31
  89. viam/gen/app/dataset/v1/dataset_pb2.pyi +36 -1
  90. viam/gen/app/datasync/v1/data_sync_grpc.py +1 -1
  91. viam/gen/app/datasync/v1/data_sync_pb2.py +61 -51
  92. viam/gen/app/datasync/v1/data_sync_pb2.pyi +52 -12
  93. viam/gen/app/mlinference/__init__.py +0 -0
  94. viam/gen/app/mlinference/v1/__init__.py +0 -0
  95. viam/gen/app/mlinference/v1/ml_inference_grpc.py +28 -0
  96. viam/gen/app/mlinference/v1/ml_inference_pb2.py +23 -0
  97. viam/gen/app/mlinference/v1/ml_inference_pb2.pyi +63 -0
  98. viam/gen/app/mltraining/v1/ml_training_grpc.py +18 -2
  99. viam/gen/app/mltraining/v1/ml_training_pb2.py +134 -101
  100. viam/gen/app/mltraining/v1/ml_training_pb2.pyi +193 -7
  101. viam/gen/app/packages/v1/packages_pb2.py +43 -40
  102. viam/gen/app/v1/app_grpc.py +290 -2
  103. viam/gen/app/v1/app_pb2.py +670 -453
  104. viam/gen/app/v1/app_pb2.pyi +3133 -947
  105. viam/gen/app/v1/billing_grpc.py +34 -2
  106. viam/gen/app/v1/billing_pb2.py +94 -35
  107. viam/gen/app/v1/billing_pb2.pyi +314 -61
  108. viam/gen/app/v1/end_user_pb2.py +50 -29
  109. viam/gen/app/v1/robot_pb2.py +120 -111
  110. viam/gen/app/v1/robot_pb2.pyi +137 -15
  111. viam/gen/common/v1/common_pb2.py +86 -66
  112. viam/gen/common/v1/common_pb2.pyi +184 -8
  113. viam/gen/component/arm/v1/arm_grpc.py +18 -2
  114. viam/gen/component/arm/v1/arm_pb2.py +68 -55
  115. viam/gen/component/arm/v1/arm_pb2.pyi +73 -3
  116. viam/gen/component/audioin/__init__.py +0 -0
  117. viam/gen/component/audioin/v1/__init__.py +0 -0
  118. viam/gen/component/audioin/v1/audioin_grpc.py +54 -0
  119. viam/gen/component/audioin/v1/audioin_pb2.py +34 -0
  120. viam/gen/component/audioin/v1/audioin_pb2.pyi +94 -0
  121. viam/gen/component/audioinput/v1/audioinput_pb2.py +35 -32
  122. viam/gen/component/audioout/__init__.py +0 -0
  123. viam/gen/component/audioout/v1/__init__.py +0 -0
  124. viam/gen/component/audioout/v1/audioout_grpc.py +54 -0
  125. viam/gen/component/audioout/v1/audioout_pb2.py +32 -0
  126. viam/gen/component/audioout/v1/audioout_pb2.pyi +47 -0
  127. viam/gen/component/base/v1/base_pb2.py +57 -54
  128. viam/gen/component/board/v1/board_pb2.py +93 -90
  129. viam/gen/component/button/__init__.py +0 -0
  130. viam/gen/component/button/v1/__init__.py +0 -0
  131. viam/gen/component/button/v1/button_grpc.py +38 -0
  132. viam/gen/component/button/v1/button_pb2.py +28 -0
  133. viam/gen/component/button/v1/button_pb2.pyi +39 -0
  134. viam/gen/component/camera/v1/camera_pb2.py +58 -55
  135. viam/gen/component/camera/v1/camera_pb2.pyi +31 -7
  136. viam/gen/component/encoder/v1/encoder_pb2.py +35 -32
  137. viam/gen/component/gantry/v1/gantry_grpc.py +9 -1
  138. viam/gen/component/gantry/v1/gantry_pb2.py +56 -51
  139. viam/gen/component/generic/v1/generic_pb2.py +15 -12
  140. viam/gen/component/gripper/v1/gripper_grpc.py +18 -2
  141. viam/gen/component/gripper/v1/gripper_pb2.py +48 -37
  142. viam/gen/component/gripper/v1/gripper_pb2.pyi +43 -1
  143. viam/gen/component/inputcontroller/v1/input_controller_pb2.py +45 -42
  144. viam/gen/component/motor/v1/motor_pb2.py +77 -74
  145. viam/gen/component/movementsensor/v1/movementsensor_pb2.py +69 -66
  146. viam/gen/component/posetracker/v1/pose_tracker_pb2.py +25 -22
  147. viam/gen/component/powersensor/v1/powersensor_pb2.py +33 -30
  148. viam/gen/component/sensor/v1/sensor_pb2.py +17 -14
  149. viam/gen/component/servo/v1/servo_pb2.py +41 -38
  150. viam/gen/component/switch/__init__.py +0 -0
  151. viam/gen/component/switch/v1/__init__.py +0 -0
  152. viam/gen/component/switch/v1/switch_grpc.py +54 -0
  153. viam/gen/component/switch/v1/switch_pb2.py +40 -0
  154. viam/gen/component/switch/v1/switch_pb2.pyi +116 -0
  155. viam/gen/component/testecho/v1/testecho_pb2.py +29 -26
  156. viam/gen/module/v1/module_pb2.py +36 -33
  157. viam/gen/module/v1/module_pb2.pyi +7 -2
  158. viam/gen/proto/rpc/examples/echo/v1/echo_pb2.py +26 -23
  159. viam/gen/proto/rpc/examples/echoresource/v1/echoresource_pb2.py +23 -20
  160. viam/gen/proto/rpc/v1/auth_pb2.py +27 -24
  161. viam/gen/proto/rpc/webrtc/v1/grpc_pb2.py +35 -32
  162. viam/gen/proto/rpc/webrtc/v1/signaling_pb2.py +62 -57
  163. viam/gen/proto/rpc/webrtc/v1/signaling_pb2.pyi +18 -4
  164. viam/gen/provisioning/v1/provisioning_grpc.py +10 -2
  165. viam/gen/provisioning/v1/provisioning_pb2.py +38 -31
  166. viam/gen/provisioning/v1/provisioning_pb2.pyi +20 -2
  167. viam/gen/robot/v1/robot_grpc.py +61 -29
  168. viam/gen/robot/v1/robot_pb2.py +186 -155
  169. viam/gen/robot/v1/robot_pb2.pyi +278 -59
  170. viam/gen/service/datamanager/v1/data_manager_grpc.py +11 -2
  171. viam/gen/service/datamanager/v1/data_manager_pb2.py +27 -17
  172. viam/gen/service/datamanager/v1/data_manager_pb2.pyi +47 -1
  173. viam/gen/service/discovery/__init__.py +0 -0
  174. viam/gen/service/discovery/v1/__init__.py +0 -0
  175. viam/gen/service/discovery/v1/discovery_grpc.py +39 -0
  176. viam/gen/service/discovery/v1/discovery_pb2.py +29 -0
  177. viam/gen/service/discovery/v1/discovery_pb2.pyi +51 -0
  178. viam/gen/service/generic/v1/generic_pb2.py +13 -10
  179. viam/gen/service/mlmodel/v1/mlmodel_pb2.py +75 -72
  180. viam/gen/service/motion/v1/motion_pb2.py +118 -85
  181. viam/gen/service/motion/v1/motion_pb2.pyi +130 -68
  182. viam/gen/service/navigation/v1/navigation_pb2.py +75 -72
  183. viam/gen/service/sensors/v1/sensors_pb2.py +59 -56
  184. viam/gen/service/shell/v1/shell_pb2.py +35 -32
  185. viam/gen/service/slam/v1/slam_pb2.py +43 -40
  186. viam/gen/service/slam/v1/slam_pb2.pyi +1 -1
  187. viam/gen/service/video/__init__.py +0 -0
  188. viam/gen/service/video/v1/__init__.py +0 -0
  189. viam/gen/service/video/v1/video_grpc.py +39 -0
  190. viam/gen/service/video/v1/video_pb2.py +29 -0
  191. viam/gen/service/video/v1/video_pb2.pyi +72 -0
  192. viam/gen/service/vision/v1/vision_pb2.py +60 -57
  193. viam/gen/service/vision/v1/vision_pb2.pyi +28 -3
  194. viam/gen/service/worldstatestore/__init__.py +0 -0
  195. viam/gen/service/worldstatestore/v1/__init__.py +0 -0
  196. viam/gen/service/worldstatestore/v1/world_state_store_grpc.py +55 -0
  197. viam/gen/service/worldstatestore/v1/world_state_store_pb2.py +39 -0
  198. viam/gen/service/worldstatestore/v1/world_state_store_pb2.pyi +171 -0
  199. viam/gen/stream/v1/stream_grpc.py +17 -1
  200. viam/gen/stream/v1/stream_pb2.py +34 -21
  201. viam/gen/stream/v1/stream_pb2.pyi +79 -1
  202. viam/gen/tagger/v1/tagger_pb2.py +9 -8
  203. viam/logging.py +77 -18
  204. viam/media/audio.py +28 -0
  205. viam/media/utils/pil/__init__.py +7 -3
  206. viam/media/video.py +80 -17
  207. viam/module/module.py +111 -38
  208. viam/module/resource_data_consumer.py +41 -0
  209. viam/module/service.py +9 -1
  210. viam/module/types.py +2 -4
  211. viam/proto/app/__init__.py +199 -0
  212. viam/proto/app/agent/__init__.py +5 -2
  213. viam/proto/app/billing.py +31 -4
  214. viam/proto/app/cloudslam/__init__.py +1 -0
  215. viam/proto/app/data/__init__.py +63 -0
  216. viam/proto/app/datapipelines/__init__.py +56 -0
  217. viam/proto/app/dataset/__init__.py +5 -0
  218. viam/proto/app/datasync/__init__.py +3 -0
  219. viam/proto/app/end_user.py +1 -0
  220. viam/proto/app/mlinference/__init__.py +15 -0
  221. viam/proto/app/mltraining/__init__.py +13 -0
  222. viam/proto/app/packages/__init__.py +1 -0
  223. viam/proto/app/robot.py +7 -0
  224. viam/proto/common/__init__.py +15 -0
  225. viam/proto/component/arm/__init__.py +7 -0
  226. viam/proto/component/audioin/__init__.py +16 -0
  227. viam/proto/component/audioinput/__init__.py +1 -0
  228. viam/proto/component/audioout/__init__.py +15 -0
  229. viam/proto/component/base/__init__.py +1 -0
  230. viam/proto/component/board/__init__.py +1 -0
  231. viam/proto/component/button/__init__.py +15 -0
  232. viam/proto/component/camera/__init__.py +1 -0
  233. viam/proto/component/encoder/__init__.py +1 -0
  234. viam/proto/component/gantry/__init__.py +1 -0
  235. viam/proto/component/generic/__init__.py +1 -0
  236. viam/proto/component/gripper/__init__.py +5 -0
  237. viam/proto/component/inputcontroller/__init__.py +1 -0
  238. viam/proto/component/motor/__init__.py +1 -0
  239. viam/proto/component/movementsensor/__init__.py +1 -0
  240. viam/proto/component/posetracker/__init__.py +1 -0
  241. viam/proto/component/powersensor/__init__.py +1 -0
  242. viam/proto/component/sensor/__init__.py +1 -0
  243. viam/proto/component/servo/__init__.py +1 -0
  244. viam/proto/component/switch/__init__.py +26 -0
  245. viam/proto/component/testecho/__init__.py +1 -0
  246. viam/proto/module/__init__.py +1 -0
  247. viam/proto/provisioning/__init__.py +5 -0
  248. viam/proto/robot/__init__.py +29 -8
  249. viam/proto/rpc/auth.py +1 -0
  250. viam/proto/rpc/examples/echo/__init__.py +1 -0
  251. viam/proto/rpc/examples/echoresource/__init__.py +1 -0
  252. viam/proto/rpc/webrtc/grpc.py +1 -0
  253. viam/proto/rpc/webrtc/signaling.py +3 -0
  254. viam/proto/service/datamanager/__init__.py +9 -1
  255. viam/proto/service/discovery/__init__.py +15 -0
  256. viam/proto/service/generic/__init__.py +1 -0
  257. viam/proto/service/mlmodel/__init__.py +1 -0
  258. viam/proto/service/motion/__init__.py +3 -0
  259. viam/proto/service/navigation/__init__.py +1 -0
  260. viam/proto/service/sensors/__init__.py +1 -0
  261. viam/proto/service/shell/__init__.py +1 -0
  262. viam/proto/service/slam/__init__.py +1 -0
  263. viam/proto/service/video/__init__.py +15 -0
  264. viam/proto/service/vision/__init__.py +1 -0
  265. viam/proto/service/worldstatestore/__init__.py +32 -0
  266. viam/proto/stream/__init__.py +11 -0
  267. viam/py.typed +0 -0
  268. viam/resource/base.py +12 -8
  269. viam/resource/easy_resource.py +24 -13
  270. viam/resource/manager.py +6 -5
  271. viam/resource/registry.py +39 -51
  272. viam/resource/rpc_client_base.py +33 -1
  273. viam/resource/types.py +13 -14
  274. viam/robot/client.py +190 -122
  275. viam/robot/service.py +2 -50
  276. viam/rpc/dial.py +54 -4
  277. viam/rpc/libviam_rust_utils.so +0 -0
  278. viam/rpc/server.py +25 -11
  279. viam/rpc/types.py +2 -4
  280. viam/services/discovery/__init__.py +12 -0
  281. viam/services/discovery/client.py +55 -0
  282. viam/services/discovery/discovery.py +52 -0
  283. viam/services/discovery/service.py +43 -0
  284. viam/services/generic/__init__.py +1 -1
  285. viam/services/generic/client.py +8 -5
  286. viam/services/generic/generic.py +2 -2
  287. viam/services/mlmodel/__init__.py +1 -1
  288. viam/services/mlmodel/client.py +17 -7
  289. viam/services/mlmodel/mlmodel.py +23 -12
  290. viam/services/mlmodel/service.py +5 -2
  291. viam/services/mlmodel/utils.py +11 -1
  292. viam/services/motion/__init__.py +2 -2
  293. viam/services/motion/client.py +32 -32
  294. viam/services/motion/motion.py +66 -62
  295. viam/services/navigation/__init__.py +1 -1
  296. viam/services/navigation/client.py +30 -20
  297. viam/services/navigation/navigation.py +23 -23
  298. viam/services/service_base.py +13 -9
  299. viam/services/service_client_base.py +3 -3
  300. viam/services/slam/__init__.py +1 -1
  301. viam/services/slam/client.py +15 -10
  302. viam/services/slam/slam.py +11 -11
  303. viam/services/vision/__init__.py +1 -1
  304. viam/services/vision/client.py +31 -24
  305. viam/services/vision/service.py +8 -8
  306. viam/services/vision/vision.py +36 -53
  307. viam/services/worldstatestore/__init__.py +18 -0
  308. viam/services/worldstatestore/client.py +94 -0
  309. viam/services/worldstatestore/service.py +55 -0
  310. viam/services/worldstatestore/worldstatestore.py +90 -0
  311. viam/sessions_client.py +115 -46
  312. viam/streams.py +3 -6
  313. viam/utils.py +44 -14
  314. viam/version_metadata.py +4 -0
  315. {viam_sdk-0.25.2.dist-info → viam_sdk-0.62.0.dist-info}/METADATA +27 -28
  316. viam_sdk-0.62.0.dist-info/RECORD +514 -0
  317. {viam_sdk-0.25.2.dist-info → viam_sdk-0.62.0.dist-info}/WHEEL +1 -1
  318. viam/gen/proto/rpc/examples/fileupload/v1/fileupload_grpc.py +0 -27
  319. viam/gen/proto/rpc/examples/fileupload/v1/fileupload_pb2.py +0 -18
  320. viam/gen/proto/rpc/examples/fileupload/v1/fileupload_pb2.pyi +0 -45
  321. viam/proto/rpc/examples/fileupload/__init__.py +0 -18
  322. viam/services/sensors/__init__.py +0 -5
  323. viam/services/sensors/client.py +0 -65
  324. viam_sdk-0.25.2.dist-info/LICENSE +0 -202
  325. viam_sdk-0.25.2.dist-info/RECORD +0 -442
  326. /viam/gen/{proto/rpc/examples/fileupload → app/datapipelines}/__init__.py +0 -0
  327. /viam/gen/{proto/rpc/examples/fileupload → app/datapipelines}/v1/__init__.py +0 -0
  328. /LICENSE → /viam_sdk-0.62.0.dist-info/licenses/LICENSE +0 -0
viam/module/module.py CHANGED
@@ -1,16 +1,20 @@
1
1
  import argparse
2
2
  import io
3
3
  import logging as pylogging
4
+ import os
4
5
  import sys
6
+ from collections.abc import Iterable
5
7
  from inspect import iscoroutinefunction
6
8
  from threading import Lock
7
9
  from typing import List, Mapping, Optional, Sequence, Tuple
8
10
 
11
+ from grpclib.metadata import Deadline
9
12
  from grpclib.utils import _service_name
10
13
  from typing_extensions import Self
11
14
 
12
15
  from viam import logging
13
16
  from viam.errors import ResourceNotFoundError, ValidationError
17
+ from viam.logging import update_log_level
14
18
  from viam.proto.app.robot import ComponentConfig
15
19
  from viam.proto.module import (
16
20
  AddResourceRequest,
@@ -26,15 +30,40 @@ from viam.proto.module import (
26
30
  from viam.proto.robot import ResourceRPCSubtype
27
31
  from viam.resource.base import ResourceBase
28
32
  from viam.resource.registry import Registry
29
- from viam.resource.types import RESOURCE_TYPE_COMPONENT, RESOURCE_TYPE_SERVICE, Model, ResourceName, Subtype, resource_name_from_string
33
+ from viam.resource.types import API, RESOURCE_TYPE_COMPONENT, RESOURCE_TYPE_SERVICE, Model, ResourceName, resource_name_from_string
30
34
  from viam.robot.client import RobotClient
31
- from viam.rpc.dial import DialOptions
35
+ from viam.rpc.dial import DialOptions, _host_port_from_url
32
36
  from viam.rpc.server import Server
33
37
 
38
+ # These imports are required to register built-in resources with the registry
39
+ from ..components.arm import Arm # noqa: F401
40
+ from ..components.audio_input import AudioInput # noqa: F401
41
+ from ..components.base import Base # noqa: F401
42
+ from ..components.board import Board # noqa: F401
43
+ from ..components.button import Button # noqa: F401
44
+ from ..components.camera import Camera # noqa: F401
45
+ from ..components.encoder import Encoder # noqa: F401
46
+ from ..components.gantry import Gantry # noqa: F401
47
+ from ..components.generic import Generic as GenericComponent # noqa: F401
48
+ from ..components.gripper import Gripper # noqa: F401
49
+ from ..components.input import Controller # noqa: F401
50
+ from ..components.motor import Motor # noqa: F401
51
+ from ..components.movement_sensor import MovementSensor # noqa: F401
52
+ from ..components.pose_tracker import PoseTracker # noqa: F401
53
+ from ..components.power_sensor import PowerSensor # noqa: F401
54
+ from ..components.sensor import Sensor # noqa: F401
55
+ from ..components.servo import Servo # noqa: F401
56
+ from ..components.switch import Switch # noqa: F401
57
+ from ..services.discovery import Discovery # noqa: F401
58
+ from ..services.generic import Generic as GenericService # noqa: F401
59
+ from ..services.motion import Motion # noqa: F401
60
+ from ..services.navigation import Navigation # noqa: F401
61
+ from ..services.slam import SLAM # noqa: F401
62
+ from ..services.vision import Vision # noqa: F401
34
63
  from .service import ModuleRPCService
35
64
  from .types import Reconfigurable, Stoppable
36
65
 
37
- LOGGER = logging.getLogger(__name__)
66
+ NO_MODULE_PARENT = os.environ.get("VIAM_NO_MODULE_PARENT", "").lower() == "true"
38
67
 
39
68
 
40
69
  def _parse_module_args() -> argparse.Namespace:
@@ -44,7 +73,8 @@ def _parse_module_args() -> argparse.Namespace:
44
73
  p = argparse.ArgumentParser(description="Start this viam python module")
45
74
  p.add_argument("socket_path", help="path where this module will serve a unix socket")
46
75
  p.add_argument("--log-level", type=lambda name: pylogging._nameToLevel[name.upper()], default=logging.INFO)
47
- return p.parse_args()
76
+ p.add_argument("--tcp-mode", action="store_true")
77
+ return p.parse_known_args()[0]
48
78
 
49
79
 
50
80
  class Module:
@@ -53,8 +83,10 @@ class Module:
53
83
  _ready: bool
54
84
  _log_level: int
55
85
  _lock: Lock
86
+ _tcp_mode: bool
56
87
  parent: Optional[RobotClient] = None
57
88
  server: Server
89
+ logger: pylogging.Logger
58
90
 
59
91
  @classmethod
60
92
  def from_args(cls) -> Self:
@@ -70,7 +102,7 @@ class Module:
70
102
  Module: a new Module instance
71
103
  """
72
104
  args = _parse_module_args()
73
- return cls(args.socket_path, log_level=args.log_level)
105
+ return cls(args.socket_path, log_level=args.log_level, tcp_mode=args.tcp_mode)
74
106
 
75
107
  @classmethod
76
108
  async def run_with_models(cls, *models: ResourceBase):
@@ -82,7 +114,7 @@ class Module:
82
114
  for model in models:
83
115
  if not hasattr(model, "MODEL"):
84
116
  raise TypeError(f"missing MODEL field on {model}. Resource implementations must define MODEL")
85
- module.add_model_from_registry(model.SUBTYPE, model.MODEL) # pyright: ignore [reportAttributeAccessIssue]
117
+ module.add_model_from_registry(model.API, model.MODEL) # pyright: ignore [reportAttributeAccessIssue]
86
118
  await module.start()
87
119
 
88
120
  @classmethod
@@ -102,7 +134,7 @@ class Module:
102
134
  module.add_model_from_registry(*key.split("/")) # pyright: ignore [reportArgumentType]
103
135
  await module.start()
104
136
 
105
- def __init__(self, address: str, *, log_level: int = logging.INFO) -> None:
137
+ def __init__(self, address: str, *, log_level: int = logging.INFO, tcp_mode: bool = False) -> None:
106
138
  # When a module is launched by viam-server, its stdout is not connected to a tty. In
107
139
  # response, python disables line buffering, which prevents `print` statements from being
108
140
  # immediately flushed to viam-server. This behavior can be confusing, interfere with
@@ -113,12 +145,21 @@ class Module:
113
145
  if isinstance(sys.stderr, io.TextIOWrapper):
114
146
  sys.stderr.reconfigure(line_buffering=True)
115
147
  self._address = address
148
+ self._tcp_mode = tcp_mode
116
149
  self.server = Server(resources=[], module_service=ModuleRPCService(self))
117
150
  self._log_level = log_level
151
+
152
+ module_name = os.environ.get("VIAM_MODULE_NAME")
153
+ # this can happen if the user is running an old version of viam-server that doesn't set `VIAM_MODULE_NAME`
154
+ if module_name is None:
155
+ module_name = __name__
156
+ self.logger = logging.getLogger(module_name)
118
157
  self._ready = True
119
158
  self._lock = Lock()
120
159
 
121
160
  async def _connect_to_parent(self):
161
+ if NO_MODULE_PARENT:
162
+ return
122
163
  if self.parent is None:
123
164
  if self._parent_address is None:
124
165
  raise ValueError("Parent address not found")
@@ -129,7 +170,7 @@ class Module:
129
170
  log_level=self._log_level,
130
171
  ),
131
172
  )
132
- LOGGER.debug("Starting module logging")
173
+ self.logger.debug("Starting module logging")
133
174
  logging.setParent(self.parent)
134
175
 
135
176
  async def _get_resource(self, name: ResourceName) -> ResourceBase:
@@ -152,18 +193,23 @@ class Module:
152
193
  async def start(self):
153
194
  """Start the module service and gRPC server"""
154
195
  try:
155
- await self.server.serve(log_level=self._log_level, path=self._address)
196
+ if self._tcp_mode:
197
+ host, port = _host_port_from_url(self._address)
198
+ await self.server.serve(log_level=self._log_level, host=host, port=port)
199
+ else:
200
+ await self.server.serve(log_level=self._log_level, path=self._address)
156
201
  finally:
157
202
  await self.stop()
158
203
 
159
204
  async def stop(self):
160
205
  """Stop the module service and gRPC server"""
161
- LOGGER.debug("Shutting down module")
206
+ self.logger.debug("Shutting down module")
162
207
  try:
208
+ logging.shutdown()
163
209
  if self.parent is not None:
164
210
  await self.parent.close()
165
211
  except Exception as e:
166
- LOGGER.error("Encountered error while shutting down module", exc_info=e)
212
+ self.logger.error("Encountered error while shutting down module", exc_info=e)
167
213
 
168
214
  def set_ready(self, ready: bool):
169
215
  """Set the module's ready state. The module automatically sets to READY on load. Setting to False can be useful
@@ -175,21 +221,24 @@ class Module:
175
221
  with self._lock:
176
222
  self._ready = ready
177
223
 
178
- async def add_resource(self, request: AddResourceRequest):
224
+ async def add_resource(self, request: AddResourceRequest, *, deadline: Optional[Deadline] = None):
179
225
  dependencies = await self._get_dependencies(request.dependencies)
180
226
  config: ComponentConfig = request.config
181
- subtype = Subtype.from_string(config.api)
227
+ api = API.from_string(config.api)
182
228
  model = Model.from_string(config.model, ignore_errors=True)
183
- creator = Registry.lookup_resource_creator(subtype, model)
229
+ creator = Registry.lookup_resource_creator(api, model)
184
230
  resource = creator(config, dependencies)
231
+ if deadline is not None and deadline.time_remaining() <= 0:
232
+ raise TimeoutError("Deadline expired")
233
+ update_log_level(resource.logger, config.log_configuration.level.upper())
185
234
  self.server.register(resource)
186
235
 
187
236
  async def reconfigure_resource(self, request: ReconfigureResourceRequest):
188
237
  dependencies = await self._get_dependencies(request.dependencies)
189
238
  config: ComponentConfig = request.config
190
- subtype = Subtype.from_string(config.api)
239
+ api = API.from_string(config.api)
191
240
  name = config.name
192
- rn = ResourceName(namespace=subtype.namespace, type=subtype.resource_type, subtype=subtype.resource_subtype, name=name)
241
+ rn = ResourceName(namespace=api.namespace, type=api.resource_type, subtype=api.resource_subtype, name=name)
193
242
  resource = self.server.get_resource(ResourceBase, rn)
194
243
  if isinstance(resource, Reconfigurable):
195
244
  resource.reconfigure(config, dependencies)
@@ -207,38 +256,41 @@ class Module:
207
256
  rn = resource_name_from_string(request.name)
208
257
  resource = self.server.get_resource(ResourceBase, rn)
209
258
  if isinstance(resource, Stoppable):
210
- if iscoroutinefunction(resource.stop):
211
- await resource.stop()
212
- else:
213
- resource.stop()
259
+ try:
260
+ if iscoroutinefunction(resource.stop):
261
+ await resource.stop()
262
+ else:
263
+ resource.stop()
264
+ except Exception as e:
265
+ self.logger.warning(f"Could not remove resource named {resource.name}", exc_info=e)
214
266
  await self.server.remove_resource(rn)
215
267
 
216
268
  async def ready(self, request: ReadyRequest) -> ReadyResponse:
217
269
  self._parent_address = request.parent_address
218
270
  await self._connect_to_parent()
219
271
 
220
- svcname_to_models: Mapping[Tuple[str, Subtype], List[Model]] = {}
221
- for subtype_model_str in Registry.REGISTERED_RESOURCE_CREATORS().keys():
222
- subtype_str, model_str = subtype_model_str.split("/")
223
- subtype = Subtype.from_string(subtype_str)
272
+ svcname_to_models: Mapping[Tuple[str, API], List[Model]] = {}
273
+ for api_model_str in Registry.REGISTERED_RESOURCE_CREATORS().keys():
274
+ api_str, model_str = api_model_str.split("/")
275
+ api = API.from_string(api_str)
224
276
  model = Model.from_string(model_str)
225
277
 
226
- registration = Registry.lookup_subtype(subtype)
278
+ registration = Registry.lookup_api(api)
227
279
  service = registration.rpc_service(self.server)
228
280
  service_name = _service_name(service)
229
281
 
230
- models = svcname_to_models.get((service_name, subtype), [])
282
+ models = svcname_to_models.get((service_name, api), [])
231
283
  models.append(model)
232
- svcname_to_models[(service_name, subtype)] = models
284
+ svcname_to_models[(service_name, api)] = models
233
285
 
234
286
  handlers: List[HandlerDefinition] = []
235
287
  for key, value in svcname_to_models.items():
236
- svc_name, subtype = key
288
+ svc_name, api = key
237
289
  rpc_subtype = ResourceRPCSubtype(
238
290
  subtype=ResourceName(
239
- namespace=subtype.namespace,
240
- type=subtype.resource_type,
241
- subtype=subtype.resource_subtype,
291
+ namespace=api.namespace,
292
+ type=api.resource_type,
293
+ subtype=api.resource_subtype,
242
294
  name="",
243
295
  ),
244
296
  proto_service=svc_name,
@@ -248,22 +300,43 @@ class Module:
248
300
 
249
301
  return ReadyResponse(ready=self._ready, handlermap=HandlerMap(handlers=handlers))
250
302
 
251
- def add_model_from_registry(self, subtype: Subtype, model: Model):
303
+ def add_model_from_registry(self, api: API, model: Model):
252
304
  """Add a pre-registered model to this Module"""
253
305
 
254
306
  # All we need to do is double check that the model has already been registered
255
307
  try:
256
- Registry.lookup_resource_creator(subtype, model)
308
+ Registry.lookup_resource_creator(api, model)
257
309
  except ResourceNotFoundError:
258
- raise ValueError(f"Cannot add model because it has not been registered. Subtype: {subtype}. Model: {model}")
310
+ raise ValueError(f"Cannot add model because it has not been registered. API: {api}. Model: {model}")
259
311
 
260
312
  async def validate_config(self, request: ValidateConfigRequest) -> ValidateConfigResponse:
261
313
  config: ComponentConfig = request.config
262
- subtype = Subtype.from_string(config.api)
314
+ api = API.from_string(config.api)
263
315
  model = Model.from_string(config.model)
264
- validator = Registry.lookup_validator(subtype, model)
316
+ validator = Registry.lookup_validator(api, model)
265
317
  try:
266
- dependencies = validator(config)
267
- return ValidateConfigResponse(dependencies=dependencies)
318
+ # backwards compatibility. Support both ([], []) or [] with deprecation warning.
319
+ # If user's validate returns [str], it will be treated as required dependencies only.
320
+ # Incorect formats, e.g. int, will raise ValidationError.
321
+ _validator_return_test = validator(config)
322
+ if not (isinstance(_validator_return_test, tuple) and len(_validator_return_test) == 2):
323
+ msg = f"Your validate function {validator.__name__} did not return \
324
+ type tuple[Sequence[str], Sequence[str]]. Got {_validator_return_test}."
325
+ self.logger.warning(msg)
326
+ if (isinstance(_validator_return_test, Iterable) and not isinstance(_validator_return_test, str)) and all(
327
+ isinstance(e, str)
328
+ for e in _validator_return_test # type: ignore
329
+ ):
330
+ self.logger.warning(
331
+ f"Detected deprecated validate function signature. \
332
+ Treating all dependencies {_validator_return_test} as required dependencies. \
333
+ Please update to new signature Tuple[Sequence[str], Sequence[str]] soon."
334
+ )
335
+ return ValidateConfigResponse(dependencies=_validator_return_test)
336
+ else:
337
+ raise ValidationError(msg)
338
+
339
+ dependencies, optional_dependencies = _validator_return_test
340
+ return ValidateConfigResponse(dependencies=dependencies, optional_dependencies=optional_dependencies)
268
341
  except Exception as e:
269
342
  raise ValidationError(f"{type(Exception)}: {e}").grpc_error
@@ -0,0 +1,41 @@
1
+ import datetime
2
+ import os
3
+ from typing import Any, Dict, List, Optional
4
+
5
+ from viam.app.viam_client import ViamClient
6
+
7
+
8
+ class ResourceDataConsumer:
9
+ """Client for retrieving historical module data from app.
10
+
11
+ Inherit from this class in a module to get access to historical module data.
12
+ """
13
+
14
+ @classmethod
15
+ def construct_query(cls, part_id: str, resource_name: str, time_back: datetime.timedelta) -> List[Dict[str, Any]]:
16
+ return [
17
+ {
18
+ "$match": {
19
+ "part_id": part_id,
20
+ "component_name": resource_name,
21
+ "time_received": {"$gte": datetime.datetime.now() - time_back},
22
+ }
23
+ }
24
+ ]
25
+
26
+ @classmethod
27
+ async def query_tabular_data(
28
+ cls, resource_name: str, time_back: datetime.timedelta, additional_stages: Optional[List[Dict[str, Any]]] = None, **kwargs
29
+ ) -> List[Dict[str, Any]]:
30
+ """Return historical data for this module, queried with MQL."""
31
+ viam_client = await ViamClient.create_from_env_vars()
32
+
33
+ org_id = os.environ["VIAM_PRIMARY_ORG_ID"]
34
+ part_id = os.environ["VIAM_MACHINE_PART_ID"]
35
+
36
+ query = cls.construct_query(part_id=part_id, resource_name=resource_name, time_back=time_back)
37
+
38
+ if additional_stages is not None:
39
+ query += additional_stages
40
+
41
+ return await viam_client.data_client.tabular_data_by_mql(org_id, query)
viam/module/service.py CHANGED
@@ -1,7 +1,9 @@
1
1
  from typing import TYPE_CHECKING
2
2
 
3
+ from grpclib import Status
3
4
  from grpclib.server import Stream
4
5
 
6
+ from viam.errors import ViamGRPCError
5
7
  from viam.proto.module import (
6
8
  AddResourceRequest,
7
9
  AddResourceResponse,
@@ -29,7 +31,13 @@ class ModuleRPCService(ModuleServiceBase):
29
31
  async def AddResource(self, stream: Stream[AddResourceRequest, AddResourceResponse]) -> None:
30
32
  request = await stream.recv_message()
31
33
  assert request is not None
32
- await self._module.add_resource(request)
34
+ try:
35
+ await self._module.add_resource(request, deadline=stream.deadline)
36
+ except TimeoutError:
37
+ raise ViamGRPCError(
38
+ message="Timeout while adding resource",
39
+ grpc_code=Status.DEADLINE_EXCEEDED,
40
+ )
33
41
  await stream.send_message(AddResourceResponse())
34
42
 
35
43
  async def ReconfigureResource(self, stream: Stream[ReconfigureResourceRequest, ReconfigureResourceResponse]) -> None:
viam/module/types.py CHANGED
@@ -9,8 +9,7 @@ from viam.resource.base import ResourceBase
9
9
  class Reconfigurable(Protocol):
10
10
  """The Reconfigurable protocol defines the requirements for making a resource Reconfigurable"""
11
11
 
12
- def reconfigure(self, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase]):
13
- ...
12
+ def reconfigure(self, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase]): ...
14
13
 
15
14
 
16
15
  @runtime_checkable
@@ -21,5 +20,4 @@ class Stoppable(Protocol):
21
20
  All resources that physically move should be Stoppable.
22
21
  """
23
22
 
24
- def stop(self, *, extra: Optional[Mapping[str, Any]] = None, timeout: Optional[float] = None, **kwargs):
25
- ...
23
+ def stop(self, *, extra: Optional[Mapping[str, Any]] = None, timeout: Optional[float] = None, **kwargs): ...