PetSafe SmartDoor Model HPA15-13808 (DTH in post 27)

Well I can verify at Lowes’s does in fact sell this door. And it does get picked up on smartthings when you try to add a new device it appears it only needs to be programmed. It utilizes zigbee. I am in dire need as to how to program this dog door

1 Like

Once it is added to ST, can you try logging into the IDE and clicking on it under MyDevices? There should be a field Raw Description. What’s in that field?

Name Thing
Label Thing
Type Unknown
Version Published
Zigbee Id 00124B000253A23C
Device Network Id 8BED
Status ACTIVE
Hub Home Hub
Date Created 2015-01-17 10:10 AM EST
Last Updated 2015-01-17 10:11 AM EST
Data No data found for device
Raw Description 0C 0104 000A 00 06 0000 0001 0003 0009 000A 0101 06 0000 0001 0003 0009 000A 0101
Current States No states found
Events List Events
In Use By SmartApps

Looks like a zigbee lock which may not be supported yet. @duncan has this changed or is a firmware update still needed?

if it isn’t supported is there a way to skin this with a smart app?

Usually when ST says there is a firmware update required it means the device uses features of Zigbee that ST hasn’t implemented yet, so there might not be anything we can do. It’s probably the security protocols or lock code features. We might be able to get basic lock/unlock to work unless we need special security messages.

I’ll try to put something together this weekend to give you the basic functions, but it’s hard to do without the device. Does it unlock for the presence tag it came with?

Honestly it is paired but it doesn’t do anything at all i need at this point is to lock unlock the door and being able to set it for at time so m-f unlock at 9am

1 Like

I’m flying blind without a device to test, but try the below code for the device type. A lot of the pieces won’t work, but I think it should be able to lock and unlock. Hopefully that works, and if you send me the live logs from a lock, unlock and refresh command; I might be able to refine it (if it works that is).

/**
 *  PetSafe Smart Door
 *
 *  Copyright 2015 Scott Gibson
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 */
metadata {
	// Automatically generated. Make future change here.
	definition (name: "PetSafe Smart Door", namespace: "sticks18", author: "Scott Gibson") {
		capability "Battery"
		capability "Polling"
		capability "Actuator"
		capability "Refresh"
		capability "Lock"

		fingerprint profileId: "0104", inClusters: "0000 0001 0003 0009 000A 0101", outClusters: "0000 0001 0003 0009 000A 0101"
	}


		simulator {
		// status "locked": "command: 9881, payload: 00 62 03 FF 00 00 FE FE"
		// status "unlocked": "command: 9881, payload: 00 62 03 00 00 00 FE FE"

		// reply "9881006201FF,delay 4200,9881006202": "command: 9881, payload: 00 62 03 FF 00 00 FE FE"
		// reply "988100620100,delay 4200,9881006202": "command: 9881, payload: 00 62 03 00 00 00 FE FE"
	}

	tiles {
		standardTile("toggle", "device.lock", width: 2, height: 2) {
			state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#79b821", nextState:"unlocking"
			state "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff", nextState:"locking"
			state "unknown", label:"unknown", action:"lock.lock", icon:"st.locks.lock.unknown", backgroundColor:"#ffffff", nextState:"locking"
			state "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#79b821"
			state "unlocking", label:'unlocking', icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff"
		}
		standardTile("lock", "device.lock", inactiveLabel: false, decoration: "flat") {
			state "default", label:'lock', action:"lock.lock", icon:"st.locks.lock.locked", nextState:"locking"
		}
		standardTile("unlock", "device.lock", inactiveLabel: false, decoration: "flat") {
			state "default", label:'unlock', action:"lock.unlock", icon:"st.locks.lock.unlocked", nextState:"unlocking"
		}
		valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
			state "battery", label:'${currentValue}% battery', unit:""
		}
		standardTile("refresh", "device.lock", inactiveLabel: false, decoration: "flat") {
			state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
		}

		main "toggle"
		details(["toggle", "lock", "unlock", "battery", "refresh"])
	}
}

// parse events into attributes
def parse(String description) {
	
    log.trace description
    
    def msg = zigbee.parse(description)
    log.trace msg
    
    
	// TODO: handle 'battery' attribute
	// TODO: handle 'lock' attribute

}

// handle commands
def poll() {
	
    log.debug "Executing 'poll'"
	refresh()
}

def refresh() {
	
    [
	"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 500",
    "st rattr 0x${device.deviceNetworkId} 1 0101 0"
    ]
    
}

def updated() {

	configure()
    
}

def lock() {
	
    log.debug "Executing 'lock'"
    sendEvent(name: "lock", value: "locked")
	"st cmd 0x${device.deviceNetworkId} 1 0101 0 {}"
    
}

def unlock() {
	
    log.debug "Executing 'unlock'"
	sendEvent(name: "lock", value: "unlocked")
	"st cmd 0x${device.deviceNetworkId} 1 0101 1 {}"
    
}

def configure() {

	String zigbeeId = swapEndianHex(device.hub.zigbeeId)
	log.debug "Confuguring Reporting and Bindings."
	def configCmds = [	

        //Lock Reporting
        "zcl global send-me-a-report 0101 0 0x30 0 3600 {01}", "delay 500",
        "send 0x${device.deviceNetworkId} 1 1", "delay 1000",

        //Battery Reporting
        "zcl global send-me-a-report 1 0x20 0x20 5 3600 {}", "delay 200",
        "send 0x${device.deviceNetworkId} 1 1", "delay 1500",

        "zdo bind 0x${device.deviceNetworkId} 1 1 0101 {${device.zigbeeId}} {}", "delay 500",
        "zdo bind 0x${device.deviceNetworkId} 1 1 1 {${device.zigbeeId}} {}"
    
    ]
    return configCmds + refresh() // send refresh cmds as part of config
}

private hex(value, width=2) {
	def s = new BigInteger(Math.round(value).toString()).toString(16)
	while (s.size() < width) {
		s = "0" + s
	}
	s
}

private Integer convertHexToInt(hex) {
	Integer.parseInt(hex,16)
}

private String swapEndianHex(String hex) {
    reverseArray(hex.decodeHex()).encodeHex()
}

private byte[] reverseArray(byte[] array) {
    int i = 0;
    int j = array.length - 1;
    byte tmp;
    while (j > i) {
        tmp = array[j];
        array[j] = array[i];
        array[i] = tmp;
        j--;
        i++;
    }
    return array
}

Testing it right now

ok none of the app works it will not lock or unlock the door in any capacity
here’s the log

11:38:48 PM: debug Executing 'poll’
11:37:42 PM: debug Executing 'unlock’
11:37:26 PM: debug Executing 'lock’
11:37:09 PM: debug Executing 'unlock’
11:36:30 PM: debug Configuring Reporting and Bindings.
11:36:14 PM: debug Executing 'lock’
11:35:49 PM: debug Configuring Reporting and Bindings.

if it helps the battery percentage isn’t showing either.

Is that from the live logs? Or just the event history? If that’s the live log, then there’s no communication happening between bulb and ST.

Can you try resetting and repairing the device with live logs running? And let it run for a few minutes.

I don’t have the parse method setup yet because I don’t know what the messages look like, so I just put in place a logging to capture them. They would be trace messages and I don’t see them in the log you sent, so we’re not getting any messages from the door.

Where are the live longs

When you log into the IDE, along the top is an option “Live Logging” (two to the right of My Device Types). It will show you a running log of all your devices, and you can select the pet door to show all messages it generates.

2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:18:26 PM: trace SmartShield(clusterId: 0x0101, command: 0x20, data: [0x02, 0x0e, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff], destinationEndpoint: 0x01, direction: 0x01, isClusterSpecific: true, isManufacturerSpecific: false, manufacturerId: 0x0000, messageType: 0x00, number: null, options: 0x0100, profileId: 0x0104, senderShortId: 0x8bed, sourceEndpoint: 0x0c, text: null)
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:18:26 PM: trace catchall: 0104 0101 0C 01 0100 00 8BED 01 00 0000 20 01 020EFF00FFFFFFFFFF
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:18:26 PM: trace null
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:18:26 PM: trace read attr - raw: 8BED0C01010825003000, dni: 8BED, endpoint: 0C, cluster: 0101, size: 08, attrId: 0025, encoding: 30, value: 00
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:18:20 PM: trace SmartShield(clusterId: 0x0101, command: 0x20, data: [0x02, 0x0e, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff], destinationEndpoint: 0x01, direction: 0x01, isClusterSpecific: true, isManufacturerSpecific: false, manufacturerId: 0x0000, messageType: 0x00, number: null, options: 0x0100, profileId: 0x0104, senderShortId: 0x8bed, sourceEndpoint: 0x0c, text: null)
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:18:20 PM: trace catchall: 0104 0101 0C 01 0100 00 8BED 01 00 0000 20 01 020EFF00FFFFFFFFFF
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:18:20 PM: trace null
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:18:20 PM: trace read attr - raw: 8BED0C01010825003000, dni: 8BED, endpoint: 0C, cluster: 0101, size: 08, attrId: 0025, encoding: 30, value: 00
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:17:59 PM: debug Executing 'unlock’
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:17:50 PM: debug Executing 'lock’
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:17:32 PM: trace SmartShield(clusterId: 0x0101, command: 0x20, data: [0x03, 0x02, 0x7f, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x6f, 0x75, 0x74], destinationEndpoint: 0x01, direction: 0x01, isClusterSpecific: true, isManufacturerSpecific: false, manufacturerId: 0x0000, messageType: 0x00, number: null, options: 0x0100, profileId: 0x0104, senderShortId: 0x8bed, sourceEndpoint: 0x0c, text: null)
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:17:32 PM: trace catchall: 0104 0101 0C 01 0100 00 8BED 01 00 0000 20 01 03027F00FFFFFFFFFF036F7574
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:16:05 PM: debug Executing 'unlock’
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:15:48 PM: debug Executing 'lock’
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:15:27 PM: debug Executing ‘unlock’

that is the live log for just the pet door with me trying to lock/unlock it the battery and the refresh

this is using the repair utility

3668231f-d28c-498d-9a25-659b8b92910c 6:39:10 PM: debug Parse returned raw:7D3B00000FFF0C0000000000, dni:7D3B, normalActual:00000FFF, normalExpected:0C, aggressiveActual:00000000, aggressiveExpected:00
14a205a5-c6b3-4c8d-892b-4c8eafab72d5 6:39:10 PM: debug Parse returned raw:852700000FFF0D0000000000, dni:8527, normalActual:00000FFF, normalExpected:0D, aggressiveActual:00000000, aggressiveExpected:00
e685e94d-b9e9-444d-984c-c99c1332fd07 6:39:09 PM: debug Parse returned raw:6E4300000FFF0C0000000000, dni:6E43, normalActual:00000FFF, normalExpected:0C, aggressiveActual:00000000, aggressiveExpected:00
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:39:04 PM: debug Executing ‘poll’
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:38:51 PM: trace SmartShield(clusterId: 0x0101, command: 0x20, data: [0x02, 0x0e, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff], destinationEndpoint: 0x01, direction: 0x01, isClusterSpecific: true, isManufacturerSpecific: false, manufacturerId: 0x0000, messageType: 0x00, number: null, options: 0x0100, profileId: 0x0104, senderShortId: 0x8bed, sourceEndpoint: 0x0c, text: null)
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:38:51 PM: trace catchall: 0104 0101 0C 01 0100 00 8BED 01 00 0000 20 01 020EFF00FFFFFFFFFF
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:38:51 PM: trace null
2b87262d-a18e-4f8d-99e3-4ffd9907404c 6:38:51 PM: trace read attr - raw: 8BED0C01010825003000, dni: 8BED, endpoint: 0C, cluster: 0101, size: 08, attrId: 0025, encoding: 30, value: 00
a9416eea-5996-441a-8cd7-250d7d08833f 6:38:51 PM: trace cp desc: desc: 0C 0104 000A 00 06 0000 0001 0003 0009 000A 0101 06 0000 0001 0003 0009 000A 0101
a9416eea-5996-441a-8cd7-250d7d08833f 6:38:50 PM: trace cp desc: ep_cnt:1, ep:0C
a9416eea-5996-441a-8cd7-250d7d08833f 6:38:50 PM: trace cp desc: join
6798f979-2921-457a-acf1-021d06b5ad0d 6:38:39 PM: debug Parse returned [[value:idle, name:thermostatOperatingState, isStateChange:false, displayed:false, linkText:Thermostat, descriptionText:Thermostat thermostat operating state is idle]]
6798f979-2921-457a-acf1-021d06b5ad0d 6:38:36 PM: debug Parse returned [[value:fanAuto, name:thermostatFanMode, displayed:false, isStateChange:false, linkText:Thermostat, descriptionText:Thermostat thermostat fan mode is fanAuto]]
6798f979-2921-457a-acf1-021d06b5ad0d 6:38:34 PM: debug Parse returned [[value:auto, name:thermostatMode, isStateChange:false, displayed:false, linkText:Thermostat, descriptionText:Thermostat thermostat mode is auto]]
6798f979-2921-457a-acf1-021d06b5ad0d 6:38:32 PM: debug Parse returned [[value:80, unit:F, displayed:false, name:coolingSetpoint, isStateChange:false, linkText:Thermostat, descriptionText:Thermostat cooling setpoint is 80°F]]
6798f979-2921-457a-acf1-021d06b5ad0d 6:38:29 PM: debug Parse returned [[value:69, unit:F, displayed:false, name:heatingSetpoint, isStateChange:false, linkText:Thermostat, descriptionText:Thermostat heating setpoint is 69°F]]
353981dc-a176-44fc-865f-59c9dbcc1c12 6:38:28 PM: debug poll is sending [], state: [‘code22’:’’, ‘code21’:’’, ‘code24’:’’, ‘code23’:’’, ‘fw’:‘2.6’, ‘code20’:’’, ‘lastbatt’:1421586697981, ‘code29’:’’, ‘code25’:’’, ‘code26’:’’, ‘code27’:’’, ‘MSR’:‘0090-0001-0001’, ‘lastPoll’:1421708653768, ‘code28’:’’, ‘code13’:’’, ‘code12’:’’, ‘code11’:’’, ‘assoc’:1, ‘code10’:’’, ‘code9’:’’, ‘code6’:’’, ‘code5’:’’, ‘sec’:‘72 86 98 80 85 70 75 62 63 4E 4C 71 8B 20 ‘, ‘code8’:’’, ‘code7’:’’, ‘code2’:’’, ‘code1’:’’, ‘codes’:30, ‘code18’:’’, ‘code4’:’’, ‘code30’:’’, ‘code19’:’’, ‘code3’:‘2660’, ‘code16’:’’, ‘code17’:’’, ‘code14’:’’, ‘code15’:’’]
a9416eea-5996-441a-8cd7-250d7d08833f 6:38:28 PM: trace cp desc: Z-Wave network repair finished
a9416eea-5996-441a-8cd7-250d7d08833f 6:38:28 PM: trace cp desc: zwStatus:ready:Z-Wave network repair finished
4a366854-a466-48ce-a7b0-56e7c067f161 6:38:20 PM: debug poll is sending [], state: [‘code22’:’’, ‘code21’:’’, ‘code24’:’’, ‘code23’:’’, ‘fw’:‘2.6’, ‘code20’:’’, ‘lastbatt’:1421586272514, ‘code29’:’’, ‘code25’:’’, ‘code26’:’’, ‘code27’:’’, ‘MSR’:‘0090-0001-0001’, ‘lastPoll’:1421706857617, ‘code28’:’’, ‘code13’:’’, ‘code12’:’’, ‘assoc’:1, ‘code11’:’’, ‘code10’:’’, ‘code9’:’’, ‘code6’:’’, ‘code5’:’’, ‘sec’:‘72 86 98 80 85 70 75 62 63 4E 4C 71 8B 20 ‘, ‘code8’:’’, ‘code7’:’’, ‘code2’:‘2660’, ‘code1’:’’, ‘codes’:30, ‘code30’:’’, ‘code18’:’’, ‘code4’:’’, ‘code3’:’’, ‘code19’:’’, ‘code16’:’’, ‘code17’:’’, ‘code14’:’’, ‘code15’:’’]
3668231f-d28c-498d-9a25-659b8b92910c 6:37:48 PM: debug Parse returned Danielle Keys has arrived
e685e94d-b9e9-444d-984c-c99c1332fd07 6:36:42 PM: debug Parse returned Matthew keys has arrived
14a205a5-c6b3-4c8d-892b-4c8eafab72d5 6:35:35 PM: debug Parse returned Rav4 has arrived
3668231f-d28c-498d-9a25-659b8b92910c 6:35:09 PM: debug Parse returned raw:7D3B00000FFF0C0000000000, dni:7D3B, normalActual:00000FFF, normalExpected:0C, aggressiveActual:00000000, aggressiveExpected:00
14a205a5-c6b3-4c8d-892b-4c8eafab72d5 6:35:09 PM: debug Parse returned raw:852700000FFF0D0000000000, dni:8527, normalActual:00000FFF, normalExpected:0D, aggressiveActual:00000000, aggressiveExpected:00
e685e94d-b9e9-444d-984c-c99c1332fd07 6:35:09 PM: debug Parse returned raw:6E4300000FFF0C0000000000, dni:6E43, normalActual:00000FFF, normalExpected:0C, aggressiveActual:00000000, aggressiveExpected:00
31e841f7-4a5b-4db9-9758-15b1d5c06ffa 6:34:53 PM: debug poll is sending [], state: [‘code22’:’’, ‘code21’:’’, ‘code24’:’’, ‘code23’:’’, ‘fw’:‘1.3’, ‘code20’:’’, ‘lastbatt’:1421536925778, ‘code29’:’’, ‘code25’:’’, ‘code26’:’’, ‘code27’:’’, ‘lastPoll’:1421710472172, ‘MSR’:‘0090-0001-0001’, ‘code28’:’’, ‘code13’:’’, ‘code12’:’’, ‘assoc’:1, ‘code11’:’’, ‘code10’:’’, ‘code9’:’’, ‘code6’:’’, ‘code5’:’’, ‘sec’:‘72 86 98 80 85 70 75 62 63 4E 4C 71 8B 20 ‘, ‘code8’:’’, ‘code7’:’’, ‘code2’:’’, ‘codes’:30, ‘code1’:’’, ‘code4’:’’, ‘code18’:’’, ‘code30’:’’, ‘code19’:’’, ‘code3’:‘2660’, ‘code16’:’’, ‘code17’:’’, ‘code14’:’’, ‘code15’:’’]
31e841f7-4a5b-4db9-9758-15b1d5c06ffa 6:34:32 PM: debug poll is sending [‘9881006202’, ‘delay 6000’], state: [‘code22’:’’, ‘code21’:’’, ‘code24’:’’, ‘code23’:’’, ‘fw’:‘1.3’, ‘code20’:’’, ‘lastbatt’:1421536925778, ‘code29’:’’, ‘code25’:’’, ‘code26’:’’, ‘code27’:’’, ‘lastPoll’:1421710472172, ‘MSR’:‘0090-0001-0001’, ‘code28’:’’, ‘code13’:’’, ‘code12’:’’, ‘assoc’:1, ‘code11’:’’, ‘code10’:’’, ‘code9’:’’, ‘code6’:’’, ‘code5’:’’, ‘sec’:‘72 86 98 80 85 70 75 62 63 4E 4C 71 8B 20 ‘, ‘code8’:’’, ‘code7’:’’, ‘code2’:’’, ‘code1’:’’, ‘codes’:30, ‘code30’:’’, ‘code18’:’’, ‘code4’:’’, ‘code3’:‘2660’, ‘code19’:’’, ‘code16’:’’, ‘code17’:’’, ‘code14’:’’, ‘code15’:’’]
a9416eea-5996-441a-8cd7-250d7d08833f 6:33:32 PM: trace cp desc: zwStatus:network repair:Z-Wave network repair started
a9416eea-5996-441a-8cd7-250d7d08833f 6:33:32 PM: trace cp desc: Z-Wave network repair started

here’s the door trying to lock

38120980-f6e4-4c3c-a5d9-5a9cd1d2adce 6:53:00 PM: debug Executing 'poll’
38120980-f6e4-4c3c-a5d9-5a9cd1d2adce 6:51:41 PM: debug Executing 'poll’
38120980-f6e4-4c3c-a5d9-5a9cd1d2adce 6:49:33 PM: debug Executing 'poll’
38120980-f6e4-4c3c-a5d9-5a9cd1d2adce 6:48:45 PM: debug Executing 'poll’
38120980-f6e4-4c3c-a5d9-5a9cd1d2adce 6:48:26 PM: debug Executing 'lock

I made a small change to the code. Can you update the code, then try the lock and unlock again (capturing live logs again)?

It doesn’t seem to respond to the lock/unlock commands at all and only responds to the refresh command, but I’m hoping we were just sending it to the wrong endpoint.

/**
 *  PetSafe Smart Door
 *
 *  Copyright 2015 Scott Gibson
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 */
metadata {
	// Automatically generated. Make future change here.
	definition (name: "PetSafe Smart Door", namespace: "sticks18", author: "Scott Gibson") {
		capability "Battery"
		capability "Polling"
		capability "Actuator"
		capability "Refresh"
		capability "Lock"

		fingerprint profileId: "0104", inClusters: "0000 0001 0003 0009 000A 0101", outClusters: "0000 0001 0003 0009 000A 0101"
	}


		simulator {
		/*  // status "locked": "command: 9881, payload: 00 62 03 FF 00 00 FE FE"
		// status "unlocked": "command: 9881, payload: 00 62 03 00 00 00 FE FE"

		// reply "9881006201FF,delay 4200,9881006202": "command: 9881, payload: 00 62 03 FF 00 00 FE FE"
		// reply "988100620100,delay 4200,9881006202": "command: 9881, payload: 00 62 03 00 00 00 FE FE"  */
	}

	tiles {
		standardTile("toggle", "device.lock", width: 2, height: 2) {
			state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#79b821", nextState:"unlocking"
			state "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff", nextState:"locking"
			state "unknown", label:"unknown", action:"lock.lock", icon:"st.locks.lock.unknown", backgroundColor:"#ffffff", nextState:"locking"
			state "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#79b821"
			state "unlocking", label:'unlocking', icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff"
		}
		standardTile("lock", "device.lock", inactiveLabel: false, decoration: "flat") {
			state "default", label:'lock', action:"lock.lock", icon:"st.locks.lock.locked", nextState:"locking"
		}
		standardTile("unlock", "device.lock", inactiveLabel: false, decoration: "flat") {
			state "default", label:'unlock', action:"lock.unlock", icon:"st.locks.lock.unlocked", nextState:"unlocking"
		}
		valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
			state "battery", label:'${currentValue}% battery', unit:""
		}
		standardTile("refresh", "device.lock", inactiveLabel: false, decoration: "flat") {
			state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
		}

		main "toggle"
		details(["toggle", "lock", "unlock", "battery", "refresh"])
	}
}

// parse events into attributes
def parse(String description) {
	
    log.trace description
    
    def msg = zigbee.parse(description)
    log.trace msg
    
    
	// TODO: handle 'battery' attribute
	// TODO: handle 'lock' attribute

}

// handle commands
def poll() {
	
    log.debug "Executing 'poll'"
	refresh()
}

def refresh() {
	
    [
	"st rattr 0x${device.deviceNetworkId} 0x0C 0101 0", "delay 500",
    "st rattr 0x${device.deviceNetworkId} 0x0C 1 0x20"
    ]
    
}

def updated() {

	configure()
    
}

def lock() {
	
    log.debug "Executing 'lock'"
    sendEvent(name: "lock", value: "locked")
	"st cmd 0x${device.deviceNetworkId} 0x0C 0101 0 {}"
    
}

def unlock() {
	
    log.debug "Executing 'unlock'"
	sendEvent(name: "lock", value: "unlocked")
	"st cmd 0x${device.deviceNetworkId} 0x0C 0101 1 {}"
    
}

def configure() {

	String zigbeeId = swapEndianHex(device.hub.zigbeeId)
	log.debug "Confuguring Reporting and Bindings."
	def configCmds = [	

        //Lock Reporting
        "zcl global send-me-a-report 0101 0 0x30 0 3600 {01}", "delay 500",
        "send 0x${device.deviceNetworkId} 1 1", "delay 1000",

        //Battery Reporting
        "zcl global send-me-a-report 1 0x20 0x20 5 3600 {}", "delay 200",
        "send 0x${device.deviceNetworkId} 1 1", "delay 1500",

        "zdo bind 0x${device.deviceNetworkId} 1 1 0101 {${device.zigbeeId}} {}", "delay 500",
        "zdo bind 0x${device.deviceNetworkId} 1 1 1 {${device.zigbeeId}} {}"
    
    ]
    return configCmds + refresh() // send refresh cmds as part of config
}

private hex(value, width=2) {
	def s = new BigInteger(Math.round(value).toString()).toString(16)
	while (s.size() < width) {
		s = "0" + s
	}
	s
}

private Integer convertHexToInt(hex) {
	Integer.parseInt(hex,16)
}

private String swapEndianHex(String hex) {
    reverseArray(hex.decodeHex()).encodeHex()
}

private byte[] reverseArray(byte[] array) {
    int i = 0;
    int j = array.length - 1;
    byte tmp;
    while (j > i) {
        tmp = array[j];
        array[j] = array[i];
        array[i] = tmp;
        j--;
        i++;
    }
    return array
}

private getEndpointId() {
	new BigInteger(device.endpointId, 16).toString()
}

I’m doing it now :smile: