[SOLVED] BasicUI - keypad

Tags: #<Tag:0x00007fc3f2286ca8>

Thanks for getting back to me. You are right, it won’t solve my issue. I’m trying to replace an old
standalone Ademco alarm with OpenHAB + Arduino. I need to handle the keypad in the basic ui (for HABdroid), so need to collect the keypresses and compare to a saved password. Maybe someone out there has coded this up. Meanwhile, I’ll keep reading docs and trying to sort it out.

That doesn’t sound like a secure solution. And I guess the reason you have an alarm, is security.
If your rule must do “If password = 1234 then sendCommand(Alarmstatus, OFF)”, then anyone who has access to your OpenHAB is able to retrieve your alarm code and switch it off.

If my insurance company would know I have coded my alarm code in my rules (allowing it to switch off my alarm), it will not compensate me, even though I am insured against theft. For them it’s the same thing as writing the alarm code on my front door.

So I would look for a solution where you only send a alarm code from OH to your alarm, and your alarm system should determine if that code is valid (and honestly, even this approach is “grey area” when you ask an insurance company).

Anyway, good luck!

Dries

I agree, security of the entire OpenHab system is required.

Hello everyone,

@Dries It for sure depends on your insurance contract but for general household insurances this is not an issue. They will nevertheless pay if they do not see culpable negligence, such as leaving the door open or unlocked. Having a plaintext password in a secure environment (such as a server with username and password) does not violate that from my point of view.

But I agree, it is not the safest solution, but it does serve my purpose to have the code entered in the rule. Also I am not a programmer (so coding might be a bit stupid), but I developed a solution that works for me, maybe it helps you @JohnChiasson to get some ideas and use parts of it. See in the screenshot what it looks like in BasicUI. Due to size restrictions it only contains 6 numbers, but equals over 45000 of possible combinations, which is enough for me:

SITEMAP

Text item=door_entrance label="Haustür [%s]"
Text item=ema_status
Switch item=keypad icon="none" mappings=[1="1",2="2",3="3",4="4",5="5",6="6"]
//vswitch below can only activate, deactivate with code only
Switch item=vswitch_ema_activate icon="none" mappings=[1="aktivieren"]
Text item=keyentered

ITEMS

Switch alarm "Alarm" <alarm> { channel="..." }
Number keypad "PIN" <lock>
String ema_status "EMA: [%s]" <shield>
Number vswitch_ema_activate "EMA:"
Switch ema
String key1 "key1: [%s]"
String key2 "key2: [%s]"
String key3 "key3: [%s]"
String key4 "key4: [%s]"
String key5 "key5: [%s]"
String keycounter "keycounter: [%s]"
String keyentered "Key entered: [%s]"

RULES

var int int_zero = 0
var int int_one = 1

var int key_digit_1 = 0
var int key_digit_2 = 0
var int key_digit_3 = 0
var int key_digit_4 = 0
var int key_digit_5 = 0
var int key_count = 0

var String unarmed = "inaktiv"
var String armed = "aktiv"



//set new status armed
	rule "EMA activate"
		when
			Item vswitch_ema_activate received command 1
		then
			postUpdate(ema_status,armed)
		end
	
//set new status unarmed	
	rule "EMA deactivate"
		when
			Item vswitch_ema_activate received command 0
		then
				postUpdate(ema_status,unarmed)
		end


	
//Key Pad Code Comparison and alarm system action
	rule "Key Digit"
		when
			Item keypad received command
		then
			//define correct keypad code here
			var int code_1 = 1
			var int code_2 = 2
			var int code_3 = 3
			var int code_4 = 2
			var int code_5 = 1

			//counter used for comparison of current keypad digit status to save the value in the correct variable
			//will be reset after 6 digits have been entered - see below
			if(	key_count == 0) {
						//read status of the keypad and write it to the variable
					key_digit_1 = (keypad.state as DecimalType).intValue
					postUpdate(key1,key_digit_1)
						//counter +1 to allow entry of next number into other variable
					key_count = key_count + 1
					postUpdate(keycounter,key_count)
						//display the just entered number in the updated text in the UI
					keyentered.postUpdate(key_digit_1.toString + "-" + key_digit_2.toString + "-" + key_digit_3.toString + "-" + key_digit_4.toString + "-" + key_digit_5.toString)
					}
				else if (key_count == 1) {
					key_count = key_count + 1
					key_digit_2 = (keypad.state as DecimalType).intValue
					postUpdate(key2,key_digit_2)
					postUpdate(keycounter,key_count)
					keyentered.postUpdate(key_digit_1.toString + "-" + key_digit_2.toString + "-" + key_digit_3.toString + "-" + key_digit_4.toString + "-" + key_digit_5.toString)
					}
				else if (key_count == 2) {
					key_digit_3 = (keypad.state as DecimalType).intValue
					postUpdate(key3,key_digit_3)
					key_count = key_count + 1
					postUpdate(keycounter,key_count)
					keyentered.postUpdate(key_digit_1.toString + "-" + key_digit_2.toString + "-" + key_digit_3.toString + "-" + key_digit_4.toString + "-" + key_digit_5.toString)
					}
				else if (key_count == 3) {
					key_digit_4 = (keypad.state as DecimalType).intValue
					postUpdate(key4,key_digit_4)
					key_count = key_count + 1
					postUpdate(keycounter,key_count)
					keyentered.postUpdate(key_digit_1.toString + "-" + key_digit_2.toString + "-" + key_digit_3.toString + "-" + key_digit_4.toString + "-" + key_digit_5.toString)
					}
				else if (key_count == 4) {
					key_digit_5 = (keypad.state as DecimalType).intValue
					key_count = key_count + 1
					postUpdate(key5,key_digit_5)
					postUpdate(keycounter,key_count)
					keyentered.postUpdate(key_digit_1.toString + "-" + key_digit_2.toString + "-" + key_digit_3.toString + "-" + key_digit_4.toString + "-" + key_digit_5.toString)
		
			//code comparison - if correct, deactivate alarm system, reset variables, counter and displayed code
			if(	key_digit_1 == code_1 &&
				key_digit_2 == code_2 &&
				key_digit_3 == code_3 &&
				key_digit_4 == code_4 &&
				key_digit_5 == code_5) {
	 
				var String success = "korrekt"
				postUpdate(ema_status,success)
				sendCommand(vswitch_ema_activate, 0)
				sendCommand(alarm, OFF)
				key_count = 0
				key_digit_1 = 0
				key_digit_2 = 0
				key_digit_3 = 0
				key_digit_4 = 0
				key_digit_5 = 0
				keyentered.postUpdate(key_digit_1.toString + "-" + key_digit_2.toString + "-" + key_digit_3.toString + "-" + key_digit_4.toString + "-" + key_digit_5.toString)
				Thread::sleep(5000)
				postUpdate(ema_status,unarmed)
				postUpdate(key1,key_digit_1)
				postUpdate(key2,key_digit_2)
				postUpdate(key3,key_digit_3)
				postUpdate(key4,key_digit_4)
				postUpdate(key5,key_digit_5)
				postUpdate(keycounter,key_count)	
				}
			
			
				//if one of the code elements does not match, activate alarm system
				else if( 	
					key_digit_1 != code_1 ||
					key_digit_2 != code_2 || 
					key_digit_3 != code_3 ||
					key_digit_4 != code_4 ||
					key_digit_5 != code_5) {
			
					var String failed = "falsch"
					postUpdate(ema_status,failed)
					sendCommand(vswitch_ema_activate, 1)
					key_count = 0
					key_digit_1 = 0
					key_digit_2 = 0
					key_digit_3 = 0
					key_digit_4 = 0
					key_digit_5 = 0
					keyentered.postUpdate(key_digit_1.toString + "-" + key_digit_2.toString + "-" + key_digit_3.toString + "-" + key_digit_4.toString + "-" + key_digit_5.toString)
					Thread::sleep(5000)
					postUpdate(ema_status,armed)
					postUpdate(key1,key_digit_1)
					postUpdate(key2,key_digit_2)
					postUpdate(key3,key_digit_3)
					postUpdate(key4,key_digit_4)
					postUpdate(key5,key_digit_5)
					postUpdate(keycounter,key_count)	
					}
			}
		end
2 Likes

For anyone who is working towards the same idea, I’ve learned the MySensors binding doesn’t query the child sensors state on startup. Without this functionality, the binding won’t know the door / window contacts states until they change. For any alarm type system, both the controller and sensor nodes need to query states on startup. Anyone have another suggestion for an arduino based system that implements that functionality?

There is rule code in this widget thread that will deal with capturing keypad entries with a mask and concatenating ready for validation:

It’s not a full alarm system example but it is binding free from a keypad entry point of view and you can easily adjust the validation code and sendCommand(Alarmstatus, OFF) equivalent to suit your needs. If my alarm code reaches a stable state I’ll share it but at the moment it still has a few too many //TODO comments in it.

I like the BasicUI sample above, nice to have an alternative to the HABPanel widget.

The whole discussion about insurance is something that I’ve thought about and for me it’s not a major concern as I’m only dealing with my residential and house insurance is not relevant to any alarm system I can avoid that specific issue. The security aspect is important in itself and you should always take appropriate system precautions but if I have a plain text copy of a PIN for now I can live with, although it’s on my to do list for one day.

In relation to someone getting at my OH instance and turning off the alarm, yes they could but in reality the people occupying the house have enough troubles using the pretty side of the UI technology so if somebody wants to go to the level of hacking their way in, reverse engineering my OH configuration to disable the alarm then good luck to them. I’m not protecting anything so valuable that I need to worry about that level of a sophisticated attack so I soon reach the conclusion that if someone was going to go to that level of effort I’m not going to keep them out.

But certainly everyone has to assess their own levels of comfort and meet their insurance requirements.

John not sure about MySensors as I’ve not seen it before but you might want to post a new thread before diverting this. Include more details about your requirements, what you have hardware wise what you’d prefer and see what others have to add or suggest.

I had managed to sort out a keypad using the Basic UI, but lost the code on an OS upgrade gone wrong. The examples everyone posted did help. I eventually plan to try a panel, but the basic ui on a phone is needed as a backup.

Agree, the mysensors issue should go in a separate thread so I’ll write it up when I get a chance.

The same rule code can be used behind the BasicUI and HabPanel so it’s easy enough to use them both as and when you like, just pick the rules you prefer and then adapt the keypad UIs to suit.

I like this, is it me or does the keypad button set continue from where it was last used, or could it clear after a time out of no use, so to start code entry with a “clean sheet”, sorry my bad, it does clear after ( 5000 )

[quote=“Chod, post:17, topic:28818”]
ear after


[/quote]’

In 1st frame only one key gets selected at a time
same behaviour in not in 2nd and 3rd frame. Any suggestion to get same behaviour in 2nd and 3rd. I do not want user to select multiple keys at same time. One key at a time .

Sitemap code :
sitemap keypad label=“KeyPad”
{
Frame label=“Alexa” {

Switch item=Bathroom_Power_A label=" keypad" icon=“alarm” mappings=[KEY1=“1”, KEY2=“2”, KEY3=“3”,KEY4=“4”, KEY5=“5”, KEY6=“6”,KEY7=“7”, KEY8=“8”, KEY9=“9”,KEYN=“X”]
// /Switch item=Bathroom_Power_A label="" icon=“alarm”/ mappings=[KEY4=“4”, KEY5=“5”, KEY6=“6”]
// Switch item=Bathroom_Power_A label="" icon=“alarm” mappings=[KEY7=“7”, KEY8=“8”, KEY9=“9”]
// Switch item=Bathroom_Power_A label="" icon=“alarm” mappings=[KEYN=“X”, KEY0=“0”, KEYY=“✓”]
}
Frame label=“Alexa 2”
Frame {
Frame {
Switch item=Bathroom_Power label=“Alarm klavier” icon=“alarm” mappings=[KEY1=“1”, KEY2=“2”, KEY3=“3”]
}
Frame{
Switch item=Bathroom_Power label="" icon=“none” mappings=[KEY4=“4”, KEY5=“5”, KEY6=“6”]
}
Frame{
Switch item=Bathroom_Power label="" icon=“none” mappings=[KEY7=“7”, KEY8=“8”, KEY9=“9”]
}
Frame{ Switch item=Bathroom_Power label="" icon=“none” mappings=[KEYN=“X”, KEY0=“0”, KEYY=“✓”]
}
}

Frame label="Alexa3" {

Switch item=Bathroom_Power_A label=" keypad" icon=“alarm” mappings=[KEY1=“1”, KEY2=“2”, KEY3=“3”]
Switch item=Bathroom_Power_A label="" icon=“alarm” mappings=[KEY4=“4”, KEY5=“5”, KEY6=“6”]
Switch item=Bathroom_Power_A label="" icon=“alarm” mappings=[KEY7=“7”, KEY8=“8”, KEY9=“9”]
Switch item=Bathroom_Power_A label="" icon=“alarm” mappings=[KEYN=“X”, KEY0=“0”, KEYY=“✓”]
}
}

Hi @Dries

Could you please share your Item definition ?

Best Nanna

Related to the key pad?
They are pretty simple:

/* Alarm keypad */
String Tex_Alarm_Keypad					"Alarm klavier"																				<alarm>					(gAlarm)
Number Tex_Alarm_Keypad_counter			"Alarm klavier - teller"																	<text>					(gAlarm)
Switch Tex_Alarm_Keypad_visibility		"Alarm klavier zichtbaar"																	<lock>					(gAlarm)

Hi @Dries

I have the Keypad/Quick arm working, but I have trouble getting your History part working - would you share the complete Item definition part?

Best nanna

Sure:

/* Alarm interface */
String Tex_UDP_Receive					"Receive UDP String [%s]"						<settings>		(gSet)					{ udp="<[192.168.3.10:*:'REGEX((.*))']" }			
String Tex_UDP_Send						"Send UDP String"								<settings>		(gSet)					{ udp=">[192.168.3.10:10000:'REGEX((.*))']" }			

/* Generic alarm items */
Number Tex_Alarm_Status								"Alarm status [MAP(tex_alarmstatus.map):%s]"									<alarm>					(gAlarm, gAlarmlogging)
Number Tex_Alarm_Partition							"Alarm Partitie [%s]"															<alarm>					(gAlarm)
String Tex_Alarm_Textline1							"Alarmklavier - lijn 1 [%s]"													<text>					(gAlarm)
String Tex_Alarm_Textline2							"Alarmklavier - lijn 2 [%s]"													<text>					(gAlarm)		
Number Tex_Alarm_User								"Gebruiker [MAP(tex_alarmusers.map):%s]"										<man_3>					(gAlarm, gAlarmlogging)
Number Tex_Alarm_ArmDisarmUser						"Gebruiker [MAP(tex_alarmusers.map):%s]"										<man_3>					(gAlarm, gAlarmlogging)
DateTime Tex_Alarm_Status_Update 					"Tijdstip wijziging alarm status  [%1$td.%1$tm.%1$tY %1$tT]"					<time>					(gAlarm, gAlarmlogging)

/* Various switches */
Switch Tex_Reset_Contacts					"Alle contacten op gesloten zetten"														<settings>		(gSet, gAlarm)
Switch Tex_QuickArm							"Snel wapenen"																			<settings>		(gAlarm)
Switch Tex_QuickArm_visibility				"Snel wapenen - visibility"																<settings>		(gAlarm)
Switch Tex_Get_LSTATUS						"Get the information on the LCD display"												<settings>		(gAlarm)

/* Waakzaam switches */
Switch Tex_Waakzaam_Status					"Waakzaam Status"		    							                                <settings>		(gAlarm)
Switch Tex_Waakzaam_CommunicatieStop		"Blokkeer communicatie"		    							                            <settings>		(gAlarm)        { expire="5m,command=OFF" }
Switch Tex_Waakzaam_SMS_Dries				"Stuur SMS naar Dries"												                    <text>		    (gAlarm)
Switch Tex_Waakzaam_TG_Dries				"Stuur Telegram naar Dries"												                <text>	    	(gAlarm)
Switch Tex_Waakzaam_SMS_Kris				"Stuur SMS naar Kris"												                    <text>	    	(gAlarm)
Switch Tex_Waakzaam_TG_Kris				    "Stuur Telegram naar Kris"												                <text>		    (gAlarm)


/* Alarm keypad */
String Tex_Alarm_Keypad					"Alarm klavier"																				<alarm>					(gAlarm)
Number Tex_Alarm_Keypad_counter			"Alarm klavier - teller"																	<text>					(gAlarm)
Switch Tex_Alarm_Keypad_visibility		"Alarm klavier zichtbaar"																	<lock>					(gAlarm)

/* Zone Status */
Number Tex_Zone_Z001						"Z01 - Sabotage Sirene [MAP(tex_contacts.map):%s]" 												<error> 		(gAlarm, gAlarmcontact)
Number Tex_Zone_Z002						"Z02 - Glasbreukdetector praktijkruimte [MAP(tex_contacts.map):%s]"								<error> 		(gKE_Praktijkruimte, gGlasbreuk, gAlarmcontact)
Number Tex_Zone_Z003						"Z03 - Glasbreukdetector garage [MAP(tex_contacts.map):%s]"										<error>			(gGV_Garage, gGlasbreuk, gAlarmcontact)
Number Tex_Zone_Z004						"Z04 - Glasbreukdetector berging [MAP(tex_contacts.map):%s]"									<error>			(gGV_Berging, gGlasbreuk, gAlarmcontact)

/* Windows */
Number Tex_Window_W01_GV_Garage_Rechts						"Raam Garage rechts [MAP(windows.map):%s]" 													<raam> 				(gAlarm, gGV_Garage, gRamen, gGV_Ramen)
Number Tex_Window_W02_GV_Garage_LinksVoor					"Raam Garage links voor [MAP(windows.map):%s]" 												<raam> 				(gAlarm, gGV_Garage, gRamen, gGV_Ramen)
Number Tex_Window_W03_GV_Garage_LinksAchter					"Raam Garage links achter [MAP(windows.map):%s]" 											<raam> 				(gAlarm, gGV_Garage, gRamen, gGV_Ramen)

/* History of last contact-changes */
String Tex_History_00				(gAlarm, gAlarmhistory)
String Tex_History_01				(gAlarm, gAlarmhistory)
String Tex_History_02				(gAlarm, gAlarmhistory)

Tkanks @Dries

I compared them to what I got and didn’t see any problems.

When the rule “History of last 10 events - part 5 - alarm status” is activated i get this error in my log, and the rule stops executing:

13:13:12.796 [ERROR] [untime.internal.engine.RuleEngineImpl] - Rule 'History of last 10 events - part 5 - alarm status': cannot invoke method public org.joda.time.DateTime org.joda.time.base.AbstractInstant.toDateTime() on null

Do you have any idea why?

The rule uses someItem.lastUpdate. You’d need a suitable persistence service working and the items persisted.
You may need to put up with it until the history gets fully populated.

@rossko57

This is the rule can you point out what to persist?

I’m using Influxdb

rule "History of last 10 events - part 5 - alarm status"

when   
   Item Tex_Alarm_Status changed

then
	var event = Tex_Alarm_Status
	var event_update = event.lastUpdate.toDateTime.toString("dd-MM-yy HH:mm")
	var event_status = transform("MAP","tex_alarmstatus.map",event.state.toString)
	var event_user = transform("MAP","tex_alarmusers.map",Tex_Alarm_ArmDisarmUser.state.toString)
          if (Tex_Alarm_Status.state != 2) {
		postUpdate(Tex_History_00, event_update + " - alarm " + event_status + " door " + event_user)
	}
end

Well, Item Tex_Alarm_Status is the Item you are trying to get lastUpdate for, so that would be a good place to start?

That’s already persisted, and I can confirm stored values.

But is your default db Influxdb? You may need to specify db in lastUpdate.
Failing that, you’ll have to break it down step by step and logInfo it out to see what is missing.