def _trigger_start(self, command, source, *args, **kwargs): original_command = kwargs.get('original', None) trigger = self._triggers.get((command, source), None) if not trigger and original_command: trigger = self._triggers.get((original_command, source), None) if not trigger: trigger = self._triggers.get((command, None), None) if not trigger: trigger = self._triggers.get((original_command, None), None) ## trigger = self._match_condition(command, source, self._triggers) if trigger and self._match_condition_item(trigger): timer = self._trigger_timers.get(trigger[Attribute.MAPPED], None) if not timer: timer = CTimer() timer.stop() if trigger[Attribute.SECS] > 0: timer.action(self.command, (trigger[Attribute.MAPPED], ), source=self, original=source) timer.interval = trigger[Attribute.SECS] self._trigger_timers.update({trigger[Attribute.MAPPED]: timer} ) timer.start() self._logger.debug('{name} command "{command}" from source "{source}" trigger started, mapped to "{mapped}" waiting {secs} secs. '.format( name=self.name, source=source.name if source else None, command=command, mapped=trigger[Attribute.MAPPED], secs=trigger[Attribute.SECS], ))
def test_3_sec_callback(self): callback = Mock() callback.test.return_value = True rt = CTimer(3) rt.action(callback.test, ()) rt.start() self.assertFalse(callback.test.called) time.sleep(4) self.assertTrue(callback.test.called)
def test_no_sec_callback(self): callback = Mock() callback.test.return_value = True rt = CTimer() rt.interval = 60 rt.action(callback.test, ()) rt.start() time.sleep(3) rt.stop() self.assertFalse(callback.test.called)
def test_double_timer_bug(self): callback = Mock() callback.test.return_value = True rt = CTimer(3) rt.action(callback.test, ()) rt.start() rt.start() rt.stop() self.assertFalse(callback.test.called) time.sleep(4) self.assertFalse(callback.test.called)
def idle(self, *args, **kwargs): command = kwargs.get('command', None) source = kwargs.get('source', None) mapped = kwargs.get(Attribute.MAPPED, None) secs = kwargs.get('secs', None) if secs: timer = CTimer() timer.interval = secs timer.action(self.command, (mapped, ), source=self, original=source, source_property=Property.IDLE) # self._idle_timer = timer self._idle_timer.update({(command, source): {Attribute.SECS: secs, Attribute.MAPPED: mapped, 'timer': timer}})
def _delay_start(self, command, source, *args, **kwargs): original_command = kwargs.get('original', None) delay = self._get_delay(command, source, original_command, include_zero=True) if delay: timer = self._delay_timers.get(delay['mapped'], None) if not timer: timer = CTimer() timer.stop() if delay['secs'] > 0: timer.action(self.command, (delay['mapped'], ), source=self, original=source, source_property=Property.DELAY) timer.interval = delay['secs'] self._delay_timers.update({delay['mapped']: timer} ) timer.start() self._logger.debug('{name} command "{command}" from source "{source}" delayed, mapped to "{mapped}" waiting {secs} secs. '.format( name=self.name, source=source.name if source else None, command=command, mapped=delay['mapped'], secs=delay['secs'], ))
def mapped(self, *args, **kwargs): command = kwargs.get('command', None) mapped = kwargs.get('mapped', None) source = kwargs.get('source', None) secs = kwargs.get('secs', None) timer = None commands = command if not isinstance(command, tuple): commands = (command, ) for c in commands: if secs: timer = CTimer() timer.interval = secs timer.action(self.command, (mapped, ), source=self, original=source) # self._maps.append({'command': command, 'mapped': mapped, 'source': source}) sources = source if not isinstance(source, tuple): sources = (source ,) for s in sources: self._maps.update({(c, s): (mapped, timer)})
def delay(self, *args, **kwargs): commands = kwargs.get('command', None) if (not isinstance(commands, tuple)): commands = (commands, ) mapped = kwargs.get('mapped', None) sources = kwargs.get('source', None) if (not isinstance(sources, tuple)): sources = (sources, ) secs = kwargs.get('secs', None) for command in commands: for source in sources: if not mapped: m = command else: m = mapped timer = CTimer() timer.interval=secs timer.action(self.command, (m, ), source=self, original=source, source_property=Property.DELAY) self._delays.update({(command, source): {'mapped': m, 'secs': secs, 'timer': timer}}) return True
class InterfaceDevice(StateDevice): def __init__(self, address=None, *args, **kwargs): self._address = address super(InterfaceDevice, self).__init__(*args, **kwargs) def _initial_vars(self, *args, **kwargs): super(InterfaceDevice, self)._initial_vars(*args, **kwargs) self._interfaces = [] self._sync = False self._sync_timer = None self._read_only = False self._send_always = config.device_send_always self._previous_interface_command = None @property def address(self): return self._address @address.setter def address(self, value): self._address = value return self._address def addressMatches(self, address): match = self.address == None or self.address == address if not match: try: match = self.address.lower() == address.lower() except Exception as ex: pass return match def _add_device(self, device): try: device.onCommand( device=self) # Register with the interface to receive events self._interfaces.append(device) self.delay(command=Command.ON, source=device, secs=0) self.delay(command=Command.OFF, source=device, secs=0) self._logger.debug("{name} added new interface {interface}".format( name=self.name, interface=device.name, )) return True except Exception as ex: return super(InterfaceDevice, self)._add_device(device) def _delegate_command(self, command, *args, **kwargs): original_state = kwargs.get('original_state', None) source = kwargs.get('source', None) original = kwargs.get('original', None) if not self._read_only: for interface in self._interfaces: if source != interface and original != interface: new_state = self._command_to_state(command, None) if self._send_always or (not self._send_always and original_state != new_state): self._previous_interface_command = command try: self._logger.debug( "{name} Send command '{command}' to interface '{interface}'" .format(name=self.name, command=command, interface=interface.name)) self._send_command_to_interface( interface, self._address, command) # if isinstance(command, tuple): # # getattr(interface, command[0])(self._address, *command[1:]) # self._send_command_to_interface(interface, self._address, *command[1:]) # else: # # getattr(interface, command)(self._address) # self._send_command_to_interface(interface, self._address, command) except Exception as ex: self._logger.error( "{name} Could not send command '{command}' to interface '{interface}. Exception: {exc}'" .format( name=self.name, command=command, interface=interface.name, exc=str(ex), )) else: self._logger.debug( "{name} is already at this new state {state} originally {original_state} for command {command} -> {new_state}, do not send to interface" .format( name=self.name, state=self.state, original_state=original_state, command=command, new_state=new_state, )) else: self._logger.debug( "{name} do not send to interface because either the current source {source} or original source {original} is the interface itself." .format( name=self.name, state=self.state, source=source, original=original, command=command, )) return super(InterfaceDevice, self)._delegate_command(command, *args, **kwargs) def _send_command_to_interface(self, interface, address, command): if isinstance(command, tuple): getattr(interface, command[0])(self._address, *command[1:]) else: getattr(interface, command)(self._address) def sync(self, value): self._sync = value if value: self._start_sync() else: self._stop_sync() return self._sync def _start_sync(self): # get a random number of secs from 30 minutes to an hour offset = random.randint(0, 30 * 60) + (30 * 60) self._sync_timer = CTimer(offset) self._sync_timer.action(self._run_sync, ()) self._sync_timer.start() def _stop_sync(self): self._sync_timer.stop() def _run_sync(self): if self.interface: getattr(self.interface, self._state)() self._start_sync() def read_only(self, value=None): if value: self._read_only = value return self._read_only def send_always(self, value=False): if value: self._send_always = value return self._send_always