Sonoff Ifan04 - ESPHome working code

@devjklein: Here is a modified version that when the fan is off, will start the fan on high for 5 seconds then switch to the target speed. I also modified the relay sequence to speed 1 is relay 1 only, speed 2 is relay 2 only and speed 3 is relay 3 only.

yaml

substitutions:
  name:  living-room-fan
  device_description: Sonoff iFan04-L
  friendly_name: Living Room Fan/Light

globals:
  - id: target_fan_speed
    type: int
  - id: start_time_offset
    type: int

esphome:
  name: ${name}
  comment: ${device_description}
  platform: ESP8266
  board: esp01_1m
  on_boot:
    priority: 225
    # turn off the light as early as possible
    then:
      - light.turn_off: fan_light
  on_loop:
    lambda: |-
      if (id(start_time_offset) && (millis() > id(start_time_offset))) {
        ESP_LOGD("IFAN04", "Delayed wakeup to select final target speed: %d", id(target_fan_speed));
        auto call = id(the_fan).turn_on();
        call.set_speed(id(target_fan_speed));
        call.perform();
        id(start_time_offset) = 0;
      }

# Disable logging on serial as it is used by the remote
logger:
  baud_rate: 0

# Enable Home Assistant API
api:

ota:
  password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  fast_connect: on

web_server:
  port: 80
  auth:
    username: !secret web_server_username
    password: !secret web_server_password
  
external_components:
  - source: github://ssieb/custom_components
    components: [ ifan04 ]

time:
  - platform: homeassistant
    id: time_homeassistant
    on_time_sync:
      - component.update: sensor_uptime_timestamp

uart:
  tx_pin: GPIO01
  rx_pin: GPIO03
  baud_rate: 9600
#  debug:
#    sequence:
#      - lambda: UARTDebug::log_hex(direction, bytes, ',');

ifan04:
  on_fan:
    - lambda: |-
        if (speed) {
          if (!id(target_fan_speed)) {
            ESP_LOGD("IFAN04", "Fan currently off, starting on max reducing to %d in 5 seconds", speed);
            id(target_fan_speed) = speed;
            speed = 3;
            id(start_time_offset) = millis() + 5000;
          } else {
            ESP_LOGD("IFAN04", "Fan already running, current speed (%d) new speed: (%d)", id(target_fan_speed), speed);
            id(start_time_offset) = 0;
            id(target_fan_speed) = speed;
          }
          auto call = id(the_fan).turn_on();
          call.set_speed(speed);
          call.perform();
          if (id(buzzer_dummy).state) {
            switch(id(target_fan_speed)) {
              case 3:
                id(buzzer_pin).turn_on();
                delay(50);
                id(buzzer_pin).turn_off();
                delay(50);
              case 2:
                id(buzzer_pin).turn_on();
                delay(50);
                id(buzzer_pin).turn_off();
                delay(50);
              case 1:
                id(buzzer_pin).turn_on();
                delay(50);
                id(buzzer_pin).turn_off();
            }
          }
        } else {
          id(target_fan_speed) = 0;
          id(start_time_offset) = 0;
          auto call = id(the_fan).turn_off();
          call.perform();
        }
  on_light:
    - light.toggle: fan_light
  on_buzzer:
    - switch.toggle: buzzer_dummy

sensor:
  - platform: uptime
    id: sensor_uptime

  - platform: template
    id: sensor_uptime_timestamp
    name: "${friendly_name} Uptime"
    device_class: "timestamp"
    accuracy_decimals: 0
    update_interval: never
    lambda: |-
      static float timestamp = (
        id(time_homeassistant).utcnow().timestamp - id(sensor_uptime).state
      );
      return timestamp;

  - platform: wifi_signal
    name: ${friendly_name} Signal
    update_interval: 60s

binary_sensor:
  - platform: gpio
    id: button
    pin: GPIO0
    on_press:
      then:
        - light.toggle: fan_light

interval:
  - interval: 500ms
    then:
      - if:
          condition:
            not:
              wifi.connected:
          then:
            - light.turn_on:
                id: led1
                brightness: 100%
                transition_length: 0s
            - delay: 250ms
            - light.turn_off:
                id: led1
                transition_length: 250ms

output:
  - platform: template
    id: fanoutput
    type: float
    write_action:
      - if:
          condition:
            lambda: return (state < 0.3);
          then:
            # OFF
            - switch.turn_off: fan_relay1
            - switch.turn_off: fan_relay2
            - switch.turn_off: fan_relay3
          else:
            if:
              condition:
                lambda: return (state < 0.6);
              then:
                # low speed
                - switch.turn_on: fan_relay1
                - switch.turn_off: fan_relay2
                - switch.turn_off: fan_relay3
              else:
                if:
                  condition:
                    lambda: return (state < 0.9);
                  then:
                    # medium speed
                    - switch.turn_off: fan_relay1
                    - switch.turn_on: fan_relay2
                    - switch.turn_off: fan_relay3

                  else:
                    # high speed
                    - switch.turn_off: fan_relay1
                    - switch.turn_off: fan_relay2
                    - switch.turn_on: fan_relay3

  - platform: gpio
    id: light_relay
    pin: GPIO9
    inverted: true

  - platform: gpio
    id: buzzer_pin
    pin: GPIO10
    inverted: true

  - platform: esp8266_pwm
    id: led_pin
    pin: GPIO13
    inverted: true

light:
  - platform: binary
    id: fan_light
    name: "${friendly_name} Light"
    output: light_relay

  - platform: monochromatic
    id: led1
    output: led_pin
    default_transition_length: 0s
    restore_mode: always off

switch:
  - platform: restart
    name: "${friendly_name} Restart"
    
  - platform: template
    id: buzzer_dummy
    name: "Buzzer"
    optimistic: True

  - platform: gpio
    id: fan_relay1
    pin: GPIO14

  - platform: gpio
    id: fan_relay2
    pin: GPIO12

  - platform: gpio
    id: fan_relay3
    pin: GPIO15

fan:
  - platform: speed
    id: the_fan
    name: "${friendly_name} Fan"
    output: fanoutput
    speed_count: 3
2 Likes