Aeon Labs panic button stopped working

Anyone out there using the Aeon Labs panic button? The one that has the single button?

I opened a ticket with support a few days ago and although they are conversing with me on the problem they still have no answer as to why they stopped working sometime after the 5th of this month.

They are still paired with my v1 hub but when the button is pressed its throwing errors in the log and failing to register the press as an event.

error java.lang.NullPointerException: Cannot get property ‘displayName’ on null object @ line 92
error Child device 2A/1 not found

I’d like to know if anyone is using these buttons and if they are still working for you.

I wouldn’t think that device would have a child device, it’s a single button. What device type handler are you using with it?

It’s the default device “Aeon Key Fob” that’s assigned by SmartThings.
As far as I can remember its the same device that has always been assigned and had been working with no problems for over a year.

Support told me that they had a similar problem and asked that I change to mode on the button. The problem is I can’t seem to change the mode on the single button. I followed the instructions on the document that came with it and there is nothing about mode change, There is another document I found online but it seems to be for the 4 button one.

“Mode” on that device is a parameter settings. Nothing to do with node in SmartThings.

It’s parameter 250. If the parameter is set to zero, that is group mode, and it uses direct association to send commands.

If the parameter is set to one, that is scene mode, and it sends a scene number to the hub.

I don’t have that device, so I don’t know if the parameter is exposed by the standard device type handler. If it is, when you look at the device in the SmartThings mobile app, there will be a little gear icon at the top of the details page for the device and when you click on that you should see the parameters you can change.

Thanks for your input on this. There appears to be nowhere for me to change this parameter as there are no options in the IDE or the APP to do so. Support told me to press the the include and learn button’s at the same time but that does nothing to fix the problem, other than defaulting the button and causing me to re-add it to the hub, which of course puts me right back to where I am.

Anon Instructions says “1. Go to the parameter settings page, specific to your Panic Button, within your gateway’s user interface”

Isn’t my gateway interface the SmartThings Hub? All I have is a Button and a SmartThing Hub. I am confused as to what the “Gateway Interface” is.

Many hubs, including Vera, Fibaro, and Homeseer, do list all of a Z wave device’s parameters on the device’s detail page and you can change them there. SmartThings, however, does not: you have to have a device Type handler that will expose them.

Perhaps @krlaframboise or @erocm1231 know of a device type handler for this that lets you change parameter 250, I don’t recall seeing one.

1 Like

I don’t know how or why this parameter got changed, or even if it was changed. If it did it certainly wasn’t by my hand. SmartThings is definitely a love/hate relationship for me. Thanks for your help. I understand things better now.

1 Like

I think it’s time to panic.

1 Like

I remember someone posting some sort of “everything” DTH that allowed you to change the configuration of any device, but I don’t remember the name of it.

Which DTH are you using with this device?

You’re probably thinking of the Z wave tweaker, which is a great DTH for changing parameter settings, but unfortunately at least the last time I looked it only worked with mains-powered devices, not battery powered devices like this one.

Yes, that’s the one.

I just looked at the code for the Aeon Key Fob DTH and it looks like parameter 250 gets set to 1 every time the device wakes up…

1 Like

I am using “Aeon Key Fob” which is the stock device handler.
I am working with support and so far most of the suggestions are unplug/plug and remove battery, install battery.

They too suggested I change the mode on the button but there is no way for me to do that.

That is why I am trying to find anyone out there with another button to see if they have the same problem or not.

I took another look at the Aeon Key Fob DTH and it’s supposed to set parameter 250 to 1 every time it wakes up which is why SmartThings keeps saying to take out the batteries and put them back in, but I’m pretty sure it’s not working because of a bug in the code.

I could be wrong, but I believe the “size” attribute is required for the configuration set command and the original code doesn’t have it.

Install the DTH below in the IDE and publish it, open the device in the IDE, switch the “Type” to Aeon Key Fob - Modified", and then wake the device up.

If you’re unsure how to wake it up, take out the batteries and put them back in.

import groovy.json.JsonOutput
/**
 *  Copyright 2015 SmartThings
 *
 *  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 {
	definition (name: "Aeon Key Fob-Modified", namespace: "smartthings", author: "SmartThings") {
		capability "Actuator"
		capability "Button"
		capability "Holdable Button"
		capability "Configuration"
		capability "Sensor"
		capability "Battery"
		capability "Health Check"

		fingerprint deviceId: "0x0101", inClusters: "0x86,0x72,0x70,0x80,0x84,0x85"
		fingerprint mfr: "0086", prod: "0001", model: "0026", deviceJoinName: "Aeon Panic Button"
	}

	simulator {
		status "button 1 pushed":  "command: 2001, payload: 01"
		status "button 1 held":  "command: 2001, payload: 15"
		status "button 2 pushed":  "command: 2001, payload: 29"
		status "button 2 held":  "command: 2001, payload: 3D"
		status "button 3 pushed":  "command: 2001, payload: 51"
		status "button 3 held":  "command: 2001, payload: 65"
		status "button 4 pushed":  "command: 2001, payload: 79"
		status "button 4 held":  "command: 2001, payload: 8D"
		status "wakeup":  "command: 8407, payload: "
	}
	tiles {

		multiAttributeTile(name: "rich-control") {
			tileAttribute("device.button", key: "PRIMARY_CONTROL") {
				attributeState "default", label: ' ', action: "", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffffff"
			}
		}
		standardTile("battery", "device.battery", inactiveLabel: false, width: 6, height: 2) {
			state "battery", label:'${currentValue}% battery', unit:""
		}
		childDeviceTiles("outlets")
	}

}


def parse(String description) {
	def results = []
	if (description.startsWith("Err")) {
		results = createEvent(descriptionText:description, displayed:true)
	} else {
		def cmd = zwave.parse(description, [0x2B: 1, 0x80: 1, 0x84: 1])
		if(cmd) results += zwaveEvent(cmd)
		if(!results) results = [ descriptionText: cmd, displayed: false ]
	}
	// log.debug("Parsed '$description' to $results")
	return results
}

def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) {
	def results = [createEvent(descriptionText: "$device.displayName woke up", isStateChange: false)]

	def prevBattery = device.currentState("battery")
	if (!prevBattery || (new Date().time - prevBattery.date.time)/60000 >= 60 * 53) {
		results << response(zwave.batteryV1.batteryGet().format())
	}
	results += configurationCmds().collect{ response(it) }
	results << response(zwave.wakeUpV1.wakeUpNoMoreInformation().format())
	return results
}

def buttonEvent(button, held) {
	button = button as Integer
	String childDni = "${device.deviceNetworkId}/${button}"
	def child = childDevices.find{it.deviceNetworkId == childDni}
	if (!child) {
		log.error "Child device $childDni not found"
	}
	if (held) {
		child?.sendEvent(name: "button", value: "held", data: [buttonNumber: 1], descriptionText: "$child.displayName was held", isStateChange: true)
		createEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was held", isStateChange: true)
	} else {
		child?.sendEvent(name: "button", value: "pushed", data: [buttonNumber: 1], descriptionText: "$child.displayName was pushed", isStateChange: true)
		createEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
	}
}

def zwaveEvent(physicalgraph.zwave.commands.sceneactivationv1.SceneActivationSet cmd) {
	Integer button = ((cmd.sceneId + 1) / 2) as Integer
	Boolean held = !(cmd.sceneId % 2)
	buttonEvent(button, held)
}

def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
	def map = [ name: "battery", unit: "%" ]
	if (cmd.batteryLevel == 0xFF) {
		map.value = 1
		map.descriptionText = "${device.displayName} has a low battery"
	} else {
		map.value = cmd.batteryLevel
	}
	createEvent(map)
}

def zwaveEvent(physicalgraph.zwave.Command cmd) {
	[ descriptionText: "$device.displayName: $cmd", linkText:device.displayName, displayed: false ]
}

def configurationCmds() {
	[ zwave.configurationV1.configurationSet(parameterNumber: 250, size: 1, scaledConfigurationValue: 1).format(),
	  zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId).format() ]
}

def configure() {
	def cmd = configurationCmds()
	log.debug("Sending configuration: $cmd")
	return cmd
}


def installed() {
	initialize()
}

def updated() {
	initialize()
	if (!childDevices) {
		createChildDevices()
	}
	else if (device.label != state.oldLabel) {
		childDevices.each {
			def segs = it.deviceNetworkId.split("/")
			def newLabel = "${device.displayName} button ${segs[-1]}"
			it.setLabel(newLabel)
		}
		state.oldLabel = device.label
	}
}

def initialize() {
	// Device only goes OFFLINE when Hub is off
	sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "zwave", scheme:"untracked"]), displayed: false)

	def zwMap = getZwaveInfo()
	def buttons = 4 // Default for Key Fob

	// Only one button for Aeon Panic Button
	if (zwMap && zwMap.mfr == "0086" && zwMap.prod == "0001" && zwMap.model == "0026") {
		buttons = 1
	}
	createChildDevices(buttons)
	sendEvent(name: "numberOfButtons", value: buttons)
}

private void createChildDevices(def num) {
	state.oldLabel = device.label
	for (i in num) {
		addChildDevice("Child Button", "${device.deviceNetworkId}/${i}", null,
				[completedSetup: true, label: "${device.displayName} button ${i}",
				 isComponent: true, componentName: "button$i", componentLabel: "Button $i"])
	}
}
2 Likes

Removed the battery from the button.
Installed & published your device handler.
Changed the button’s device type to Aeon Key Fob-Modified and pressed Update
Unplugged the V1 hub for 1 minute then plugged back in
Reinstalled the battery in the button.
Pressed button.

Results are the same error showing up.
support did say to leave the battery out for at least 3 hours so I could do that and report back later this evening.

3:17:20 PM: error java.lang.NullPointerException: Cannot get property ‘displayName’ on null object @ line 92
3:17:20 PM: error Child device 2A/1 not found

I probably should have read your first post completely. That error has nothing to do with that parameter, It looks like the button press is working as expected and the code is failing because it’s looking for a child device that doesn’t exist.

I’m assuming you don’t need your panic button to show as 2 different devices in SmartThings so in the version below I stripped out the child device related code that was generating the error.

I can’t say for sure that it won’t generate a new error, but it’s worth a shot.

import groovy.json.JsonOutput
/**
 *  Copyright 2015 SmartThings
 *
 *  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 {
	definition (name: "Aeon Key Fob", namespace: "smartthings", author: "SmartThings") {
		capability "Actuator"
		capability "Button"
		capability "Holdable Button"
		capability "Configuration"
		capability "Sensor"
		capability "Battery"
		capability "Health Check"

		fingerprint deviceId: "0x0101", inClusters: "0x86,0x72,0x70,0x80,0x84,0x85"
		fingerprint mfr: "0086", prod: "0001", model: "0026", deviceJoinName: "Aeon Panic Button"
	}

	simulator {
		status "button 1 pushed":  "command: 2001, payload: 01"
		status "button 1 held":  "command: 2001, payload: 15"
		status "button 2 pushed":  "command: 2001, payload: 29"
		status "button 2 held":  "command: 2001, payload: 3D"
		status "button 3 pushed":  "command: 2001, payload: 51"
		status "button 3 held":  "command: 2001, payload: 65"
		status "button 4 pushed":  "command: 2001, payload: 79"
		status "button 4 held":  "command: 2001, payload: 8D"
		status "wakeup":  "command: 8407, payload: "
	}
	tiles {

		multiAttributeTile(name: "rich-control") {
			tileAttribute("device.button", key: "PRIMARY_CONTROL") {
				attributeState "default", label: ' ', action: "", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffffff"
			}
		}
		standardTile("battery", "device.battery", inactiveLabel: false, width: 6, height: 2) {
			state "battery", label:'${currentValue}% battery', unit:""
		}
		childDeviceTiles("outlets")
	}

}


def parse(String description) {
	def results = []
	if (description.startsWith("Err")) {
		results = createEvent(descriptionText:description, displayed:true)
	} else {
		def cmd = zwave.parse(description, [0x2B: 1, 0x80: 1, 0x84: 1])
		if(cmd) results += zwaveEvent(cmd)
		if(!results) results = [ descriptionText: cmd, displayed: false ]
	}
	// log.debug("Parsed '$description' to $results")
	return results
}

def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) {
	def results = [createEvent(descriptionText: "$device.displayName woke up", isStateChange: false)]

	def prevBattery = device.currentState("battery")
	if (!prevBattery || (new Date().time - prevBattery.date.time)/60000 >= 60 * 53) {
		results << response(zwave.batteryV1.batteryGet().format())
	}
	results += configurationCmds().collect{ response(it) }
	results << response(zwave.wakeUpV1.wakeUpNoMoreInformation().format())
	return results
}

def buttonEvent(button, held) {
	button = button as Integer
	// String childDni = "${device.deviceNetworkId}/${button}"
	// def child = childDevices.find{it.deviceNetworkId == childDni}
	// if (!child) {
		// log.error "Child device $childDni not found"
	// }
	if (held) {
		// child?.sendEvent(name: "button", value: "held", data: [buttonNumber: 1], descriptionText: "$child.displayName was held", isStateChange: true)
		
		createEvent(name: "button", value: "held", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was held", isStateChange: true)
	} else {
		// child?.sendEvent(name: "button", value: "pushed", data: [buttonNumber: 1], descriptionText: "$child.displayName was pushed", isStateChange: true)
		createEvent(name: "button", value: "pushed", data: [buttonNumber: button], descriptionText: "$device.displayName button $button was pushed", isStateChange: true)
	}
}

def zwaveEvent(physicalgraph.zwave.commands.sceneactivationv1.SceneActivationSet cmd) {
	Integer button = ((cmd.sceneId + 1) / 2) as Integer
	Boolean held = !(cmd.sceneId % 2)
	buttonEvent(button, held)
}

def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
	def map = [ name: "battery", unit: "%" ]
	if (cmd.batteryLevel == 0xFF) {
		map.value = 1
		map.descriptionText = "${device.displayName} has a low battery"
	} else {
		map.value = cmd.batteryLevel
	}
	createEvent(map)
}

def zwaveEvent(physicalgraph.zwave.Command cmd) {
	[ descriptionText: "$device.displayName: $cmd", linkText:device.displayName, displayed: false ]
}

def configurationCmds() {
	[ zwave.configurationV1.configurationSet(parameterNumber: 250, scaledConfigurationValue: 1).format(),
	  zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId).format() ]
}

def configure() {
	def cmd = configurationCmds()
	log.debug("Sending configuration: $cmd")
	return cmd
}


def installed() {
	initialize()
}

def updated() {
	initialize()
	// if (!childDevices) {
		// createChildDevices()
	// }
	// else if (device.label != state.oldLabel) {
		// childDevices.each {
			// def segs = it.deviceNetworkId.split("/")
			// def newLabel = "${device.displayName} button ${segs[-1]}"
			// it.setLabel(newLabel)
		// }
		// state.oldLabel = device.label
	// }
}

def initialize() {
	// Device only goes OFFLINE when Hub is off
	sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "zwave", scheme:"untracked"]), displayed: false)

	def zwMap = getZwaveInfo()
	def buttons = 4 // Default for Key Fob

	// Only one button for Aeon Panic Button
	if (zwMap && zwMap.mfr == "0086" && zwMap.prod == "0001" && zwMap.model == "0026") {
		buttons = 1
	}
	// createChildDevices(buttons)
	sendEvent(name: "numberOfButtons", value: buttons)
}

// private void createChildDevices(def num) {
	// state.oldLabel = device.label
	// for (i in num) {
		// addChildDevice("Child Button", "${device.deviceNetworkId}/${i}", null,
				// [completedSetup: true, label: "${device.displayName} button ${i}",
				 // isComponent: true, componentName: "button$i", componentLabel: "Button $i"])
	// }
// }
3 Likes

Yep! That fixed it. Button is working as it should.

It took you a fraction of time to figure it out while support has been working on it for days and still trying to figure out.

Thank you very much!

3 Likes

Kevin, any idea why that DTH would have stuff to generate child devices to begin with? This is a one button remote.

I’m glad to hear it’s working.

That DTH is for the Aeon Key Fob which has 4 buttons and instead of properly implementing the button capability they made it create a child device for each button.

They put the panic button fingerprint in that DTH and added a line that changes the number of buttons from 4 to 1 when the device is the panic button.

If ST had spent 10 minutes extracting the necessary code for the panic button into its own DTH we wouldn’t be having this conversation…

2 Likes

Yeah, I’m confused about treating a handheld remote as a parent to its buttons since the buttons cannot be individually actuated anyway. And don’t have an individual status.

IMG_3778

Unlike a true composite device, such as Zooz power strip, where each child Device can be actuated, and therefore it makes sense to break them out.

IMG_3777

I know you know all of that, just filling out the context for those who don’t. :sunglasses:

edited to update: there is consistency in treating these two types of devices in the same way, and also although the physical device button cannot be individually actuated on a minimote, you could simulate the button press through the SmartThings mobile app so in that sense it could be actuated. I don’t know if that’s what they were trying to do, but I only thought of that after talking with SmartThings engineering so I wanted to update this post.

3 Likes

Child devices for a button controller? Seems very strange. I wonder where they are going with that idea.