Gate controller using cover

So here’s the thing,

I am a long time (more than 10 years now) Arduino hobbyist and I am having trouble wrapping my mind around ESPhome though I am totally into it…

I can set pretty much anything up but setting interdependencies between them is causing me issues. Normally I would just set a loop to read everything, then put all the values into variables, then another loop to evaluate those input variables, producing output variables that I use another loop to change the physical states of all the output pins. There seems to be implicit behavior built into the esphome modules that I do not understand.

Project setup
I have an Apollo gate control. Basically it does one thing. on a press (connecting a sig to gnd on the board) the gate opens. another press results in the gate closing.
1 output
4 inputs, closed switch, open switch, motor open and motor close.
So I reused an old project for a water timer to start this. I have actually managed to get most of it working except I can’t get the timer to start based on the condition of one of the binary sensors.


I need to start the gate close timer (the time the gate will remain open before shutting automatically) at the point the gate fully opens (gateisopen goes high) rather than at the point of activating the template switch. code is below. Please know I don’t really know what I am doing here and since I can’t just make a bunch of loops to do the jobs I need done, like Arduino, I probably am missing some very fundamental understandings here.

code below

###############################subs###############################
substitutions:
  devicename: gatecontrol ##this will be the device name like "water_station_1" "outdoor_light_5"
  purpose: entry ##this will be the purpose of the switch like recirculation, illumination, or irrigation
  subject: gate  ## this is what its interface is acting on like "garden", "water heater", or "zone_1"
  outputpin: GPIO05 #D01 #output wire
  gateisclosed: GPIO04 #D02 #orange wire 5v
  gateisopen: GPIO13 #D07 #white wire 5v
  gateisopening: GPIO12 #D06 #black wire 12v
  gateisclosing: GPIO14 #D05 #red wire 12v
##################################################################
packages:
  device_base: !include /config/esphome/common/eas8266common.yaml  # wifisig/uptime/status

esphome:
  name: $devicename


esp8266:
  board: d1_mini

mdns:
  disabled: false

# Enable logging
logger:
  level: DEBUG

# Enable Home Assistant API
api:

ota:
  password: ""

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  domain: .local
  fast_connect: true

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Gatecontrol Fallback Hotspot"
    password: "HMzrqenCwpHt"

captive_portal:



globals:

  - id: gatestate
    type: int
    restore_value: no
    
# 1 is fully closed 2 is opening, 3 is fully open and 4 is closing 
    
  # ============================================================================= #
   # Irrigation time remaining
  - id: remaining_time_1
    type: int
    restore_value: no
    initial_value: "0"
  # Store previous values to verify change.
  - id: remaining_time_1_previous
    type: int
    restore_value: no
    initial_value: "0"
#===============================================================================#    
  - id: runonce
    type: bool
    initial_value: "false"

    
#################self contained onoff for gate===================

switch:  
  - platform: gpio
    pin: $outputpin
    id: ${devicename}_${subject}_switch
    name: "Gate Control Switch"
    icon: "mdi:gate"
    on_turn_on:
    - delay: 500ms
    - switch.toggle: ${devicename}_${subject}_switch


############################################################

###########template switch functions##############

  - platform: template
    id: ${devicename}_${subject}_open_close
    name: "Gate Remote Open/Close"
    icon: "mdi:gate"
    optimistic: true
    on_turn_on:
      then:
        if:
          condition:
            lambda: 'return id(${purpose}_${subject}_duration).state > 0 && (id(${subject}_open_switch) == 1);'
          then:
        # Start the countdown timer.
            - globals.set:
                id: remaining_time_1
                value: !lambda return (id(${purpose}_${subject}_duration).state);
        # Show the remaining time.
            - sensor.template.publish:
                id: ${purpose}_${subject}_remaining
                state: !lambda return id(${purpose}_${subject}_duration).state;
            - switch.toggle: ${devicename}_${subject}_switch
    on_turn_off:
      - switch.toggle: ${devicename}_${subject}_switch
      

############################################




################switch sensors####################


binary_sensor:   
  - platform: gpio
    pin: 
      number: $gateisopen
      id: ${subject}_open_switch
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Gate is open"


  - platform: gpio
    pin: 
      number: $gateisclosed
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Gate is closed"
##################################################

#############Motor running sensors################
    
  - platform: gpio
    pin: 
      number: $gateisopening
      id: ${subject}_opening_motor
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Gate is opening"
    
  - platform: gpio
    pin: 
      number: $gateisclosing
      id: ${subject}_closing_motor
      mode:
        input: true
        pullup: true
      inverted: true
    name: "Gate is closing"
##################################################    


sensor:
  # ============================================================================= #
  # Retrieve durations settings from the Home Assistant UI.
  - platform: homeassistant
    id: ui_${subject}_duration
    entity_id: input_number.${purpose}_${subject}_duration
    on_value:
      #if:
      #  condition:
      #    api.connected:
      then:
        - sensor.template.publish:
            id: ${purpose}_${subject}_duration
            state: !lambda return id(ui_${subject}_duration).state;
  # ============================================================================= #
  # Store durations so if HA cant be reached the last value still remains
  - platform: template
    name: ${purpose} duration - ${subject}
    id: ${purpose}_${subject}_duration
    accuracy_decimals: 0
    unit_of_measurement: sec
    icon: mdi:camera-timer
  # ============================================================================= #
  # Countdown sensors.
  - platform: template
    name: Remaining Time - ${subject}
    id: ${purpose}_${subject}_remaining
    #lambda: "return 0;"
    accuracy_decimals: 0
    unit_of_measurement: sec
    icon: mdi:timer
    #on_value:
    #  then:
    #    - if:
    #        condition:
    #          lambda: return id(remaining_time_1) == 0;
    #        then:
    #         - switch.toggle: ${devicename}_${subject}_switch

###############################virtual visual indicator lights#######################

  - platform: template
    name: ${subject} Status
    id: ${purpose}_${subject}_status

cover:
  - platform: template
    name: "Main Gate"
    device_class: Gate

    open_action:
      # Cancel any previous action
      - switch.toggle: ${devicename}_${subject}_switch

    close_action:
      - switch.toggle: ${devicename}_${subject}_switch
      
    stop_action:
      - switch.toggle: ${devicename}_${subject}_switch
    optimistic: true
    assumed_state: true
# Update the countdown timers every 1 seconds.
interval:
  - interval: 1s
    then:
      - lambda: |-
          if (id(remaining_time_1) > 0) {
            // Store the previous time.
            id(remaining_time_1_previous) = id(remaining_time_1);
          }
            
            // When the open/close switch is on.
          if (id(${devicename}_${subject}_open_close).state) {
            if (id(${subject}_open_switch)) {
              // Decrement the timer.
              id(remaining_time_1) -= 1;
                if (id(remaining_time_1) <= 0) {
                  id(remaining_time_1) = 0;
                  id(${devicename}_${subject}_open_close).turn_off();
              }
            }
          }     
               // Update the remaining time display.
          if (id(remaining_time_1_previous) != id(remaining_time_1)) {
              id(${purpose}_${subject}_remaining).publish_state( (id(remaining_time_1) ) );
              }


Endstop Cover

1 Like

Right, and that looks exactly what I need, except the switches I need are just indicators of position. My gate controller isn’t actually going to be stopping the gate, that happens internally. What I need is something that I can use to open stop, close or “open/wait/close” with the wait controlled by a slider in HA but all timers internal to ESphome. I got the slider and countdown part working sorta, however right here
In my lambda I am trying to start the gate countdown after the gate is opened so the timer doesn’t decrement until the gate has reached fully open position.

If I flip the open/close template switch <initial user action
then Lambda
If timer slider ${purpose}_${subject}_duration has a value > than 0 AND ${subject}_open_switch has become +V then put the duration value into global variable remaining_time_1

This however fails to compile and appears to have trouble with &&

I know this is probably a hodgepodge of syntax errors, please let me know what they are.

###########template switch functions##############

  - platform: template
    id: ${devicename}_${subject}_open_close
    name: "Gate Remote Open/Close"
    icon: "mdi:gate"
    optimistic: true
    on_turn_on:
      then:
        if:
          condition:
            lambda: |- 
              if ((id(${purpose}_${subject}_duration).state > 0)  &&  (id(${subject}_open_switch).state)) {
                  id(remaining_time_1) = return (id(${purpose}_${subject}_duration));
                  }
          then:
        # Show the remaining time.
          - sensor.template.publish:
              id: ${purpose}_${subject}_remaining
              state: !lambda return id(${purpose}_${subject}_duration).state;
    on_turn_off:
      - switch.toggle: ${devicename}_${subject}_switch
      

############################################