class TurnSlowlyStatic(AbstractMessage): def __init__(self): super().__init__() self.topic = settings.Mqtt.TOPIC + settings.Messages.TURN_SLOWLY_STATIC self.light_controller = LightController() def _parse_payload(self, payload): self._logger.debug('Executing Turn Slowly Static message') color = payload.get(settings.Messages.COLOR, None) if color is None: error_msg = f'Couln\'t read state, color or time span from ' \ f'message {payload}' self._logger.error(error_msg) raise IncorrectPayloadException(error_msg) color = utils.color_message_to_tuple(color) brightness = payload.get(settings.Messages.BRIGHTNESS, max(color)) time_span = payload.get(settings.Messages.TIME_SPAN, 10) return color, brightness, time_span def execute(self, payload: Dict[str, Any]): color, brightness, time_span = self._parse_payload(payload) self.light_controller.state_on() action = ChangeColorAction(color, brightness, time_span) self.light_controller.add_action(action)
class ChangeColorAction(LightAction): def __init__(self, color, brightness, time_span): self.light_controller = LightController() super().__init__(method=None) self.color: Tuple[int, int, int] = color self.brightness = brightness self.time_span = time_span def _calculate_steps(self, time_span): steps = int(time_span * 1000 / settings.Lights.SLOW_CHANGE_WAIT_MS) steps = max(steps, settings.Lights.MIN_STEPS) return steps def _calculate_color_changes(self, color, time_span): current_colors = self.light_controller.read_colors() steps = self._calculate_steps(time_span) leds_colors = utils.create_colors_change_table( current_colors, [color] * len(current_colors), steps) self._logger.debug(f'Changing leds of colors {current_colors} ' f'to {color} in {steps} steps') color_sets = list(zip(*leds_colors)) return color_sets def calculate_brightness_changes(self, brightness, time_span): steps = self._calculate_steps(time_span) current_brightness = self.light_controller.read_brightness() brightness_changes = utils.create_value_change_table( current_brightness, brightness, steps) return brightness_changes def evaluate_payload(self, payload) -> bool: """ Check if payload is at least type {'state': 'ON'} :raises: IncorrectPayloadException if state has wrong value """ has_state = utils.message_has_state(payload) if not has_state: return False state_off = payload[settings.Messages.STATE] == settings.Messages.OFF return state_off def execute(self): """ Add multiple light color actions into light_controller """ color_sets = self._calculate_color_changes(self.color, self.time_span) brightness_changes = self.calculate_brightness_changes( self.brightness, self.time_span) wait_time = self.time_span / len(color_sets) for color_set, brightness in zip(color_sets, brightness_changes): action = LightAction( self.light_controller.turn_into_colors_and_wait, args=[color_set, brightness, wait_time]) self.light_controller.add_action(action)
class SetBrightness(LightAction): def __init__(self): self.light_controller = LightController() super().__init__(method=self.light_controller.set_brightness) self._payload = None def evaluate_payload(self, payload: Dict[str, Any]) -> bool: """ Check if payload is type {'state': 'ON', 'brightness': int} :raises: IncorrectPayloadException if state or brightness have wrong value """ has_state = utils.message_has_state(payload) has_brightness = utils.message_has_brightness(payload) keys = payload.keys() if not has_state or not has_brightness or len(keys) > 2: return False if payload[settings.Messages.STATE] == settings.Messages.ON: self._payload = payload self.arguments = [payload.get(settings.Messages.BRIGHTNESS)] return True return False def execute(self): self.light_controller.state_on() super().execute()
class SetColor(LightAction): def __init__(self): self.light_controller = LightController() super().__init__(method=self.light_controller.turn_static_color) self._color: Optional[Tuple[int, int, int]] = None self._brightness: Optional[int] = None def evaluate_payload(self, payload: Dict[str, Any]) -> bool: """ Check if payload is type { 'state': 'ON', 'color': {'r': int, 'g': int, 'b': int} } :raises: IncorrectPayloadException if state, brightness or color have wrong value """ has_state = utils.message_has_state(payload) has_color = utils.message_has_color(payload) if not has_state or not has_color: return False if sum([has_state, has_color]) != 2: return False if payload[settings.Messages.STATE] == settings.Messages.OFF: return False self._logger.debug('Received payload that fits to set color action') color = payload.get(settings.Messages.COLOR) self._color = utils.color_message_to_tuple(color) self._brightness = self.light_controller.get_brightness() self._logger.debug(f'Received color: {self._color} and brightness: ' f'{self._brightness}') return True def execute(self): self.light_controller.state_on() if not self._color: raise ValueError('Color not set. Run evaluate_payload before ' 'calling execute') if not self._brightness: self._brightness = max(self._color) self.arguments = [self._color, self._brightness] super().execute()
class TurnStatic(AbstractMessage): def __init__(self): super().__init__() self.topic = settings.Mqtt.TOPIC + settings.Messages.TURN_STATIC self.light_controller = LightController() def create_action(self, payload): for action in ACTIONS: if action.evaluate_payload(payload): return action return None def execute(self, payload: Dict[str, Any]): self._logger.debug(f'Executing TurnStatic message with payload ' f'{payload}') action = self.create_action(payload) if not action: msg = f'Turn static message has unexpected payload: {payload}' raise IncorrectPayloadException(msg) self.light_controller.add_action(action)
def __init__(self, color, brightness, time_span): self.light_controller = LightController() super().__init__(method=None) self.color: Tuple[int, int, int] = color self.brightness = brightness self.time_span = time_span
def __init__(self): self.light_controller = LightController() super().__init__(method=self.light_controller.turn_off, priority=settings.Actions.TURN_OFF_PRIORITY)
def __init__(self): super().__init__() self.topic = settings.Mqtt.TOPIC + settings.Messages.TURN_STATIC self.light_controller = LightController()
def __init__(self): self.light_controller = LightController() super().__init__(method=self.light_controller.turn_on)
from lights.light_controller.light_controller import LightController from lights.messages.message_manager import MessageManager, MESSAGES from lights.mqtt_client.mqtt_client import MQTTClient if __name__ == '__main__': now = datetime.now() dt_string = now.strftime("%Y_%m_%d__%H_%M_%S") logging.basicConfig(filename=f'/home/pi/projects/lights/logs/{dt_string}.log', filemode='a', format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s', datefmt='%H:%M:%S', level=logging.DEBUG) logging.info('Starting lights controller') light_controller = LightController() light_controller.start() logging.info('Starting mqtt client') client = MQTTClient([msg.topic for msg in MESSAGES]) client.connect() logging.info('Starting message manager') message_manager = MessageManager(client.message_queue, client.publish) light_controller.update_publish_method(message_manager.publish) message_manager.start() try: client.loop_forever() except KeyboardInterrupt: light_controller.stop()
def __init__(self): self.light_controller = LightController() super().__init__(method=self.light_controller.set_brightness) self._payload = None
def __init__(self): self.light_controller = LightController() super().__init__(method=self.light_controller.turn_static_color) self._color: Optional[Tuple[int, int, int]] = None self._brightness: Optional[int] = None