substitutions:
  devicename: og-te-ro-sun
  friendly_name: og-te-ro-sun
  devicestring: Terrasse Rollo

esphome:
  name: ${devicename}
  platform: ESP8266
  board: nodemcuv2
  esp8266_restore_from_flash: true
  on_boot: 
    priority: 550.0
    then:
      # 1. Set stepper current position as stored in memory
      # 2. Present down value set for down_position (where is "down")
      # 3. If it is the same as down position, update the state of the switch
      - lambda: |-
            id(my_stepper).report_position(id(last_known_position));
            id(bed_down_pos).publish_state(id(down_position));
            if (id(last_known_position)==id(down_position)){
              id(rollerblind_bed_down).publish_state(true);
            }

globals:
  # The actual position of the rollerblind
  - id: last_known_position
    type: int
    restore_value: true
    initial_value: '1'
  # The number of steps to reach to the down position of the rollerblind
  - id: down_position
    type: int
    restore_value: true
    initial_value: '0'

# Enable logging
logger:
  level: DEBUG


# Enable Home Assistant API
api:
  encryption:
    key: "1b5VG2dp8E+p1b7tlxLILWbvArqOVdnlh0+/yZ9Irms="

ota:
  password: "ee384bfbcfc7b49c8d6e6632c19a8a36"

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

  manual_ip:
    static_ip: 192.168.1.195
    gateway: 192.168.1.1
    subnet: 255.255.255.0
    
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "${devicename}"
    password: "iyoRMuoMH8Wi"

captive_portal:

stepper:
  - platform: uln2003
    id: my_stepper
    # Reversed order as it turned the wrong way
#    pin_a: D4
#    pin_b: D2
#    pin_c: D3
#    pin_d: D1

    pin_a: D1
    pin_b: D2
    pin_c: D3
    pin_d: D4
    max_speed: 675 steps/s
    sleep_when_done: true

    # Optional:
    acceleration: inf
    deceleration: inf

sensor:
  - platform: wifi_signal
    name: "${devicename} Wi-Fi Signal"
    update_interval: 60s

  - platform: uptime
    name: "${devicename} Uptime"
    update_interval: 60s

  - platform: template
    name: $devicestring Down position
    id: bed_down_pos
    
  - platform: template
    name: $devicestring Percentage position
    id: bed_perc_pos

  - platform: template
    name: $devicestring Last position
    id: bed_last_pos

switch:
  - platform: restart
    name: "${devicename} Neustart"

  # Save current position to 0
  - platform: template
    name: $devicestring Save Top Position
    id: reset_switch
    turn_on_action:
      then:
        # Reset DOWN
        - switch.template.publish:
            id: move_down
            state: OFF
        # Reset UP
        - switch.template.publish:
            id: move_up
            state: OFF
        # Reset stepper position
        - stepper.report_position:
            id: my_stepper
            position: 0
        - stepper.set_target:
            id: my_stepper
            target: 0
        # Save global variable for reboot
        - lambda: |-
            id(last_known_position) = 0;
  # Save current position to max down
  - platform: template
    name: $devicestring Save Down Position
    id: save_down_switch
    turn_on_action:
      then:
        # Reset DOWN
        - switch.template.publish:
            id: move_down
            state: OFF
        # Reset UP
        - switch.template.publish:
            id: move_up
            state: OFF
        # Save global variable for reboot down_position
        # Save current position
        # Update sensor with stored value
        # Set position as in DOWN state (switch)
        - lambda: |-
            id(down_position) = id(my_stepper).current_position;
            id(last_known_position) = id(down_position);
            id(bed_down_pos).publish_state(id(down_position));
            id(rollerblind_bed_down).publish_state(true);
            id(bed_last_pos).publish_state(id(last_known_position));
#            id(bed_perc_pos).publish_state((id(down_position) / id(last_known_position)) * 100);
        - logger.log:
            format: "Saving down position %.1i"
            args: [ 'id(down_position)']

  - platform: template
    name: $devicestring Down
    id: move_down
    turn_on_action:
      # Enable switch
      - switch.template.publish:
          id: move_down
          state: ON
      # Reset back
      - switch.template.publish:
          id: move_up
          state: OFF
      # Reset master
      - switch.template.publish:
          id: rollerblind_bed_down
          state: OFF  
      # Set current position to last_known
      - lambda: |-
          id(down_position) = id(my_stepper).current_position;
          id(last_known_position) = id(down_position);
          id(bed_down_pos).publish_state(id(down_position));
          id(rollerblind_bed_down).publish_state(true);
          id(last_known_position) = id(my_stepper).current_position;
          id(bed_last_pos).publish_state(id(last_known_position));
#          id(bed_perc_pos).publish_state((id(down_position) / id(last_known_position)) * 100);
      # Set to move long
      - lambda: |-
          id(my_stepper).set_target(1000000);
    turn_off_action:
      - switch.template.publish:
          id: move_down
          state: OFF
      # Stop motor and report position
      - lambda: |-
          id(last_known_position) = id(my_stepper).current_position;
          id(my_stepper).set_target(id(last_known_position));
          id(bed_last_pos).publish_state(id(last_known_position));
#          id(bed_perc_pos).publish_state((id(down_position) / id(last_known_position)) * 100);
      - logger.log:
          format: "Current position (down) %.1i"
          args: [ 'id(last_known_position)']

  - platform: template
    name: $devicestring Up
    id: move_up
    turn_on_action:
      # Enable switch
      - switch.template.publish:
          id: move_up
          state: ON
      # Reset down
      - switch.template.publish:
          id: move_down
          state: OFF
      # Reset master
      - switch.template.publish:
          id: rollerblind_bed_down
          state: OFF
      # Set current position to last_known
      - lambda: |-
          id(last_known_position) = id(my_stepper).current_position;
          id(bed_last_pos).publish_state(id(last_known_position));
#          id(bed_perc_pos).publish_state((id(down_position) / id(last_known_position)) * 100);
      # Set to move long
      - lambda: |-
          id(my_stepper).set_target(-1000000);
    turn_off_action:
      - switch.template.publish:
          id: move_up
          state: OFF
      # Stop motor and report position
      - lambda: |-
          id(last_known_position) = id(my_stepper).current_position;
          id(my_stepper).set_target(id(last_known_position));
          id(bed_last_pos).publish_state(id(last_known_position));
#          id(bed_perc_pos).publish_state((id(down_position) / id(last_known_position)) * 100);
      - logger.log:
          format: "Current position (up) %.1i"
          args: [ 'id(last_known_position)']

  - platform: template
    name: $devicestring Closed
    id: rollerblind_bed_down
    turn_on_action:
      # Reset DOWN and UP manual
      - switch.template.publish:
          id: move_up
          state: OFF
      - switch.template.publish:
          id: move_down
          state: OFF
      # Enable switch
      - switch.template.publish:
          id: rollerblind_bed_down
          state: ON
      # Set last_known_position to the final position
      #   It might not necessarily be the final position and
      #   Can be a challenge if power breaks upon moving
      - lambda: |-
          id(last_known_position) = id(down_position);
          id(my_stepper).set_target(id(down_position));
          id(bed_last_pos).publish_state(id(last_known_position));
#          id(bed_perc_pos).publish_state(round((id(down_position) / id(last_known_position)) * 100));
    turn_off_action:
      - switch.template.publish:
          id: rollerblind_bed_down
          state: OFF
      # Set last_known_position to the start position (0)
      #   It might not necessarily be the start position and
      #   Can be a challenge if power breaks upon moving
      - lambda: |-
          id(last_known_position) = 0;
          id(my_stepper).set_target(0);
          id(bed_last_pos).publish_state(id(last_known_position));
#          id(bed_perc_pos).publish_state(round((id(down_position) / id(last_known_position)) * 100));

# On a regular basis store the position of the roller blind
#   Don't do it too frequently as it might impact the move of the blind
time:
  - platform: sntp
    id: sntp_time
    on_time:
      # Every 5 minutes
      - seconds: 0
        minutes: /5
        then:
          - lambda: |-
              id(last_known_position) = id(my_stepper).current_position;
              id(bed_last_pos).publish_state(id(last_known_position));
#              id(bed_perc_pos).publish_state((id(down_position) / id(last_known_position)) * 100);

# Example configuration entry
cover:
  - platform: template
    name: "OG_te_RO_sun"
    lambda: |-
      if (id(rollerblind_bed_down).state) {
        return COVER_CLOSED;
      } else {
        return COVER_OPEN;
      }
    open_action:
      - switch.turn_off: rollerblind_bed_down
    close_action:
      - switch.turn_on: rollerblind_bed_down
    stop_action:
      - switch.turn_off: move_up
      - switch.turn_off: move_down
    optimistic: true