[ALPHA RELEASE] Simple Door Chime App

Door chime app

Features:

  • Contact Sensor Debounce
  • Multiple contact sensor selection
  • Supports chime / tts / tone type devices
  • Parses soundEffects list from driver (chime devices only)
  • Faster response time than RM

https://github.com/djdizzyd/hubitat/blob/master/Apps/simple-doorchime/doorchime.groovy

Let me know of any feature requests / bugs

5 Likes

I have a couple questions/comments if I may? And, after taking a look at your app, I have a few. But i don't want this to sound like criticism. It takes a lot to put your stuff out there for everyone to see and judge. All of my questions are just questions and all of my comments are intended to help you to better the app. That said, if you don't want it, you're welcome to ignore it completely.

First, is there some reason why you are subscribing to the contact sensors like this:

for (dev in contactDev) {
        log.debug "subscribing to " + dev.getDisplayName()
	    subscribe(dev, "contact", handler)

instead of simply doing this:

subscribe (contactDev, "contact", handler)

Is there a specific reason you wanted to call each of them out individually? A device wrapper will result in the same subscriptions as the iterative.

Your debounce function is very interesting. You schedule another event superseding the schedule of the first one. Is it your intention to have this delay be very short (500ms) and that's why you have the debounce function in there? If so, I would recommend hard-coding the delay. Most folks are going to look at that and not know what to put. And, if you have the delay long enough to open and close the sensor, you get no tone at all.

lso, unless you intended to be able to use the debounce function to prevent tones for contacts closed within the timeout, I would suggest modifying your subscriptions to only be to the open events, by changing it to "contact.open" instead. That would prevent 1/2 of the events that the app has to process but still eliminate the double toning of a "bouncy" sensor.

The TTS option is also completely broken. There is no capability speachSynthesis it's speechSynthesis. (don't worry, I have always been a terrible speller and I had to look it up to confirm that was the problem) Once that option is fixed though, it works. 3 spots it needs to be corrected.

I would also be cautious of logging event.device. This is what you get in the logs.

Not very useful. I would log event.device.label instead. As that would be the label that was applied by the user.

Lastly, Apps typically do not leave Debug Logging for everything on permanently. You've got a lot of logging in there. This has a tendency to fill up internal logs unnecessarily. For example, all built in drivers automatically turn off debug logging 30 mins after it is turned on. And most of the built in apps have a boolean option to turn debug logging on/off. I'd recommend adding that if you update the app and maybe leave one line logged permanently.

Let me know if you have any questions.

5 Likes

First app written... After my first drivers

Did not know this one

Stolen from app example

Great suggestion

Whoops .. Will be my first fix

Yea.. I know.. Still testing will remove soon

2 Likes

Renamed to Alpha Release.. Will push an update tomorrow to address the first list of issues pointed out by @Ryan780

4 Likes

Just went to add my Ring V1 Keypad to Simple Door Chime App tonight. It will work with beep/tone, but not with chime. (Is it not considered a chime device?) I am getting the below errors:

I'm getting this same error. Is this not a viable app?

I made some changes to this app and got it working again. Added an option to turn debug logging on/off. Fixed the Java Array Parsing error (tested with Wink Siren), reporting the integer list options on the log and requiring user to enter a number viewable from the log list or device page. Also, I added in an HSM status subscribe option so it only chimes when HSM is disarmed, or always, if the user so opts.

To be frank, I've never posted code on the internet before - and this isn't my app, so let me know if anyone wants it - or what to do with it.

Nice to get this one off of rule machine, thanks @bcopeland

Cheers!

I tried to save this driver but it report an error "no signature method". Not sure what the problem is.

This is an App NOT a driver so make sure you loaded the code as an App. :blush:

1 Like

Doh! I can't believe I did that

Oh No Facepalm GIF by Aminé

Would love to use this with your changes!
I'd suggest just throwing it on here with preformatted text or adding to your own github and posting the link.

Alternatively you could use something like pastebin.

Been working great! Although, the HSM subscription would probably be more useful listening to the hub modes instead. Below is the app code I am using currently:

definition(
	name: "Door Chime",
	namespace: "djdizzyd",
	author: "Bryan Copeland",
	description: "Door Chime App",
	category: "Convenience",
	iconUrl: "",
	iconX2Url: "",
	importUrl: "https://raw.githubusercontent.com/djdizzyd/hubitat/master/Apps/simple-doorchime/doorchime.groovy"
)

preferences {
	page(name: "mainPage")
}

def mainPage() {
	dynamicPage(name: "mainPage", title: " ", install: true, uninstall: true) {
		section {
			input "thisName", "text", title: "Name this door chime", submitOnChange: true
			if(thisName) app.updateLabel("$thisName") else app.updateSetting("thisName", "Door Chime")
			input "contactDev", "capability.contactSensor", title: "Select Contact Sensor", submitOnChange: true, required: true, multiple: true
			input "debounce", "bool", title: "Enable Debounce", submitOnChange: true, required: true, defaultValue: false
			if (debounce) {
				input "delayTime", "number", title: "Enter number of milliseconds to delay for debounce", submitOnChange: true, defaultValue: 1000
			}
			input "chimeType", "enum", title: "Type of chime device", options: ["chime": "chime", "speechSynthesis": "TTS", "tone": "Tone/Beep"], submitOnChange: true
			if (chimeType){
				input "chimeDev", "capability.$chimeType", title: "Select Chime Device", submitOnChange:true, required: true, hideWhenEmpty: "chimeType"
			}
			if (chimeDev) {
				switch (chimeType) {
					case "chime":
						if (chimeDev.hasAttribute("soundEffects")) {
                            def soundEffectsList = chimeDev.currentState("soundEffects").value
                            if(enableLog==null) {log.debug "sound effects list: " + soundEffectsList
                                                } else {
                                if(enableLog) log.debug "sound effects list: " + soundEffectsList
                            }
							input "soundNum", "number", title: "Sound to play", submitOnChange: false, required: true
						}
						break;
					case "speechSynthesis":
						input "speakText", "text", title: "Text to speak", submitOnChange: false, required: true
						break;
				}
			}
            input "useHSM", "enum", title: "Use HSM Status for Chime?", options: ["disUse": "No", "disArmed": "Only when Disarmed"], submitOnChange: false, defaultValue: "No"
            input "enableLog", "bool", title: "Enable Logging", submitOnChange: false, required: true, defaultValue: true
		}
	}
}

def installed() {
	initialize()
}

def updated() {
	unsubscribe()
	unschedule()
	initialize()
}

def initialize() {
    if(enableLog) log.debug "initializing"
    for (dev in contactDev) {
        if(enableLog) log.debug "subscribing to " + dev.getDisplayName()
	    subscribe(dev, "contact.open", handler)
        }
    if (useHSM=="disArmed") { 
            if(enableLog) log.debug "subscribing to HSM Status"
            subscribe(location, "hsmStatus", statusHandler)
            }
}

def handler(evt) { 
    if(useHSM=="disArmed") {
        if(location.hsmStatus=="allDisarmed") {
	if (debounce) {
		runInMillis(delayTime, debounced, [data: [o: evt.value, d: evt.device.getDisplayName()]])
		if(enableLog) log.info "Contact $evt.device $evt.value, start delay of $delayTime milliseconds"
	} else {
		debounced([o: evt.value, d: evt.device.getDisplayName()])
	}
        } else {
            if(location.hsmStatus=="disarmed") {
            	if (debounce) {
		runInMillis(delayTime, debounced, [data: [o: evt.value, d: evt.device.getDisplayName()]])
		if(enableLog) log.info "Contact $evt.device $evt.value, start delay of $delayTime milliseconds"
	} else {
		debounced([o: evt.value, d: evt.device.getDisplayName()])
	}
}
    }
    } else {
                    	if (debounce) {
		runInMillis(delayTime, debounced, [data: [o: evt.value, d: evt.device.getDisplayName()]])
		if(enableLog) log.info "Contact $evt.device $evt.value, start delay of $delayTime milliseconds"
    } else {
		debounced([o: evt.value, d: evt.device.getDisplayName()])
                        }
    }
}

def debounced(data) {
	if(data.o == "open") {
		if(enableLog) log.info "Contact $data.d debounced chiming" +  chimeDev.getDisplayName() + " sound number $soundNum"
		chimeAction()
	} 
}
                        

def chimeAction() {
	log.info "Chime Action"
	switch(chimeType) {
		case("chime"): 
			//chime Type
			if(enableLog) log.debug "playing sound: $soundNum on " + chimeDev.getDisplayName()
			chimeDev.playSound(soundNum.toInteger())
			break;
		case("speechSynthesis"):
			// speech Type
			if(enableLog) log.debug "Speaking '$speakText' on " + chimeDev.getDisplayName()
			chimeDev.speak(speakText)
			break;
		case("tone"):
			// tone Type
			if(enableLog) log.debug "Sending beep to " + chimeDev.getDisplayName()
			chimeDev.beep()
			break;
	}
}
1 Like

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.