Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 30 additions & 30 deletions devicetypes/smartthings/zigbee-lock.src/zigbee-lock.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ metadata {
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0009,0020,0101,0402,0B05,FDBD", outClusters: "000A,0019", manufacturer: "Kwikset", model: "SMARTCODE_LEVER_5", deviceJoinName: "Kwikset 5-Button Lever"
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0009,0020,0101,0402,0B05,FDBD", outClusters: "000A,0019", manufacturer: "Kwikset", model: "SMARTCODE_DEADBOLT_10", deviceJoinName: "Kwikset 10-Button Deadbolt"
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0009,0020,0101,0402,0B05,FDBD", outClusters: "000A,0019", manufacturer: "Kwikset", model: "SMARTCODE_DEADBOLT_10T", deviceJoinName: "Kwikset 10-Button Touch Deadbolt"
fingerprint inClusters: "0000, 0003, 0101", manufacturer:"Kwikset", model:"Smartcode", deviceJoinName: "Kwikset Smartcode Lock"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0101", manufacturer:"Kwikset", model:"Smartcode", deviceJoinName: "Kwikset Smartcode Lock"
}

tiles(scale: 2) {
Expand Down Expand Up @@ -156,7 +156,7 @@ def poll() {
cmds << zigbee.readAttribute(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING)
state.lastbatt = now()
}

if (cmds) {
log.info "ZigBee DTH - poll() returning with cmds:- $cmds"
return cmds
Expand Down Expand Up @@ -207,7 +207,7 @@ def doConfigure() {
DataType.UINT8, 600, 21600, 0x01) +
zigbee.configureReporting(CLUSTER_ALARM, ALARM_ATTR_ALARM_COUNT,
DataType.UINT16, 0, 21600, null)

def allCmds = refresh() + cmds + reloadAllCodes()
log.info "ZigBee DTH - doConfigure() returning with cmds:- $allCmds"
allCmds // send refresh and reloadAllCodes cmds as part of configureDevice
Expand Down Expand Up @@ -250,7 +250,7 @@ def reloadAllCodes() {
state.checkCode = state.checkCode ?: 0
}
cmds += requestCode(state.checkCode)

log.info "ZigBee DTH - reloadAllCodes() returning with cmds:- $cmds"
return cmds
}
Expand All @@ -272,7 +272,7 @@ def setCode(codeID, code, codeName = null) {
nameSlot(codeID, codeName)
return
}

log.trace "ZigBee DTH - Executing setCode() for device ${device.displayName}"
if (isValidCodeID(codeID) && isValidCode(code)) {
log.debug "Zigbee DTH - setting code in slot number $codeID"
Expand All @@ -289,7 +289,7 @@ def setCode(codeID, code, codeName = null) {
} else {
cmds << zigbee.command(CLUSTER_DOORLOCK, DOORLOCK_CMD_USER_CODE_SET, setPayload).first()
}

def strname = (codeName ?: "Code $codeID")
state["setname$codeID"] = strname
if(attrCmds) {
Expand Down Expand Up @@ -383,7 +383,7 @@ def updateCodes(codeSettings) {
}
} else log.warn("unexpected entry $name: $updated")
}

if (set_cmds && get_cmds) {
def allCmds = []
allCmds = delayBetween(set_cmds, 2200) + ["delay 2200"] + delayBetween(get_cmds, 4200)
Expand Down Expand Up @@ -500,7 +500,7 @@ private def parseAttributeResponse(String description) {
log.trace "ZigBee DTH - parseAttributeResponse() - ignoring attribute response"
return null
}

if (responseMap.data) {
responseMap.data.lockName = deviceName
} else {
Expand All @@ -522,15 +522,15 @@ private def parseCommandResponse(String description) {
Map descMap = zigbee.parseDescriptionAsMap(description)
def deviceName = device.displayName
log.trace "ZigBee DTH - Executing parseCommandResponse() for device ${deviceName}"

def result = []
Map responseMap = [:]
def data = descMap.data
def lockCodes = loadLockCodes()

def cmd = descMap.commandInt
def clusterInt = descMap.clusterInt

if (clusterInt == CLUSTER_DOORLOCK && (cmd == DOORLOCK_CMD_LOCK_DOOR || cmd == DOORLOCK_CMD_UNLOCK_DOOR)) {
log.trace "ZigBee DTH - Executing DOOR LOCK/UNLOCK SUCCESS for device ${deviceName} with description map:- $descMap"
// Reading lock state with a delay of 4200 as some locks do not report their state change
Expand All @@ -542,14 +542,14 @@ private def parseCommandResponse(String description) {
log.trace "ZigBee DTH - Executing DOORLOCK_RESPONSE_OPERATION_EVENT for device ${deviceName} with description map:- $descMap"
def eventSource = Integer.parseInt(data[0], 16)
def eventCode = Integer.parseInt(data[1], 16)

responseMap.name = "lock"
responseMap.displayed = true
responseMap.isStateChange = true

def desc = ""
def codeName = ""

if (eventSource == 0) {
def codeID = Integer.parseInt(data[3] + data[2], 16)
if (!isValidCodeID(codeID, true)) {
Expand All @@ -565,7 +565,7 @@ private def parseCommandResponse(String description) {
desc = "manually"
responseMap.data = [ method: "manual" ]
}

switch (eventCode) {
case 1:
responseMap.value = "locked"
Expand Down Expand Up @@ -636,14 +636,14 @@ private def parseCommandResponse(String description) {
// Programming event is generated when the user creates/updates/deletes a code manually on the lock.
// Ideally it should be generated even when the user tries to create/update a code through the
// SmartApp as well, but that is not the case with Yale locks.

responseMap.name = "codeChanged"
responseMap.isStateChange = true
responseMap.displayed = true

def codeID = Integer.parseInt(data[3] + data[2], 16)
def codeName

def eventCode = Integer.parseInt(data[1], 16)
switch (eventCode) {
case 1: // MasterCodeChanged
Expand Down Expand Up @@ -688,25 +688,25 @@ private def parseCommandResponse(String description) {
}
} else if (clusterInt == CLUSTER_DOORLOCK && cmd == DOORLOCK_CMD_USER_CODE_GET) {
log.trace "ZigBee DTH - Executing DOORLOCK_CMD_USER_CODE_GET for device ${deviceName}"
// This is called only when the user creates/updates a code using the SmartApp (in case of Yale locks)
// This is called only when the user creates/updates a code using the SmartApp (in case of Yale locks)
// or when the user tries to scan the lock by calling reloadAllCodes()

def userStatus = Integer.parseInt(data[2], 16)
def codeID = Integer.parseInt(data[1] + data[0], 16)
def codeName = getCodeNameFromState(lockCodes, codeID)

// PIN code saved in the state - it will be non null only in case of Yale locks
def localCode = decrypt(state["setcode$codeID"])

responseMap.name = "codeChanged"
responseMap.isStateChange = true
responseMap.displayed = true

// userStatus = 1 indicates that the code slot is occupied
if (userStatus == 1) {
if (localCode && isYaleLock()) {
// This will be applicable for Yale locks - both create and update through the SmartApp

// PIN code fetched from the lock
def serverCode = getCodeFromOctet(data)
if (localCode == serverCode) {
Expand Down Expand Up @@ -752,7 +752,7 @@ private def parseCommandResponse(String description) {
// or lock is out of range, or there is wireless interference, the Lock will not be able to respond
// back with user code get response.
responseMap.data = [isCodeDuplicate: true]

def codeReportMap = [ name: "codeReport", value: codeID, data: [ code: "" ], isStateChange: true, displayed: false ]
codeReportMap.descriptionText = "Code $codeID is not set"
result << createEvent(codeReportMap)
Expand All @@ -770,7 +770,7 @@ private def parseCommandResponse(String description) {
}
}
clearStateForSlot(codeID)

if (codeID == state.checkCode) {
log.debug "Code scanning in progress..."
def defaultMaxCodes = isYaleLock() ? 8 : 7
Expand Down Expand Up @@ -829,7 +829,7 @@ private def parseCommandResponse(String description) {
} else {
log.trace "ZigBee DTH - parseCommandResponse() - ignoring command response"
}

if(responseMap["value"]) {
if (responseMap.data) {
responseMap.data.lockName = deviceName
Expand Down Expand Up @@ -901,7 +901,7 @@ private def allCodesDeletedEvent() {
lockCodes.each { id, code ->
result << createEvent(name: "codeReport", value: id, data: [ code: "" ], descriptionText: "code $id was deleted",
displayed: false, isStateChange: true)

def codeName = code
result << createEvent(name: "codeChanged", value: "$id deleted",
data: [ codeName: codeName, lockName: deviceName, notify: true,
Expand Down Expand Up @@ -953,7 +953,7 @@ private def getCodeFromOctet(data) {
* Checks if the slot number is within the allowed limits
*
* @param codeID The code slot number
*
*
* @param allowMasterCode Flag to indicate if master code slot should be allowed as a valid slot
*
* @return true if valid, false if not
Expand Down Expand Up @@ -1134,7 +1134,7 @@ def reportsBatteryIncorrectly() {

/**
* Reads the code name from the device state
*
*
* @param lockCodes: map with lock code names
*
* @param codeID: The code slot number
Expand Down