drop unused event id from spawn_child
[~helmut/onoff.git] / onoff / command.py
1 import logging
2
3 from .common import OnoffDevice, ST_ACTIVE, ST_TRANSITION
4 from .gobject import spawn_child
5
6 logger = logging.getLogger("onoff.command")
7
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
13             it lives.
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
18     """
19     def __init__(self, oncommand, offcommand):
20         """
21
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
27                 looked up in $PATH.
28         """
29         OnoffDevice.__init__(self)
30         self.oncommand = oncommand
31         self.offcommand = offcommand
32         self.desired_state = 0 # bit mask of just ST_ACTIVE
33         self.pid = None
34         self.target_state = 0 # state the last command targeted
35
36     @property
37     def state(self):
38         if self.pid is not None:
39             return self.desired_state | ST_TRANSITION
40         return self.desired_state
41
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)
50
51     def process_died(self, pid, condition):
52         assert self.pid == pid
53         self.pid = None
54         logger.info("command %d targeting %d completed", pid, self.target_state)
55         if self.desired_state == self.target_state:
56             self.changestate(self.state)
57         else:
58             logger.info("desired state changed to %d during invocation " +
59                         "targeting %d", self.desired_state, self.target_state)
60             self.transition(self.desired_state)
61
62     def activate(self):
63         if self.desired_state != ST_ACTIVE:
64             self.desired_state = ST_ACTIVE
65             if self.pid is None:
66                 self.transition(self.desired_state)
67
68     def deactivate(self):
69         if self.desired_state != 0:
70             self.desired_state = 0
71             if self.pid is None:
72                 self.transition(self.desired_state)