Using a binary_sensor as a read only switch

Hi all,

I have an RF keypad that is really a binary_sensor, ie it has no state to write to. I would like to have it show on the web interface as a switch and not a sensor. I have tried this:

switch:
  - platform: template
    switches:
      kitchen_pad1:
        value_template: "{{ is_state('binary_sensor.kitchen_motion', 'on') }}"
        turn_on:
          service: switch.turn_on
          data:
            entity_id: switch.kitchen_pad1_on
        turn_off:
          service: switch.turn_off
          data:
            entity_id: switch.kitchen_pad1_off

When I press the ‘ON’ button on the keypad the web interface follows the state, however, when I toggle the switch on the web interface, it turns on and then off about 2 seconds later. I would like it to remain on.
Is there a way to do this?
Thanks.

I really don’t understand what’s happening here. Can you format your YAML like the blue box at the top says to? It’s hard to read when everything is at the same indent level.

It looks like you have a template-based switch, that is reading from a motion sensor for its state, and turns one switch on when it is turned on, and a different switch off when it turns off.

If you can’t set a state what is the point of having a switch? Just because you like the way it looks in the interface? I guess that’s fair.

switch:
  platform: template
  switches:
    kitchen_pad1:
      value_template: "{{ is_state('binary_sensor.kitchen_motion', 'on') }}"
      turn_on:
        # Not sure if you can have an empty script in a template switch
        - delay: "00:00:01"
      turn_off:
        - delay: "00:00:01"

That would make a switch that will effectively ignore any toggling that you do to it, but display according to the state of binary_sensor.kitchen_motion What exactly are switch.kitchen_pad1_on and switch.kitchen_pad_off supposed to be? I am kind of confused by a switch that you only ever turn on, and another one that you only ever turn off.

Your last statement that the switch toggles back after you switch it makes perfect sense to me because the state of the switch will be keyed to the motion sensor.

1 Like

Ideally, that shouldn’t even be possible, right? If it’s truly read-only, the switch should be grayed out but that feature, to my knowledge, is unavailable. Therein lies the problem of attempting to bend the rules and present a binary_sensor using a switch.

Sorry about the formatting I was on a phone and it’s not the best for posting. Maybe it’s better if I explain the issue differently.

I have an X10 radio receiver that receives events from motion sensors and keypads. The motion sensors are obvious binary_sensors, no problem. The keypads have an ‘ON’ and an ‘OFF’ button so a ‘switch’ to a human but since they are read only, in other words HA cannot send a state to the keypad, they are, as I have been told by the developers, a binary_sensor.

What I want though is to use it as a switch, the keypad can send ON or OFF and the web interface will follow the state, but also the web interface displays as a switch that can be turned ON or OFF. It can then be used in an automation.

I was told to use a “Template” but can’t get it to work completely.

Ok, correct me if I’m wrong: I’m guessing that you want the sensor to be turned on by both by the keypad turning on and off, and by a tripping a motion sensor (and subsequently timing out?) In this case, it’s a bit more complicated, but not much.

Input booleans:

input_boolean:
  # this boolean stores the state of the keypad, since
  # the state is controlled only by a momentary button
  # press
  kitchen_pad1_state:
    name: kitchen pad background state
  
  # This boolean stores the motion detected in the kitchen
  # since the state of the sensor is ephemeral
  kitchen_motion_detected:
    name: Kitchen motion detected

Script:

script:
  # This script will be executed by the automation
  # that is triggered by the motion detector
  # and turn on the input_boolean for 10 minutes.
  # The fact that it's a script will let us cancel
  # it and restart it, resetting the delay.
  SetKitchenMotionDetected:
    sequence:
      - service: input_boolean.turn_on
        entity_id: input_boolean.kitchen_motion_detected
      - delay: "00:10:00" # 10 minutes
      - service: input_boolean,turn_off
        entity_id: input_boolean.kitchen_motion_detected      

Automations for the key pad button presses:

automation:
  # Turn on the input boolean for the kitchen pad
  # when the "On" button is pressed
  - id: SetKitchenPad1StateOn
    alias: Set kitchen pad1 state
    trigger:
      - However you detect the 'ON' button press
    action:
      - service: input_boolean.turn_on
        entity_id: input_boolean.kitchen_pad1_state

  # Turn off the input boolean for the kitchen pad
  # When the "Off" button is pressed
  - id: SetKitchenPad1StateOff
    alias: Set kitchen pad1 state to off
    trigger:
      - However you detect the 'OFF' button press
    action:
      - service: input_boolean.turn_off
        entity_id: input_boolean.kitchen_pad1_state

Automation for the motion detector:

  # Run the script to set the input_boolean for kitchen
  # motion detected for some amount of time.
  - id: SetKitchenMotionDetected
    alias: Set kitchen motion detected
    trigger:
      - platform: state
        entity_id: binary_sensor.kitchen_motion
        from: 'off'
        to: 'on'
    action:
      # first, we'll turn the script 'off' so it will cancel
      #  the script if it was already running
      - service: script.turn_off
        entity_id: script.setkitchenmotiondetected
      # Now we'll run the script again so the delay
      # will reset.
      - service: script.turn_on
        entity_id: script.setkitchenmotiondetected

Finally, the binary_sensor that you can use to turn on a light or whatever. It’ll be true if either the keypad has been turned on or if motion has been detected.

binary_sensor:
  - platform: template
    sensors:
      SomethingHappeningInTheKitchen:
        friendly_name: Something is happening in the kitchen
        value_template: >-
          {{ is_state('input_boolean.kitchen_pad1_state', 'on') or is_state('input_boolean.kitchen_motion_detected', 'on') }}

I wrote that all from memory, so if that all works as typed, it’ll be a miracle :slight_smile: But you can certainly see the idea that I’m going for.

Wow thanks for that. You know the funny thing is I actually wrote a switch platform for this that would allow the same thing with this:

switch:
  - platform: w800rf32
    devices:
      c2:
        name: kitchen_pad1

So so much simpler, however, I was told HA couldn’t have a switch platform that was one way. I disagree, I don’t see a reason a switch can’t just hold state in memory, maybe with a “pushbutton” attribute or something similar.

The “switch” you described here is one that could not be actuated from Home Assistant. That, to me, anyway is a binary sensor.

I guess I still don’t really understand what you’re after.

OK, now I have a better handle on the issue.

To put it bluntly, this is due to a deficiency in Home Assistant. To be fair, it’s not only Home Assistant, openHAB shares the same blind spot.

I’ve been using another Home Automation system for many years and it does not have this deficiency, namely the lack of a basic pushbutton.

It’s not an on/off switch, nor a binary_sensor, nor some other attempt to fit a ‘square peg in a round hole’, in its simplest form it’s a ‘momentary boolean’. Enable it and it goes true and then, a moment later, goes back to false. It has a hundred and one real-world applications.

A more sophisticated model is not ‘momentary’ but supports states and duration such as press, release, hold, and doubletap. However, for your purposes, a basic ‘momentary boolean’ would easily resolve this issue.

In Premise, here’s how I specify that a boolean, called ‘Activated’, is momentary (you just tick a box). Done. I can later render it in the UI with a pushbutton widget.

It puzzles me why this ‘primitive’ is missing in both openHAB and Home Assistant. In both systems, a ‘momentary boolean’ is simulated by, quite frankly, very roundabout techniques. Anyone who takes issue with my use of the word ‘roundabout’ only needs to look at Steve’s solution (above). That’s pretty much the standard way of simulating a pushbutton in Home Assistant.

In addition, Feature Requests have been made over the years, typically for a pushbutton widget for Frontend UI, and nothing has resulted other than replies saying you can already do that (not really), followed by a lengthy example involving scripts and automations.

Unfortunately, none of what I said helps you. Plus, this all probably sounded like a rant, except that’s not my intention. I’d like to have a beer with the core developers and ask what kind of house they live in where none of their gadgetry has pushbuttons.

Perhaps I ought to submit a Feature Request to enhance Input Boolean. It could benefit from having a ‘momentary’ type. When momentary, it’s default state is always false. Calling input_boolean.turn_on or input_boolean.toggle (existing services) would make it momentarily change state to true then return to false. The service input_boolean.turn_off would do nothing. The UI widget for it would be a simple pushbutton (like what we already see in the alarm panel’s keypad).

I call that a script. Hit ‘execute’ and it does something. If you want that with a switch-like GUI that switches on when it runs and off when it’s done, stick ‘delay: “00:00:01”’ at the end.

By the way, this does not work, or certainly does not do want I want at least based on your example above.

Well except my keypad has an ON and an OFF button so it NEVER goes back to false after a few seconds.
Hmmm I need to clarify this statement. Yes the keypad ON button when pressed goes to a TRUE state and then back to a FALSE state, however, the device inside HA stays in a TRUE state until the OFF button is pressed.

So press the ON button the switch goes on and stays on until the OFF button is pressed. It’s a switch in the true sense of the word.

What kind of X10 keypad is it? It wouldn’t happen to be a Palmpad HR12A?

It is a KR19A and I wrote a component for a W800rf32 to read them.

It works the same way as an X10 PalmPad HR12A.

In its simplest form, each button is nothing more than a momentary boolean. Its default state is false, becomes true when depressed, which triggers an RF transmission, upon release it returns to its resting state (false).

In the more sophisticated model, the default state is ‘release’ and the active state is ‘press’. My memory is foggy but an HR12A’s buttons might support ‘hold’ but not ‘doubletap’.

Technically that isn’t true. HA is capable of actuating the switch and the state, ON or OFF, is held in the instance object just like many other switches in HA.

Now you could argue that HA will send a command to a “hub” or physical device, but the state is still held in the instance of the switch object inside HA. The state in many cases may be held in the “hub” or in the physical device but the fact is it’s still help in memory. Many devices loose state on power failure and thus HA looses their state. In this case the switch could be polled and if a last known state is 'ON" if the state is still in memory or it defaults to “OFF”.

This is doable and would make the use of pushbutton style switches or soft switches useful and easy to use for the end user. The interface is one of the “featured” strengths of HA, let make it useful for the end user.

Ok, I have obviously totally misunderstood the situation from the beginning then. You said,

I thought that meant there was no state and home assistant could not affect the state because there was none.

@horga83

Maybe this will be useful. I needed a pushbutton that would trigger an announcement. I used a script mostly because it’s rendered in the Frontend UI with an “EXECUTE” quasi-pushbutton (“quasi” because it works like a pushbutton but doesn’t look like one).

The announcement is actually part of a scene in my Premise server. Home Assistant talks to Premise via an MQTT topic: premise/command/scenes/reportevents/play

In Premise, scenes can have one of two behaviors:

  • Set-Restore. This is an on/off switch and behaves like Home Assistant’s scenes.
  • Set. This is a momentary boolean (a trigger) and has no equivalent in Home Assistant.

The ‘Report Events’ scene is a ‘Set’ behavior (momentary boolean) so, with no counterpart in Home Assistant, it’s simulated with an MQTT Switch.

In switches.yaml:

  - platform: mqtt
    name: "Report Events"
    state_topic: "premise/scenes/reportevents/play"
    command_topic: "premise/command/scenes/reportevents/play"
    payload_on: "1"
    payload_off: "0"
    state_on: "1"
    state_off: "0"
    retain: false

I don’t want to see this switch in the UI because it’ll be rendered as a toggle button. So I use customize.yaml to hide it.

script.report_events:
  icon: mdi:voice
switch.report_events:
  hidden: true

To simulate momentary boolean functionality, I need to set the switch to true momentarily then return it to false. That’s easily done in a script which also happens to be rendered in the UI with that quasi-pushbutton I mentioned earlier.

In scripts.yaml:

  report_events:
    alias: Report Events
    sequence:
      - service: switch.turn_on
        data:
          entity_id: switch.report_events
      - service: switch.turn_off
        data:
          entity_id: switch.report_events

The result is the last line in this Scenes card:

Scenes

The first four scenes are ‘Set-Restore’ behavior so they are easily modeled with switches. FWIW, the word “EXECUTE” is the default and cannot be modified unless you install Custom UI (which offers that ability and much more).


EDIT

The (hidden) MQTT Switch isn’t necessary to get the job done and was included to illustrate a point (simulating a pushbutton with an existing switch). Here’s a simplified version that only uses a script:

  report_events:
    alias: Report Events
    sequence:
      - service: mqtt.publish
        data:
          topic: 'premise/command/scenes/reportevents/play'
          payload: '1'
      - service: mqtt.publish
        data:
          topic: 'premise/command/scenes/reportevents/play'
          payload: '0'

This is a lot of effort and way to confusing for a new user. they need to be able to just use something like this:

switch:
  - platform: w800rf32
    devices:
      c2:
        name: kitchen_pad1
```

This is why I will leave my switch code up on my site so people can use it. You can find it here at cowlug.org Just grab the w800rf32-switch.py code and stick it in components/switch and you are good to go.

Can’t argue with that but, for better or worse, that’s how it’s currently done.

Just grab the w800rf32-switch.py code and stick it in components/switch and you are good to go.

Would that be in custom_components/switch?

Well it’s certainly for the worse, from the users view it’s actually complete chaos if you do some searching in the forums. So many different ways and not all working, just look at this thread for example. As to custom_components, I’ve not tried putting it there but it certainly works if you put it in components/switch.

I’ve yet to see a technical reason why this can’t be a switch.
Cheers