Skip to content

Commit a372745

Browse files
RSDK-5109 - add close function (#458)
1 parent d256ed8 commit a372745

File tree

17 files changed

+154
-15
lines changed

17 files changed

+154
-15
lines changed

docs/examples/example.ipynb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,9 @@
269269
"from typing import Any, Dict, Mapping, Optional\n",
270270
"\n",
271271
"from viam.components.sensor import Sensor\n",
272+
"from viam.logging import getLogger\n",
273+
"\n",
274+
"LOGGER = getLogger(__name__)\n",
272275
"\n",
273276
"\n",
274277
"class MySensor(Sensor):\n",
@@ -282,6 +285,11 @@
282285
" async def get_geometries(self, *, extra: Optional[Dict[str, Any]] = None, timeout: Optional[float] = None) -> List[Geometry]:\n",
283286
" raise NotImplementedError\n",
284287
"\n",
288+
" def close(self):\n",
289+
" # This is a completely optional function to include. This will be called when the resource is removed from the config or the module\n",
290+
" # is shutting down.\n",
291+
" LOGGER.debug(f\"{self.name} is closed.\")\n",
292+
"\n",
285293
"# Anything below this line is optional and will be replaced later, but may come in handy for debugging and testing.\n",
286294
"# To use, call `python wifi_sensor_module.py` in the command line while in the `src` directory.\n",
287295
"async def main():\n",

docs/examples/module_step2.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
from typing_extensions import Self
55

66
from viam.components.sensor import Sensor
7+
from viam.logging import getLogger
78
from viam.proto.app.robot import ComponentConfig
89
from viam.proto.common import ResourceName
910
from viam.resource.base import ResourceBase
1011
from viam.resource.registry import Registry, ResourceCreatorRegistration
1112
from viam.resource.types import Model, ModelFamily
1213

14+
LOGGER = getLogger(__name__)
15+
1316

1417
class MySensor(Sensor):
1518
# Subclass the Viam Sensor component and implement the required functions
@@ -26,6 +29,11 @@ async def get_readings(self, extra: Optional[Dict[str, Any]] = None, **kwargs) -
2629
wifi_signal = [x for x in content[2].split(" ") if x != ""]
2730
return {"link": wifi_signal[2], "level": wifi_signal[3], "noise": wifi_signal[4]}
2831

32+
def close(self):
33+
# This is a completely optional function to include. This will be called when the resource is removed from the config or the module
34+
# is shutting down.
35+
LOGGER.debug(f"{self.name} is closed.")
36+
2937

3038
async def main():
3139
Registry.register_resource_creator(Sensor.SUBTYPE, MySensor.MODEL, ResourceCreatorRegistration(MySensor.new))

docs/examples/module_step2_optional.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@
44
from typing_extensions import Self
55

66
from viam.components.sensor import Sensor
7+
from viam.logging import getLogger
78
from viam.proto.app.robot import ComponentConfig
89
from viam.proto.common import ResourceName
910
from viam.resource.base import ResourceBase
1011
from viam.resource.registry import Registry, ResourceCreatorRegistration
1112
from viam.resource.types import Model, ModelFamily
1213

14+
LOGGER = getLogger(__name__)
15+
1316

1417
class MySensor(Sensor):
1518
# Subclass the Viam Sensor component and implement the required functions
@@ -48,6 +51,11 @@ def reconfigure(self, config: ComponentConfig, dependencies: Mapping[ResourceNam
4851
multiplier = 1.0
4952
self.multiplier = multiplier
5053

54+
def close(self):
55+
# This is a completely optional function to include. This will be called when the resource is removed from the config or the module
56+
# is shutting down.
57+
LOGGER.debug(f"{self.name} is closed.")
58+
5159

5260
async def main():
5361
Registry.register_resource_creator(Sensor.SUBTYPE, MySensor.MODEL, ResourceCreatorRegistration(MySensor.new, MySensor.validate_config))

docs/examples/module_step3.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
from typing_extensions import Self
55

66
from viam.components.sensor import Sensor
7+
from viam.logging import getLogger
78
from viam.module.module import Module
89
from viam.proto.app.robot import ComponentConfig
910
from viam.proto.common import ResourceName
1011
from viam.resource.base import ResourceBase
1112
from viam.resource.registry import Registry, ResourceCreatorRegistration
1213
from viam.resource.types import Model, ModelFamily
1314

15+
LOGGER = getLogger(__name__)
16+
1417

1518
class MySensor(Sensor):
1619
# Subclass the Viam Sensor component and implement the required functions
@@ -27,6 +30,11 @@ async def get_readings(self, extra: Optional[Dict[str, Any]] = None, **kwargs) -
2730
wifi_signal = [x for x in content[2].split(" ") if x != ""]
2831
return {"link": wifi_signal[2], "level": wifi_signal[3], "noise": wifi_signal[4]}
2932

33+
def close(self):
34+
# This is a completely optional function to include. This will be called when the resource is removed from the config or the module
35+
# is shutting down.
36+
LOGGER.debug(f"{self.name} is closed.")
37+
3038

3139
async def main():
3240
"""

docs/examples/my_cool_arm.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@
55
from typing import Any, Dict, List, Optional, Tuple
66

77
from viam.components.arm import Arm, JointPositions, KinematicsFileFormat, Pose
8+
from viam.logging import getLogger
89
from viam.operations import run_with_operation
910
from viam.proto.common import Capsule, Geometry, Sphere
1011

12+
LOGGER = getLogger(__name__)
13+
1114

1215
class MyCoolArm(Arm):
1316
# Subclass the Viam Arm component and implement the required functions
@@ -102,3 +105,8 @@ async def get_geometries(self, *, extra: Optional[Dict[str, Any]] = None, timeou
102105

103106
async def get_kinematics(self, extra: Optional[Dict[str, Any]] = None, **kwargs) -> Tuple[KinematicsFileFormat.ValueType, bytes]:
104107
return KinematicsFileFormat.KINEMATICS_FILE_FORMAT_SVA, self.kinematics
108+
109+
def close(self):
110+
# This is a completely optional function to include. This will be called when the resource is removed from the config or the module
111+
# is shutting down.
112+
LOGGER.debug(f"{self.name} is closed.")

examples/complex_module/src/arm/my_arm.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@
55
from typing_extensions import Self
66

77
from viam.components.arm import Arm, JointPositions, KinematicsFileFormat, Pose
8+
from viam.logging import getLogger
89
from viam.operations import run_with_operation
910
from viam.proto.app.robot import ComponentConfig
1011
from viam.proto.common import Capsule, Geometry, ResourceName, Sphere
1112
from viam.resource.base import ResourceBase
1213
from viam.resource.types import Model, ModelFamily
1314

15+
LOGGER = getLogger(__name__)
16+
1417

1518
class MyArm(Arm):
1619
# Subclass the Viam Arm component and implement the required functions
@@ -104,3 +107,8 @@ async def get_kinematics(self, extra: Optional[Dict[str, Any]] = None, **kwargs)
104107
with open(filepath, mode="rb") as f:
105108
file_data = f.read()
106109
return (KinematicsFileFormat.KINEMATICS_FILE_FORMAT_SVA, file_data)
110+
111+
def close(self):
112+
# This is a completely optional function to include. This will be called when the resource is removed from the config or the module
113+
# is shutting down.
114+
LOGGER.debug(f"{self.name} is closed.")

examples/complex_module/src/gizmo/my_gizmo.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from typing_extensions import Self
44

5+
from viam.logging import getLogger
56
from viam.module.types import Reconfigurable
67
from viam.proto.app.robot import ComponentConfig
78
from viam.proto.common import ResourceName
@@ -10,6 +11,8 @@
1011

1112
from ..gizmo.api import Gizmo
1213

14+
LOGGER = getLogger(__name__)
15+
1316

1417
class MyGizmo(Gizmo, Reconfigurable):
1518
"""This is the specific implementation of a ``Gizmo`` (defined in api.py).
@@ -68,3 +71,8 @@ async def do_two(self, arg1: bool, **kwargs) -> str:
6871

6972
def reconfigure(self, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase]):
7073
self.my_arg = config.attributes.fields["arg1"].string_value
74+
75+
def close(self):
76+
# This is a completely optional function to include. This will be called when the resource is removed from the config or the module
77+
# is shutting down.
78+
LOGGER.debug(f"{self.name} is closed.")

examples/simple_module/src/main.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
from typing_extensions import Self
55

66
from viam.components.sensor import Sensor
7+
from viam.logging import getLogger
78
from viam.module.module import Module
89
from viam.proto.app.robot import ComponentConfig
910
from viam.proto.common import ResourceName
@@ -12,6 +13,8 @@
1213
from viam.resource.types import Model, ModelFamily
1314
from viam.utils import ValueTypes
1415

16+
LOGGER = getLogger(__name__)
17+
1518

1619
class MySensor(Sensor):
1720
# Subclass the Viam Sensor component and implement the required functions
@@ -49,6 +52,11 @@ def reconfigure(self, config: ComponentConfig, dependencies: Mapping[ResourceNam
4952
multiplier = 1.0
5053
self.multiplier = multiplier
5154

55+
def close(self):
56+
# This is a completely optional function to include. This will be called when the resource is removed from the config or the module
57+
# is shutting down.
58+
LOGGER.debug(f"{self.name} is closed.")
59+
5260

5361
async def main():
5462
"""This function creates and starts a new module, after adding all desired resource models.

src/viam/module/module.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ async def reconfigure_resource(self, request: ReconfigureResourceRequest):
150150
else:
151151
resource.stop()
152152
add_request = AddResourceRequest(config=request.config, dependencies=request.dependencies)
153-
self.server.remove_resource(rn)
153+
await self.server.remove_resource(rn)
154154
await self.add_resource(add_request)
155155

156156
async def remove_resource(self, request: RemoveResourceRequest):
@@ -161,7 +161,7 @@ async def remove_resource(self, request: RemoveResourceRequest):
161161
await resource.stop()
162162
else:
163163
resource.stop()
164-
self.server.remove_resource(rn)
164+
await self.server.remove_resource(rn)
165165

166166
async def ready(self, request: ReadyRequest) -> ReadyResponse:
167167
self._parent_address = request.parent_address

src/viam/resource/base.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,12 @@ def get_operation(self, kwargs: Mapping[str, Any]) -> Operation:
8484
viam.operations.Operation: The operation associated with this function
8585
"""
8686
return kwargs.get(Operation.ARG_NAME, Operation._noop())
87+
88+
async def close(self):
89+
"""Safely shut down the resource and prevent further use.
90+
91+
Close must be idempotent. Later configuration may allow a resource to be "open" again.
92+
If a resource does not want or need a close function, it is assumed that the resource does not need to retun errors when future
93+
non-Close methods are called.
94+
"""
95+
return

0 commit comments

Comments
 (0)