currentValue("lock") not updating

I have a simple app I've written to try and make sure all of my homes doors are locked. Due to what I think is an unrelated issue (See thread: HSM Arming Multiple States) I've been running into some issues with locks not always locking when commanded.

To try and alleviate this issue I've added a pretty basic IF check after sending a door lock command:

			lock.lock()
			pause(6000)
			if (lock.currentValue("lock") != "locked")
			{
				lock.lock()
				pause(12000)
			}
			if (lock.currentValue("lock") != "locked")
			{
				sendMessage("FAILED to lock ${lock.displayName} after HSM Armed, lock.currentValue = " + lock.currentValue("lock"))
			}

So the idea here is to:

  1. Send the lock command
  2. Wait 6 seconds.
  3. Check to see if the door successfully locked
  4. If not make one more attempt at locking it.
  5. Wait 12 seconds
  6. If still not showing a successful lock: Send a warning message.

This seems pretty straightforward but I'm finding that even when the lock is successfully locked it always sends the warning message claiming the lock failed to lock. Here's a log entry:

[app:581](http://192.168.0.55/logs#app581)2019-02-11 08:01:49.221 pm [info](http://192.168.0.55/installedapp/configure/581)FAILED to lock Front Door Lock after HSM Armed, lock.currentValue = unlocked

Here's the screenshot showing the actual time the lock was successfully locked:

If you can't read the screenshot that timestamp is: 2019-02-11 08:01:35.709

So to re-cap: The lock reported a successful locked status at 8:01:35pm, and at 8:01:49pm my IF statement checked the value of lock.currentValue("lock") and it still reported "unlocked", a full 14 seconds after the lock reported a successful lock status.

Am I doing something wrong here? Is currentValue("lock") not the correct way to asses the locks latest lock status?

Thanks,
-Jeremy

I have the same type of issue. The currentvalue doesn't get updated live in the thread.

I got around it by calling the routine again using a runIn statement.

My theory is that when you use a runIn, it reloads AL of the new values and you see the updates.

You can do something like create another method for verification , then execute it with a runIn command. I bet you will see the update when you check there.

I'll be watching this closely though to see what the devs say.

Correct.

@mike.maxwell Is there a recommended way to verify that a lock was successfully locked after sending the lock command?

Check the state like you're doing, if it's not locked call runIn(5,lockLock) (or something similar) where lockLock is a new method that sends the lock command.
You probably want to wire your notify based on a retry state variable counter that you manage so the thing doesn't go on forever...
In other words if it doesn't lock after three tries give up and notify or something...

You might be able to do this entire thing with a rule as well...

Ok, I'm following up until here. But now that I've called the "lockLock" method wouldn't that method still see the old lockState after sending the lock command? Wouldn't I still be in the same situation where I don't know if it locked successfully or not? I may need to just sleep on this because I feel like I'm missing something obvious. Keep in mind I'm doing this in a FOR loop with 6 locks, so that adds to the complexity of having to fire off all these child methods to check the status and report back.

Out of curiosity: Is there any particular architectural reason why the currentValue("lock") is frozen to the state that it was when the method begins execution, rather than always accessing the most recent status in the HE database? Is this a compatibility thing with ST apps?

Thanks,
-Jeremy

Hey everyone,

Interesting thread that I just ran into because I'm having a similar issue with my Yale YRD226's (3 of them) periodically not locking after being sent the lock command. Additionally, manually locking or unlocking them sometimes isn't properly reflected in HE.

Do we know the root cause of why these locks aren't correctly locking and/or updating state based on manual operation?

Thanks.

@jeremy.akers - Ok, I just read the associated thread about HSM and your hypothesis that you were overloading the mesh by having RM send 6 lock commands at once.

That was my original thought too, so, I have 3 separate rules that I trigger with delays in between to lock my locks (the rules also check the contact sensor state for those doors to make sure they are closed before attempting a lock). How long of a delay did you find worked most of the time for this? I may try adjusting my delays within the rules themselves.

Thanks.

@guywmartin So I ended doing a for loop in Groovy: For each lock: Send the lock command and then wait 5 seconds, then proceed to the next lock.

After that I wait 10 more seconds and call another method to check the status of each lock (Using the "runIn" method described above.) That method does the same for loop: for each lock: Check the status and if the status is unlocked, then send another lock command. This time wait 7 seconds between each lock.

This works 99% of the time. I still occasionally have locks that fail to lock though, so I may add a 3rd retry loop to the mix.

That said: This is one of many steps I've taken to address this lock issue. I've found it requires a combination of:

1.) Ensure each lock has at least one nearby "beaming" Z-wave repeater. Take a look at this thread where this is discussed. All Z-wave "Plus" devices are supposed to support beaming but in practice not all of them do it correctly (or well?) so some suggested repeaters are listed in this thread: Kiwkset Lock - Zwave to Zigbee Conversion
2.) Ensure that there are no older non-Zwave Plus repeaters also nearby (Or any known "bad" repeaters). I found that some of my older Appliance Outlets were causing issues. Because even though I had a good repeater close by the mesh would still sometimes try to route through one of the bad repeaters with mixed results.
3.) Ensure that these repeaters have line of sight to the lock. A repeating light switch that's 8 inches from the lock may not work because it doesn't have line of sight. It's close but it has to go through the door framing and that can sometimes be a lot of studs. An outlet that's 10 ft away but on a tangential wall will likely work better. Basically if you can tie a string to the lock handle and run the string to your repeater without going through the door or any walls that's ideal.
4.) Finally: Don't try to send the command to all your locks at once. Lock them one at a time, give them time to respond and then lock the next one.

On that final topic: This thread suggests you need to use runIn in order to start a new thread and check the lock status. However that may not be true. See this thread: Sendevent command not instantaneous?

I'm a little curious why @mike.maxwell Didn't mention you can just add a second paramater "true" to the currentValue() method to get the latest status. Would have been much easier than re-writing everything using runIn to create multiple threads. :slight_smile:

-Jeremy

Because I've never had a need for this use case, so didn't even know it existed...

I think Chuck actually mentioned it.

Edit: I re-read your statement, and misunderstood. I thought you were asking DIDN'T mike mention that. NEVER MIND. I have poor reading comprehension I guess. :smile:

You know it's niche if even @mike.maxwell doesn't know about it. :slight_smile:

Yeah, several weeks later in an unrelated thread. :stuck_out_tongue:

Oh well, I got to practice a new technique in groovy.

-Jeremy

1 Like

Interesting - I have a ton of beaming capable switches (Aeon Nano Dimmers - ZWave-plus) that meet all of these qualifications, including being in good spots in relation each of the locks. However, the switches are all joined as insecure, the locks are joined as secure. Does the beaming still function properly in that case? Your assertion that the hub's radio is getting clogged and busy with other things makes sense if the request isn't being offloaded to one of the many beaming devices nearby.

I assumed it had not, which is what caused me to move the hub from my office (back corner of house on the 2nd floor) to our great room TV cabinet (bottom floor of the house - line of sight with only a single wall between hub and locks - largest distance about 40 ft.).

If the beaming requires that the beaming device also be paired securely, this is gonna be a bear, because my Z-wave mesh will most likely have to be completely rebuilt with all 20+ Aeon Dimmers being removed and paired securely.

Thanks for any thoughts/suggestions.

it does not, don't waste your time on this.

1 Like

Yes. They just repeat the encrypted signals, they don't need to decrypt or decipher it. All of my repeaters are joined insecure and they repeat for the secure locks just fine.

That said: I think that's why some repeaters work better than others: Because not all of them repeat the encrypted traffic properly.

The hub itself definitely doesn't handle the beaming as well as a repeater. I did the same thing: I moved my hub closer to the locks and the problem got worse instead of better. By ensuring there's a repeater near the lock, even if the hub s fairly close will help because the hub can off-load the beaming to the repeater.

Literally the locks I had the most trouble with were the two locks nearest my hub. Adding repeaters between them helped immensely even though the hub was ~10ft away with unobstructed line of sight to the locks.

-Jeremy

1 Like

Thanks everyone - ok.. well, then this is puzzling - I have an all Z-wave Plus house, with every switch location being either an Aeotec Nano Dimmer or Nano Switch, both of which appear to be on the 'good repeater' list. I have several Z-Wave Plus Outlets that could also be repeating (GE's).

In other words, there should be plenty of beaming capability close enough to these locks. I'm trying some other things I've seen elsewhere in the forums about refreshing the lock status (since they can't be polled) to see if that might help, and I've adjusted my 3 Lock Check/Lock rules to delay 15 seconds before executing the lock commands.

Good to know that insecure/secure doesn't matter though.. thanks for that.

Some of the ones I had trouble with were GE outlets. They were older (Not plus) but it might be worth trying to swap those out, doing a repair and see if it helps. I replaced all of my GE outlets with either Neo Coolcam "Mini Plugs" or Zooz ZEN06 outlets and it made a world of difference for me.

https://www.amazon.com/gp/product/B0794T2Z24/
https://www.amazon.com/gp/product/B01MTRZXHF/

-Jeremy

2 Likes

I added the Zen06's next to all three of my kwikset locks and the results have been extrememly better. Still not 100% but 90% now which is better than the 50% before.

@jeremy.akers - any chance you'd be willing to share your full code? I'd like to try this approach, as it appears that my attempts to do this with discrete rules in RM isn't working, even with randomized delays.. which would make sense, as RM is most likely just spawning threads and moving on, making these operations non-deterministic.

Thanks.

Sure. I'm planning on re-writing this using the new method that @chuck.schwer gave me where you add a second boolean "true" parameter to currentValue to avoid all of the "runIn" nonsense... But in the meantime this is what I have that's working fairly well for me right now. It's very specific to my use case so you may need to make some modifications for yours:

definition(
    name: "Auto Lock and Unlock Doors",
    namespace: "jeremyakers",
    author: "Jeremy Akers",
    description: "Automatically lock and unlock doors based on HSM state and presense.",
    category: "Safety & Security",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience%402x.png"
)

preferences {
	section("Parameters: ")
	{
		input "presence", "capability.presenceSensor", title: "Presence sensors: ", multiple: true
		input "locksToLock","capability.lock", title: "Locks to lock when HSM armed: ", multiple: true
		input "locksToUnlock","capability.lock", title: "Locks to unlock when anyone arrives: ", multiple: true
		input "unlock", "enum", title: "Unlock when presence is detected?", options: ["Yes","No"]
		input "recipients", "capability.speechSynthesis", title: "Notifications Device", multiple: true
		input "driveway_motion", "capability.motionSensor", title: "Driveway Motion", required: true, multiple: true
		input "driveway_virtual_motion", "capability.motionSensor", title: "Virtual Driveway Motion sensor to use trigger lighting", required: true
		input "seconds", "number", title: "Seconds", required: true
		input "garage_door", "capability.doorControl", title: "Garage Door to Open When home", required: true
		input "chimes", "capability.speechSynthesis", title: "Devices to Chime for Driveway Notifications", multiple: true
		input "chime_choice", "number", title: "Which chime sound to generate when driveway motion detected"
		input "mute_seconds", "number", title: "Seconds to mute driveway Pushover notifcations after closing garage door."
		
	}
}

def installed()
{
	subscribe(presence, "presence", statusHandler)
	subscribe(location, "hsmStatus", statusHandler)
	subscribe(driveway_motion, "motion", motionHandler)
}

def updated()
{
	unsubscribe()
	subscribe(presence, "presence", statusHandler)
	subscribe(location, "hsmStatus", statusHandler)
	subscribe(driveway_motion, "motion", motionHandler)
}

def statusHandler(evt)
{
	def triggerTime = atomicState.triggerTime
	if((now() - triggerTime) < 5000)
	{
		return
	}
	atomicState.triggerTime = now()
	
	if (evt.value == "present") 
	{
		if (unlock == "Yes") 
		{
			if (locksToUnlock.count{it.currentLock == "unlocked"} != locksToUnlock.size()) 
			{
				sendMessage("[N]Unlocking doors at arrival of $evt.linkText")
			}
			runIn(3, unlockDoors)
		}
	}
	else if(evt.value == "armedAway" || evt.value == "armedHome") 
	{
		runIn(5, lockDoors)
	}
	else if(evt.value == "disarmed")
	{
		sendMessage("[N]HSM was disarmed")
	}
	//log.info("Thread leaving synchronized block: " + randomThreadID)

}

def unlockDoors()
{
	//locksToUnlock.unlock()
	for(lock in locksToUnlock)
	{
		//sendMessage("Unlocking door at arrival of $evt.linkText")
		lock.unlock()
		pause(2000)
	}
}

def lockDoors()
{
	if (locksToLock.count{it.currentLock == "locked"} != locksToLock.size()) 
	{
		sendMessage("[L]Locking doors after HSM Armed.")
	}
	//locksToLock.lock()
	for(lock in locksToLock)
	{
		//sendMessage("Door locked after HSM Armed.")
		lock.lock()
		pause(5000)
	}
	runIn(10, retryLocks)
}

def retryLocks()
{
	for(lock in locksToLock)
	{
		if (lock.currentValue("lock") != "locked")
		{
			log.info("Lock failed to lock on first try, retrying: ${lock.displayName}")
			lock.lock()
			pause(7000)
		}
	}
	runIn(15, verifyLocks)
}


def verifyLocks()
{
	for(lock in locksToLock)
	{
		if (lock.currentValue("lock") != "locked")
		{
			sendMessage("FAILED to lock ${lock.displayName} after HSM Armed, lock.currentValue = " + lock.currentValue("lock"))
		}
	}
	sendMessage("[L]All doors successfully locked and verified after HSM Armed.")
}

def motionHandler(evt)
{
	def triggerTime = atomicState.motionTriggerTime
	if(((now() - triggerTime)) < 10000)
	{
		return
	}
	atomicState.motionTriggerTime = now()
	if(presence.collect { it.eventsSince(new Date(now() - (1000 * seconds)))}.flatten().findAll{ it.value=="present" }) // If someone has recently become "present" after being away.
	{
		garage_door.open()
		sendMessage("Opening Garage door after detecting presence and driveway motion within ${seconds} seconds")
		// Give garage door opener time to respond before flooding z-wave network with other commands:
		pause(500) 
	}
	chimes.speak(chime_choice.toString()) // Play driveway notification on chime devices.
	driveway_virtual_motion.active() // Trigger lighting rules.
}

def sendMessage(msg) 
{
	log.info(msg)
	recipients.speak(msg)
}
1 Like