Description text logging - actionable?

I am interested in knowing if an unlock or lock was performed by a person via code entry (lock), manually (unlock), or programatically (lock, unlock) by Hubitat. Descriptive Text logging exposes this, but events are generic.

dev:3032019-06-27 10:20:02.757 am infoFront Door Lock was unlocked by digital command
dev:3032019-06-27 10:20:00.530 am infoFront Door Lock was unlocked

Is there a way to grab the descriptive text logging info and use it in a rule?

Example:
If unlock = manual
then
disarm alarm
and
announce alarm is disarmed

YF

You'd need to write your own app to do this. I threw something together for my Yale for a similar reason but my use case is inverted - I wanted to arm the alarm when the lock wasn't manually locked. Your handler method can look at the event type and the description; e.g,

def lockHandler(evt) {
	if (evt.type == 'physical' && evt.descriptionText.endsWith('by manual')) {
		log "${lock.displayName} was locked manually"
	} else {
		log "${lock.displayName} was locked"
	}
}

I doubt the description format is guaranteed to remain stable but it seems reasonable as long as you're aware of that :slight_smile:

It looks like your lock has a slightly different format so maybe you'd want to change the if condition a bit but the syntax shouldn't be drastically different.

I have a Yale Assure SL so they should be the same. Pardon my "pseudo code" example.

I am not a coder, but have done some scripting. Feel like sharing your app?

YF.

Sure. I haven't used it much so I can't speak to how reliable it is but it seemed to work ok the few days it was used (we don't use the front door much and my use case is for a pet sitter). I can't remember why but I added the ability to bind two types of virtual switches - one that is on when manually locked and off when manually unlocked and the other is the opposite (on when manually unlocked).

definition(
    name: "Manual Lock Events",
    namespace: "rvrolyk",
    author: "Russ Vrolyk",
    description: "Tracks when a lock is manually controlled and updates virtual switch",
    category: "Convenience",
	iconUrl: "",
    iconX2Url: "",
    iconX3Url: "")


def lock = [
    name: "lock",
    type: "capability.lock",
    title: "Lock",
    description: "Select the lock to monitor.",
    required: true,
    multiple: false
]

def virtualLockedSwitch = [
    name: "virtualLockedSwitch",
    type: "capability.switch",
    title: "Virtual Lock Switch",
    description: "Virtual switch that should be turned on when lock is manually locked.",
    required: true,
    multiple: false
]

def virtualUnlockedSwitch = [
    name: "virtualUnlockedSwitch",
    type: "capability.switch",
    title: "Virtual Unlock Switch",
    description: "Virtual switch that should be turned on when lock is manually unlocked.",
    required: false,
    multiple: false
]

def enableLogging = [
    name:				"enableLogging",
    type:				"bool",
    title:				"Enable debug Logging?",
    defaultValue:		false,
    required:			true
]

preferences {
	page(name: "mainPage", title: "<b>Lock to monitor:</b>", install: true, uninstall: true) {
		section("") {
			input lock
			input virtualLockedSwitch
			input virtualUnlockedSwitch
			label title: "Assign an app name", required: false
		}
		section ("<b>Advanced Settings</b>") {
			input enableLogging
		}
	}
}

def installed() {
	log.info "Installed with settings: ${settings}"
	initialize()
}

def updated() {
	log.info "Updated with settings: ${settings}"
	unsubscribe()
	initialize()
}

def initialize() {
    log "Lock status: ${lock.displayName} " + lockStatus()
	subscribe(lock, "lock.locked", lockHandler)
	subscribe(lock, "lock.unlocked", unlockHandler)
}

def lockStatus() {
	return lock.currentValue("lock")
}

def lockHandler(evt) {
	log("Lock event: ${evt.name} : ${evt.descriptionText}")
	if (evt.type == 'physical' && evt.descriptionText.endsWith('by manual')) {
		log "${lock.displayName} was locked manually"
		virtualLockedSwitch.on()
		if (virtualUnlockedSwitch) {
			virtualUnlockedSwitch.off()
		}
	} else {
		log "${lock.displayName} was locked"
	}
}

def unlockHandler(evt) {
	log("Unlock event: ${evt.name} : ${evt.descriptionText}")
	if (evt.type == 'physical' && evt.descriptionText.endsWith('by manual')) {
		log "${lock.displayName} was unlocked manually"
		virtualLockedSwitch.off()
		if (virtualUnlockedSwitch) {
			virtualUnlockedSwitch.on()
		}
	} else {
		log "${lock.displayName} was unlocked"
	}
}

def log(msg) {
    if (enableLogging) {
        log.debug msg
    }
}
1 Like

Thanks! This gives me something to play around with.

There isn't much effort spent in unifying an events displayText attribute across all drivers, nor is there any guarantee it wouldnt get changed, cleaned up or otherwise modified when a specific driver gets updated for whatever reason. This type of change won't ever be in the realase notes since its an optional attribute whos content has no schematic definition.

Thanks Mike, that's more or less what I meant to imply :slight_smile:
I'm certainly not counting on the code I wrote to work forever and won't be surprised if/when it breaks because the description format changed. I probably should figure out some way to detect that but my use case isn't critical enough or frequent enough for me to have bothered yet.

1 Like

I know this is an old thread but I just want to thank Russ for this! I just got my hub a couple of days ago and I am rebuilding everything coming over from ST. I have a Schlage lock and setup a rule to report who unlocked the door using the LastCodeName but this also was triggered by manually unlocking the door. I updated this app code to match my lock and it works perfectly. I can now also check the status of the virtual switch in my rule so manual unlocks are no longer falsely reported as being unlocked by the user defined in the LastCodeName.

For the Schalge lock, I just had to update the 2nd part of the if statement from 'by manual' to 'thumb turn [physical]' for the statement to be true.

I an not a coder and have never done this before but I tried to use .includes instead of .endsWith and check for the word thumb but that didn't work. The change above worked so I am good with that. :grin:

Thanks again Russ!

Glad to hear it worked out for you @chipworkz! It's been working for me for a while now but as mentioned above, be advised the description format isn't guaranteed so it may break (and require looking for different strings) in the future. I'm trying to get some other code wrapped up but maybe at some point I'll clean this up and allow the string handling to be a preference and then share it via github... not sure when I'll have time but it seems like a good goal :slight_smile:

1 Like

It isn't too big of a deal if the description changes although if the lock is not being upgraded, I would be surprised if something changed the text. I am just putting this out there in case someone else out there has a Schlage lock and wants to use this. The purpose for this will vary per user but it was a GREAT starting point that you provided.

For the Schlage lock, there are several Events that can be looked at. I wanted this app to account for everything other than a user code unlocking the door. So I added some or statements to your if conditions. Now the virtual switches will be set correctly if I lock or unlock the door from inside, from the keypad outside, or using the "Lock" dashboard tile. The Dashboard tile is still technically manually locking or unlocking the door in my opinion but that event is digital instead of physical.

For my purpose I am having the virtual switches turn off after a short time otherwise when a user code is entered to unlock the door, the "Locked Manually" switch stays on and doesn't toggle off like it would if the door was manually unlocked. In the end, I will most likely only use the Unlocked switch and set the Locked switch required to false since my rule is just checking to see if the Unlocked Manually switch is off to proceed. I just wanted to update the if statements to learn and give more options in case they were needed.

I am still tweaking things and just learning this but thought I would share to give others some ideas on what can be done with your app.

def lockHandler(evt) {
log("Lock event: ${evt.name} : ${evt.descriptionText}")
if (evt.type == 'physical' && (evt.descriptionText.endsWith('thumb turn [physical]') || evt.descriptionText.endsWith('keypad [physical]'))) || (evt.type == 'digital' && (evt.descriptionText.endsWith('locked [digital]'))) {
log "${lock.displayName} was locked manually"
virtualLockedSwitch.on()
if (virtualUnlockedSwitch) {
virtualUnlockedSwitch.off()
}
} else {
log "${lock.displayName} was locked"
}
}

def unlockHandler(evt) {
log("Unlock event: ${evt.name} : ${evt.descriptionText}")
if (evt.type == 'physical' && evt.descriptionText.endsWith('thumb turn [physical]') || (evt.type == 'digital' && (evt.descriptionText.endsWith('unlocked [digital]'))) {
log "${lock.displayName} was unlocked manually"
virtualLockedSwitch.off()
if (virtualUnlockedSwitch) {
virtualUnlockedSwitch.on()
}
} else {
log "${lock.displayName} was unlocked"

Schlage Lock Events for Reference
Lock name = Front Door Lock. (Varies per installation)

Locked using keypad Schlage button or code.
Lock event: lock : Front Door Lock was locked by keypad [physical]

Locked using inside dial.
Lock event: lock : Front Door Lock was locked by thumb turn [physical]

Locked using automation or dashboard tile.
Lock event: lock : Front Door Lock was locked [digital]

Unlocked using code.
Unlock event: lock : Front Door Lock was unlocked by John

Unlocked using inside dial.
Unlock event: lock : Front Door Lock was unlocked by thumb turn [physical]

Unlocked using automation or dashboard tile.
Unlock event: lock : Front Door Lock was unlocked [digital]

I know this is an old thread. But I need this manual lock app to work with my yale locks.
I am using the generic zwave driver
I have tried to change the ends with to evt.descriptionText.endsWith('manually [physical][21]'))
but still doesnt seem to work.

This is what my log looks like. I am new to modding groovy
locked
dev:2582020-12-24 03:11:52.700 pm infoP - Porch Lock was locked manually [physical][21]

Unlocked
dev:2582020-12-24 03:12:02.089 pm infoP - Porch Lock was unlocked manually [physical][22]

Thanks
Mike

My Schlage BE468 (z-wave) acts strangely. For starters, the unlockHandler(evt) function shows the following log for a manual unlock by thumb turn:

  Unlock event: lock : XYZ was unlocked [digital] : digital

Why is "digital" registered for a manual lock by physical thumb turn? Okay, so I changed line 99 to:

if (evt.type == 'digital' && evt.descriptionText.endsWith('was unlocked [digital]')) {

The problem is that when using the keypad to unlock, the unlockHandler is called twice: once as event type digital, and immediately again as event type "physical". No idea why a keypad unlock would call unlockHandler twice. Here is the log for a single unlock using the keypad as UserA:

23:21:29.398 debug Lock - XYZ Door was unlocked
23:21:29.395 debug Unlock event: lock : XYZ was unlocked by UserA : evt.type = physical
23:21:29.250 info Switch - XYZ Wrapper was turned on
23:21:29.240 debug XYZ was unlocked manually
23:21:29.236 debug Unlock event: lock : XYZ was unlocked [digital] : evt.type = digital

Hey man, I am breaking my head desperately to get my lock automations working right with the manual thumb turn from the inside. Would you be able to share with me your app-code for the manual lock events that you modified to suit the schlage lock? :pray:

I tried changing the original code with your tweaks, but keep getting error with the code. So most likely it didn't translate correctly on the thread post.

FWIW, this is possible using Rule Machine without any custom apps. Here's an example of how to do it (i.e. manual thumb turn) with Rule Machine that I posted for someone else a couple days ago:

1 Like

Sorry it has been a few years since I even looked at this. Currently I am only looking at who unlocked the door and not if it was unlocked manually.

When I see these advanced RM rules, my illusory superiority with creating rules instantly goes away.

I went with what I believe should work and dumbed down... I utilized the app from within this thread and created the virtual switches. I used the unlocked switch with the following RM rule.

Does it look right? Haven't had a chance to test it as I'm on lunch break at work...

I utilized rvrolyk's code with your modification for schlage locks. Going to test tonight and if it's a no-go. I'll be utilizing @aaiyar method. :ok_hand:

Really love this community and the responsiveness from everyone. Blessings to you all!

1 Like

I don't have that app ...... but if the app works, your rule should work I think.

Never mind, still playing with this. Something changed in the last two years since I was doing this. :slight_smile:

At some point in time, the text description logging changed so if your lock is working the same as mine, you can't really use it via my app code or the rule machine text description method.

See if your lock is reporting the multiple descriptions for the one event of turning the knob to lock or unlock the door. If it is and if yours reports the [digital] as the first thing, they we can't use the description for much of anything anymore unless someone wants to get really fancy.

image

Which driver are you using?