[OBSOLETE] Lock User Management (LUM)

Lock User Management (LUM) is a reliable Lock Manager for remotely managing users and locks

It works with the standard Z-Wave Lock/ZigBee device handler that comes with SmartThings and works with any lock that supports remote codes.

It can be used to program user codes, be notified when user codes are used and also take actions when codes are used.

For automatically generating user codes for rental properties check out Rental Lock Automater (RLA).

Click here for a list of lock recommendations

Click here for where to buy Z-Wave locks





You can find installation instructions for LUM here

Lock Code User Management (LUM) is a very reliable and comprehensive commercial grade Lock and User Code Management SmartApp with many (unique) features:

  • Works with the built in SmartThings device handler (Z-Wave and ZigBee)
  • Sure-Programming engine: verifies that programming was successful
  • Unlimited users and locks
  • Program multiple locks simultaneously (supports fixed and variable pin lengths)
  • Easy and intuitive setup
    • Colored icons show user state
      • green → active
      • grey → inactive
      • yellow → pending
      • red → error
  • Different types of users such as:
    • permanent
    • one time
    • expiration (start/end date/time)
    • scheduled (daily/weekly etc) with multiple schedules per user
    • presence based
      • (optional) lock and unlock doors automatically
    • mode based and many more
  • Support for different types of locks and ZigBee/Ring keypads, (bluetooth, RFID, etc)
  • Define custom individual Unlock and Lock actions for users such as:
    • Exit delay actions (wait for X minutes before running actions)
    • Separate actions for Keypad and Manual locking/unlocking and per door actions
    • Create custom actions for security Keypad away/stay/night buttons
    • Turning on lights if it’s dark outside
    • Unlocking/locking secondary locks
    • Opening/closing garage doors
    • Notifications on type of lock/unlock (manual, code, keypad, bluetooth, rfid etc)
    • Changing modes
    • Arming/Disarming STHM
    • Turning on/off switches
    • Custom notifications settings (who and how many)
    • Define rules when to run and not run actions
  • Define Door Open/Close actions such as
    • Automatically relocking the door when it’s closed
    • Ringing chimes when door is opened
    • Notifications if door is left open
    • Define actions for each door separately
  • Lots of built in safety mechanisms to ensure users have a reliable experience
  • Compatibility with SmartLocks
  • and lots more…

You can find the LUM FAQ document here

Please ensure that your lock is within 20ft of a buffering device for the best experience (the hub does not buffer)

Check out this post which compares different locks brands features and certain lock limitations.

Optionally you can use the Enhanced Universal Z-Wave Lock or the Universal ZigBee Lock device handler for a more customized lock experience.

Some examples of how folks are using this app:

  1. I give my landlord an access code for the lock but I want it disabled when I’m at home (presence based users)
  2. When my children are at home and the parents aren’t home, then allow the babysitter’s code to work (presence based users)
  3. When we’re away, allow my neighbor’s code to work (mode based users)
  4. I can schedule a code for my nanny with multiple schedules per day (morning and evening)
  5. I can program ahead for my vacation rental properties with a start and end date/time for my guests
  6. When I lock my door from outside I want my house to lock up behind me (close garage doors, lock all other doors, turn off switches, arm the security system etc)
  7. When I unlocked my outer door I want the inner door to also unlock and the lights to turn on but only at night
  8. I want my employees to have access only during business hours or on specifics days/modes
  9. I want to open Garage door A when I press the away button and Garage door B when I press the Stay button on my Keypad
  10. I want to control my STHM state using an external keypad and also control my patio door

This app is available on the RBoy Apps Server.

Visit our website for more details and to get access to all our apps.

Visit our Facebook page for updates on new apps: http://www.facebook.com/RBoySTApps


Single user lock code management

OVERVIEW and INSTRUCTIONS
The below a basic version which allows you to manage the door user codes individually. This is for security if you don’t want history of user codes to be left in the app or are managing the user codes manually from the lock also. It can be used with multiple locks simultaneously (make sure they have the same code lengths) but can only program (add/update/delete) one user at a time. It also supports expiry of single user codes. It has NO memory of previously programmed codes. It’s a once and done shot. It is good for ad-hoc code management.

The latest version of all apps with updates are available on the RBoy Apps server.

/* **DISCLAIMER**
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Without limitation of the foregoing, Contributors/Regents expressly does not warrant that:
* 1. the software will meet your requirements or expectations;
* 2. the software or the software content will be free of bugs, errors, viruses or other defects;
* 3. any results, output, or data provided through or generated by the software will be accurate, up-to-date, complete or reliable;
* 4. the software will be compatible with third party software;
* 5. any errors in the software will be corrected.
* The user assumes all responsibility for selecting the software and for the results obtained from the use of the software. The user shall bear the entire risk as to the quality and the performance of the software.
*/ 

/**
* Add and remove user codes for locks
*
* Copyright RBoy Apps
* Redistribution of any changes or code is not allowed without permission
*
* Change Log:
* 2016-5-15 - Fix issue with non existent timezone
* 2015-7-6 - Fixed issue with code expiry not working
* 2015-6-17 - Fix for dynamic preferences not working after ST platform update
* 2015-5-27 - Bugfix for expiration date entry
* 2015-2-11 - Added support for expiration dates
* 2015-1-1 - Added option to customizing name
* 2014-11-27 - Stable created
*
*/
definition(
    name: "Lock single user code management",
    namespace: "rboy",
    author: "RBoy",
    description: "Add and Delete Single User Codes for Locks",
    category: "Safety & Security",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Allstate/lock_it_when_i_leave.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Allstate/lock_it_when_i_leave@2x.png"
)

import org.joda.time.DateTime

preferences {
    page(name: "setupApp")
}

def setupApp() {
    dynamicPage(name: "setupApp", title: "Lock User Management", install: true, uninstall: true) {    
        section("Select Lock(s)") {
            input "locks","capability.lock", title: "Lock", multiple: true,  submitOnChange:true
        }
        section("User Management") {
            input "user", "number", title: "User Slot Number", description: "This is the user slot number on the lock and not the user passcode",  submitOnChange:true
            input "action", "enum", title: "Add/Update/Delete User?", required: true, options: ["Add/Update","Delete"],  submitOnChange:true
        }

        if (action == "Add/Update") {
            def invalidDate = true
            if (expDate) {
                log.debug "Found expiry date in setup"
                try {
                    Date.parse("yyyy-MM-dd", expDate)
                    invalidDate = false
                }
                catch (Exception e) {
                    log.debug "Invalid expiry date in setup"
                    invalidDate = true
                }
            }

            section("Add/Update User Code") {
                input "code", "text", title: "User Passcode (check your lock passcode length)", defaultValue: "X", description: "The user passcode for adding/updating a new user (enter X for deleting user)"
            }

            section("Code Expiration Date and Time (Optional)") {
                if (expDate && invalidDate == true) {
                    paragraph "INVALID DATE - PLEASE CHECK YOUR DATE FORMAT"
                }
                else if (expDate) {
                    def ed = Date.parse("yyyy-MM-dd", expDate)
                    paragraph "Code expiry date set for ${ed.format("EEE MMM dd yyyy")}"
                }

                if (expDate) {
                    if (!expTime) {
                        paragraph "PLEASE ENTER TIME FOR CODE EXPIRY"
                    }
                }

                input "expDate", "date", title: "Code expiration date (YYYY-MM-DD)", description: "Date on which the code should be deleted", required: false,  submitOnChange:true
                input "expTime", "time", title: "Code expiration time", description: "(Touch here to set time) The code would be deleted within 5 minutes of this time", required: false,  submitOnChange:true
            }
        }

        section([mobileOnly:true]) {
            label title: "Assign a name for this SmartApp", required: false
        }
    }
}

def installed()
{
    log.debug "Install Settings: $settings"
    state.codes = [:]
    unschedule()
    runEvery5Minutes(expireCodeCheck)
    runIn(1, appTouch)
}

def updated()
{
    log.debug "Update Settings: $settings"
    if (!state.codes) {
        state.codes = [:]
    }
    unschedule()
    runEvery5Minutes(expireCodeCheck)
    runIn(1, appTouch)
}

def appTouch() {
    if (action == "Delete") {
        for (lock in locks) {
            lock.deleteCode(user)
            log.info "$lock deleted user: $user"
            sendNotificationEvent("$lock deleted user: $user")
            sendPush "$lock deleted user: $user"
        }
        log.debug "Removing tracking expiry of user $user"
        state.codes.remove((user as String)) // remove it from the tracker, we don't an unexpected code removal later
    } else {
        for (lock in locks) {
            lock.setCode(user, code)
            log.info "$lock added user: $user, code: $code"
            sendNotificationEvent("$lock added user: $user")
            sendPush "$lock added user: $user"
        }

        if (expDate && expTime) {
            TimeZone timeZone = location.timeZone
            if (!timeZone) {
                timeZone = TimeZone.getDefault()
                log.error "Hub location/timezone not set, using ${timeZone.getDisplayName()} timezone. Please set Hub location and timezone for the codes to work accurately"
                sendPush "Hub location/timezone not set, using ${timeZone.getDisplayName()} timezone. Please set Hub location and timezone for the codes to work accurately"
            }
            log.trace "The date/time on the hub now is ${(new Date(now())).format("EEE MMM dd yyyy HH:mm z", timeZone)}"
            def midnightToday = timeToday("2000-01-01T00:00:00.000-0000", timeZone)
            def expT = (timeToday(expTime, timeZone).time - midnightToday.time)
            String dst = timeZone.getDisplayName(timeZone.inDaylightTime(new Date(now())), TimeZone.SHORT) // Keep current timezone
            def expD = Date.parse("yyyy-MM-dd Z", expDate + " " + dst).toCalendar()
            def exp = expD.getTimeInMillis() + expT
            log.debug "Removing any existing tracking expiry of user $user"
            state.codes.remove((user as String)) // remove it from the tracker so we don't duplicate if the code being overwritten
            state.codes.put(user,exp) // Add to the expiry list
            def expStr = (new Date(exp)).format("EEE MMM dd yyyy HH:mm z", timeZone)
            log.info "$locks user code expiration set to $expStr"
            sendNotificationEvent("$locks user $user code will expire on $expStr")
            sendPush "$locks user $user code will expire on $expStr"
        }
    }
}

def expireCodeCheck() {
    log.debug "ExpireCodeCheck called"
    def allCodes = state.codes.collect() // make a copy otherwise we can't remove it from the for loop (concurrent exception)
    for (code in allCodes) {
        TimeZone timeZone = location.timeZone
        if (!timeZone) {
            timeZone = TimeZone.getDefault()
            log.error "Hub location/timezone not set, using ${timeZone.getDisplayName()} timezone. Please set Hub location and timezone for the codes to work accurately"
            sendPush "Hub location/timezone not set, using ${timeZone.getDisplayName()} timezone. Please set Hub location and timezone for the codes to work accurately"
        }
        log.trace "The date/time on the hub now is ${(new Date(now())).format("EEE MMM dd yyyy HH:mm z", timeZone)}"
        def expStr = (new Date(code.value)).format("EEE MMM dd yyyy HH:mm z", timeZone)
        log.debug "user ${code.key} expires $expStr"
        if (code.value < now()) {
            def user = code.key as Integer // Convert back to integer, groovy converts to string in a key value pair
            for (lock in locks) {
                lock.deleteCode(user)
                log.info "$lock deleted expired user: $user"
                sendNotificationEvent("$lock deleted expired user: $user")
                sendPush "$lock deleted expired user: $user"
            }
            log.debug "Removing tracking of user $user"
            state.codes.remove((user as String)) // remove it from the tracker, we're done here
        }
    }
}

Copyright (c) RBoy Apps

34 Likes

I have Kwiksets and I have the same issue. I would love to have this functionality so I can add codes when I’m away. I’m fairly certain that Revolv had the functionality. I’m hoping ST can get it integrated.

This is what I use and it works with Kwikset 914’s

thanks @acastal I tried that but it isn’t working with either of my 2 locks. It doesn’t seem to get a response from the lock after sending the command to add the user code.

Could it be because the lock doesn’t report the capability to manage user codes? What is what I see in my raw description. I don’t see 0x63

Raw Description 0 0 0x4003 0 0 0 5 0x22 0x72 0x7A 0x98 0x86

For me it just worked. Months after installing the first lock when I installed my second one I forgot the change the device from Zwave lock to the custom lock type so it did not work until i remembered to do that as well.

Any you can pull up the raw capability list from your Device List and post it here to me to compare?

Raw Description 0 0 0x4003 0 0 0 3 0x72 0x86 0x98

Is that what you are looking for? This is with Custom Lock device type.

yes thanks, I don’t see 0x63 (user codes) in your list but it seems to be working for you. I’m guessing there’s something different about schlage locks, maybe they use sub channels to communicate. (like the CT100 uses sub channels for RH parameters). Wonder where I can get that info.

Interestingly CasaVerde supports remote codes for schalge locks.
http://wiki.micasaverde.com/index.php/Schlage_Lock

@duncan and @urman on another thread you had mentioned that Schlage locks remote administration features are supported but they haven’t been implemented due to a backlog.

Can you please share some pointers with us on how we can communicate / setup the communication with the schlage locks so we can manually modify the device apps for now to make it work. Unfortunatley I can’t find any technical documentation on how to access teh remote pin code features for Schlage and the setUserCode is not working (nothing is being returned from the lock).

Pointers would be much appreciated. thanks

Probably you aren’t getting any response because you aren’t subscribing to the right attribute. Here’s a post I wrote on the Lock Codes capability:

Also, user should be an integer, not a string.

The reason you don’t see user codes in the command class list is because it is only available encapsulated by the security command class, 0x98.

1 Like

@duncan you are a freaking GENIUS!! I’ve been breaking my head on this for weeks and ONLY issue was I send a text instead of an integer. Add, update and remove user all work great with the standard Z-Wave lock device type. I’ll post the updated Smart App above.

One last question - I’m trying to create a dynamic page, ie. when the user select add user it should pop up one more input for the code other when selecting delete user it should not have any inputs. I can’t find the right documentation, could you point me in the right direction here.

Thanks again.

2 Likes

RB,

Just wanted to say thanks for this code. This is wonderful.

Looking forward to the repost of the updated app. I tried @acastal 's app last night but the code didn’t seem to take on a test (and yes I was using an integer for the user). There are so many great app’s like this buried in the private depths of the 11,000 apps. Sure hope there is a common, searchable, repository one day.

I didn’t have to make any changes to the device type, it just worked with the standard z-wave lock device type.

And I complete agree with you. We’re all reinventing the wheel here and hopefully we’ll have a app repository soon with categories. I’ve even submitted these apps to ST to publish.

1 Like

RB,

Just wanted to say thanks. This works great!!!

Thanks for the work, will this work with the Yale locks?

I only have a Schlage lock to test with. Maybe you can try it and let us know, if the Yale lock follows the same z-wave commands I don’t see why not. I think it should work with any lock unless the lock has a custom way to communicating the user information.
It’s just a SmartApp so no harm done :smile:

I saw you mentioned posting an updated Smart App that’s why I mentioned the repost.
When I have the app installed I only have the option of Delete with yes/no boolean. You mention Add, update and remove. Am I running the same code?

Correct when it’s not deleting it will Add (or Update if the slot is already filled). I’m still trying to figure out how to create a dynamic page to make it clearer. Any help for folks who know dynamic pages would be helpful :smile: