I’ve seen protected cards that require using a keyboard but that’s a bit fussy on a phone. I wanted to be able to show a card by quickly punching a sequence of UI buttons.
The logic is simple. Every time you press a key button, it appends the value of that key to a global variable. If the global variable then equals your password it turns on an input_boolean, and starts a timer to turn off the input_boolean in 30 seconds. Your hidden card is within a Conditional card triggered by that input_boolean.
At the same time, when you press a key button it starts a timer to reset the global variable to null in 5 seconds. That means you must press each required key no more than five seconds apart, and if you press a wrong key you must wait five seconds to start entering your password from the beginning.
Notes:
- This is designed to stop casual or accidental access but is not ironclad security.
- Your password can be as many digits as you want. You can also show as many different key buttons as you want including numbers and letters.
- My timer node is node-red-contrib-stoptimer. You can easily change the length of the timers.
- And I’m not a pro. Someone could probably replace this using a single line of code with a dozen levels of abstraction conjured up by devilish nested templates. If you do, please share.
# configuration.yaml
input_boolean:
unlock_card:
input_text:
unlock_code:
name: Unlock
# ui-lovelace.yaml
# Keypad to open hidden card
- type: horizontal-stack
cards:
- type: custom:button-card
template: key_link
name: 1
tap_action:
action: call-service
service: input_text.set_value
service_data:
entity_id: 'input_text.unlock_code'
value: '1'
- type: custom:button-card
template: key_link
name: 2
tap_action:
action: call-service
service: input_text.set_value
service_data:
entity_id: 'input_text.unlock_code'
value: '2'
- type: custom:button-card
template: key_link
name: 3
tap_action:
action: call-service
service: input_text.set_value
service_data:
entity_id: 'input_text.unlock_code'
value: '3'
- type: custom:button-card
template: key_link
name: 4
tap_action:
action: call-service
service: input_text.set_value
service_data:
entity_id: 'input_text.unlock_code'
value: '4'
# your hidden card in ui-lovelace.yaml
- type: conditional
conditions:
- entity: input_boolean.unlock_card
state: "on"
card:
type:
# ... etc
# Custom Button card templates
dummy_colors:
color: &blue_gradient 'linear-gradient( 135deg, rgb(192, 222, 237) 10%, rgb(59, 171, 221) 100%)'
key_link:
color_type: card
styles:
card:
- height: 50px
#- margin: 5px 5px 5px 5px
- padding: 5px 15px
- background-image: *blue_gradient
- border-radius: 10px
- -webkit-box-shadow: 0px 5px 5px 0px rgb(3, 150, 255, .4)
- box-shadow: 2px 5px 5px 0px rgb(3, 150, 255, .4)
- color: *black_label
# Node Red
[{"id":"8e1f103e.14258","type":"comment","z":"786db0c1.8b55b","name":"Keypad Unlock","info":"","x":120,"y":1340,"wires":[]},{"id":"7debae70.d2b66","type":"server-state-changed","z":"786db0c1.8b55b","name":"input_text.unlock_code","server":"2bcf671a.f2b3c8","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_text.unlock_code","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":false,"x":140,"y":1380,"wires":[["14b51ef9.e3ab41","98c05bef.e2b688"]]},{"id":"7dc5eb1c.e49374","type":"function","z":"786db0c1.8b55b","name":"Update variable","func":"var temp=global.get(\"unlock\")+msg.payload\n\nglobal.set(\"unlock\", temp)\n\nmsg.payload = temp\n\nreturn msg;","outputs":1,"noerr":0,"x":740,"y":1380,"wires":[["71e4d418.a242cc"]]},{"id":"14b51ef9.e3ab41","type":"switch","z":"786db0c1.8b55b","name":"","property":"unlock","propertyType":"global","rules":[{"t":"cont","v":"undefined","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":370,"y":1380,"wires":[["4ca166de.57a858"],["7dc5eb1c.e49374"]]},{"id":"4ca166de.57a858","type":"change","z":"786db0c1.8b55b","name":"","rules":[{"t":"set","p":"unlock","pt":"global","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":530,"y":1340,"wires":[["7dc5eb1c.e49374"]]},{"id":"71e4d418.a242cc","type":"switch","z":"786db0c1.8b55b","name":"Test for PW","property":"unlock","propertyType":"global","rules":[{"t":"eq","v":"1234","vt":"str"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":930,"y":1380,"wires":[["293fedab.8a79b2","ac3de3b1.9711a"],[]]},{"id":"30de7811.a7abc8","type":"stoptimer","z":"786db0c1.8b55b","duration":"5","units":"Second","payloadtype":"str","payloadval":"","name":"5 seconds","x":750,"y":1420,"wires":[["c8aada48.0b7088"],[]]},{"id":"c8aada48.0b7088","type":"change","z":"786db0c1.8b55b","name":"Reset Global","rules":[{"t":"set","p":"unlock","pt":"global","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":930,"y":1420,"wires":[[]]},{"id":"98c05bef.e2b688","type":"api-call-service","z":"786db0c1.8b55b","name":"input_text.unlock_code","server":"2bcf671a.f2b3c8","version":1,"debugenabled":false,"service_domain":"input_text","service":"set_value","entityId":"input_text.unlock_code","data":"{\"value\":\"\" }","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":420,"y":1420,"wires":[["30de7811.a7abc8"]]},{"id":"ac3de3b1.9711a","type":"api-call-service","z":"786db0c1.8b55b","name":"unlock_card ON","server":"2bcf671a.f2b3c8","version":1,"debugenabled":false,"service_domain":"input_boolean","service":"turn_on","entityId":"input_boolean.unlock_card ","data":"","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1360,"y":1360,"wires":[[]]},{"id":"293fedab.8a79b2","type":"stoptimer","z":"786db0c1.8b55b","duration":"30","units":"Second","payloadtype":"bool","payloadval":"false","name":"30 seconds","x":1130,"y":1400,"wires":[["6f6d0928.072958"],[]]},{"id":"6f6d0928.072958","type":"api-call-service","z":"786db0c1.8b55b","name":"unlock_card OFF","server":"2bcf671a.f2b3c8","version":1,"debugenabled":false,"service_domain":"input_boolean","service":"turn_off","entityId":"input_boolean.unlock_card ","data":"","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1360,"y":1400,"wires":[[]]},{"id":"2bcf671a.f2b3c8","type":"server","z":"","name":"Home Assistant","legacy":false,"hassio":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]