Tag Archives

smartthings

SmartThings Create a Virtual Timer for a Light

September 14, 2017 0 comments

So I have been using Tasker a lot however I’m on the T-Mobile jump program and I switch from phone to phone quite a bit.  I was going to reinsert all of my Tasker profiles however I decided to see if SmartThings had a better method yet of presence sensing.  So I decided to relink my Android device as my presence sensor.  I’ve been testing this for about a week now and it seems to be more accurate then all of my Tasker/AutoLocation profiles.

How I have my house configured as my car approaches the house I want my Yale Smart Deadbolts to unlock, and turn on my Front porch and side porch lights; they are wired to (Lutron Caseta Switches).

Everything worked great however I had a Tasker profile that would wait 10 minutes and turn off the porch lights.  At first I tried creating a rule in SmartThings but it would turn the lights off constantly after 10 minutes even if I manual turned them on.  I figured out what I need to create is a SmartThings Virtual Switch.

Below is my configuration.

Step 1.  Create a virtual switch to be the timer. 

[Review] Samsung SmartThings Arrival Sensor v2

January 18, 2017 0 comments

Here is my first Product review on the Samsung SmartThings Arrival Sensor.  When I first started getting on board with the SmartThings hub and the entire smart house experience.  This was definitely one of the things I wanted most was proximity sensing.  I wanted to have the lights turn on and my deadbolts unlock and whatever I wanted to add in the future.

After getting all my Lutron Caseta light switches installed, my Yale deadbolts installed and attached to the SmartThings hub.  I was finally able to play around with the Samsung SmartThings Arrival Sensor fob.  I loved the idea that I can just place this product right on my key ring and its so compact and lightweight.

So I set up my SmartThings app, and created a rule automation routine that when I was in the area it would turn my porch lights on and the deadbolts would unlock.  It worked great the first few times but it was never reliable.  It worked probably about 80% of the time and this was killer to me; i just wanted the product to work.  After about 3-4 weeks of using the fob/sensor the battery was already down to about 30%.  When it went below 30% the device just stayed “Away” in the SmartThings app it never came back.  I had to change out the battery, remove it from my SmartThings app and re-add it.

I went to the Community forum, and started posting my findings a lot of people had good work a-rounds but still worked about 80% of the time.  Every time I came home and it didn’t work correctly I was pissed off.  I was ready to just scrap the entire idea of having anything Smart related especially if the products just didn’t work.

That same post topic another user suggested I follow this method using Tasker/SharpTools/AutoLocation.  You need to have the paid version of these apps which will cost you about $5.00  which is nothing since i’m already about $1000.00 invested in SmartHome products.

So basically my review of the SmartThings Arrival sensor is absolute garbage.  I want a product that’s just going to work 100% of the time and changing batteries monthly is another downfall.

Please check back for my post about using your Android or iPhone device as your SmartThings proximity sensor with Tasker/SharpTools/AutoLocation.  I’ve been testing it so far for a week and it’s been 100% all of the time. It’s a long process on getting it installed on your device but it’s definitely worth it.

ProsCons
  • Light weight
  • Compact
  • Didn’t work all of the time
  • Poor battery life
  • SmartThings Notification through Multiple Sonos Speakers

    January 12, 2017 0 comments

    Since I have my Aeotec by Aeon Labs ZW056 Doorbell with SmartThings, and my custom Device Handler in SmartThings to control the doorbell.  I wanted to have a custom notification sound play through my multiple Sonos speakers.

    If you need help pairing the Aeotec/Aeon labs doorbell with SmartThings visit the link below.

    How I was able to pair Aeon Labs Doorbell with SmartThings

     

    First things first you need to login to your SmartThings IDE

    https://graph.api.smartthings.com

    Next Click on “My Hubs” (this was my biggest problem at first, it wasn’t actually pulling up my devices so the Device Handler at first was never getting installed to my Hub).   If you see a message that says “You don’t have any hubs yet. Please use the SmartThings mobile app to claim your hub.”  You need to click on “My Locations“, then Click on your Hub Name mine was  called “Home“.  It should ask you to login again.  You should now see your Hub information.  Great you are now actually logged into your account.

    Step 2.  Now that you are logged in we are going to be creating a new SmartThings SmartApp.  So click on My Smart Apps at the top.

    Next Click on “New Smart App” in green on the top right of the page.

    Next Choose “From Code“.

    The following code I used thanks to SmartThings Community can be found by clicking here.

    /**
     *  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.
     *
     *  Sonos Custom Message
     *
     *  Author: SmartThings
     *  Date: 2014-1-29
     */
    definition(
        name: "Sonos Notify with Sound_Multiple",
        namespace: "smartthings",
        author: "SmartThings",
        description: "Play a sound or custom message through your Sonos when the mode changes or other events occur.",
        category: "SmartThings Labs",
        iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/sonos.png",
        iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/sonos@2x.png"
    )
    
    preferences {
        page(name: "mainPage", title: "Play a message on your Sonos when something happens", install: true, uninstall: true)
        page(name: "chooseTrack", title: "Select a song or station")
        page(name: "timeIntervalInput", title: "Only during a certain time") {
            section {
                input "starting", "time", title: "Starting", required: false
                input "ending", "time", title: "Ending", required: false
            }
        }
    }
    
    def mainPage() {
        dynamicPage(name: "mainPage") {
            def anythingSet = anythingSet()
            if (anythingSet) {
                section("Play message when"){
                    ifSet "motion", "capability.motionSensor", title: "Motion Here", required: false, multiple: true
                    ifSet "contact", "capability.contactSensor", title: "Contact Opens", required: false, multiple: true
                    ifSet "contactClosed", "capability.contactSensor", title: "Contact Closes", required: false, multiple: true
                    ifSet "acceleration", "capability.accelerationSensor", title: "Acceleration Detected", required: false, multiple: true
                    ifSet "mySwitch", "capability.switch", title: "Switch Turned On", required: false, multiple: true
                    ifSet "mySwitchOff", "capability.switch", title: "Switch Turned Off", required: false, multiple: true
                    ifSet "arrivalPresence", "capability.presenceSensor", title: "Arrival Of", required: false, multiple: true
                    ifSet "departurePresence", "capability.presenceSensor", title: "Departure Of", required: false, multiple: true
                    ifSet "smoke", "capability.smokeDetector", title: "Smoke Detected", required: false, multiple: true
                    ifSet "water", "capability.waterSensor", title: "Water Sensor Wet", required: false, multiple: true
                    ifSet "button1", "capability.button", title: "Button Press", required:false, multiple:true //remove from production
                    ifSet "triggerModes", "mode", title: "System Changes Mode", required: false, multiple: true
                    ifSet "timeOfDay", "time", title: "At a Scheduled Time", required: false
                }
            }
            def hideable = anythingSet || app.installationState == "COMPLETE"
            def sectionTitle = anythingSet ? "Select additional triggers" : "Play message when..."
    
            section(sectionTitle, hideable: hideable, hidden: true){
                ifUnset "motion", "capability.motionSensor", title: "Motion Here", required: false, multiple: true
                ifUnset "contact", "capability.contactSensor", title: "Contact Opens", required: false, multiple: true
                ifUnset "contactClosed", "capability.contactSensor", title: "Contact Closes", required: false, multiple: true
                ifUnset "acceleration", "capability.accelerationSensor", title: "Acceleration Detected", required: false, multiple: true
                ifUnset "mySwitch", "capability.switch", title: "Switch Turned On", required: false, multiple: true
                ifUnset "mySwitchOff", "capability.switch", title: "Switch Turned Off", required: false, multiple: true
                ifUnset "arrivalPresence", "capability.presenceSensor", title: "Arrival Of", required: false, multiple: true
                ifUnset "departurePresence", "capability.presenceSensor", title: "Departure Of", required: false, multiple: true
                ifUnset "smoke", "capability.smokeDetector", title: "Smoke Detected", required: false, multiple: true
                ifUnset "water", "capability.waterSensor", title: "Water Sensor Wet", required: false, multiple: true
                ifUnset "button1", "capability.button", title: "Button Press", required:false, multiple:true //remove from production
                ifUnset "triggerModes", "mode", title: "System Changes Mode", description: "Select mode(s)", required: false, multiple: true
                ifUnset "timeOfDay", "time", title: "At a Scheduled Time", required: false
            }
            section{
                input "actionType", "enum", title: "Action?", required: true, defaultValue: "Custom Message", options: [
                    "Custom Message",
                    "Bell 1",
                    "Bell 2",
                    "Dogs Barking",
                    "Fire Alarm",
                    "The mail has arrived",
                    "A door opened",
                    "There is motion",
                    "Smartthings detected a flood",
                    "Smartthings detected smoke",
                    "Someone is arriving",
                    "Piano",
                    "Lightsaber",
                    "National Lampoon",
                    "Leave it on the door",
                    "Plain Doorbell"]
                input "message","text",title:"Play this message", required:false, multiple: false
            }
            section {
                input "sonos", "capability.musicPlayer", title: "On this Sonos player", required: true, multiple: true
            }
            section("More options", hideable: true, hidden: true) {
                input "resumePlaying", "bool", title: "Resume currently playing music after notification", required: false, defaultValue: true
                href "chooseTrack", title: "Or play this music or radio station", description: song ? state.selectedSong?.station : "Tap to set", state: song ? "complete" : "incomplete"
    
                input "volume", "number", title: "Temporarily change volume", description: "0-100%", required: false
                input "frequency", "decimal", title: "Minimum time between actions (defaults to every event)", description: "Minutes", required: false
                href "timeIntervalInput", title: "Only during a certain time", description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : "incomplete"
                input "days", "enum", title: "Only on certain days of the week", multiple: true, required: false,
                    options: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
                if (settings.modes) {
                    input "modes", "mode", title: "Only when mode is", multiple: true, required: false
                }
                input "oncePerDay", "bool", title: "Only once per day", required: false, defaultValue: false
            }
            section([mobileOnly:true]) {
                label title: "Assign a name", required: false
                mode title: "Set for specific mode(s)", required: false
            }
        }
    }
    
    def chooseTrack() {
        dynamicPage(name: "chooseTrack") {
            section{
                input "song","enum",title:"Play this track", required:true, multiple: false, options: songOptions()
            }
        }
    }
    
    private songOptions() {
    
        // Make sure current selection is in the set
    
        def options = new LinkedHashSet()
        if (state.selectedSong?.station) {
            options << state.selectedSong.station
        }
        else if (state.selectedSong?.description) {
            // TODO - Remove eventually? 'description' for backward compatibility
            options << state.selectedSong.description
        }
    
        // Query for recent tracks
        def states = sonos.statesSince("trackData", new Date(0), [max:30])
        def dataMaps = states.collect{it.jsonValue}
        options.addAll(dataMaps.collect{it.station})
    
        log.trace "${options.size()} songs in list"
        options.take(20) as List
    }
    
    private saveSelectedSong() {
        try {
            def thisSong = song
            log.info "Looking for $thisSong"
            def songs = sonos.statesSince("trackData", new Date(0), [max:30]).collect{it.jsonValue}
            log.info "Searching ${songs.size()} records"
    
            def data = songs.find {s -> s.station == thisSong}
            log.info "Found ${data?.station}"
            if (data) {
                state.selectedSong = data
                log.debug "Selected song = $state.selectedSong"
            }
            else if (song == state.selectedSong?.station) {
                log.debug "Selected existing entry '$song', which is no longer in the last 20 list"
            }
            else {
                log.warn "Selected song '$song' not found"
            }
        }
        catch (Throwable t) {
            log.error t
        }
    }
    
    private anythingSet() {
        for (name in ["motion","contact","contactClosed","acceleration","mySwitch","mySwitchOff","arrivalPresence","departurePresence","smoke","water","button1","timeOfDay","triggerModes","timeOfDay"]) {
            if (settings[name]) {
                return true
            }
        }
        return false
    }
    
    private ifUnset(Map options, String name, String capability) {
        if (!settings[name]) {
            input(options, name, capability)
        }
    }
    
    private ifSet(Map options, String name, String capability) {
        if (settings[name]) {
            input(options, name, capability)
        }
    }
    
    def installed() {
        log.debug "Installed with settings: ${settings}"
        subscribeToEvents()
    }
    
    def updated() {
        log.debug "Updated with settings: ${settings}"
        unsubscribe()
        unschedule()
        subscribeToEvents()
    }
    
    def subscribeToEvents() {
        subscribe(app, appTouchHandler)
        subscribe(contact, "contact.open", eventHandler)
        subscribe(contactClosed, "contact.closed", eventHandler)
        subscribe(acceleration, "acceleration.active", eventHandler)
        subscribe(motion, "motion.active", eventHandler)
        subscribe(mySwitch, "switch.on", eventHandler)
        subscribe(mySwitchOff, "switch.off", eventHandler)
        subscribe(arrivalPresence, "presence.present", eventHandler)
        subscribe(departurePresence, "presence.not present", eventHandler)
        subscribe(smoke, "smoke.detected", eventHandler)
        subscribe(smoke, "smoke.tested", eventHandler)
        subscribe(smoke, "carbonMonoxide.detected", eventHandler)
        subscribe(water, "water.wet", eventHandler)
        subscribe(button1, "button.pushed", eventHandler)
    
        if (triggerModes) {
            subscribe(location, modeChangeHandler)
        }
    
        if (timeOfDay) {
            schedule(timeOfDay, scheduledTimeHandler)
        }
    
        if (song) {
            saveSelectedSong()
        }
    
        loadText()
    }
    
    def eventHandler(evt) {
        log.trace "eventHandler($evt?.name: $evt?.value)"
        if (allOk) {
            log.trace "allOk"
            def lastTime = state[frequencyKey(evt)]
            if (oncePerDayOk(lastTime)) {
                if (frequency) {
                    if (lastTime == null || now() - lastTime >= frequency * 60000) {
                        takeAction(evt)
                    }
                    else {
                        log.debug "Not taking action because $frequency minutes have not elapsed since last action"
                    }
                }
                else {
                    takeAction(evt)
                }
            }
            else {
                log.debug "Not taking action because it was already taken today"
            }
        }
    }
    def modeChangeHandler(evt) {
        log.trace "modeChangeHandler $evt.name: $evt.value ($triggerModes)"
        if (evt.value in triggerModes) {
            eventHandler(evt)
        }
    }
    
    def scheduledTimeHandler() {
        eventHandler(null)
    }
    
    def appTouchHandler(evt) {
        takeAction(evt)
    }
    
    private takeAction(evt) {
    
        log.trace "takeAction()"
    
        if (song) {
            sonos.playSoundAndTrack(state.sound.uri, state.sound.duration, state.selectedSong, volume)
        }
        else if (resumePlaying){
            sonos.playTrackAndResume(state.sound.uri, state.sound.duration, volume)
        }
        else {
            sonos.playTrackAndRestore(state.sound.uri, state.sound.duration, volume)
        }
    
        if (frequency || oncePerDay) {
            state[frequencyKey(evt)] = now()
        }
        log.trace "Exiting takeAction()"
    }
    
    private frequencyKey(evt) {
        "lastActionTimeStamp"
    }
    
    private dayString(Date date) {
        def df = new java.text.SimpleDateFormat("yyyy-MM-dd")
        if (location.timeZone) {
            df.setTimeZone(location.timeZone)
        }
        else {
            df.setTimeZone(TimeZone.getTimeZone("America/New_York"))
        }
        df.format(date)
    }
    
    private oncePerDayOk(Long lastTime) {
        def result = true
        if (oncePerDay) {
            result = lastTime ? dayString(new Date()) != dayString(new Date(lastTime)) : true
            log.trace "oncePerDayOk = $result"
        }
        result
    }
    
    // TODO - centralize somehow
    private getAllOk() {
        modeOk && daysOk && timeOk
    }
    
    private getModeOk() {
        def result = !modes || modes.contains(location.mode)
        log.trace "modeOk = $result"
        result
    }
    
    private getDaysOk() {
        def result = true
        if (days) {
            def df = new java.text.SimpleDateFormat("EEEE")
            if (location.timeZone) {
                df.setTimeZone(location.timeZone)
            }
            else {
                df.setTimeZone(TimeZone.getTimeZone("America/New_York"))
            }
            def day = df.format(new Date())
            result = days.contains(day)
        }
        log.trace "daysOk = $result"
        result
    }
    
    private getTimeOk() {
        def result = true
        if (starting && ending) {
            def currTime = now()
            def start = timeToday(starting, location?.timeZone).time
            def stop = timeToday(ending, location?.timeZone).time
            result = start < stop ? currTime >= start && currTime <= stop : currTime <= stop || currTime >= start
        }
        log.trace "timeOk = $result"
        result
    }
    
    private hhmm(time, fmt = "h:mm a")
    {
        def t = timeToday(time, location.timeZone)
        def f = new java.text.SimpleDateFormat(fmt)
        f.setTimeZone(location.timeZone ?: timeZone(time))
        f.format(t)
    }
    
    private getTimeLabel()
    {
        (starting && ending) ? hhmm(starting) + "-" + hhmm(ending, "h:mm a z") : ""
    }
    // TODO - End Centralize
    
    private loadText() {
        switch ( actionType) {
            case "Bell 1":
                state.sound = [uri: "http://s3.amazonaws.com/smartapp-media/sonos/bell1.mp3", duration: "10"]
                break;
            case "Bell 2":
                state.sound = [uri: "http://s3.amazonaws.com/smartapp-media/sonos/bell2.mp3", duration: "10"]
                break;
            case "Dogs Barking":
                state.sound = [uri: "http://s3.amazonaws.com/smartapp-media/sonos/dogs.mp3", duration: "10"]
                break;
            case "Fire Alarm":
                state.sound = [uri: "http://s3.amazonaws.com/smartapp-media/sonos/alarm.mp3", duration: "17"]
                break;
            case "The mail has arrived":
                state.sound = [uri: "http://s3.amazonaws.com/smartapp-media/sonos/the+mail+has+arrived.mp3", duration: "1"]
                break;
            case "A door opened":
                state.sound = [uri: "http://s3.amazonaws.com/smartapp-media/sonos/a+door+opened.mp3", duration: "1"]
                break;
            case "There is motion":
                state.sound = [uri: "http://s3.amazonaws.com/smartapp-media/sonos/there+is+motion.mp3", duration: "1"]
                break;
            case "Smartthings detected a flood":
                state.sound = [uri: "http://s3.amazonaws.com/smartapp-media/sonos/smartthings+detected+a+flood.mp3", duration: "2"]
                break;
            case "Smartthings detected smoke":
                state.sound = [uri: "http://s3.amazonaws.com/smartapp-media/sonos/smartthings+detected+smoke.mp3", duration: "1"]
                break;
            case "Someone is arriving":
                state.sound = [uri: "http://s3.amazonaws.com/smartapp-media/sonos/someone+is+arriving.mp3", duration: "1"]
                break;
            case "Piano":
                state.sound = [uri: "http://s3.amazonaws.com/smartapp-media/sonos/piano2.mp3", duration: "10"]
                break;
            case "Lightsaber":
                state.sound = [uri: "http://s3.amazonaws.com/smartapp-media/sonos/lightsaber.mp3", duration: "10"]
                break;
                case "National Lampoon":
                state.sound = [uri: "http://l5j.net/sounds/nationallampoon.mp3", duration: "27"]
                break;
                case "Leave it on the door":
                state.sound = [uri: "http://l5j.net/sounds/leaveitonthedoor.mp3", duration: "8"]
                break;
                 case "Plain Doorbell":
                state.sound = [uri: "http://l5j.net/sounds/doorbell.mp3", duration: "11"]
                break;
            default:
                if (message) {
                    state.sound = textToSpeech(message instanceof List ? message[0] : message) // not sure why this is (sometimes) needed)
                }
                else {
                    state.sound = textToSpeech("You selected the custom message option but did not enter a message in the $app.label Smart App")
                }
                break;
        }
    }

    Once your code has been pasted Choose “Save“, then “Publish“.

    Next Open up your SmartThings application on your android or iPhone.

    Click on “Add a SmartApp” at the bottom.

    Next all the way down and choose “My Apps” since this was a custom App that we added.

    You should now see your Sonos Notify with Sound_Multiple.  This will allow you to choose multiple Sonos speakers for your Doorbell notifications.

    Here’s how I set up my doorbell.  I made sure on the Doorbell Button Press (Aeotec Doorbell) was triggered it would play the custom .mp3 that I have added.  ( I will explain in my next post on how to add your own custom sounds to the list).   If you used my code from the top you will notice I added the “National Lampoons Christmas Vacation Doorbell“.  It’s also set to play throughout my Sonos speakers.

    Here’s some more settings you can also set.  I wanted to make sure if I was playing music and someone rang the doorbell, the music would continue playing.

    Also I wanted to temporarily change the music volume so I could hear the doorbell notification sound.