Skip to content

Commit f35ca02

Browse files
committed
button protocol and driver: Add a new protocol and driver for a Button
A button can be used to simulate pressing a physical button on a device. For example a DigitalOutputButtonDriver can be used when a reset button is connected via a relay to a DigitalOutput. In addition there are the ManualButtonDriver and ExternalButtonDriver drivers analogous to the ManualPowerDriver and ExternalPowerDriver drivers. Operations on a button include "press", "release", "press_for", and "get". Signed-off-by: Perry Melange <[email protected]>
1 parent e8aadae commit f35ca02

File tree

4 files changed

+135
-0
lines changed

4 files changed

+135
-0
lines changed

labgrid/driver/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
DigitalOutputPowerDriver, YKUSHPowerDriver, \
1717
USBPowerDriver, SiSPMPowerDriver, NetworkPowerDriver, \
1818
PDUDaemonDriver
19+
from .buttondriver import ManualButtonDriver, ExternalButtonDriver, \
20+
DigitalOutputButtonDriver
1921
from .usbloader import MXSUSBDriver, IMXUSBDriver, BDIMXUSBDriver, RKUSBDriver, UUUDriver
2022
from .usbsdmuxdriver import USBSDMuxDriver
2123
from .usbsdwiredriver import USBSDWireDriver

labgrid/driver/buttondriver.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import shlex
2+
import time
3+
import math
4+
from importlib import import_module
5+
6+
import attr
7+
8+
from ..factory import target_factory
9+
from ..protocol import ButtonProtocol, DigitalOutputProtocol
10+
from ..step import step
11+
from ..util.proxy import proxymanager
12+
from ..util.helper import processwrapper
13+
from .common import Driver
14+
from .exception import ExecutionError
15+
16+
17+
@target_factory.reg_driver
18+
@attr.s(eq=False)
19+
class ManualButtonDriver(Driver, ButtonProtocol):
20+
"""ManualButtonDriver - Driver to tell the user to control a target's button"""
21+
22+
@Driver.check_active
23+
@step()
24+
def press(self):
25+
self.target.interact(
26+
f"Press and hold the button on target {self.target.name} and press enter"
27+
)
28+
29+
@Driver.check_active
30+
@step()
31+
def release(self):
32+
self.target.interact(
33+
f"Release the button on the target {self.target.name} press enter"
34+
)
35+
36+
@Driver.check_active
37+
@step()
38+
def press_for(self):
39+
self.target.interact(
40+
f"Press and then Release the button on target {self.target.name} for {self.delay} seconds and press enter"
41+
)
42+
43+
@target_factory.reg_driver
44+
@attr.s(eq=False)
45+
class ExternalButtonDriver(Driver, ButtonProtocol):
46+
"""ExternalButtonDriver - Driver using an external command to control a target's button"""
47+
cmd_press = attr.ib(validator=attr.validators.instance_of(str))
48+
cmd_release = attr.ib(validator=attr.validators.instance_of(str))
49+
cmd_press_for = attr.ib(validator=attr.validators.instance_of(str))
50+
delay = attr.ib(default=1.0, validator=attr.validators.instance_of(float))
51+
52+
@Driver.check_active
53+
@step()
54+
def press(self):
55+
cmd = shlex.split(self.cmd_press)
56+
processwrapper.check_output(cmd)
57+
58+
@Driver.check_active
59+
@step()
60+
def release(self):
61+
cmd = shlex.split(self.cmd_release)
62+
processwrapper.check_output(cmd)
63+
64+
@Driver.check_active
65+
@step()
66+
def press_for(self):
67+
if self.cmd_press_for is not None:
68+
cmd = shlex.split(self.cmd_press_for)
69+
processwrapper.check_output(cmd)
70+
else:
71+
self.press()
72+
time.sleep(self.delay)
73+
self.release()
74+
75+
@target_factory.reg_driver
76+
@attr.s(eq=False)
77+
class DigitalOutputButtonDriver(Driver, ButtonProtocol):
78+
"""
79+
DigitalOutputButtonDriver uses a DigitalOutput to control a button
80+
"""
81+
bindings = {"output": DigitalOutputProtocol, }
82+
delay = attr.ib(default=1.0, validator=attr.validators.instance_of(float))
83+
84+
def __attrs_post_init__(self):
85+
super().__attrs_post_init__()
86+
87+
@Driver.check_active
88+
@step()
89+
def press(self):
90+
self.output.set(True)
91+
92+
@Driver.check_active
93+
@step()
94+
def release(self):
95+
self.output.set(False)
96+
97+
@Driver.check_active
98+
@step()
99+
def press_for(self):
100+
self.press()
101+
time.sleep(self.delay)
102+
self.release()
103+
104+
@Driver.check_active
105+
@step()
106+
def get(self):
107+
return self.output.get()

labgrid/protocol/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from .consoleprotocol import ConsoleProtocol
44
from .linuxbootprotocol import LinuxBootProtocol
55
from .powerprotocol import PowerProtocol
6+
from .buttonprotocol import ButtonProtocol
67
from .filetransferprotocol import FileTransferProtocol
78
from .infoprotocol import InfoProtocol
89
from .digitaloutputprotocol import DigitalOutputProtocol

labgrid/protocol/buttonprotocol.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import abc
2+
3+
4+
class ButtonProtocol(abc.ABC):
5+
"""Abstract class providing the ButtonProtocol interface"""
6+
7+
@abc.abstractmethod
8+
def press(self):
9+
"""Implementations should "press and hold" the button."""
10+
raise NotImplementedError
11+
12+
@abc.abstractmethod
13+
def release(self):
14+
"""Implementations should "release" the button"""
15+
raise NotImplementedError
16+
17+
@abc.abstractmethod
18+
def press_for(self, time: float):
19+
"""Implementations should "press" the button for time seconds and then "release" the button again"""
20+
raise NotImplementedError
21+
22+
@abc.abstractmethod
23+
def get(self):
24+
"""Implementations should return the status of the button"""
25+
raise NotImplementedError

0 commit comments

Comments
 (0)