Last active
January 21, 2026 00:43
-
-
Save adrianslabu/0a163a38edfc684fc3a2d6e42b6f9e7e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| esphome: | |
| name: smart-cafe | |
| friendly_name: Smart Cafe | |
| on_boot: | |
| priority: -100 | |
| then: | |
| - lambda: |- | |
| if (id(cold_lever).state) { | |
| id(lever_state).publish_state("Cold"); | |
| } else if (id(hot_lever).state) { | |
| id(lever_state).publish_state("Hot"); | |
| } else if (id(off_lever).state) { | |
| id(lever_state).publish_state("Off"); | |
| } | |
| id(script_running).publish_state("False"); | |
| if (id(light_sensor).state > 0.014) { | |
| id(device_state).publish_state(true); | |
| } else { | |
| id(device_state).publish_state(false); | |
| } | |
| esp32: | |
| board: esp32-c3-devkitm-1 | |
| framework: | |
| type: esp-idf | |
| output: | |
| - platform: gpio | |
| pin: GPIO1 | |
| id: power_pin | |
| button: | |
| - platform: template | |
| name: "Power" | |
| id: power | |
| on_press: | |
| - if: | |
| condition: | |
| lambda: 'return id(device_state).state;' | |
| then: | |
| - lambda: |- | |
| if (id(valve_mode).current_option() != "Off") { id(valve_mode).publish_state("Off"); } | |
| - delay: 100ms | |
| - output.turn_on: power_pin | |
| - delay: 100ms | |
| - output.turn_off: power_pin | |
| else: | |
| - output.turn_on: power_pin | |
| - delay: 100ms | |
| - output.turn_off: power_pin | |
| - delay: 100ms | |
| - lambda: |- | |
| if (id(valve_mode).current_option() != "Off") { id(valve_mode).publish_state("Off"); } | |
| - platform: template | |
| id: blue_btn | |
| name: "Blue Button" | |
| on_press: | |
| - lambda: |- | |
| if (id(child_lock).state) { | |
| } else { | |
| std::string button = "blue"; | |
| if (id(script_running).state == "True") { | |
| button = "off"; | |
| } | |
| if (id(device_state).state) { | |
| id(buttons_script).execute(button); | |
| } | |
| } | |
| - platform: template | |
| id: yellow_btn | |
| name: "Yellow Button" | |
| on_press: | |
| - lambda: |- | |
| if (id(child_lock).state) { | |
| } else { | |
| std::string button = "yellow"; | |
| if (id(script_running).state == "True") { | |
| button = "off"; | |
| } | |
| if (id(device_state).state) { | |
| id(buttons_script).execute(button); | |
| } | |
| } | |
| - platform: template | |
| id: red_btn | |
| name: "Red Button" | |
| on_press: | |
| - lambda: |- | |
| if (id(child_lock).state) { | |
| } else { | |
| std::string button = "red"; | |
| if (id(script_running).state == "True") { | |
| button = "off"; | |
| } | |
| if (id(device_state).state) { | |
| id(buttons_script).execute(button); | |
| } | |
| } | |
| switch: | |
| - platform: gpio | |
| name: "Hot Valve" | |
| id: hot_valve | |
| pin: GPIO2 | |
| interlock: [ cold_valve ] | |
| restore_mode: ALWAYS_OFF | |
| internal: False | |
| - platform: gpio | |
| name: "Cold Valve" | |
| id: cold_valve | |
| pin: GPIO3 | |
| interlock: [ hot_valve ] | |
| restore_mode: ALWAYS_OFF | |
| internal: False | |
| - platform: template | |
| name: "Child Lock" | |
| id: child_lock | |
| optimistic: true | |
| restore_mode: ALWAYS_OFF | |
| select: | |
| - platform: template | |
| name: "Valve" | |
| id: valve_mode | |
| optimistic: true | |
| options: | |
| - "Off" | |
| - "Cold" | |
| - "Hot" | |
| on_value: | |
| - if: | |
| condition: | |
| lambda: 'return x == "Off";' | |
| then: | |
| - switch.turn_off: cold_valve | |
| - switch.turn_off: hot_valve | |
| - if: | |
| condition: | |
| lambda: 'return x == "Cold";' | |
| then: | |
| - switch.turn_off: hot_valve | |
| - switch.turn_on: cold_valve | |
| - if: | |
| condition: | |
| lambda: 'return x == "Hot";' | |
| then: | |
| - switch.turn_off: cold_valve | |
| - switch.turn_on: hot_valve | |
| number: | |
| - platform: template | |
| id: blue_time | |
| name: "Blue Button Time" | |
| min_value: 1 | |
| max_value: 60 | |
| step: 1 | |
| optimistic: true | |
| restore_value: true | |
| initial_value: 30 | |
| - platform: template | |
| id: yellow_time | |
| name: "Yellow Button Time" | |
| min_value: 1 | |
| max_value: 60 | |
| step: 1 | |
| optimistic: true | |
| restore_value: true | |
| initial_value: 10 | |
| - platform: template | |
| id: red_time | |
| name: "Red Button Time" | |
| min_value: 1 | |
| max_value: 60 | |
| step: 1 | |
| optimistic: true | |
| restore_value: true | |
| initial_value: 13 | |
| binary_sensor: | |
| - platform: gpio | |
| pin: | |
| number: GPIO5 | |
| mode: INPUT_PULLDOWN | |
| id: cold_lever | |
| internal: true | |
| on_state: | |
| lambda: |- | |
| if (id(cold_lever).state) { | |
| id(lever_state).publish_state("Cold"); | |
| } | |
| - platform: gpio | |
| pin: | |
| number: GPIO6 | |
| mode: INPUT_PULLDOWN | |
| id: hot_lever | |
| internal: true | |
| on_state: | |
| lambda: |- | |
| if (id(hot_lever).state) { | |
| id(lever_state).publish_state("Hot"); | |
| } | |
| - platform: template | |
| id: off_lever | |
| internal: true | |
| lambda: |- | |
| return !id(cold_lever).state && !id(hot_lever).state; | |
| on_state: | |
| then: | |
| - lambda: |- | |
| if (id(off_lever).state) { | |
| id(lever_state).publish_state("Off"); | |
| } | |
| - platform: gpio | |
| pin: | |
| number: GPIO4 | |
| mode: INPUT_PULLDOWN | |
| id: blue_button | |
| internal: true | |
| on_press: | |
| - button.press: blue_btn | |
| - platform: gpio | |
| pin: | |
| number: GPIO7 | |
| mode: INPUT_PULLDOWN | |
| id: yellow_button | |
| internal: true | |
| on_press: | |
| - button.press: yellow_btn | |
| - platform: gpio | |
| pin: | |
| number: GPIO10 | |
| mode: INPUT_PULLDOWN | |
| id: red_button | |
| internal: true | |
| on_press: | |
| - button.press: red_btn | |
| - platform: template | |
| id: device_state | |
| name: "State" | |
| sensor: | |
| - platform: adc | |
| pin: GPIO0 | |
| id: light_sensor | |
| name: "Light Sensor" | |
| update_interval: 0.1s | |
| internal: True | |
| filters: | |
| - exponential_moving_average: | |
| alpha: 0.1 | |
| send_every: 1 | |
| on_value_range: | |
| - above: 0.014 | |
| then: | |
| - delay: 500ms | |
| - if: | |
| condition: | |
| sensor.in_range: | |
| id: light_sensor | |
| above: 0.014 | |
| then: | |
| - binary_sensor.template.publish: | |
| id: device_state | |
| state: ON | |
| - below: 0.013 | |
| then: | |
| - delay: 500ms | |
| - if: | |
| condition: | |
| sensor.in_range: | |
| id: light_sensor | |
| below: 0.013 | |
| then: | |
| - binary_sensor.template.publish: | |
| id: device_state | |
| state: OFF | |
| text_sensor: | |
| - platform: template | |
| id: lever_state | |
| name: "Lever State" | |
| update_interval: never | |
| - platform: template | |
| id: script_running | |
| name: "Script Running" | |
| update_interval: never | |
| - platform: template | |
| id: active_button | |
| name: "Active Button" | |
| update_interval: never | |
| script: | |
| - id: buttons_script | |
| mode: restart | |
| parameters: | |
| button: string | |
| then: | |
| - lambda: |- | |
| if (id(script_running).state == "True") { | |
| id(valve_mode).publish_state("Off"); | |
| id(script_running).publish_state("False"); | |
| return; | |
| } | |
| if (id(lever_state).state == "Cold") { | |
| id(valve_mode).publish_state("Cold"); | |
| } else if (id(lever_state).state == "Hot") { | |
| id(valve_mode).publish_state("Hot"); | |
| } else { | |
| id(script_running).publish_state("False"); | |
| return; | |
| } | |
| id(script_running).publish_state("True"); | |
| if (button == "blue") { | |
| id(active_button).publish_state("Blue"); | |
| } else if (button == "yellow") { | |
| id(active_button).publish_state("Yellow"); | |
| } else if (button == "red") { | |
| id(active_button).publish_state("Red"); | |
| } else { | |
| id(active_button).publish_state("Idle"); | |
| } | |
| - delay: !lambda 'return (button == "blue") ? id(blue_time).state * 1000 : (button == "yellow") ? id(yellow_time).state * 1000 : (button == "red") ? id(red_time).state * 1000 : 0;' | |
| - lambda: |- | |
| id(valve_mode).publish_state("Off"); | |
| id(script_running).publish_state("False"); | |
| id(active_button).publish_state("Idle"); | |
| # Enable logging | |
| logger: | |
| # Enable Home Assistant API | |
| api: | |
| encryption: | |
| key: "your key" | |
| ota: | |
| - platform: esphome | |
| password: "your password" | |
| wifi: | |
| ssid: !secret wifi_ssid | |
| password: !secret wifi_password | |
| # Enable fallback hotspot (captive portal) in case wifi connection fails | |
| ap: | |
| ssid: "Smart-Cafe Fallback Hotspot" | |
| password: "W0a33gCSdq3x" | |
| captive_portal: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| type: vertical-stack | |
| cards: | |
| - type: custom:bubble-card | |
| card_type: pop-up | |
| hash: "#smartcafe" | |
| name: SmartCafe | |
| icon: mdi:coffee-maker-outline | |
| button_type: name | |
| show_header: true | |
| show_icon: true | |
| show_name: true | |
| styles: > | |
| .bubble-button-card-container { border-radius: 14px; background: none | |
| !important; } | |
| .bubble-icon { | |
| --mdc-icon-size: 50px !important; | |
| } | |
| .bubble-icon-container { | |
| background: none; | |
| } | |
| .bubble-pop-up { | |
| background: radial-gradient(ellipse at bottom, red, blue); | |
| } | |
| card_layout: normal | |
| modules: | |
| - "!default" | |
| - "!opacity" | |
| sub_button: | |
| main: [] | |
| bottom: [] | |
| - type: custom:bubble-card | |
| card_type: separator | |
| styles: | | |
| .bubble-line { | |
| background: var(--primary-text-color); | |
| opacity: 0.1; | |
| } | |
| name: Buttons | |
| - type: custom:bubble-card | |
| card_type: button | |
| button_type: state | |
| name: Power | |
| show_state: true | |
| icon: mdi:power | |
| show_attribute: false | |
| force_icon: false | |
| entity: binary_sensor.smart_cafe_state | |
| tap_action: | |
| action: none | |
| button_action: | |
| tap_action: | |
| action: perform-action | |
| perform_action: button.press | |
| target: | |
| entity_id: button.smart_cafe_power | |
| sub_button: | |
| - entity: sensor.smart_cafe_lever_state | |
| show_state: true | |
| show_name: true | |
| name: Lever | |
| icon: mdi:dip-switch | |
| tap_action: | |
| action: none | |
| - entity: switch.smart_cafe_child_lock | |
| icon: mdi:lock-open-variant | |
| state_background: false | |
| show_background: false | |
| name: Child Lock | |
| show_name: true | |
| show_state: true | |
| tap_action: | |
| action: toggle | |
| styles: |- | |
| { | |
| .bubble-button-card-container { | |
| background-color: ${hass.states['binary_sensor.smart_cafe_state'].state === 'on' ? '#056bb8' : ''} !important; | |
| } | |
| ${subButtonIcon[1].setAttribute( | |
| "icon", | |
| hass.states['switch.smart_cafe_child_lock'].state === 'on' | |
| ? 'mdi:lock' | |
| : 'mdi:lock-open-variant' | |
| )} | |
| - type: horizontal-stack | |
| cards: | |
| - type: custom:bubble-card | |
| card_type: button | |
| button_type: switch | |
| entity: button.smart_cafe_blue_button | |
| name: Blue | |
| show_state: false | |
| icon: mdi:button-pointer | |
| show_attribute: false | |
| force_icon: false | |
| styles: |- | |
| { | |
| .bubble-button-card-container { | |
| background-color: ${hass.states['sensor.smart_cafe_active_button'].state === 'Blue' ? '#056bb8' : ''} !important; | |
| } | |
| .bubble-icon { | |
| color: #056bb8 !important; | |
| } | |
| - type: custom:bubble-card | |
| card_type: button | |
| button_type: slider | |
| show_state: true | |
| icon: mdi:tune-variant | |
| entity: number.smart_cafe_blue_button_time | |
| force_icon: true | |
| show_icon: true | |
| scrolling_effect: true | |
| name: Blue Button Time | |
| - type: horizontal-stack | |
| cards: | |
| - type: custom:bubble-card | |
| card_type: button | |
| button_type: switch | |
| name: Yellow | |
| show_state: false | |
| icon: mdi:button-pointer | |
| show_attribute: false | |
| force_icon: false | |
| entity: button.smart_cafe_yellow_button | |
| styles: |- | |
| { | |
| .bubble-button-card-container { | |
| background-color: ${hass.states['sensor.smart_cafe_active_button'].state === 'Yellow' ? '#056bb8' : ''} !important; | |
| } | |
| .bubble-icon { | |
| color: yellow !important; | |
| } | |
| - type: custom:bubble-card | |
| card_type: button | |
| button_type: slider | |
| show_state: true | |
| icon: mdi:tune-variant | |
| force_icon: true | |
| show_icon: true | |
| scrolling_effect: true | |
| name: Yellow Button Time | |
| entity: number.smart_cafe_yellow_button_time | |
| - type: horizontal-stack | |
| cards: | |
| - type: custom:bubble-card | |
| card_type: button | |
| button_type: switch | |
| name: Red | |
| show_state: false | |
| icon: mdi:button-pointer | |
| show_attribute: false | |
| force_icon: false | |
| entity: button.smart_cafe_red_button | |
| styles: |- | |
| { | |
| .bubble-button-card-container { | |
| background-color: ${hass.states['sensor.smart_cafe_active_button'].state === 'Red' ? '#056bb8' : ''} !important; | |
| } | |
| .bubble-icon { | |
| color: red !important; | |
| } | |
| - type: custom:bubble-card | |
| card_type: button | |
| button_type: slider | |
| show_state: true | |
| icon: mdi:tune-variant | |
| force_icon: true | |
| show_icon: true | |
| scrolling_effect: true | |
| name: Red Button Time | |
| entity: number.smart_cafe_red_button_time | |
| - type: custom:bubble-card | |
| card_type: separator | |
| styles: | | |
| .bubble-line { | |
| background: var(--primary-text-color); | |
| opacity: 0.1; | |
| } | |
| name: Valves | |
| - type: horizontal-stack | |
| cards: | |
| - type: custom:bubble-card | |
| card_type: button | |
| show_state: true | |
| icon: mdi:coach-lamp | |
| button_type: switch | |
| entity: switch.smart_cafe_hot_valve | |
| name: Hot Valve | |
| - type: custom:bubble-card | |
| card_type: button | |
| button_type: switch | |
| name: Cold Valve | |
| show_state: true | |
| icon: mdi:ceiling-light-multiple-outline | |
| entity: switch.smart_cafe_cold_valve | |
| grid_options: | |
| columns: 12 | |
| rows: auto |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment