Aeon Doorbell Type Beta

Hey Everyone,

This is my first device type that I’ve done anything this extensive with (be kind). It is a beta, so no guarantees, warranties, etc. The code is ugly, but works ok. Here is what I have working:

  1. Pressing CONFIGURE will set up everything so you can get notified (not notifications, yet) when the door bell button is pushed. You should see the main screen toggle from OFF to ACTIVATED.
  2. Pressing the RINGTONE button will cycle through Ringtone 1-5
  3. Pressing OFF will turn OFF any noise
  4. Pressing STATUS is where I am playing around right now. But it will set the NUMBER OF RINGTONES to 1.
  5. The slide will set the VOLUME of the RINGTONE
  6. Pressing the SPEAKER icon will trigger the doorbell.

Like I said this is Beta but the basic functionality seems there.

/**
 *  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.
 *
 *	Aeon Siren
 *
 *	Author: Thomas Howard
 *	Date: 2015-11-10
 */
 
preferences {
	input("ringTone", "number", title: "Ringtone (1-100)", required: true, defaultValue: 1, description: "Ringtone to Use for the Doorbell")
	input("volume", "number", title: "Volume (1-10)", required: true, defaultValue: 1, description: "Volume of the Door Bell")
	input("numTimes", "number", title: "Number (1-100)", required: true, defaultValue: 2, description: "Number of Times to Play the Ringtone")
}

metadata {
 definition (name: "Aeon Doorbell", namespace: "smartthings", author: "thoward1234") {
	capability "Alarm"
	capability "Switch"
    capability "Battery"
    capability "Switch Level"
    
	command "test"
    command "configure" 
    command "setRingTone"
    command "refresh" 
     
	fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98"
 }

 simulator {
	// reply messages
	reply "9881002001FF,9881002002": "command: 9881, payload: 002003FF"
	reply "988100200100,9881002002": "command: 9881, payload: 00200300"
	reply "9881002001FF,delay 3000,988100200100,9881002002": "command: 9881, payload: 00200300"
 }

 tiles(scale: 2) {
	multiAttributeTile(name:"alarm", type: "thermostat", width: 6, height: 4){
		tileAttribute ("device.alarm", key: "PRIMARY_CONTROL") {
			attributeState "off", label:'off', action:'alarm.siren', icon:"st.Electronics.electronics14", backgroundColor:"#ffffff"
			attributeState "both", label:'Activated', action:'alarm.off', icon:"st.Electronics.electronics14", backgroundColor:"#e86d13"
		}
        tileAttribute ("device.level", key: "SLIDER_CONTROL") {
				attributeState "level", action:"switch level.setLevel"
		}
      
	}
    standardTile("ringtone", "device.ringTone", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
		state "ringTone1", label:'Ringtone #1', action:"setRingTone", icon:"st.Entertainment.entertainment2"
        state "ringTone2", label:'Ringtone #2', action:"setRingTone", icon:"st.Entertainment.entertainment2"
        state "ringTone3", label:'Ringtone #3', action:"setRingTone", icon:"st.Entertainment.entertainment2"
        state "ringTone4", label:'Ringtone #4', action:"setRingTone", icon:"st.Entertainment.entertainment2"
        state "ringTone5", label:'Ringtone #5', action:"setRingTone", icon:"st.Entertainment.entertainment2"
	}
	standardTile("off", "device.alarm", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
		state "default", label:'', action:"alarm.off", icon:"st.secondary.off"
	}
    standardTile("configure", "device.alarm", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
		state "default", label:'Configure', action:"configure", icon:"st.Office.office6"
	}
    standardTile("refresh", "device.alarm", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
		state "default", label:'Status', action:"refresh", icon:"st.Weather.weather1"
	}
    

	main "alarm"
	details(["alarm", "ringtone", "off", "configure", "refresh"])
 }
}

def updated() {
	updatePreferences((settings.ringTone as Short), (settings.volume as Short), (settings.numTimes as Short));
}

def updatePreferences(Short ringTone, Short volume, Short numTImes){
	//Deal with lack of state data
	    
    log.debug "DOORBELL UPDATE:: Processing Selections: ringTone = $ringTone; volume = $volume; numTimes = $numTimes"
    delayBetween([
        		secure(zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: ringTone)),
                secure(zwave.configurationV1.configurationSet(parameterNumber: 0x08, size: 1, scaledConfigurationValue: volume)),
                secure(zwave.configurationV1.configurationSet(parameterNumber: 0x02, size: 1, scaledConfigurationValue: numTimes))
    ], 200);
}

def parse(String description) {
	log.debug "In parse callback ($description)"
	def result = null
	def cmd = zwave.parse(description, [0x98: 1, 0x20: 1, 0x70: 1, 0x80: 1, 0x25: 1])
	if (cmd) {
		result = zwaveEvent(cmd)
	}
	log.debug "Parse returned ${result?.inspect()}"
	return result
}

//HAIL COMMAND
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
	log.debug "Event: Hail ($cmd)"
}

//SECURITY ENCAPSULATED
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
	log.debug "Event: Encapsulated: $cmd"
    def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x85: 2, 0x70: 1])
	if (encapsulatedCommand) {
    	log.debug"     $encapsulatedCommand"
		zwaveEvent(encapsulatedCommand)
	}
}

//BASIC REPORT
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
	log.debug "Event: Basic ($cmd)"
	[
		createEvent([name: "switch", value: cmd.value ? "on" : "off", displayed: false]),
		createEvent([name: "alarm", value: cmd.value ? "both" : "off"])
	]
}

//SWITCH BINARY REPORT
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
	log.debug "Event: Binary Switch ($cmd)"
}

//COMMAND REPORT
def zwaveEvent(physicalgraph.zwave.Command cmd) {
	log.debug "Event: Command ($cmd)"
	createEvent(displayed: false, descriptionText: "$device.displayName: $cmd")()
}

//MULTI-LEVEL
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelReport cmd) {
	log.debug "Event: MultiLevel ($cmd)"
}

//BASIC SET
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
    log.debug "Event: Basic Set ($cmd)"    
}

//BATTERY REPORT
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
	log.debug "Event: Battery Report ($cmd)"    
}

//ASSOCIATION REPORT
def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) {
	log.debug "Event: Association Report ($cmd)"    
}

def setLevel(value) {
	def valueaux = value as Integer
	def level_ = Math.round(Math.min(valueaux, 99)/10)
	
    log.debug "Selected Volume Level is $level_"
    delayBetween([
    	secure(zwave.configurationV1.configurationSet(parameterNumber: 0x08, size: 1, scaledConfigurationValue: level_))
    ], 200);
}

def setRingTone(){
    if(!state.ringTone) state.ringTone = 1
	log.debug "Current RingTone: $state.ringTone"
    state.ringTone = state.ringTone+1;
    if (state.ringTone > 5) state.ringTone = 1;
    log.debug "Setting RingTone: $state.ringTone"
    
    def request;
    switch (state.ringTone){
    	case 1: 
        	request = [
    		zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 1)
    		];
            sendEvent(name: "ringTone", value: "ringTone1", display: false);
            break;
        case 2: 
        	request = [
    		zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 2)
    		];
            sendEvent(name: "ringTone", value: "ringTone2", display: false);
            break;
        case 3: 
        	request = [
    		zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 3)
    		];
            sendEvent(name: "ringTone", value: "ringTone3", display: false);
            break;
        case 4: 
        	request = [
    		zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 4)
    		];
            sendEvent(name: "ringTone", value: "ringTone4", display: false);
            break;
        case 5: 
        	request = [
    		zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 5)
    		];
            sendEvent(name: "ringTone", value: "ringTone5", display: false);
            break;
    }
    commands(request);
}

def configure() {
	state.ringTone = 1;
	log.debug "Sending Configuration"
	delayBetween([
    	secure(zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)),
    	secure(zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)),
    	secure(zwave.configurationV1.configurationSet(parameterNumber: 0x80, size: 1, scaledConfigurationValue: 2)),  //Configure to send basic report
        secure(zwave.configurationV1.configurationSet(parameterNumber: 0x81, size: 1, scaledConfigurationValue: 2))	  //Configure to send Battery Report
     	
    ], 500)
    log.debug "Configuration Sent"
}

def refresh() {
		log.debug "Sending Refresh"
        // Some examples of Get commands
        delayBetween([
                secure(zwave.configurationV1.configurationSet(parameterNumber: 0x02, size: 1, scaledConfigurationValue: 1)),
                secure(zwave.switchBinaryV1.switchBinaryGet()),
                secure(zwave.switchMultilevelV1.switchMultilevelGet()),
                secure(zwave.associationV2.associationReport()),
                secure(zwave.batteryV1.batteryGet()),
                secure(zwave.basicV1.basicGet()),
                secure(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId)),
    			secure(zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId))
        ], 1200)
}

def on() {
	log.debug "sending on"
	[
		secure(zwave.basicV1.basicSet(value: 0xFF)),
		secure(zwave.basicV1.basicGet())
	]
}

def off() {
	log.debug "sending off"
	[
		secure(zwave.basicV1.basicSet(value: 0x00)),
		secure(zwave.basicV1.basicGet())
	]
}

def strobe() {
	on()
}

def siren() {
	on()
}

def both() {
	on()
}

def test() {
	[
		secure(zwave.basicV1.basicSet(value: 0xFF)),
		"delay 3000",
		secure(zwave.basicV1.basicSet(value: 0x00)),
		secure(zwave.basicV1.basicGet())
	]
}

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

private commands(commands, delay=200) {
	delayBetween(commands.collect{ secure(it) }, delay)
}
7 Likes

@thoward1234 When I switched the device type from the Aeon Siren to your device type, I got this error. I tried couple of times, same problem

Oh No! Something Went Wrong!
Error
500: Internal Server Error
URI
/device/update
Reference Id
bcd3be4a-1214-4953-a8a3-7edc15ffef5d
Date
Fri Nov 13 03:41:10 UTC 2015

im getting same thing
500: Internal Server Error
URI
/device/update
Reference Id
478f01ec-c99c-40c7-8b6b-9055182dc3ef
Date
Fri Nov 13 04:01:24 UTC 2015

Odd. I took the code that I posted and switched my device type. No issues. What version of the hub are you running?

Me as well:

Error500: Internal Server Error
URI
/device/update
Reference Id8f0d2b5d-89f7-4062-ad48-f7359ac9e8f5
DateFri Nov 13 14:00:15 UTC 2015

Hub Info:

Firmware Version : 000.014.00008
Hardware Version : hub v2, US customer Rev E

Where does the error occur? After you install/publish the device type?

Nope, the device type takes just fine. It happens when I try to change the Type from Aeon Siren to Aeon Doorbell in my device. It happens on “Update”.

I’ll work on it this afternoon and clean some things up…

Try changing the updated method to


def updated() {
	try {
		Short ringTone = (settings.ringTone as Short) ?: 1
		Short volume = (settings.volume as Short) ?: 10
		Short numTimes = (settings.numTimes as Short) ?: 2
		response(updatePreferences(ringTone, volume, numTimes))
	} catch (e) {
		log.warn "updatePreferences failed: $e"
	}
}
1 Like

New update; see if this works

First button: RingTone (1-5)
Second Button: Number times to ring (1-5)
Third Button: Mute
Slider: Volume

/**
 *  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.
 *
 *	Aeon Siren
 *
 *	Author: Thomas Howard
 *	Date: 2015-11-10
 */
 
preferences {
	input("ringTone", "number", title: "Ringtone (1-100)", required: true, defaultValue: 1, description: "Ringtone to Use for the Doorbell")
	input("volume", "number", title: "Volume (1-10)", required: true, defaultValue: 1, description: "Volume of the Door Bell")
	input("numTimes", "number", title: "Number (1-100)", required: true, defaultValue: 2, description: "Number of Times to Play the Ringtone")
}

metadata {
 definition (name: "Aeon Doorbell", namespace: "smartthings", author: "thoward1234") {
	capability "Alarm"
	capability "Switch"
    capability "Battery"
    capability "Switch Level"
    capability "Refresh"
    
	command "test"
    command "configure" 
    command "setRingTone"
    command "setNumRings" 
    command "setMute"
     
	fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98"
 }

 simulator {
	// reply messages
	reply "9881002001FF,9881002002": "command: 9881, payload: 002003FF"
	reply "988100200100,9881002002": "command: 9881, payload: 00200300"
	reply "9881002001FF,delay 3000,988100200100,9881002002": "command: 9881, payload: 00200300"
 }

 tiles(scale: 2) {
	multiAttributeTile(name:"alarm", type: "thermostat", width: 6, height: 4){
		tileAttribute ("device.alarm", key: "PRIMARY_CONTROL") {
			attributeState "off", label:'off', action:'alarm.siren', icon:"st.Electronics.electronics14", backgroundColor:"#ffffff"
			attributeState "both", label:'Activated', action:'alarm.off', icon:"st.Electronics.electronics14", backgroundColor:"#e86d13"
		}
        tileAttribute ("device.level", key: "SLIDER_CONTROL") {
				attributeState "level", action:"switch level.setLevel"
		}
      
	}
    standardTile("ringtone", "device.ringTone", inactiveLabel: false, width: 2, height: 2) {
		state "default", label:'${currentValue}', action:"setRingTone", icon:"st.Electronics.electronics10"
	}
    standardTile("numRings", "device.numRings", inactiveLabel: false, width: 2, height: 2) {
		state "default", label:'${currentValue}', action:"setNumRings", icon:"st.Entertainment.entertainment2"
	}
    standardTile("volume", "device.volume", inactiveLabel: false, width: 2, height: 2) {
		state "default", label:'${currentValue}', action:"setMute", icon:"st.custom.sonos.unmuted"
        state "muted", label: 'Mute', action:"setMute", icon:"st.custom.sonos.unmuted"
	}
	standardTile("off", "device.alarm", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
		state "default", label:'', action:"alarm.off", icon:"st.secondary.off"
	}
    standardTile("configure", "device.alarm", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
		state "default", label:'Configure', action:"configure", icon:"st.Office.office6"
	}
   
	main "alarm"
	details(["alarm", "ringtone", "numRings", "volume", "off", "configure"])
 }
}

def updated() {
	updatePreferences((settings.ringTone as Short), (settings.volume as Short), (settings.numTimes as Short));
}

def updatePreferences(Short ringTone, Short volume, Short numTImes){
	//Deal with lack of state data
	    
    log.debug "DOORBELL UPDATE:: Processing Selections: ringTone = $ringTone; volume = $volume; numTimes = $numTimes"
    delayBetween([
        		secure(zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: ringTone)),
                secure(zwave.configurationV1.configurationSet(parameterNumber: 0x08, size: 1, scaledConfigurationValue: volume)),
                secure(zwave.configurationV1.configurationSet(parameterNumber: 0x02, size: 1, scaledConfigurationValue: numTimes))
    ], 200);
}

def parse(String description) {
	log.debug "In parse callback ($description)"
	def result = null
	def cmd = zwave.parse(description, [0x98: 1, 0x20: 1, 0x70: 1, 0x80: 1, 0x25: 1])
	if (cmd) {
		result = zwaveEvent(cmd)
	}
	log.debug "Parse returned ${result?.inspect()}"
	return result
}

//HAIL COMMAND
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
	log.debug "Event: Hail ($cmd)"
}

//SECURITY ENCAPSULATED
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
	log.debug "Event: Encapsulated: $cmd"
    def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x85: 2, 0x70: 1])
	if (encapsulatedCommand) {
    	log.debug"     $encapsulatedCommand"
		zwaveEvent(encapsulatedCommand)
	}
}

//BASIC REPORT
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
	log.debug "Event: Basic ($cmd)"
	[
		createEvent([name: "switch", value: cmd.value ? "on" : "off", displayed: false]),
		createEvent([name: "alarm", value: cmd.value ? "both" : "off"])
	]
}

//SWITCH BINARY REPORT
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
	log.debug "Event: Binary Switch ($cmd)"
}

//COMMAND REPORT
def zwaveEvent(physicalgraph.zwave.Command cmd) {
	log.debug "Event: Command ($cmd)"
	createEvent(displayed: false, descriptionText: "$device.displayName: $cmd")()
}

//MULTI-LEVEL
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelReport cmd) {
	log.debug "Event: MultiLevel ($cmd)"
}

//BASIC SET
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
    log.debug "Event: Basic Set ($cmd)"    
}

//BATTERY REPORT
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
	log.debug "Event: Battery Report ($cmd)"    
}

//ASSOCIATION REPORT
def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) {
	log.debug "Event: Association Report ($cmd)"    
}

def setLevel(value) {
	def valueaux = value as Integer
	def level_ = Math.round(Math.min(valueaux, 99)/10)
	def request =  [
    		zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId),
    	    zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId),
    		zwave.configurationV1.configurationSet(parameterNumber: 0x08, size: 1, scaledConfigurationValue: level_)
    ];
    log.debug "Selected Volume Level is $level_"
    setMuteVal(level_ as Short)
    if (level!=0) state.volume = level_;
    commands(request);
    
}

def setRingTone(){
    if(!state.ringTone) state.ringTone = 1
	log.debug "Current RingTone: $state.ringTone"
    state.ringTone = state.ringTone+1;
    if (state.ringTone > 5) state.ringTone = 1;
    log.debug "Setting RingTone: $state.ringTone"
    
    def request =  [
    		zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId),
    	    zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId),
    		zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: state.ringTone)
    ];
    def dispValue = String.format("#%d", state.ringTone);
    log.debug "Send Event $dispValue"
    sendEvent(name: "ringTone", value: dispValue as String, display: false);
    commands(request);
}

def setNumRings(){
    if(!state.numRings) state.numRings = 1
	log.debug "Current numRings: $state.numRings"
    state.numRings = state.numRings+1;
    if (state.numRings > 5) state.numRings = 1;
    log.debug "Setting numRings: $state.numRings"
    
    def request =  [
    		zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId),
    	    zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId),
    		zwave.configurationV1.configurationSet(parameterNumber: 0x02, size: 1, scaledConfigurationValue: state.numRings)
    ];
    def dispValue = String.format("%d", state.numRings);
    sendEvent(name: "numRings", value: dispValue as String, display: false);
    commands(request);
}

def setMuteVal(Short level){
	
    if (level == 0) state.mute = true;
    else state.mute = false;
    log.debug "Mute = $state.mute"
    if (state.mute){ 
    	def dispValue = String.format("--");
    	sendEvent(name:"volume", value:dispValue as String, display:false)
    } else {
        def dispValue = String.format("%d", level);
    	sendEvent(name:"volume", value: dispValue as String, display:false);
     }
    
    
}

def setMute(){
	
    def level_ = 0;
   
    if (state.mute) {
        level_ = state.volume;
        state.mute = false;
    } else {
    	state.mute = true;
    }
    setMuteVal(level_ as Short);
    
    def request =  [
    		zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId),
    	    zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId),
    		zwave.configurationV1.configurationSet(parameterNumber: 0x08, size: 1, scaledConfigurationValue: level_)
    ];
    log.debug "Selected Volume Level is $level_"
    commands(request);
    
}


def configure() {
	state.ringTone = 1;
	log.debug "Sending Configuration"
	delayBetween([
    	secure(zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)),
    	secure(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId)),
    	secure(zwave.configurationV1.configurationSet(parameterNumber: 0x80, size: 1, scaledConfigurationValue: 2)),  //Configure to send basic report
        secure(zwave.configurationV1.configurationSet(parameterNumber: 0x81, size: 1, scaledConfigurationValue: 2))	  //Configure to send Battery Report
     	
    ], 500)
    log.debug "Configuration Sent"
}

def refresh() {
		
}

def on() {
	log.debug "sending on"
	[
		secure(zwave.basicV1.basicSet(value: 0xFF)),
		secure(zwave.basicV1.basicGet())
	]
}

def off() {
	log.debug "sending off"
	[
		secure(zwave.basicV1.basicSet(value: 0x00)),
		secure(zwave.basicV1.basicGet())
	]
}

def strobe() {
	on()
}

def siren() {
	on()
}

def both() {
	on()
}

def test() {
	[
		secure(zwave.basicV1.basicSet(value: 0xFF)),
		"delay 3000",
		secure(zwave.basicV1.basicSet(value: 0x00)),
		secure(zwave.basicV1.basicGet())
	]
}

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

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

I’m still getting:

Ok after I added Duncan’s code it worked! Testing now!

Admitedly nothing to do with the DH, APP here…

Does the outside doorbell button hook up to existing powered doorbell wiring?

The remote is battery powered and wireless. The siren plugs into a standard outlet.

Updated 11/16 Aeon Doorbell Type with the following changes:

  1. Added @duncan code from above (thanks)
  2. Changed how device group association works. If you were not getting notifications from the doorbell button (hardware) please press “Configure” (wait at least 3 seconds) and test again.
  3. Removed constant group re-association (it only needs to be done once).

Let me know how it works out

/**
 *  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.
 *
 *	Aeon Siren
 *
 *	Author: Thomas Howard
 *	Date: 2015-11-10
 */
 
preferences {
	input("ringTone", "number", title: "Ringtone (1-100)", required: true, defaultValue: 1, description: "Ringtone to Use for the Doorbell")
	input("volume", "number", title: "Volume (1-10)", required: true, defaultValue: 1, description: "Volume of the Door Bell")
	input("numTimes", "number", title: "Number (1-100)", required: true, defaultValue: 2, description: "Number of Times to Play the Ringtone")
}

metadata {
 definition (name: "Aeon Doorbell", namespace: "smartthings", author: "thoward1234") {
	capability "Alarm"
	capability "Switch"
    capability "Battery"
    capability "Switch Level"
    capability "Refresh"
    
	command "test"
    command "configure" 
    command "setRingTone"
    command "setNumRings" 
    command "setMute"
     
	fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98"
 }

 simulator {
	// reply messages
	reply "9881002001FF,9881002002": "command: 9881, payload: 002003FF"
	reply "988100200100,9881002002": "command: 9881, payload: 00200300"
	reply "9881002001FF,delay 3000,988100200100,9881002002": "command: 9881, payload: 00200300"
 }

 tiles(scale: 2) {
	multiAttributeTile(name:"alarm", type: "thermostat", width: 6, height: 4){
		tileAttribute ("device.alarm", key: "PRIMARY_CONTROL") {
			attributeState "off", label:'off', action:'alarm.siren', icon:"st.Electronics.electronics14", backgroundColor:"#ffffff"
			attributeState "both", label:'Activated', action:'alarm.off', icon:"st.Electronics.electronics14", backgroundColor:"#e86d13"
		}
        tileAttribute ("device.level", key: "SLIDER_CONTROL") {
				attributeState "level", action:"switch level.setLevel"
		}
      
	}
    standardTile("ringtone", "device.ringTone", inactiveLabel: false, width: 2, height: 2) {
		state "default", label:'${currentValue}', action:"setRingTone", icon:"st.Electronics.electronics10"
	}
    standardTile("numRings", "device.numRings", inactiveLabel: false, width: 2, height: 2) {
		state "default", label:'${currentValue}', action:"setNumRings", icon:"st.Entertainment.entertainment2"
	}
    standardTile("volume", "device.volume", inactiveLabel: false, width: 2, height: 2) {
		state "default", label:'${currentValue}', action:"setMute", icon:"st.custom.sonos.unmuted"
        state "muted", label: 'Mute', action:"setMute", icon:"st.custom.sonos.unmuted"
	}
	standardTile("off", "device.alarm", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
		state "default", label:'', action:"alarm.off", icon:"st.secondary.off"
	}
    standardTile("configure", "device.alarm", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
		state "default", label:'Configure', action:"configure", icon:"st.Office.office6"
	}
   
	main "alarm"
	details(["alarm", "ringtone", "numRings", "volume", "off", "configure"])
 }
}

def updated() {
	updatePreferences((settings.ringTone as Short), (settings.volume as Short), (settings.numTimes as Short));
}

def updatePreferences(Short ringTone, Short volume, Short numTImes){
	//Deal with lack of state data
	    
    log.debug "DOORBELL UPDATE:: Processing Selections: ringTone = $ringTone; volume = $volume; numTimes = $numTimes"
    delayBetween([
    			secure(zwave.associationV1.associationRemove(groupingIdentifier:1, nodeId:zwaveHubNodeId)),
              	secure(zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)),
    			secure(zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)),
        		secure(zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: ringTone)),
                secure(zwave.configurationV1.configurationSet(parameterNumber: 0x08, size: 1, scaledConfigurationValue: volume)),
                secure(zwave.configurationV1.configurationSet(parameterNumber: 0x02, size: 1, scaledConfigurationValue: numTimes)),
    			secure(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId))
    ], 200);
}

def parse(String description) {
	log.debug "In parse callback ($description)"
	def result = null
	def cmd = zwave.parse(description, [0x98: 1, 0x20: 1, 0x70: 1, 0x80: 1, 0x25: 1])
	if (cmd) {
		result = zwaveEvent(cmd)
	}
	log.debug "Parse returned ${result?.inspect()}"
	return result
}

//HAIL COMMAND
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
	log.debug "Event: Hail ($cmd)"
}

//SECURITY ENCAPSULATED
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
	log.debug "Event: Encapsulated: $cmd"
    def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x85: 2, 0x70: 1])
	if (encapsulatedCommand) {
    	log.debug"     $encapsulatedCommand"
		zwaveEvent(encapsulatedCommand)
	}
}

//BASIC REPORT
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
	log.debug "Event: Basic ($cmd)"
	[
		createEvent([name: "switch", value: cmd.value ? "on" : "off", displayed: false]),
		createEvent([name: "alarm", value: cmd.value ? "both" : "off"])
	]
}

//SWITCH BINARY REPORT
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
	log.debug "Event: Binary Switch ($cmd)"
}

//COMMAND REPORT
def zwaveEvent(physicalgraph.zwave.Command cmd) {
	log.debug "Event: Command ($cmd)"
	createEvent(displayed: false, descriptionText: "$device.displayName: $cmd")()
}

//MULTI-LEVEL
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelReport cmd) {
	log.debug "Event: MultiLevel ($cmd)"
}

//BASIC SET
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
    log.debug "Event: Basic Set ($cmd)"    
}

//BATTERY REPORT
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
	log.debug "Event: Battery Report ($cmd)"    
}

//ASSOCIATION REPORT
def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) {
	log.debug "Event: Association Report ($cmd)"    
}

def setLevel(value) {
	def valueaux = value as Integer
	def level_ = Math.round(Math.min(valueaux, 99)/10)
	def request =  [
    		zwave.configurationV1.configurationSet(parameterNumber: 0x08, size: 1, scaledConfigurationValue: level_)
    ];
    log.debug "Selected Volume Level is $level_"
    setMuteVal(level_ as Short)
    if (level!=0) state.volume = level_;
    commands(request);
    
}

def setRingTone(){
    if(!state.ringTone) state.ringTone = 1
	log.debug "Current RingTone: $state.ringTone"
    state.ringTone = state.ringTone+1;
    if (state.ringTone > 5) state.ringTone = 1;
    log.debug "Setting RingTone: $state.ringTone"
    
    def request =  [
    		zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: state.ringTone)
    ];
    def dispValue = String.format("#%d", state.ringTone);
    log.debug "Send Event $dispValue"
    sendEvent(name: "ringTone", value: dispValue as String, display: false);
    commands(request);
}

def setNumRings(){
    if(!state.numRings) state.numRings = 1
	log.debug "Current numRings: $state.numRings"
    state.numRings = state.numRings+1;
    if (state.numRings > 5) state.numRings = 1;
    log.debug "Setting numRings: $state.numRings"
    
    def request =  [
    		zwave.configurationV1.configurationSet(parameterNumber: 0x02, size: 1, scaledConfigurationValue: state.numRings)
    ];
    def dispValue = String.format("%d", state.numRings);
    sendEvent(name: "numRings", value: dispValue as String, display: false);
    commands(request);
}

def setMuteVal(Short level){
	
    if (level == 0) state.mute = true;
    else state.mute = false;
    log.debug "Mute = $state.mute"
    if (state.mute){ 
    	def dispValue = String.format("--");
    	sendEvent(name:"volume", value:dispValue as String, display:false)
    } else {
        def dispValue = String.format("%d", level);
    	sendEvent(name:"volume", value: dispValue as String, display:false);
     }
    
    
}

def setMute(){
	
    def level_ = 0;
   
    if (state.mute) {
        level_ = state.volume;
        state.mute = false;
    } else {
    	state.mute = true;
    }
    setMuteVal(level_ as Short);
    
    def request =  [
    		zwave.configurationV1.configurationSet(parameterNumber: 0x08, size: 1, scaledConfigurationValue: level_)
    ];
    log.debug "Selected Volume Level is $level_"
    commands(request);
    
}

def configure() {
	state.ringTone = 1;
	log.debug "Sending Configuration"
	delayBetween([
    	secure(zwave.associationV1.associationRemove(groupingIdentifier:1, nodeId:zwaveHubNodeId)),
    	secure(zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)),
    	secure(zwave.configurationV1.configurationSet(parameterNumber: 0x80, size: 1, scaledConfigurationValue: 2)),  //Configure to send basic report
        secure(zwave.configurationV1.configurationSet(parameterNumber: 0x81, size: 1, scaledConfigurationValue: 2)),	  //Configure to send Battery Report
        secure(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId))
    ], 500)
    log.debug "Configuration Sent"
}

def refresh() {
	try {
		Short ringTone = (settings.ringTone as Short) ?: 1
		Short volume = (settings.volume as Short) ?: 10
		Short numTimes = (settings.numTimes as Short) ?: 2
		response(updatePreferences(ringTone, volume, numTimes))
	} catch (e) {
		log.warn "updatePreferences failed: $e"
	}	
}

def on() {
	log.debug "sending on"
	[
		secure(zwave.basicV1.basicSet(value: 0xFF)),
		secure(zwave.basicV1.basicGet())
	]
}

def off() {
	log.debug "sending off"
	[
		secure(zwave.basicV1.basicSet(value: 0x00)),
		secure(zwave.basicV1.basicGet())
	]
}

def strobe() {
	on()
}

def siren() {
	on()
}

def both() {
	on()
}

def test() {
	[
		secure(zwave.basicV1.basicSet(value: 0xFF)),
		"delay 3000",
		secure(zwave.basicV1.basicSet(value: 0x00)),
		secure(zwave.basicV1.basicGet())
	]
}

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

private commands(commands, delay=200) {
	delayBetween(commands.collect{ secure(it) }, delay)
}
1 Like

Thanks will give it a shot this evening when I get home!

Press each button. That should change them (giving a initial value)

i still had to go back and fix ducans code in the new script and it now updates the setting changes to the doorbell so I can Change the number of times it rings and also which mp3 but it doesnt notify the app still it has been clicked

I can confirm what @udpflood15 said, I have to add Duncan’s code to remove the 500 error. Then I can update the device type, then the configure button does send a command which appears in the log.

After this I can ring the bell from the ST app and change the settings with some regularity (however once the volume button is pressed three times it stays on “null” and can’t be changed. In order to change the settings after this occurs you need to login to your developer account and do it manually.

Finally the remote button still does nothing, it does ring the bell however nothing appears in the log.

I’m wondering since you said you added Duncan’s code and it is not there if you didn’t maybe paste the wrong code?

Otherwise I’m not sure what is needed.

Where did you “add Duncan’s code”. I added it to the update function. Also, when you change the volume, do you use the slider?

As for getting the doorbell button to work, the Configure button should do everything. I wish there was a way to check associations. Why I believe it is not working is because the “ideal” state has ST associated as a group 1 AND group 2 device. ST has to be group 1 to receive notifications. Ugh. Let me think on this and look at the docs Aeon sent me…

Checking associations isn’t that tough — check the zwave api reference for get association, then log the report that’s returned. Keep in mind that you can’t copy the functions right over, you have to modify their names in accordance with the undocumented need for camel case and a few other slight changes.

1 Like