viam-sdk 0.41.1__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 (225) hide show
  1. viam/app/app_client.py +225 -51
  2. viam/app/billing_client.py +47 -5
  3. viam/app/data_client.py +771 -234
  4. viam/app/ml_training_client.py +3 -5
  5. viam/app/provisioning_client.py +3 -5
  6. viam/app/viam_client.py +58 -11
  7. viam/components/arm/arm.py +1 -1
  8. viam/components/arm/service.py +1 -1
  9. viam/components/audio_in/__init__.py +24 -0
  10. viam/components/audio_in/audio_in.py +74 -0
  11. viam/components/audio_in/client.py +76 -0
  12. viam/components/audio_in/service.py +83 -0
  13. viam/components/audio_out/__init__.py +21 -0
  14. viam/components/audio_out/audio_out.py +72 -0
  15. viam/components/audio_out/client.py +67 -0
  16. viam/components/audio_out/service.py +63 -0
  17. viam/components/base/base.py +1 -1
  18. viam/components/board/board.py +8 -2
  19. viam/components/board/client.py +2 -1
  20. viam/components/board/service.py +1 -0
  21. viam/components/button/__init__.py +10 -0
  22. viam/components/button/button.py +41 -0
  23. viam/components/button/client.py +52 -0
  24. viam/components/button/service.py +46 -0
  25. viam/components/camera/camera.py +15 -30
  26. viam/components/camera/client.py +10 -21
  27. viam/components/camera/service.py +15 -28
  28. viam/components/component_base.py +2 -2
  29. viam/components/gantry/client.py +17 -2
  30. viam/components/gantry/gantry.py +32 -1
  31. viam/components/gantry/service.py +21 -5
  32. viam/components/gripper/__init__.py +2 -0
  33. viam/components/gripper/client.py +25 -2
  34. viam/components/gripper/gripper.py +76 -1
  35. viam/components/gripper/service.py +32 -3
  36. viam/components/input/input.py +1 -1
  37. viam/components/motor/motor.py +1 -1
  38. viam/components/power_sensor/power_sensor.py +1 -1
  39. viam/components/switch/__init__.py +10 -0
  40. viam/components/switch/client.py +83 -0
  41. viam/components/switch/service.py +72 -0
  42. viam/components/switch/switch.py +98 -0
  43. viam/gen/app/agent/v1/agent_pb2.py +1 -1
  44. viam/gen/app/cloudslam/v1/cloud_slam_pb2.py +1 -1
  45. viam/gen/app/data/v1/data_grpc.py +74 -2
  46. viam/gen/app/data/v1/data_pb2.py +198 -104
  47. viam/gen/app/data/v1/data_pb2.pyi +563 -31
  48. viam/gen/app/datapipelines/__init__.py +0 -0
  49. viam/gen/app/datapipelines/v1/__init__.py +0 -0
  50. viam/gen/app/datapipelines/v1/data_pipelines_grpc.py +84 -0
  51. viam/gen/app/datapipelines/v1/data_pipelines_pb2.py +57 -0
  52. viam/gen/app/datapipelines/v1/data_pipelines_pb2.pyi +387 -0
  53. viam/gen/app/dataset/v1/dataset_grpc.py +10 -2
  54. viam/gen/app/dataset/v1/dataset_pb2.py +8 -4
  55. viam/gen/app/dataset/v1/dataset_pb2.pyi +36 -1
  56. viam/gen/app/datasync/v1/data_sync_pb2.py +39 -35
  57. viam/gen/app/datasync/v1/data_sync_pb2.pyi +21 -8
  58. viam/gen/app/mlinference/v1/ml_inference_pb2.py +7 -7
  59. viam/gen/app/mlinference/v1/ml_inference_pb2.pyi +4 -2
  60. viam/gen/app/mltraining/v1/ml_training_grpc.py +10 -2
  61. viam/gen/app/mltraining/v1/ml_training_pb2.py +63 -43
  62. viam/gen/app/mltraining/v1/ml_training_pb2.pyi +112 -7
  63. viam/gen/app/packages/v1/packages_pb2.py +1 -1
  64. viam/gen/app/v1/app_grpc.py +74 -3
  65. viam/gen/app/v1/app_pb2.py +600 -545
  66. viam/gen/app/v1/app_pb2.pyi +1108 -258
  67. viam/gen/app/v1/billing_grpc.py +26 -2
  68. viam/gen/app/v1/billing_pb2.py +52 -36
  69. viam/gen/app/v1/billing_pb2.pyi +158 -4
  70. viam/gen/app/v1/end_user_pb2.py +1 -1
  71. viam/gen/app/v1/robot_pb2.py +95 -89
  72. viam/gen/app/v1/robot_pb2.pyi +121 -9
  73. viam/gen/common/v1/common_pb2.py +76 -58
  74. viam/gen/common/v1/common_pb2.pyi +186 -17
  75. viam/gen/component/arm/v1/arm_grpc.py +10 -2
  76. viam/gen/component/arm/v1/arm_pb2.py +5 -3
  77. viam/gen/component/audioin/__init__.py +0 -0
  78. viam/gen/component/audioin/v1/__init__.py +0 -0
  79. viam/gen/component/audioin/v1/audioin_grpc.py +54 -0
  80. viam/gen/component/audioin/v1/audioin_pb2.py +34 -0
  81. viam/gen/component/audioin/v1/audioin_pb2.pyi +94 -0
  82. viam/gen/component/audioinput/v1/audioinput_pb2.py +1 -1
  83. viam/gen/component/audioout/__init__.py +0 -0
  84. viam/gen/component/audioout/v1/__init__.py +0 -0
  85. viam/gen/component/audioout/v1/audioout_grpc.py +54 -0
  86. viam/gen/component/audioout/v1/audioout_pb2.py +32 -0
  87. viam/gen/component/audioout/v1/audioout_pb2.pyi +47 -0
  88. viam/gen/component/base/v1/base_pb2.py +1 -1
  89. viam/gen/component/board/v1/board_pb2.py +1 -1
  90. viam/gen/component/button/v1/button_pb2.py +1 -1
  91. viam/gen/component/camera/v1/camera_grpc.py +1 -0
  92. viam/gen/component/camera/v1/camera_pb2.py +37 -36
  93. viam/gen/component/camera/v1/camera_pb2.pyi +31 -4
  94. viam/gen/component/encoder/v1/encoder_pb2.py +1 -1
  95. viam/gen/component/gantry/v1/gantry_grpc.py +9 -1
  96. viam/gen/component/gantry/v1/gantry_pb2.py +5 -3
  97. viam/gen/component/generic/v1/generic_pb2.py +1 -1
  98. viam/gen/component/gripper/v1/gripper_grpc.py +18 -2
  99. viam/gen/component/gripper/v1/gripper_pb2.py +12 -4
  100. viam/gen/component/gripper/v1/gripper_pb2.pyi +43 -1
  101. viam/gen/component/inputcontroller/v1/input_controller_pb2.py +1 -1
  102. viam/gen/component/motor/v1/motor_pb2.py +1 -1
  103. viam/gen/component/movementsensor/v1/movementsensor_pb2.py +1 -1
  104. viam/gen/component/posetracker/v1/pose_tracker_pb2.py +1 -1
  105. viam/gen/component/powersensor/v1/powersensor_pb2.py +1 -1
  106. viam/gen/component/sensor/v1/sensor_pb2.py +1 -1
  107. viam/gen/component/servo/v1/servo_pb2.py +1 -1
  108. viam/gen/component/switch/v1/switch_pb2.py +5 -5
  109. viam/gen/component/switch/v1/switch_pb2.pyi +9 -2
  110. viam/gen/component/testecho/v1/testecho_pb2.py +1 -1
  111. viam/gen/module/v1/module_pb2.py +5 -5
  112. viam/gen/module/v1/module_pb2.pyi +7 -2
  113. viam/gen/opentelemetry/__init__.py +0 -0
  114. viam/gen/opentelemetry/proto/__init__.py +0 -0
  115. viam/gen/opentelemetry/proto/common/__init__.py +0 -0
  116. viam/gen/opentelemetry/proto/common/v1/__init__.py +0 -0
  117. viam/gen/opentelemetry/proto/common/v1/common_grpc.py +0 -0
  118. viam/gen/opentelemetry/proto/common/v1/common_pb2.py +27 -0
  119. viam/gen/opentelemetry/proto/common/v1/common_pb2.pyi +208 -0
  120. viam/gen/opentelemetry/proto/resource/__init__.py +0 -0
  121. viam/gen/opentelemetry/proto/resource/v1/__init__.py +0 -0
  122. viam/gen/opentelemetry/proto/resource/v1/resource_grpc.py +0 -0
  123. viam/gen/opentelemetry/proto/resource/v1/resource_pb2.py +18 -0
  124. viam/gen/opentelemetry/proto/resource/v1/resource_pb2.pyi +59 -0
  125. viam/gen/opentelemetry/proto/trace/__init__.py +0 -0
  126. viam/gen/opentelemetry/proto/trace/v1/__init__.py +0 -0
  127. viam/gen/opentelemetry/proto/trace/v1/trace_grpc.py +0 -0
  128. viam/gen/opentelemetry/proto/trace/v1/trace_pb2.py +37 -0
  129. viam/gen/opentelemetry/proto/trace/v1/trace_pb2.pyi +402 -0
  130. viam/gen/proto/rpc/examples/echo/v1/echo_pb2.py +1 -1
  131. viam/gen/proto/rpc/examples/echoresource/v1/echoresource_pb2.py +1 -1
  132. viam/gen/proto/rpc/v1/auth_pb2.py +1 -1
  133. viam/gen/proto/rpc/webrtc/v1/grpc_pb2.py +1 -1
  134. viam/gen/proto/rpc/webrtc/v1/signaling_pb2.py +1 -1
  135. viam/gen/provisioning/v1/provisioning_grpc.py +10 -2
  136. viam/gen/provisioning/v1/provisioning_pb2.py +32 -26
  137. viam/gen/provisioning/v1/provisioning_pb2.pyi +46 -5
  138. viam/gen/robot/v1/robot_grpc.py +51 -34
  139. viam/gen/robot/v1/robot_pb2.py +147 -142
  140. viam/gen/robot/v1/robot_pb2.pyi +153 -86
  141. viam/gen/service/datamanager/v1/data_manager_grpc.py +11 -2
  142. viam/gen/service/datamanager/v1/data_manager_pb2.py +15 -8
  143. viam/gen/service/datamanager/v1/data_manager_pb2.pyi +47 -1
  144. viam/gen/service/discovery/v1/discovery_pb2.py +1 -1
  145. viam/gen/service/generic/v1/generic_pb2.py +1 -1
  146. viam/gen/service/mlmodel/v1/mlmodel_pb2.py +1 -1
  147. viam/gen/service/motion/v1/motion_pb2.py +92 -62
  148. viam/gen/service/motion/v1/motion_pb2.pyi +130 -68
  149. viam/gen/service/navigation/v1/navigation_pb2.py +1 -1
  150. viam/gen/service/sensors/v1/sensors_pb2.py +1 -1
  151. viam/gen/service/shell/v1/shell_pb2.py +1 -1
  152. viam/gen/service/slam/v1/slam_pb2.py +1 -1
  153. viam/gen/service/slam/v1/slam_pb2.pyi +1 -1
  154. viam/gen/service/video/__init__.py +0 -0
  155. viam/gen/service/video/v1/__init__.py +0 -0
  156. viam/gen/service/video/v1/video_grpc.py +39 -0
  157. viam/gen/service/video/v1/video_pb2.py +29 -0
  158. viam/gen/service/video/v1/video_pb2.pyi +72 -0
  159. viam/gen/service/vision/v1/vision_pb2.py +27 -27
  160. viam/gen/service/vision/v1/vision_pb2.pyi +28 -3
  161. viam/gen/service/worldstatestore/__init__.py +0 -0
  162. viam/gen/service/worldstatestore/v1/__init__.py +0 -0
  163. viam/gen/service/worldstatestore/v1/world_state_store_grpc.py +55 -0
  164. viam/gen/service/worldstatestore/v1/world_state_store_pb2.py +39 -0
  165. viam/gen/service/worldstatestore/v1/world_state_store_pb2.pyi +171 -0
  166. viam/gen/stream/v1/stream_pb2.py +1 -1
  167. viam/gen/tagger/v1/tagger_pb2.py +1 -1
  168. viam/logging.py +9 -8
  169. viam/media/audio.py +22 -10
  170. viam/media/utils/pil/__init__.py +5 -1
  171. viam/media/video.py +54 -40
  172. viam/module/module.py +85 -16
  173. viam/module/resource_data_consumer.py +41 -0
  174. viam/module/service.py +9 -1
  175. viam/proto/app/__init__.py +68 -0
  176. viam/proto/app/billing.py +16 -0
  177. viam/proto/app/data/__init__.py +48 -0
  178. viam/proto/app/datapipelines/__init__.py +56 -0
  179. viam/proto/app/dataset/__init__.py +4 -0
  180. viam/proto/app/mltraining/__init__.py +6 -0
  181. viam/proto/app/robot.py +6 -0
  182. viam/proto/common/__init__.py +14 -0
  183. viam/proto/component/audioin/__init__.py +16 -0
  184. viam/proto/component/audioout/__init__.py +15 -0
  185. viam/proto/component/camera/__init__.py +0 -2
  186. viam/proto/component/gripper/__init__.py +4 -0
  187. viam/proto/opentelemetry/__init__.py +0 -0
  188. viam/proto/opentelemetry/proto/__init__.py +0 -0
  189. viam/proto/opentelemetry/proto/common/__init__.py +15 -0
  190. viam/proto/opentelemetry/proto/resource/__init__.py +10 -0
  191. viam/proto/opentelemetry/proto/trace/__init__.py +15 -0
  192. viam/proto/provisioning/__init__.py +6 -0
  193. viam/proto/robot/__init__.py +16 -8
  194. viam/proto/service/datamanager/__init__.py +8 -1
  195. viam/proto/service/motion/__init__.py +2 -0
  196. viam/proto/service/video/__init__.py +15 -0
  197. viam/proto/service/worldstatestore/__init__.py +32 -0
  198. viam/resource/easy_resource.py +5 -9
  199. viam/resource/manager.py +4 -3
  200. viam/resource/registry.py +2 -2
  201. viam/resource/types.py +2 -2
  202. viam/robot/client.py +38 -59
  203. viam/rpc/dial.py +48 -5
  204. viam/rpc/libviam_rust_utils.so +0 -0
  205. viam/rpc/server.py +24 -10
  206. viam/services/motion/client.py +8 -9
  207. viam/services/motion/motion.py +48 -46
  208. viam/services/navigation/navigation.py +2 -2
  209. viam/services/vision/client.py +1 -1
  210. viam/services/vision/service.py +5 -8
  211. viam/services/vision/vision.py +5 -3
  212. viam/services/worldstatestore/__init__.py +18 -0
  213. viam/services/worldstatestore/client.py +94 -0
  214. viam/services/worldstatestore/service.py +55 -0
  215. viam/services/worldstatestore/worldstatestore.py +90 -0
  216. viam/sessions_client.py +115 -46
  217. viam/version_metadata.py +2 -2
  218. {viam_sdk-0.41.1.dist-info → viam_sdk-0.66.0.dist-info}/METADATA +10 -6
  219. {viam_sdk-0.41.1.dist-info → viam_sdk-0.66.0.dist-info}/RECORD +221 -152
  220. {viam_sdk-0.41.1.dist-info → viam_sdk-0.66.0.dist-info}/WHEEL +1 -1
  221. viam/components/audio_input/__init__.py +0 -18
  222. viam/components/audio_input/audio_input.py +0 -81
  223. viam/components/audio_input/client.py +0 -70
  224. viam/components/audio_input/service.py +0 -114
  225. {viam_sdk-0.41.1.dist-info → viam_sdk-0.66.0.dist-info}/licenses/LICENSE +0 -0
viam/app/app_client.py CHANGED
@@ -52,10 +52,14 @@ from viam.proto.app import (
52
52
  GetFragmentHistoryResponse,
53
53
  GetFragmentRequest,
54
54
  GetFragmentResponse,
55
+ GetLocationMetadataRequest,
56
+ GetLocationMetadataResponse,
55
57
  GetLocationRequest,
56
58
  GetLocationResponse,
57
59
  GetModuleRequest,
58
60
  GetModuleResponse,
61
+ GetOrganizationMetadataRequest,
62
+ GetOrganizationMetadataResponse,
59
63
  GetOrganizationNamespaceAvailabilityRequest,
60
64
  GetOrganizationNamespaceAvailabilityResponse,
61
65
  GetOrganizationRequest,
@@ -66,10 +70,14 @@ from viam.proto.app import (
66
70
  GetRegistryItemResponse,
67
71
  GetRobotAPIKeysRequest,
68
72
  GetRobotAPIKeysResponse,
73
+ GetRobotMetadataRequest,
74
+ GetRobotMetadataResponse,
69
75
  GetRobotPartHistoryRequest,
70
76
  GetRobotPartHistoryResponse,
71
77
  GetRobotPartLogsRequest,
72
78
  GetRobotPartLogsResponse,
79
+ GetRobotPartMetadataRequest,
80
+ GetRobotPartMetadataResponse,
73
81
  GetRobotPartRequest,
74
82
  GetRobotPartResponse,
75
83
  GetRobotPartsRequest,
@@ -134,15 +142,23 @@ from viam.proto.app import (
134
142
  UnshareLocationRequest,
135
143
  UpdateFragmentRequest,
136
144
  UpdateFragmentResponse,
145
+ UpdateLocationMetadataRequest,
146
+ UpdateLocationMetadataResponse,
137
147
  UpdateLocationRequest,
138
148
  UpdateLocationResponse,
139
149
  UpdateModuleRequest,
140
150
  UpdateModuleResponse,
141
151
  UpdateOrganizationInviteAuthorizationsRequest,
142
152
  UpdateOrganizationInviteAuthorizationsResponse,
153
+ UpdateOrganizationMetadataRequest,
154
+ UpdateOrganizationMetadataResponse,
143
155
  UpdateOrganizationRequest,
144
156
  UpdateOrganizationResponse,
145
157
  UpdateRegistryItemRequest,
158
+ UpdateRobotMetadataRequest,
159
+ UpdateRobotMetadataResponse,
160
+ UpdateRobotPartMetadataRequest,
161
+ UpdateRobotPartMetadataResponse,
146
162
  UpdateRobotPartRequest,
147
163
  UpdateRobotPartResponse,
148
164
  UpdateRobotRequest,
@@ -193,6 +209,7 @@ class RobotPart:
193
209
  self.local_fqdn = robot_part.local_fqdn
194
210
  self.created_on = robot_part.created_on.ToDatetime() if robot_part.HasField("created_on") else None
195
211
  self.secrets = list(robot_part.secrets)
212
+ self.last_updated = robot_part.last_updated.ToDatetime() if robot_part.HasField("last_updated") else None
196
213
  return self
197
214
 
198
215
  id: str
@@ -209,6 +226,7 @@ class RobotPart:
209
226
  local_fqdn: str
210
227
  created_on: Optional[datetime]
211
228
  secrets: Optional[List[SharedSecret]]
229
+ last_updated: Optional[datetime]
212
230
 
213
231
  @property
214
232
  def proto(self) -> RobotPartPB:
@@ -227,6 +245,7 @@ class RobotPart:
227
245
  local_fqdn=self.local_fqdn,
228
246
  created_on=datetime_to_timestamp(self.created_on) if self.created_on else None,
229
247
  secrets=self.secrets,
248
+ last_updated=datetime_to_timestamp(self.last_updated) if self.last_updated else None,
230
249
  )
231
250
 
232
251
 
@@ -352,6 +371,7 @@ class Fragment:
352
371
  self.organization_count = fragment.organization_count
353
372
  self.only_used_by_owner = fragment.only_used_by_owner
354
373
  self.visibility = Fragment.Visibility.from_proto(fragment.visibility)
374
+ self.last_updated = fragment.last_updated.ToDatetime() if fragment.HasField("last_updated") else None
355
375
  return self
356
376
 
357
377
  id: str
@@ -365,6 +385,7 @@ class Fragment:
365
385
  organization_count: int
366
386
  only_used_by_owner: bool
367
387
  visibility: Visibility
388
+ last_updated: Optional[datetime]
368
389
 
369
390
  @property
370
391
  def proto(self) -> FragmentPB:
@@ -380,6 +401,7 @@ class Fragment:
380
401
  organization_count=self.organization_count,
381
402
  only_used_by_owner=self.only_used_by_owner,
382
403
  visibility=self.visibility.to_proto(),
404
+ last_updated=datetime_to_timestamp(self.last_updated) if self.last_updated else None,
383
405
  )
384
406
 
385
407
 
@@ -508,11 +530,9 @@ class AppClient:
508
530
  async def main():
509
531
 
510
532
  # Make a ViamClient
511
- viam_client = await connect()
512
- # Instantiate an AppClient called "cloud" to run cloud app API methods on
513
- cloud = viam_client.app_client
514
-
515
- viam_client.close()
533
+ async with await connect() as viam_client:
534
+ # Instantiate an AppClient called "cloud" to run cloud app API methods on
535
+ cloud = viam_client.app_client
516
536
 
517
537
  if __name__ == '__main__':
518
538
  asyncio.run(main())
@@ -520,22 +540,19 @@ class AppClient:
520
540
  For more information, see `Fleet Management API <https://docs.viam.com/dev/reference/apis/fleet/>`_.
521
541
  """
522
542
 
523
- def __init__(self, channel: Channel, metadata: Mapping[str, str], location_id: Optional[str] = None):
543
+ def __init__(self, channel: Channel, metadata: Mapping[str, str]):
524
544
  """Create an `AppClient` that maintains a connection to app.
525
545
 
526
546
  Args:
527
547
  channel (grpclib.client.Channel): connection to app.
528
548
  metadata (Mapping[str, str]): Required authorization token to send requests to app.
529
- location_id (Optional[str]): Default location ID.
530
549
  """
531
550
  self._metadata = metadata
532
551
  self._app_client = AppServiceStub(channel)
533
- self._location_id = location_id
534
552
  self._channel = channel
535
553
 
536
554
  _app_client: AppServiceStub
537
555
  _metadata: Mapping[str, str]
538
- _location_id: Optional[str]
539
556
  _channel: Channel
540
557
  _organization_id: Optional[str] = None
541
558
 
@@ -764,7 +781,7 @@ class AppClient:
764
781
 
765
782
  Args:
766
783
  org_id (str): The ID of the organization.
767
- You can obtain your organization ID from the Viam app's organization settings page.
784
+ You can obtain your organization ID from the organization settings page.
768
785
 
769
786
  For more information, see `Fleet Management API <https://docs.viam.com/dev/reference/apis/fleet/#deleteorganization>`_.
770
787
  """
@@ -780,7 +797,7 @@ class AppClient:
780
797
 
781
798
  Args:
782
799
  org_id (str): The ID of the organization to list members of.
783
- You can obtain your organization ID from the Viam app's organization settings page.
800
+ You can obtain your organization ID from the organization settings page.
784
801
 
785
802
  Returns:
786
803
  Tuple[List[viam.proto.app.OrganizationMember], List[viam.proto.app.OrganizationInvite]]: A tuple containing two lists; the first
@@ -807,7 +824,7 @@ class AppClient:
807
824
 
808
825
  Args:
809
826
  org_id (str): The ID of the organization to create an invite for.
810
- You can obtain your organization ID from the Viam app's organization settings page.
827
+ You can obtain your organization ID from the organization settings page.
811
828
  email (str): The email address to send the invite to.
812
829
  authorizations (Optional[List[viam.proto.app.Authorization]]): Specifications of the
813
830
  authorizations to include in the invite. If not provided, full owner permissions will
@@ -865,7 +882,7 @@ class AppClient:
865
882
 
866
883
  Args:
867
884
  org_id (str): The ID of the organization that the invite is for.
868
- You can obtain your organization ID from the Viam app's organization settings page.
885
+ You can obtain your organization ID from the organization settings page.
869
886
  email (str): Email of the user the invite was sent to.
870
887
  add_authorizations (Optional[List[viam.proto.app.Authorization]]): Optional list of authorizations to add to the invite.
871
888
  remove_authorizations (Optional[List[viam.proto.app.Authorization]]): Optional list of authorizations to remove from the invite.
@@ -899,7 +916,7 @@ class AppClient:
899
916
 
900
917
  Args:
901
918
  org_id (str): The ID of the org to remove the user from.
902
- You can obtain your organization ID from the Viam app's organization settings page.
919
+ You can obtain your organization ID from the organization settings page.
903
920
  user_id (str): The ID of the user to remove.
904
921
 
905
922
  For more information, see `Fleet Management API <https://docs.viam.com/dev/reference/apis/fleet/#deleteorganizationmember>`_.
@@ -916,7 +933,7 @@ class AppClient:
916
933
 
917
934
  Args:
918
935
  org_id (str): The ID of the organization that the invite to delete was for.
919
- You can obtain your organization ID from the Viam app's organization settings page.
936
+ You can obtain your organization ID from the organization settings page.
920
937
  email (str): The email address the pending invite was sent to.
921
938
 
922
939
  Raises:
@@ -936,7 +953,7 @@ class AppClient:
936
953
 
937
954
  Args:
938
955
  org_id (str): The ID of the organization that the invite to resend was for.
939
- You can obtain your organization ID from the Viam app's organization settings page.
956
+ You can obtain your organization ID from the organization settings page.
940
957
  email (str): The email address associated with the invite.
941
958
 
942
959
  Raises:
@@ -960,7 +977,7 @@ class AppClient:
960
977
 
961
978
  Args:
962
979
  org_id (str): The ID of the organization to create the location under.
963
- You can obtain your organization ID from the Viam app's organization settings page.
980
+ You can obtain your organization ID from the organization settings page.
964
981
  name (str): Name of the location.
965
982
  parent_location_id (Optional[str]): Optional parent location to put the location under. Defaults to a root-level location if no
966
983
  location ID is provided.
@@ -996,7 +1013,7 @@ class AppClient:
996
1013
 
997
1014
  For more information, see `Fleet Management API <https://docs.viam.com/dev/reference/apis/fleet/#getlocation>`_.
998
1015
  """
999
- request = GetLocationRequest(location_id=location_id if location_id else self._location_id if self._location_id else "")
1016
+ request = GetLocationRequest(location_id=location_id if location_id else "")
1000
1017
  response: GetLocationResponse = await self._app_client.GetLocation(request, metadata=self._metadata)
1001
1018
  return response.location
1002
1019
 
@@ -1072,7 +1089,7 @@ class AppClient:
1072
1089
 
1073
1090
  Args:
1074
1091
  org_id (str): The ID of the org to list locations for.
1075
- You can obtain your organization ID from the Viam app's organization settings page.
1092
+ You can obtain your organization ID from the organization settings page.
1076
1093
 
1077
1094
  Returns:
1078
1095
  List[viam.proto.app.Location]: The list of locations.
@@ -1135,7 +1152,7 @@ class AppClient:
1135
1152
 
1136
1153
  For more information, see `Fleet Management API <https://docs.viam.com/dev/reference/apis/fleet/#locationauth>`_.
1137
1154
  """
1138
- request = LocationAuthRequest(location_id=location_id if location_id else self._location_id if self._location_id else "")
1155
+ request = LocationAuthRequest(location_id=location_id if location_id else "")
1139
1156
  response: LocationAuthResponse = await self._app_client.LocationAuth(request, metadata=self._metadata)
1140
1157
  return response.auth
1141
1158
 
@@ -1159,7 +1176,7 @@ class AppClient:
1159
1176
 
1160
1177
  For more information, see `Fleet Management API <https://docs.viam.com/dev/reference/apis/fleet/#createlocationsecret>`_.
1161
1178
  """
1162
- request = CreateLocationSecretRequest(location_id=location_id if location_id else self._location_id if self._location_id else "")
1179
+ request = CreateLocationSecretRequest(location_id=location_id if location_id else "")
1163
1180
  response: CreateLocationSecretResponse = await self._app_client.CreateLocationSecret(request, metadata=self._metadata)
1164
1181
  return response.auth
1165
1182
 
@@ -1183,9 +1200,7 @@ class AppClient:
1183
1200
 
1184
1201
  For more information, see `Fleet Management API <https://docs.viam.com/dev/reference/apis/fleet/#deletelocationsecret>`_.
1185
1202
  """
1186
- request = DeleteLocationSecretRequest(
1187
- location_id=location_id if location_id else self._location_id if self._location_id else "", secret_id=secret_id
1188
- )
1203
+ request = DeleteLocationSecretRequest(location_id=location_id if location_id else "", secret_id=secret_id)
1189
1204
  await self._app_client.DeleteLocationSecret(request, metadata=self._metadata)
1190
1205
 
1191
1206
  async def get_robot(self, robot_id: str) -> Robot:
@@ -1219,7 +1234,7 @@ class AppClient:
1219
1234
 
1220
1235
  Args:
1221
1236
  org_id (str): The ID of the organization to list rover rental robots for.
1222
- You can obtain your organization ID from the Viam app's organization settings page.
1237
+ You can obtain your organization ID from the organization settings page.
1223
1238
 
1224
1239
  Returns:
1225
1240
  List[viam.proto.app.RoverRentalRobot]: The list of rover rental robots.
@@ -1255,13 +1270,20 @@ class AppClient:
1255
1270
  return [RobotPart.from_proto(robot_part=part) for part in response.parts]
1256
1271
 
1257
1272
  async def get_robot_part(self, robot_part_id: str, dest: Optional[str] = None, indent: int = 4) -> RobotPart:
1258
- """Get a machine part.
1273
+ """Get a machine part including its part config, part address, and other information.
1259
1274
 
1260
1275
  ::
1261
1276
 
1262
1277
  my_robot_part = await cloud.get_robot_part(
1263
1278
  robot_part_id="abc12345-1a23-1234-ab12-a22a22a2aa22"
1264
1279
  )
1280
+ # Get the part's config
1281
+ machine_part_config = my_robot_part.robot_config
1282
+ # Get the part's address
1283
+ address = my_robot_part.fqdn
1284
+ # Check if machine is live (last access time less than 10 sec ago)
1285
+ if (time.time() - my_robot_part.last_access.timestamp()) <= 10000:
1286
+ print("Machine is live.")
1265
1287
 
1266
1288
  Args:
1267
1289
  robot_part_id (str): ID of the machine part to get. You can retrieve this value by navigating to the machine's page,
@@ -1426,7 +1448,9 @@ class AppClient:
1426
1448
  response: GetRobotPartHistoryResponse = await self._app_client.GetRobotPartHistory(request, metadata=self._metadata)
1427
1449
  return [RobotPartHistoryEntry.from_proto(part_history) for part_history in response.history]
1428
1450
 
1429
- async def update_robot_part(self, robot_part_id: str, name: str, robot_config: Optional[Mapping[str, Any]] = None) -> RobotPart:
1451
+ async def update_robot_part(
1452
+ self, robot_part_id: str, name: str, robot_config: Optional[Mapping[str, Any]] = None, last_known_update: Optional[datetime] = None
1453
+ ) -> RobotPart:
1430
1454
  """Change the name and assign an optional new configuration to a machine part.
1431
1455
 
1432
1456
  ::
@@ -1440,16 +1464,23 @@ class AppClient:
1440
1464
  name (str): New name to be updated on the robot part.
1441
1465
  robot_config (Mapping[str, Any]): Optional new config represented as a dictionary to be updated on the machine part. The machine
1442
1466
  part's config will remain as is (no change) if one isn't passed.
1443
-
1467
+ last_known_update (datetime): Optional time of the last known update to this part's config. If provided, this will result in a
1468
+ GRPCError if the upstream config has changed since this time, indicating that the local config is out of date. Omitting this
1469
+ parameter will result in an overwrite of the upstream config.
1444
1470
  Raises:
1445
- GRPCError: If either an invalid machine part ID, name, or config is passed.
1446
-
1471
+ GRPCError: If either an invalid machine part ID, name, or config is passed, or if the upstream config has changed since
1472
+ last_known_update.
1447
1473
  Returns:
1448
1474
  viam.app.app_client.RobotPart: The newly updated robot part.
1449
1475
 
1450
1476
  For more information, see `Fleet Management API <https://docs.viam.com/dev/reference/apis/fleet/#updaterobotpart>`_.
1451
1477
  """
1452
- request = UpdateRobotPartRequest(id=robot_part_id, name=name, robot_config=dict_to_struct(robot_config) if robot_config else None)
1478
+ request = UpdateRobotPartRequest(
1479
+ id=robot_part_id,
1480
+ name=name,
1481
+ robot_config=dict_to_struct(robot_config) if robot_config else None,
1482
+ last_known_update=datetime_to_timestamp(last_known_update),
1483
+ )
1453
1484
  response: UpdateRobotPartResponse = await self._app_client.UpdateRobotPart(request, metadata=self._metadata)
1454
1485
  return RobotPart.from_proto(robot_part=response.part)
1455
1486
 
@@ -1619,7 +1650,7 @@ class AppClient:
1619
1650
 
1620
1651
  For more information, see `Fleet Management API <https://docs.viam.com/dev/reference/apis/fleet/#listrobots>`_.
1621
1652
  """
1622
- request = ListRobotsRequest(location_id=location_id if location_id else self._location_id if self._location_id else "")
1653
+ request = ListRobotsRequest(location_id=location_id if location_id else "")
1623
1654
  response: ListRobotsResponse = await self._app_client.ListRobots(request, metadata=self._metadata)
1624
1655
  return list(response.robots)
1625
1656
 
@@ -1643,7 +1674,7 @@ class AppClient:
1643
1674
 
1644
1675
  For more information, see `Fleet Management API <https://docs.viam.com/dev/reference/apis/fleet/#newrobot>`_.
1645
1676
  """
1646
- request = NewRobotRequest(location=location_id if location_id else self._location_id if self._location_id else "", name=name)
1677
+ request = NewRobotRequest(location=location_id if location_id else "", name=name)
1647
1678
  response: NewRobotResponse = await self._app_client.NewRobot(request, metadata=self._metadata)
1648
1679
  return response.id
1649
1680
 
@@ -1673,9 +1704,7 @@ class AppClient:
1673
1704
 
1674
1705
  For more information, see `Fleet Management API <https://docs.viam.com/dev/reference/apis/fleet/#updaterobot>`_.
1675
1706
  """
1676
- request = UpdateRobotRequest(
1677
- id=robot_id, name=name, location=location_id if location_id else self._location_id if self._location_id else ""
1678
- )
1707
+ request = UpdateRobotRequest(id=robot_id, name=name, location=location_id if location_id else "")
1679
1708
  response: UpdateRobotResponse = await self._app_client.UpdateRobot(request, metadata=self._metadata)
1680
1709
  return response.robot
1681
1710
 
@@ -1708,7 +1737,7 @@ class AppClient:
1708
1737
 
1709
1738
  Args:
1710
1739
  org_id (str): The ID of the organization to list fragments for.
1711
- You can obtain your organization ID from the Viam app's organization settings page.
1740
+ You can obtain your organization ID from the organization settings page.
1712
1741
  show_public (bool): Optional boolean specifying whether or not to only show public fragments. If True, only public fragments
1713
1742
  will return. If False, only private fragments will return. Defaults to True.
1714
1743
 
@@ -1730,7 +1759,7 @@ class AppClient:
1730
1759
  response: ListFragmentsResponse = await self._app_client.ListFragments(request, metadata=self._metadata)
1731
1760
  return [Fragment.from_proto(fragment=fragment) for fragment in response.fragments]
1732
1761
 
1733
- async def get_fragment(self, fragment_id: str) -> Fragment:
1762
+ async def get_fragment(self, fragment_id: str, version: Optional[str] = None) -> Fragment:
1734
1763
  """Get a fragment.
1735
1764
 
1736
1765
  ::
@@ -1742,6 +1771,7 @@ class AppClient:
1742
1771
 
1743
1772
  Args:
1744
1773
  fragment_id (str): ID of the fragment to get.
1774
+ version (str): Optional specification of the fragment version to get (revision or tag).
1745
1775
 
1746
1776
  Raises:
1747
1777
  GRPCError: If an invalid fragment ID is passed.
@@ -1751,7 +1781,7 @@ class AppClient:
1751
1781
 
1752
1782
  For more information, see `Fleet Management API <https://docs.viam.com/dev/reference/apis/fleet/#getfragment>`_.
1753
1783
  """
1754
- request = GetFragmentRequest(id=fragment_id)
1784
+ request = GetFragmentRequest(id=fragment_id, version=version)
1755
1785
  response: GetFragmentResponse = await self._app_client.GetFragment(request, metadata=self._metadata)
1756
1786
  return Fragment.from_proto(fragment=response.fragment)
1757
1787
 
@@ -1764,7 +1794,7 @@ class AppClient:
1764
1794
 
1765
1795
  Args:
1766
1796
  org_id (str): The ID of the organization to create the fragment within.
1767
- You can obtain your organization ID from the Viam app's organization settings page.
1797
+ You can obtain your organization ID from the organization settings page.
1768
1798
  name (str): Name of the fragment.
1769
1799
  config (Optional[Mapping[str, Any]]): Optional Dictionary representation of new config to assign to specified fragment. Can be
1770
1800
  assigned by updating the fragment.
@@ -1788,6 +1818,7 @@ class AppClient:
1788
1818
  config: Optional[Mapping[str, Any]] = None,
1789
1819
  public: Optional[bool] = None,
1790
1820
  visibility: Optional[Fragment.Visibility] = None,
1821
+ last_known_update: Optional[datetime] = None,
1791
1822
  ) -> Fragment:
1792
1823
  """Update a fragment name AND its config and/or visibility.
1793
1824
 
@@ -1810,9 +1841,11 @@ class AppClient:
1810
1841
  visibility (Optional[FragmentVisibility]): Optional FragmentVisibility list specifying who should be allowed
1811
1842
  to view the fragment. Not passing this parameter will leave the fragment's visibility unchanged.
1812
1843
  A fragment is private by default when created.
1813
-
1844
+ last_known_update (datetime): Optional time of the last known update to this fragment's config. If provided, this will result in
1845
+ a GRPCError if the upstream config has changed since this time, indicating that the local config is out of date. Omitting
1846
+ this parameter will result in an overwrite of the upstream config.
1814
1847
  Raises:
1815
- GRPCError: if an invalid ID, name, or config is passed.
1848
+ GRPCError: if an invalid ID, name, or config is passed, or if the upstream fragment config has changed since last_known_update.
1816
1849
 
1817
1850
  Returns:
1818
1851
  viam.app.app_client.Fragment: The newly updated fragment.
@@ -1825,6 +1858,7 @@ class AppClient:
1825
1858
  config=dict_to_struct(config) if config else None,
1826
1859
  public=public,
1827
1860
  visibility=visibility.to_proto() if visibility else None,
1861
+ last_known_update=datetime_to_timestamp(last_known_update),
1828
1862
  )
1829
1863
  response: UpdateFragmentResponse = await self._app_client.UpdateFragment(request, metadata=self._metadata)
1830
1864
  return Fragment.from_proto(response.fragment)
@@ -1902,7 +1936,7 @@ class AppClient:
1902
1936
 
1903
1937
  Args:
1904
1938
  org_id (str): The ID of the organization to create the role in.
1905
- You can obtain your organization ID from the Viam app's organization settings page.
1939
+ You can obtain your organization ID from the organization settings page.
1906
1940
  identity_id (str): ID of the entity the role belongs to (for example, a user ID).
1907
1941
  role (Union[Literal["owner"], Literal["operator"]]): The role to add.
1908
1942
  resource_type (Union[Literal["organization"], Literal["location"], Literal["robot"]]): Type of the resource to add role to.
@@ -1947,7 +1981,7 @@ class AppClient:
1947
1981
 
1948
1982
  Args:
1949
1983
  org_id (str): The ID of the organization the role exists in.
1950
- You can obtain your organization ID from the Viam app's organization settings page.
1984
+ You can obtain your organization ID from the organization settings page.
1951
1985
  identity_id (str): ID of the entity the role belongs to (for example, a user ID).
1952
1986
  role (Union[Literal["owner"], Literal["operator"]]): The role to remove.
1953
1987
  resource_type (Union[Literal["organization"], Literal["location"], Literal["robot"]]): Type of the resource the role is being
@@ -2092,7 +2126,7 @@ class AppClient:
2092
2126
  response: CheckPermissionsResponse = await self._app_client.CheckPermissions(request, metadata=self._metadata)
2093
2127
  return list(response.authorized_permissions)
2094
2128
 
2095
- async def get_registry_item(self, item_id: str) -> RegistryItem:
2129
+ async def get_registry_item(self, item_id: str, include_markdown_documentation: bool = False) -> RegistryItem:
2096
2130
  """Get registry item by ID.
2097
2131
 
2098
2132
  ::
@@ -2110,7 +2144,7 @@ class AppClient:
2110
2144
 
2111
2145
  For more information, see `Fleet Management API <https://docs.viam.com/dev/reference/apis/fleet/#getregistryitem>`_.
2112
2146
  """
2113
- request = GetRegistryItemRequest(item_id=item_id)
2147
+ request = GetRegistryItemRequest(item_id=item_id, include_markdown_documentation=include_markdown_documentation)
2114
2148
  response: GetRegistryItemResponse = await self._app_client.GetRegistryItem(request, metadata=self._metadata)
2115
2149
  return response.item
2116
2150
 
@@ -2250,7 +2284,7 @@ class AppClient:
2250
2284
 
2251
2285
  Args:
2252
2286
  org_id (str): The ID of the organization to create the module under.
2253
- You can obtain your organization ID from the Viam app's organization settings page.
2287
+ You can obtain your organization ID from the organization settings page.
2254
2288
  name (str): The name of the module. Must be unique within your organization.
2255
2289
 
2256
2290
  Raises:
@@ -2391,7 +2425,7 @@ class AppClient:
2391
2425
 
2392
2426
  Args:
2393
2427
  org_id (str): The ID of the organization to list modules for.
2394
- You can obtain your organization ID from the Viam app's organization settings page.
2428
+ You can obtain your organization ID from the organization settings page.
2395
2429
 
2396
2430
  Returns:
2397
2431
  List[viam.proto.app.Module]: The list of modules.
@@ -2425,7 +2459,7 @@ class AppClient:
2425
2459
 
2426
2460
  Args:
2427
2461
  org_id (str): The ID of the organization to create the key for.
2428
- You can obtain your organization ID from the Viam app's organization settings page.
2462
+ You can obtain your organization ID from the organization settings page.
2429
2463
  authorizations (List[viam.proto.app.Authorization]): A list of authorizations to associate
2430
2464
  with the key.
2431
2465
  name (Optional[str]): A name for the key. If None, defaults to the current timestamp.
@@ -2491,7 +2525,7 @@ class AppClient:
2491
2525
 
2492
2526
  Args:
2493
2527
  org_id (str): The ID of the organization to list API keys for.
2494
- You can obtain your organization ID from the Viam app's organization settings page.
2528
+ You can obtain your organization ID from the organization settings page.
2495
2529
 
2496
2530
  Returns:
2497
2531
  List[viam.proto.app.APIKeyWithAuthorizations]: The existing API keys and authorizations.
@@ -2507,7 +2541,7 @@ class AppClient:
2507
2541
 
2508
2542
  ::
2509
2543
 
2510
- id, key = await cloud.rotate_key("key-id")
2544
+ key, id = await cloud.rotate_key("key-id")
2511
2545
 
2512
2546
  Args:
2513
2547
  id (str): The ID of the key to be rotated.
@@ -2520,3 +2554,143 @@ class AppClient:
2520
2554
  request = RotateKeyRequest(id=id)
2521
2555
  response: RotateKeyResponse = await self._app_client.RotateKey(request, metadata=self._metadata)
2522
2556
  return response.key, response.id
2557
+
2558
+ async def get_organization_metadata(self, org_id: str) -> Mapping[str, Any]:
2559
+ """Get an organization's user-defined metadata.
2560
+
2561
+ ::
2562
+
2563
+ metadata = await cloud.get_organization_metadata(org_id="<YOUR-ORG-ID>")
2564
+
2565
+ Args:
2566
+ org_id (str): The ID of the organization with which the user-defined metadata is associated.
2567
+ You can obtain your organization ID from the organization settings page.
2568
+
2569
+ Returns:
2570
+ Mapping[str, Any]: The user-defined metadata converted from JSON to a Python dictionary
2571
+ """
2572
+ request = GetOrganizationMetadataRequest(organization_id=org_id)
2573
+ response: GetOrganizationMetadataResponse = await self._app_client.GetOrganizationMetadata(request, metadata=self._metadata)
2574
+ return struct_to_dict(response.data)
2575
+
2576
+ async def update_organization_metadata(self, org_id: str, metadata: Mapping[str, Any]) -> None:
2577
+ """Update an organization's user-defined metadata.
2578
+
2579
+ ::
2580
+
2581
+ await cloud.update_organization_metadata(org_id="<YOUR-ORG-ID>", metadata={
2582
+ "TEST_API_KEY": "ABC123",
2583
+ })
2584
+
2585
+ Args:
2586
+ organization_id (str): The ID of the organization with which to associate the user-defined metadata.
2587
+ You can obtain your organization ID from the organization settings page.
2588
+ metadata (Mapping[str, Any]): The user-defined metadata to upload as a Python dictionary.
2589
+ """
2590
+ request = UpdateOrganizationMetadataRequest(organization_id=org_id, data=dict_to_struct(metadata))
2591
+ _: UpdateOrganizationMetadataResponse = await self._app_client.UpdateOrganizationMetadata(request, metadata=self._metadata)
2592
+
2593
+ async def get_location_metadata(self, location_id: str) -> Mapping[str, Any]:
2594
+ """Get a location's user-defined metadata.
2595
+
2596
+ ::
2597
+
2598
+ metadata = await cloud.get_location_metadata(location_id="<YOUR-LOCATION-ID>")
2599
+
2600
+ Args:
2601
+ location_id (str): The ID of the location with which the user-defined metadata is associated.
2602
+ You can obtain your location ID from the location's page.
2603
+
2604
+ Returns:
2605
+ Mapping[str, Any]: The user-defined metadata converted from JSON to a Python dictionary.
2606
+ """
2607
+ request = GetLocationMetadataRequest(location_id=location_id)
2608
+ response: GetLocationMetadataResponse = await self._app_client.GetLocationMetadata(request, metadata=self._metadata)
2609
+ return struct_to_dict(response.data)
2610
+
2611
+ async def update_location_metadata(self, location_id: str, metadata: Mapping[str, Any]) -> None:
2612
+ """Update a location's user-defined metadata.
2613
+
2614
+ ::
2615
+
2616
+ await cloud.update_location_metadata(location_id="<YOUR-LOCATION-ID>", metadata={
2617
+ "TEST_API_KEY": "ABC123",
2618
+ })
2619
+
2620
+ Args:
2621
+ location_id (str): The ID of the location with which to associate the user-defined metadata.
2622
+ You can obtain your location ID from the location's page.
2623
+ metadata (Mapping[str, Any]): The user-defined metadata converted from JSON to a Python dictionary.
2624
+ """
2625
+ request = UpdateLocationMetadataRequest(location_id=location_id, data=dict_to_struct(metadata))
2626
+ _: UpdateLocationMetadataResponse = await self._app_client.UpdateLocationMetadata(request, metadata=self._metadata)
2627
+
2628
+ async def get_robot_metadata(self, robot_id: str) -> Mapping[str, Any]:
2629
+ """Get a robot's user-defined metadata.
2630
+
2631
+ ::
2632
+
2633
+ metadata = await cloud.get_robot_metadata(robot_id="<YOUR-ROBOT-ID>")
2634
+
2635
+ Args:
2636
+ robot_id (str): The ID of the robot with which the user-defined metadata is associated.
2637
+ You can obtain your robot ID from the machine page.
2638
+
2639
+ Returns:
2640
+ Mapping[str, Any]: The user-defined metadata converted from JSON to a Python dictionary.
2641
+ """
2642
+ request = GetRobotMetadataRequest(id=robot_id)
2643
+ response: GetRobotMetadataResponse = await self._app_client.GetRobotMetadata(request, metadata=self._metadata)
2644
+ return struct_to_dict(response.data)
2645
+
2646
+ async def update_robot_metadata(self, robot_id: str, metadata: Mapping[str, Any]) -> None:
2647
+ """Update a robot's user-defined metadata.
2648
+
2649
+ ::
2650
+
2651
+ await cloud.update_robot_metadata(robot_id="<YOUR-ROBOT-ID>", metadata={
2652
+ "TEST_API_KEY": "ABC123",
2653
+ })
2654
+
2655
+ Args:
2656
+ robot_id (str): The ID of the robot with which to associate the user-defined metadata.
2657
+ You can obtain your robot ID from the machine page.
2658
+ metadata (Mapping[str, Any]): The user-defined metadata converted from JSON to a Python dictionary.
2659
+ """
2660
+ request = UpdateRobotMetadataRequest(id=robot_id, data=dict_to_struct(metadata))
2661
+ _: UpdateRobotMetadataResponse = await self._app_client.UpdateRobotMetadata(request, metadata=self._metadata)
2662
+
2663
+ async def get_robot_part_metadata(self, robot_part_id: str) -> Mapping[str, Any]:
2664
+ """Get a robot part's user-defined metadata.
2665
+
2666
+ ::
2667
+
2668
+ metadata = await cloud.get_robot_part_metadata(robot_part_id="<YOUR-ROBOT-PART-ID>")
2669
+
2670
+ Args:
2671
+ robot_part_id (str): The ID of the robot part with which the user-defined metadata is associated.
2672
+ You can obtain your robot part ID from the machine page.
2673
+
2674
+ Returns:
2675
+ Mapping[str, Any]: The user-defined metadata converted from JSON to a Python dictionary.
2676
+ """
2677
+ request = GetRobotPartMetadataRequest(id=robot_part_id)
2678
+ response: GetRobotPartMetadataResponse = await self._app_client.GetRobotPartMetadata(request, metadata=self._metadata)
2679
+ return struct_to_dict(response.data)
2680
+
2681
+ async def update_robot_part_metadata(self, robot_part_id: str, metadata: Mapping[str, Any]) -> None:
2682
+ """Update a robot part's user-defined metadata.
2683
+
2684
+ ::
2685
+
2686
+ await cloud.update_robot_part_metadata(robot_part_id="<YOUR-ROBOT-PART-ID>", metadata={
2687
+ "TEST_API_KEY": "ABC123",
2688
+ })
2689
+
2690
+ Args:
2691
+ robot_id (str): The ID of the robot part with which to associate the user-defined metadata.
2692
+ You can obtain your robot part ID from the machine page.
2693
+ metadata (Mapping[str, Any]): The user-defined metadata converted from JSON to a Python dictionary.
2694
+ """
2695
+ request = UpdateRobotPartMetadataRequest(id=robot_part_id, data=dict_to_struct(metadata))
2696
+ _: UpdateRobotPartMetadataResponse = await self._app_client.UpdateRobotPartMetadata(request, metadata=self._metadata)