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
- Colored icons show user state
- 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)
- Multiple/international SMS’s
- Speak notifications (e.g. Alexa or Sonos or Bose or Ikea-Sonos SYMFONISK)
- 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:
- I give my landlord an access code for the lock but I want it disabled when I’m at home (presence based users)
- When my children are at home and the parents aren’t home, then allow the babysitter’s code to work (presence based users)
- When we’re away, allow my neighbor’s code to work (mode based users)
- I can schedule a code for my nanny with multiple schedules per day (morning and evening)
- I can program ahead for my vacation rental properties with a start and end date/time for my guests
- 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)
- When I unlocked my outer door I want the inner door to also unlock and the lights to turn on but only at night
- I want my employees to have access only during business hours or on specifics days/modes
- 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
- 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
}
}
}