3 from .common import OnoffDevice, OnoffState
4 from .gobject import spawn_child
6 logger = logging.getLogger("onoff.command")
8 class OnoffCommand(OnoffDevice):
9 """A device that is enabled and disabled by executing separate commands.
10 The transition period is the duration of the commands.
11 @type pid: int or None
12 @ivar pid: is either None or the pid of a transition command as long as
14 @type desired_state: bool
15 @ivar desired_state: is the state that should be transitioned to
16 @type target_state: bool
17 @ivar target_state: is the state that we are currently transitioning to
19 def __init__(self, oncommand, offcommand):
22 @type oncommand: [str]
23 @param oncommand: an argument vector to be executed for activation.
24 @type offcommand: [str]
25 @param offcommand: an argument vector to be executed for deactivation.
26 @note: For both commands the first element is used as executable and
29 OnoffDevice.__init__(self)
30 self.oncommand = oncommand
31 self.offcommand = offcommand
32 self.desired_state = OnoffState.inactive
34 self.target_state = OnoffState.inactive # last command target state
38 if self.pid is not None:
39 return self.desired_state | OnoffState.transition
40 return self.desired_state
42 def transition(self, state):
43 command, name = [(self.offcommand, "offcommand"),
44 (self.oncommand, "oncommand")][state]
45 self.target_state = state
46 logger.info("invoking %s %s", name, " ".join(command))
47 self.pid = spawn_child(command, self.process_died)
48 logger.debug("started %s as pid %d", name, self.pid)
49 self.changestate(self.state)
51 def process_died(self, pid, condition):
52 assert self.pid == pid
54 logger.info("command %d targeting %s completed", pid,
55 self.target_state.name)
56 if self.desired_state == self.target_state:
57 self.changestate(self.state)
59 logger.info("desired state changed to %s during invocation " +
60 "targeting %s", self.desired_state.name,
61 self.target_state.name)
62 self.transition(self.desired_state)
65 if self.desired_state != OnoffState.active:
66 self.desired_state = OnoffState.active
68 self.transition(self.desired_state)
71 if self.desired_state != OnoffState.inactive:
72 self.desired_state = OnoffState.inactive
74 self.transition(self.desired_state)