Skip to content

powermanager

plantimager.controller.scanner.powermanager Link

Manages the switching on and off of the various components of the scanner via the GPIO

PowerManager Link

PowerManager(warmup_period, parent=None)

Bases: QObject

Initialize the PowerManager instance.

This class provides control over the power management system, including handling CNC connections, light toggling, and manual/automatic power management modes. It relies on GPIO for hardware interactions and provides timing mechanisms to manage various operations.

Parameters:

Name Type Description Default
warmup_period float

The duration (in seconds) required for components to warm up before a specific operation.

required
parent optional

The parent QObject for the timers created within the object. Defaults to None.

None

Attributes:

Name Type Description
cnc AbstractCNC or None

Represents the CNC connection object. Defaults to None until an active connection is established.

warmup_period float

The configured warmup period (in seconds).

manual_mode_timer QTimer

A single-shot timer used to manage the manual mode timeout. It triggers after 5 minutes (converted to milliseconds).

cnc_connect_timer QTimer

A regular timer used to periodically attempt CNC reconnections. It is triggered every 1.2 seconds (1200 milliseconds).

_mode PowerManagerMode

Tracks the current power management mode. Defaults to PowerManagerMode.AUTO.

_next_warmup_date datetime or None

Holds the date and time of the next warmup operation. Defaults to None.

Source code in plantimager/controller/scanner/powermanager.py
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
def __init__(self, warmup_period: float, parent=None):
    """
    Initialize the PowerManager instance.

    This class provides control over the power management system, including
    handling CNC connections, light toggling, and manual/automatic power
    management modes. It relies on GPIO for hardware interactions and provides
    timing mechanisms to manage various operations.

    Parameters
    ----------
    warmup_period : float
        The duration (in seconds) required for components to warm up before a
        specific operation.
    parent : optional
        The parent QObject for the timers created within the object. Defaults
        to ``None``.

    Attributes
    ----------
    cnc : AbstractCNC or None
        Represents the CNC connection object. Defaults to ``None`` until an
        active connection is established.
    warmup_period : float
        The configured warmup period (in seconds).
    manual_mode_timer : QTimer
        A single-shot timer used to manage the manual mode timeout. It triggers
        after 5 minutes (converted to milliseconds).
    cnc_connect_timer : QTimer
        A regular timer used to periodically attempt CNC reconnections. It is
        triggered every 1.2 seconds (1200 milliseconds).
    _mode : PowerManagerMode
        Tracks the current power management mode. Defaults to
        ``PowerManagerMode.AUTO``.
    _next_warmup_date : datetime.datetime or None
        Holds the date and time of the next warmup operation. Defaults to ``None``.
    """
    super().__init__(parent)
    gpio.setup(
        (GPIO_CNC_PIN, GPIO_LIGHTS_PIN, GPIO_GROWTH_LIGHTS_PIN),
        mode=gpio.OUT,
        initial=gpio.LOW
    )
    self.cnc: AbstractCNC | None = None
    self.warmup_period: float = warmup_period
    self.manual_mode_timer = QTimer(parent=self, singleShot=True, interval=60 * 5 * 1000)  # 5 minutes in ms
    self.manual_mode_timer.timeout.connect(self._manual_mode_timeout)
    self.cnc_connect_timer = QTimer(parent=self, singleShot=False, interval=1200)
    self.cnc_connect_timer.timeout.connect(self._cnc_connect)
    self._mode: PowerManagerMode = PowerManagerMode.AUTO
    self.modeChanged.connect(self._on_mode_changed)
    self._next_warmup_date: datetime.datetime | None = None
    self._resume_auto()

activity_monitor Link

activity_monitor(obj, callback)

Wraps all methods of the given obj to trigger a specified callback before executing the original method. This is useful for monitoring or observing object activity, such as logging or tracking method calls.

This function dynamically intercepts all methods of the input obj object and wraps them such that the callback function is executed prior to the method's actual invocation. The wrapped methods retain their arguments, return values, and attributes.

Parameters:

Name Type Description Default
obj object

The target object whose methods are to be monitored. All methods of this object will be wrapped to include the callback.

required
callback Callable[[], None]

A zero-argument callable that is executed before any method of obj is invoked.

required

Returns:

Type Description
object

The original obj, with its methods wrapped to call callback before execution.

Raises:

Type Description
AttributeError

If an attribute of obj cannot be fetched or set while wrapping methods.

Notes

The callback function is expected to handle side-effects or monitoring concerns (e.g., logging, notifications). This function does not guarantee thread safety if the obj's methods are accessed simultaneously from multiple threads.

See Also

functools.update_wrapper : Used internally to update the wrapped function's metadata to match the original function.

Examples:

>>> from functools import partial
>>> class MyClass:
...     def method(self, x):
...         print(f'Method called with {x}')
>>> obj = MyClass()
>>> def my_callback():
...     print('Callback triggered!')
>>> monitored_obj = activity_monitor(obj, my_callback)
>>> monitored_obj.method(10)
Callback triggered!
Method called with 10
Source code in plantimager/controller/scanner/powermanager.py
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
def activity_monitor(obj: object, callback: Callable[[], None]):
    """
    Wraps all methods of the given `obj` to trigger a specified callback before executing
    the original method. This is useful for monitoring or observing object activity, such
    as logging or tracking method calls.

    This function dynamically intercepts all methods of the input `obj` object and wraps
    them such that the `callback` function is executed prior to the method's actual
    invocation. The wrapped methods retain their arguments, return values, and
    attributes.

    Parameters
    ----------
    obj : object
        The target object whose methods are to be monitored. All methods of this object
        will be wrapped to include the `callback`.
    callback : Callable[[], None]
        A zero-argument callable that is executed before any method of `obj` is invoked.

    Returns
    -------
    object
        The original `obj`, with its methods wrapped to call `callback` before
        execution.

    Raises
    ------
    AttributeError
        If an attribute of `obj` cannot be fetched or set while wrapping methods.

    Notes
    -----
    The `callback` function is expected to handle side-effects or monitoring concerns
    (e.g., logging, notifications). This function does not guarantee thread safety if
    the `obj`'s methods are accessed simultaneously from multiple threads.

    See Also
    --------
    functools.update_wrapper : Used internally to update the wrapped function's
        metadata to match the original function.

    Examples
    --------
    >>> from functools import partial
    >>> class MyClass:
    ...     def method(self, x):
    ...         print(f'Method called with {x}')
    >>> obj = MyClass()
    >>> def my_callback():
    ...     print('Callback triggered!')
    >>> monitored_obj = activity_monitor(obj, my_callback)
    >>> monitored_obj.method(10)
    Callback triggered!
    Method called with 10
    """
    for attr in dir(obj):
        if inspect.ismethod(getattr(obj, attr)):
            original_method = getattr(obj, attr)

            def f(*args, **kwargs):
                callback()
                original_method(*args, **kwargs)
            setattr(obj, attr, update_wrapper(f, original_method))
    return obj