I need help not over engineering a NOT condition in automation

I wrote an automation that requires that you enter a password and then select from a dropdown to run certain commands from HA. Like reboot, shutdown, harestart, etc It works fine.

I have implemented this with three components
action: input_select - the drop down list
password: input_text - the required password
result: input_text - the status of the request (OK if password correct, Failed if password incorrect)

I created an automation on input_select with condition password state matches !secret action_password. That works perfectly.

So now I just wanted to update “result” with “Failed” if password is incorrect and action is attempted. So I just want the same trigger but the opposite condition. When password != !secret action_password. But there is no NOT condition so I searched and found instruction to use a template to accomplish the != condition. However templates don’t like !secret action_password

The rule I created works until I try to hide the password from my config.
So this works with a hard coded password

- id: Action Password Required
    alias: 'Action Password Required'
    trigger:
        platform: state
        entity_id: input_select.actions
    condition:
        - condition: template
          value_template: "{{ states.input_text.action_password.state != 'HardCodedPassword' }}"
    action:
      - service: input_text.set_value
        data:
          entity_id: input_text.action_result
          value: 'failed-Password Required'

but when I try to use secrets in a template it fails.

...
          value_template: "{{ states.input_text.action_password.state != '!secret action_password' }}"
...

The only solution I can come up with for this is to create another input_text and set the value initially to the !secret action_password. Then use that input_text state in the template.
I am concerned my password would be revealed in the states UI and I don’t like having another input just to hold a static value. I think I can add hide: true to the input but not sure if that hides it from the states screen. I was hoping there is a better way to do this.

Any other ideas on how to implement this “not” condition?

UPDATE: As feared when I make the hidden input_text it does still appear in plain text in the states section of the UI. So I now don’t have any solution to this that doesn’t reveal my password.

Don’t put the condition in the automation itself. Have the automation call a script, and pass the correct password as a variable to the script. The script’s first step would then be the condition comparing input_text.action_password to the passed in variable. If you need help writing this, let us know.

since you are offering :slight_smile:

Not sure what you mean because I have not read up on scripts yet. But that’s a good clue. I will read the scripts docs and examples to see if I can figure it out. If not I will ask for help.

Thanks.

Ok, no problem. Here’s the basic idea:

Updated automation:

- id: Action Password Required
  alias: 'Action Password Required'
  trigger:
    platform: state
    entity_id: input_select.actions
  action:
    service: script.check_bad_password
    data:
      action_password: !secret action_password

And new script:

check_bad_password:
  sequence:
    # Check if password is wrong. If so, set result accordingly.
    - condition: template
      value_template: >
        {{ not is_state('input_text.action_password', action_password) }}
    - service: input_text.set_value
      data:
        entity_id: input_text.action_result
        value: 'failed-Password Required'

@pnbruckner Thanks I have it working perfectly now.

Can you explain “value_template: >” what does the > mean?

Is there a static text component I can use for my action_result? I don’t mind the input_text but it would be nicer to have a non-editable text area.

You could create a template sensor whose value is the same as input_text.action_result:

sensor:
  - platform: template
    sensors:
      action_result:
        value_template: "{{ states('input_text.action_result') }}"

then show it (sensor.action_result) and hide input_text.action_result. Except I think you might need to shorten the value quite a bit. I’m not really a “frontend” guy, so maybe someone else might have a better idea. Maybe you want to start a new topic to ask how to do that.

1 Like

I get that :slight_smile: HA is more for automations and I am moving in that direction.
What I am building here is a menu on the frontend to shutdown and reboot the pi as well as restart ha (not as useful).

I changed my message to add another question and I think you answered while I was changing.
My question about your solution is
Can you explain “value_template: >” what does the > mean?

Thanks again. Great help!

https://yaml-multiline.info/

Everything you ever wanted to know about that, plus way more! :slight_smile:

@pnbruckner I asked for something like this on one of my first posts. Asking for places to learn what I need to know and was told…just ask here, haha

This is perfect! Thanks! Technically the > wasn’t necessary since there is only one line but I get it now.

One more question if you don’t mind. Is it possible to pass a state value to a shell_command?
I found a year old thread on this and revived it but basically it said just use the following.

shell_command:
    take_action: '/home/homeassistant/.homeassistant/shell_scripts/take_action.sh {{ states.input_select.actions.state) }}'

That doesn’t work for me. I get a blank value passed.

Yes, shell_commands can use templates. And those templates can access the “usual” things, and can access “variables” passed into the service call. What exactly are you trying to do? Can you share what you’ve tried?

I have the following in config

input_select:
  actions:
    name: actions
    initial: "--select action--"
    options:
      - "--select action--"
      - "-----------."
      - "reboot now"
      - "shutdown now"
      - "----------.."
      - "ha restart"

.
.
.
shell_command:
  take_action: '/home/homeassistant/.homeassistant/shell_scripts/take_action.sh {{ states.input_select.actions.state }}'

In scripts.yaml

  check_action_password_pass:
    sequence:
      - condition: template
        value_template: >
          {{ is_state('input_text.action_password', action_password_arg) }}
      - service: input_text.set_value
        data:
          entity_id: input_text.action_result
          value: 'OK'
      - delay: '00:00:03'
      - service: shell_command.take_action

  check_action_password_fail:
    sequence:
      - condition: template
        value_template: >
          {{ not is_state('input_text.action_password', action_password_arg) }}
      - service: input_text.set_value
        data:
          entity_id: input_text.action_result
          value: 'failed'
      - delay: '00:00:05'
      - service: input_text.set_value
        data:
          entity_id: input_text.action_result
          value: 'Password Required'

in automation.yaml

  - id: Action Password Required
    alias: 'Action Password Required'
    trigger:
        platform: state
        entity_id: input_select.actions
    action:
      # report if this will fail because of incorrect password
      - service: script.check_action_password_fail
        data:
          action_password_arg: !secret action_password
      # take action if correct password
      - service: script.check_action_password_pass
        data:
          action_password_arg: !secret action_password

It works fine. Error if password is wrong and script gets called if password is correct.
But the script doesn’t get any argument passed.

To test my script just does

echo $1 > /tmp/action.log

From the shell_command doc page:

The commands can be dynamic, using templates to insert values for arguments. When using templates, shell_command runs in a more secure environment which doesn’t allow any shell helpers like automatically expanding the home dir ~ or using pipe symbols to run multiple commands.

Maybe this means output redirection doesn’t work either, which would mean your test can’t work. Don’t really know. Can you try replacing $1 with a fixed string and see if you at least get that string in /tmp/action.log?

BTW, ultimately you’re trying to do privileged things, but these commands are being run by the homeassistant user, which probably can’t do them, right???

@pnbruckner

I got it working. I had two issues. One was a typo in the shell script.
Then I had an issue that $1 contained ha for “ha restart” so I had to change the shell command to add quotes around the state.

take_action: '/home/homeassistant/.homeassistant/shell_scripts/take_action.sh "{{ states.input_select.actions.state }}"'

Working perfectly now with minimal scripting. I used to have four automations now I have 2 automations, some scripts and some shell_scripts…much cleaner design.

Thank You. I am on to my next task :slight_smile:

1 Like