Schlage Z-Wave lock Successes and Solutions

Where did you get the parts for the upgrade?

Sorry just read the rest of the thread and see you already answered.

1 Like

If you just get the electronics module, make sure the seller sends you a photo of the back of the mounting plate, which is where the S2 DSK is printed. You will need that to pair S2. There was a procedure given in the forum that enabled you to get the DSK using PC Controller, but that procedure is rumored not to work any more. It did work when the posting was made (I tested), but I haven’t needed it since.

Edit: found the post:

I just acquired one of these locks and after trying to implement them into hubitat with no success I started searching. Well I found the code given in this post https://community.hubitat.com/t/schlage-locks-its-the-built-in-driver-stupid/106650/43

and after reading it was a bit clunky I passed it through chatgpt to see what it will come up with and here is the result. I am trying it right now and see if it works.

/**
 *   This is a modification of work originally copyrighted by "SmartThings."
 *   All modifications to their work are released under specific terms outlined here.
 */

import groovy.json.JsonOutput
import groovy.json.JsonSlurper
import hubitat.zwave.commands.doorlockv1.*
import hubitat.zwave.commands.usercodev1.*
import groovy.transform.Field

metadata {
    definition(name: "Schlage BE469NX", namespace: "org.mynhier", author: "Jeremy Mynhier") {
        capability "Lock"
        capability "Configuration"
        capability "Refresh"
        capability "Lock Codes"

        attribute "alarmMode", "string" // "unknown", "Off", "Alert", "Tamper", "Kick"
        attribute "alarmSensitivity", "number" // 0 is unknown, otherwise 1-5 scaled to 1-99
        attribute "beeperMode", "string"
        attribute "batteryLevel", "number"
        attribute "lastIncomingEvent", "Date"
        attribute "lastIncomingEventEpoch", "number"

        command "setAlarmMode", [[name: "Alarm Mode", type: "ENUM", constraints: ["Off", "Alert", "Tamper", "Kick"]]]
        command "setAlarmSensitivity", [[name: "Alarm Sensitivity", type: "ENUM", constraints: [1, 2, 3, 4, 5]]]
        command "setBeeperMode", [[name: "Beeper Mode", type: "ENUM", constraints: ["On", "Off"]]]
    }

    preferences {
        input name: "optEncrypt", type: "bool", title: "Enable lockCode encryption", defaultValue: false
        input name: "debugLoggingEnabled", type: "bool", title: "Enable debug logging", defaultValue: false
        input name: "descTxtLoggingEnabled", type: "bool", title: "Enable descriptionText logging", defaultValue: true
    }
}

@Field static final Integer TWELVE_HOURS_IN_MILLIS = 43200000
@Field static final Integer THIRTY_SECONDS_IN_MILLIS = 30000
@Field static final Integer ONE_HOUR_IN_SECONDS = 3600
@Field static final Integer ONE_HALF_HOUR_IN_SECONDS = 1800
@Field static final Integer ASSOCIATION_QUERY_CHARACTER_LIMIT = 9000
@Field static final Integer ALARM_MODE_OFF = 0x0
@Field static final Integer ALARM_MODE_ALERT = 0x1
@Field static final Integer ALARM_MODE_TAMPER = 0x2
@Field static final Integer ALARM_MODE_KICK = 0x3

def configure() {
    state.configured = true
    def cmds = [
        secure(zwave.doorLockV1.doorLockOperationGet()),
        secure(zwave.batteryV1.batteryGet())
    ]
    cmds = delayBetween(cmds, THIRTY_SECONDS_IN_MILLIS)
    if (descTxtLoggingEnabled) log.info "${device.displayName} was configured"
    cmds
}

def installed() {
    sendEvent(name: "checkInterval", value: ONE_HOUR_IN_SECONDS, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"])
    scheduleInstalledCheck()
}

def scheduleInstalledCheck() {
    runIn(120, installedCheck)
}

void updated() {
    log.info "updated..."
    log.warn "description logging is: ${descTxtLoggingEnabled}"
    log.warn "debug logging is: ${debugLoggingEnabled}"
    log.warn "encryption is: ${optEncrypt}"
    updateEncryption()
    if (debugLoggingEnabled) runIn(ONE_HALF_HOUR_IN_SECONDS, logsOff)
}

def parse(String description) {
    sendEvent(name: 'lastIncomingEventEpoch', value: now(), displayed: true)
    sendEvent(name: 'lastIncomingEvent', value: new Date().format('yyyy-MM-dd HH:mm:ss'), displayed: true)
    if (debugLoggingEnabled) log.debug "Parsing a message"
    def result = null
    if (description.startsWith("Err")) {
        result = createEvent(descriptionText: description, isStateChange: true, displayed: false)
    } else {
        def cmd = zwave.parse(description, [0x98: 1, 0x62: 1, 0x63: 1, 0x71: 2, 0x72: 2, 0x80: 1, 0x85: 2, 0x86: 1])
        if (cmd) result = zwaveEvent(cmd)
    }
    result
}

def refresh() {
    def cmds = secureSequence([zwave.doorLockV1.doorLockOperationGet(), zwave.batteryV1.batteryGet()])
    cmds
}

def lock() {
    if (debugLoggingEnabled) log.debug "Sending Lock Command"
    lockAndCheck(DoorLockOperationSet.DOOR_LOCK_MODE_DOOR_SECURED)
}

def unlock() {
    if (debugLoggingEnabled) log.debug "Sending Unlock Command"
    lockAndCheck(DoorLockOperationSet.DOOR_LOCK_MODE_DOOR_UNSECURED)
}

def lockAndCheck(doorLockMode) {
    secureSequence([
        zwave.doorLockV1.doorLockOperationSet(doorLockMode: doorLockMode),
        zwave.doorLockV1.doorLockOperationGet()
    ], 4200)
}

private secure(hubitat.zwave.Command cmd) {
    zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
}

private secureSequence(commands, delay = 4200) {
    delayBetween(commands.collect { secure(it) }, delay)
}

def setAlarmMode(String newValue = null) {
    Integer newMode
    def currentMode = device.currentValue("alarmMode")
    if (newValue == null) {
        newMode = (currentMode == "Off" ? ALARM_MODE_ALERT : currentMode == "Alert" ? ALARM_MODE_TAMPER : ALARM_MODE_OFF)
    } else {
        switch (newValue) {
            case "Off":
                newMode = ALARM_MODE_OFF
                break
            case "Alert":
                newMode = ALARM_MODE_ALERT
                break
            case "Tamper":
                newMode = ALARM_MODE_TAMPER
                break
            case "Kick":
                newMode = ALARM_MODE_KICK
                break
            default:
                log.warn "Invalid alarm mode: $newValue"
                return
        }
    }
    sendEvent(name: 'alarmMode', value: newValue ?: "unknown")
    secureSequence([zwave.configurationV2.configurationSet(parameterNumber: 7, size: 1, configurationValue: [newMode])])
}

def setAlarmSensitivity(newValue) {
    if (newValue < 1 || newValue > 5) {
        log.warn "Alarm sensitivity out of range: $newValue"
        return
    }
    def paramToSet = 0
    def cs = device.currentValue("alarmMode")
    switch (cs) {
        case "Alert": paramToSet = 0x8; break
        case "Tamper": paramToSet = 0x9; break
        case "Kick": paramToSet = 0xA; break
        case "Off": return
    }
    if (paramToSet != 0) {
        sendEvent(name: 'alarmSensitivity', value: 0, displayed: false)
        secureSequence([zwave.configurationV2.configurationSet(parameterNumber: paramToSet, size: 1, configurationValue: [newValue])])
    }
}

def updateEncryption() {
    String lockCodes = device.currentValue("lockCodes")
    if (lockCodes && ((optEncrypt && lockCodes[0] != "{") || (!optEncrypt && lockCodes[0] == "{"))) {
        sendEvent(name: "lockCodes", value: optEncrypt ? encrypt(lockCodes) : decrypt(lockCodes))
    }
}

void logsOff() {
    log.warn "debug logging disabled..."
    device.updateSetting("debugLoggingEnabled", [value: "false", type: "bool"])
}

Any success with this?