Last active
November 20, 2025 21:30
-
-
Save adrianslabu/91bf7586484f2f1b3973de915d6a3891 to your computer and use it in GitHub Desktop.
03. Youtube - Turn a regular FAN into a SMART fan
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: fan-gym | |
| friendly_name: Fan Gym | |
| on_boot: | |
| - if: | |
| condition: | |
| switch.is_off: child_lock | |
| then: | |
| - lambda: |- | |
| if (id(switch_rotation).state) { id(rotation).turn_on(); } | |
| if (id(switch_speed_1).state) { id(fan_speed).publish_state(1); } | |
| else if (id(switch_speed_2).state) { id(fan_speed).publish_state(2); } | |
| else if (id(switch_speed_3).state) { id(fan_speed).publish_state(3); } | |
| else { id(fan_speed).publish_state(0); } | |
| else: | |
| - lambda: |- | |
| id(fan_speed).publish_state(0); | |
| esp32: | |
| board: esp32-c3-devkitm-1 | |
| framework: | |
| type: esp-idf | |
| switch: | |
| - platform: gpio | |
| name: "Speed 1" | |
| pin: | |
| number: GPIO1 | |
| inverted: true | |
| id: speed_1 | |
| internal: true | |
| - platform: gpio | |
| name: "Speed 2" | |
| pin: | |
| number: GPIO2 | |
| inverted: true | |
| id: speed_2 | |
| internal: true | |
| - platform: gpio | |
| name: "Speed 3" | |
| pin: | |
| number: GPIO3 | |
| inverted: true | |
| id: speed_3 | |
| internal: true | |
| - platform: gpio | |
| name: "Rotation" | |
| pin: | |
| number: GPIO4 | |
| inverted: true | |
| id: rotation | |
| icon: "mdi:rotate-360" | |
| - platform: template | |
| name: "Child Lock" | |
| id: child_lock | |
| icon: "mdi:lock" | |
| optimistic: true | |
| number: | |
| - platform: template | |
| name: "Speed" | |
| id: fan_speed | |
| min_value: 0 | |
| max_value: 3 | |
| step: 1 | |
| optimistic: true | |
| icon: "mdi:fan" | |
| on_value: | |
| then: | |
| - script.execute: set_fan_speed | |
| script: | |
| - id: set_fan_speed | |
| mode: restart | |
| then: | |
| - lambda: |- | |
| id(speed_1).turn_off(); id(speed_2).turn_off(); id(speed_3).turn_off(); | |
| - delay: 200ms | |
| - lambda: |- | |
| if (id(fan_speed).state == 0) { id(rotation).turn_off(); id(fan_state).publish_state("Off"); } | |
| else if (id(fan_speed).state == 1) { id(speed_1).turn_on(); id(fan_state).publish_state("On"); } | |
| else if (id(fan_speed).state == 2) { id(speed_2).turn_on(); id(fan_state).publish_state("On"); } | |
| else if (id(fan_speed).state == 3) { id(speed_3).turn_on(); id(fan_state).publish_state("On"); } | |
| text_sensor: | |
| - platform: template | |
| name: "Fan State" | |
| id: fan_state | |
| update_interval: never | |
| binary_sensor: | |
| - platform: gpio | |
| pin: | |
| number: GPIO5 | |
| mode: INPUT_PULLDOWN | |
| id: switch_speed_1 | |
| internal: true | |
| on_state: | |
| - if: | |
| condition: | |
| switch.is_off: child_lock | |
| then: | |
| - lambda: |- | |
| if (id(switch_speed_1).state) { id(fan_speed).publish_state(1); } | |
| - delay: 100ms | |
| - lambda: |- | |
| if (id(switch_rotation).state) { id(rotation).turn_on(); } | |
| else { id(rotation).turn_off(); } | |
| - platform: gpio | |
| pin: | |
| number: GPIO6 | |
| mode: INPUT_PULLDOWN | |
| id: switch_speed_2 | |
| internal: true | |
| on_state: | |
| - if: | |
| condition: | |
| switch.is_off: child_lock | |
| then: | |
| - lambda: |- | |
| if (id(switch_speed_2).state) { id(fan_speed).publish_state(2); } | |
| - delay: 100ms | |
| - lambda: |- | |
| if (id(switch_rotation).state) { id(rotation).turn_on(); } | |
| else { id(rotation).turn_off(); } | |
| - platform: gpio | |
| pin: | |
| number: GPIO7 | |
| mode: INPUT_PULLDOWN | |
| id: switch_speed_3 | |
| internal: true | |
| on_state: | |
| - if: | |
| condition: | |
| switch.is_off: child_lock | |
| then: | |
| - lambda: |- | |
| if (id(switch_speed_3).state) { id(fan_speed).publish_state(3); } | |
| - delay: 100ms | |
| - lambda: |- | |
| if (id(switch_rotation).state) { id(rotation).turn_on(); } | |
| else { id(rotation).turn_off(); } | |
| - platform: gpio | |
| pin: | |
| number: GPIO10 | |
| mode: INPUT_PULLDOWN | |
| id: switch_rotation | |
| internal: true | |
| - platform: template | |
| id: switch_off_position | |
| internal: true | |
| lambda: |- | |
| if (!id(switch_speed_1).state && !id(switch_speed_2).state && !id(switch_speed_3).state && !id(switch_rotation).state) { | |
| return true; | |
| } else { | |
| return false; | |
| } | |
| on_state: | |
| - if: | |
| condition: | |
| switch.is_off: child_lock | |
| then: | |
| - lambda: |- | |
| if (x) { | |
| id(fan_speed).publish_state(0); | |
| } | |
| logger: | |
| api: | |
| encryption: | |
| key: "ey5yfd26+yxqREwtOwVlhEbM1eiic3biGjO/7Qs3SfQ=" | |
| ota: | |
| - platform: esphome | |
| password: "4734b8ad677b48692b628985192527fd" | |
| wifi: | |
| ssid: !secret wifi_ssid | |
| password: !secret wifi_password | |
| ap: | |
| ssid: "Fan-Gym Fallback Hotspot" | |
| password: "1VaxJ6FEF7Lj" | |
| 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
| - platform: template | |
| sensors: | |
| fan_gym_icon: | |
| value_template: > | |
| {% set nr = states('number.fan_gym_speed') | int %} | |
| {% if nr == 0 %} | |
| mdi:fan-off | |
| {% elif nr == 1 %} | |
| mdi:fan-speed-1 | |
| {% elif nr == 2 %} | |
| mdi:fan-speed-2 | |
| {% elif nr == 3 %} | |
| mdi:fan-speed-3 | |
| {% endif %} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment