Switch with HA-only state based on 2 other switches + 20s movement time

Hi,
I wonder what is the best way to implement quite specific switch. I have a water valve connected via RPI GPIO ports. Separate port for opening, separate one for closing. The open/close movement takes 20 seconds.The HA is the only thing operating this valve right now, so theoretically it can know its state.

I would like to have single switch in HA, with state kept by HA where turning on switches the “valve open” for 20s, and turning off switches the “Valve close” for 20s, and never open and close are turned on at once.

I know that template switch allows to define separate turn on and off actions, however I have problem with state and the 20s duration.

Thanks in advance for any help.

Could you explain a bit better?
The valve takes 20 seconds from fully off -> fully on and 20 seconds the other way around.
You have connected each movement to a different GPIO. How does that work?
Say the valve is off.
You power a certain GPIO for 20 seconds untill it’s fully open.
When the valve is fully open and you turn off your gpio switch, does it stay open?
If you stop powering the GPIO it stays at xx% (say 50% at 10 seconds?)

Does the equivalent stuff happen when the valve is open and you want to close it?

Sure

  1. valve has 3 wires, 1 neutral, 1x 230v for opening, 1x230v for closing. I have a relay board plugged into the RPI GPIO, so 1 pin goes for opening and 1 pin goes for closing
  2. yes, 20s fully off -> fully on, 20s fully on -> fully off
  3. “When the valve is fully open and you turn off your gpio switch, does it stay open?” yes, its not NC or NO but “bistable”. it does not take electricity to stay opened/closed, only for movement
  4. “If you stop powering the GPIO it stays at xx% (say 50% at 10 seconds?)” AFAIK yes, but its not documented hmmm.
    “Does the equivalent stuff happen when the valve is open and you want to close it?” yes

I would go about it somewhat like this:
Two switches as you have already set up:

switch:
  - platform: rpi_gpio
    ports:
      4: valve_open
      3: valve_close

An input select to guess or manually enter what the state of the valve is

input_select:
  valve_state:
    name: Valve State
    options:
      - Closed
      - Opening
      - Open
      - Closing

Two scripts to fully open and close the valve (since you dont need any in-between state) and set the equivalent input text state:

script:
  valve_open:
    sequence: 
      - service: switch.turn_on
        entity_id: switch.valve_open
      - service: input_select.select_option
        data:
          entity_id: input_select.valve_state
          option: "Opening"
      - delay:
          seconds: 20
      - service: switch.turn_off
        entity_id: switch.valve_open
      - service: input_select.select_option
        data:
          entity_id: input_select.valve_state
          option: "Open"

  valve_close:
    sequence: 
      - service: switch.turn_on
        entity_id: switch.valve_close
      - service: input_select.select_option
        data:
          entity_id: input_select.valve_state
          option: "Closing"
      - delay:
          seconds: 20
      - service: switch.turn_off
        entity_id: switch.valve_close
      - service: input_select.select_option
        data:
          entity_id: input_select.valve_state
          option: "Closed"

Then a teplate switch to read the input_text and act accordingly.

switch:
  - platform: template
    switches:
      valve: 
        value_template: >-
          {% if is_state("input_select.valve_state", "Closed") %}
            off 
          {% elif is_state("input_select.valve_state", "Opening") %}
            on
          {% elif is_state("input_select.valve_state", "Open") %}
            on
          {% elif is_state("input_select.valve_state", "Closing") %}
            off
          {% endif %}
        turn_on:
          service: script.turn_on
          data:
            entity_id: switch.valve_open
        turn_off:
          service: switch.turn_on
          data:
            entity_id: switch.valve_close

Having some uncertainty if the value_template part of the switch will be working ok, im terribly bad at templating, but check it out.
Also try it with 'on' and 'off'.
Or maybe someone could point us to the right syntax.

Or perhaps even simpler:
(without closing and opening)

input_select:
  valve_state:
    name: Valve State
    options:
      - Closed
      - Open

Scripts:

script:
  valve_open:
    sequence: 
      - service: input_select.select_option
        data:
          entity_id: input_select.valve_state
          option: "Open"
      - service: switch.turn_on
        entity_id: switch.valve_open
      - delay:
          seconds: 20
      - service: switch.turn_off
        entity_id: switch.valve_open


  valve_close:
    sequence: 
      - service: input_select.select_option
        data:
          entity_id: input_select.valve_state
          option: "Closed"
      - service: switch.turn_on
        entity_id: switch.valve_close
      - delay:
          seconds: 20
      - service: switch.turn_off
        entity_id: switch.valve_close

template switch:

switch:
  - platform: template
    switches:
      valve: 
        value_template: "{{ is_state('input_select.valve_state', 'Open') }}"
        turn_on:
          service: script.turn_on
          data:
            entity_id: switch.valve_open
        turn_off:
          service: switch.turn_on
          data:
            entity_id: switch.valve_close

(so that it only checks two conditions, open and closed)