From c9d65b29fd19aa8a5b67cbc36600e6784462b1d1 Mon Sep 17 00:00:00 2001 From: Pierre Date: Sun, 10 May 2026 22:41:23 +0200 Subject: [PATCH] Added support for the senseo --- apps/ad_toolbox | 2 +- apps/rooms/kitchen.yaml | 73 ++++++++++++++++++++++++++++++++++++++++- apps/senseo.py | 46 ++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 apps/senseo.py diff --git a/apps/ad_toolbox b/apps/ad_toolbox index 8454cc9..05a910b 160000 --- a/apps/ad_toolbox +++ b/apps/ad_toolbox @@ -1 +1 @@ -Subproject commit 8454cc95f5d8ed816ba7552b5e43fb39da792cca +Subproject commit 05a910ba806d98e55c7594570b1cd751765e8037 diff --git a/apps/rooms/kitchen.yaml b/apps/rooms/kitchen.yaml index cda26a7..ebeaef4 100644 --- a/apps/rooms/kitchen.yaml +++ b/apps/rooms/kitchen.yaml @@ -19,4 +19,75 @@ light_kitchen_sink_switch: entity: light.kitchen_sink_switch off_events: - - turn_off_all_lights \ No newline at end of file + - turn_off_all_lights + +senseo_quadrante: + module: senseo + class: Senseo + + virtual_sensors: + default_values: + # this is done to break the circular dependencies between sensor.senseo_cup_icon and sensor.senseo_cup + sensor.senseo_cup_icon: "" # "mdi:coffee-off-outline" + sensors: + value_selector.senseo_cup: + attributes: + friendly_name: Tasse + sensor_attributes: + icon: sensor.senseo_cup_icon + values: + unavailable: sensor.senseo_quadrante_operating_state == 'unavailable' + PrĂȘte: binary_sensor.senseo_quadrante_cup_available and binary_sensor.senseo_quadrante_cup_full + Service en cours: binary_sensor.senseo_quadrante_cup_available and sensor.senseo_quadrante_operating_state == 'SENSEO_BREWING' + Vide: binary_sensor.senseo_quadrante_cup_available + Absente: True + + value_selector.senseo_cup_icon: + "mdi:coffee": sensor.senseo_cup == 'PrĂȘte' + "mdi:coffee-outline": sensor.senseo_cup == 'Vide' or sensor.senseo_cup == 'Service en cours' + "mdi:coffee-off-outline": True + + value_selector.senseo_programmation: + attributes: + friendly_name: Programme + icon: mdi:coffee-to-go + values: + unavailable: sensor.senseo_quadrante_operating_state == 'unavailable' + 1 Tasse (douche): binary_sensor.senseo_quadrante_has_program and binary_sensor.senseo_quadrante_has_program.cup_size == 1 and binary_sensor.senseo_quadrante_has_program.power_pressed + 2 Tasses (douche): binary_sensor.senseo_quadrante_has_program and binary_sensor.senseo_quadrante_has_program.cup_size == 2 and binary_sensor.senseo_quadrante_has_program.power_pressed + 1 Tasse: binary_sensor.senseo_quadrante_has_program and binary_sensor.senseo_quadrante_has_program.cup_size == 1 + 2 Tasses: binary_sensor.senseo_quadrante_has_program and binary_sensor.senseo_quadrante_has_program.cup_size == 2 + Aucun: True + + clear_program_button: button.senseo_quadrante_clear_program + + programs: + one_cup_shower: + events: + shower_finished: + event_name: shower_finished + button: button.senseo_quadrante_brew_coffee_normal + condition: binary_sensor.senseo_quadrante_has_program and binary_sensor.senseo_quadrante_has_program.cup_size == 1 and binary_sensor.senseo_quadrante_has_program.power_pressed + + two_cup_shower: + events: + shower_finished: + event_name: shower_finished + button: button.senseo_quadrante_brew_coffee_double + condition: binary_sensor.senseo_quadrante_has_program and binary_sensor.senseo_quadrante_has_program.cup_size == 2 and binary_sensor.senseo_quadrante_has_program.power_pressed + + one_cup_morning: + delay: 10 + events: + good_morning: + event_name: good_morning + button: button.senseo_quadrante_brew_coffee_normal + condition: binary_sensor.senseo_quadrante_has_program and binary_sensor.senseo_quadrante_has_program.cup_size == 1 and not binary_sensor.senseo_quadrante_has_program.power_pressed + + two_cup_morning: + delay: 10 + events: + good_morning: + event_name: good_morning + button: button.senseo_quadrante_brew_coffee_double + condition: binary_sensor.senseo_quadrante_has_program and binary_sensor.senseo_quadrante_has_program.cup_size == 2 and not binary_sensor.senseo_quadrante_has_program.power_pressed \ No newline at end of file diff --git a/apps/senseo.py b/apps/senseo.py new file mode 100644 index 0000000..bfa91fe --- /dev/null +++ b/apps/senseo.py @@ -0,0 +1,46 @@ +from ad_toolbox.smartobject import SmartObject +import ad_toolbox.smartcondition as SmartCondition +from ad_toolbox.eventhandler import EventHandler + +class Senseo(SmartObject): + + def on_initialize_smart_object(self): + super().on_initialize_smart_object() + self.delay_cb_handle = None + self.smartconditions = dict() + self.event_handlers = list() + + try: self.program_configs = self.args['programs'] + except KeyError: self.program_configs = None + + for config_name in self.program_configs: + config = self.program_configs[config_name] + self.smartconditions[config_name] = SmartCondition.Evaluator(self,config['condition'],condition_name = config_name) + if not self.entity_exists(config['button']): self.log_error(f"Entity not found {config['button']}") + + self.event_handlers.append(EventHandler(self,config["events"],self.on_event,config_name)) + + def on_event(self, event_name, event_data,config_name): + self.log_info(f"Event {event_name} received. Config name = {config_name}") + config = self.program_configs[config_name] + + try: delay = config['delay'] + except KeyError: delay = 0 + + if self.smartconditions[config_name].evaluate() == SmartCondition.Result.Succeeded: + if (delay > 0): + if self.delay_cb_handle: self.cancel_timer(self.delay_cb_handle) + self.log_info(f"The coffee will be prepared in {delay}s") + self.delay_cb_handle = self.run_in(self.on_delay_elapse,delay,config_name = config_name) + else: + self.prepare_coffee(config_name) + + def on_delay_elapse(self, kwargs): + self.delay_cb_handle = None + self.prepare_coffee(kwargs['config_name']) + + def prepare_coffee(self,config_name): + config = self.program_configs[config_name] + self.log_info(f"Preparing Coffee ({config_name})") + self.call_service("button/press", entity_id = config['button']) + self.call_service("button/press", entity_id = self.args['clear_program_button'])