Mode Switch device/app

I put together a very simple virtual device and helper app in order to quickly switch modes (and see which mode is active). The modes are hard-coded in the device, since can’t change the UI dynamically. Devices can’t do setLocationMode, thus the need for the helper. The one I’m posting here has Home, Away, and Night as the modes. The screenshot has Office instead of Home. Thought somebody might find it helpful.


Installation Instructions

Install the DH in the IDE

  • click “My Device Handlers”
  • click “Create New Device Handler”
  • click “From Code”
  • paste the code for the device
  • click “Create”
  • click “My Devices”
  • click “New Device”
  • enter “Name”
  • enter “Device Network ID” (any number, I recommend > 991)
  • choose “Type” “Mode Switch”
  • choose “Location”
  • click “Create”

Install the SmartApp

  • click “My SmartApps”
  • click “New SmartApp”
  • click “From Code”
  • paste the code for the helper
  • click “Create”
  • click “Publish” “For Me”

In Mobile App

  • tap “Marketplace”
  • tap “My Apps” at the bottom
  • tap “Mode Switch Helper”
  • tap “Which?”
  • select “Mode Switch” (or whatever name you gave the device)
  • tap “Done”

6 Likes

Instructions on changing the code to customize the display. Only the device handler needs to be modified.

To change the modes shown – for example change Home to Office

    command "modeHome"
    command "modeAway"
    command "modeNight"

to

    command "modeOffice"
    command "modeAway"
    command "modeNight"

    standardTile("Home", "device.Home", decoration: "flat", width: 2, height: 2) {
		state "inactive", label:'Home', action:"modeHome", icon:"st.Home.home2", backgroundColor:"#ffffff"
		state "active", label:'Home', action:"modeHome", icon:"st.Home.home2", backgroundColor:"#dcdcdc"
    }

to

    standardTile("Office", "device.Office", decoration: "flat", width: 2, height: 2) {
		state "inactive", label:'Office', action:"modeOffice", icon:"st.Home.home15", backgroundColor:"#ffffff"
		state "active", label:'Office', action:"modeOffice", icon:"st.Home.home15", backgroundColor:"#dcdcdc"
    } 

if (newMode != "Home") events << sendEvent(name: "Home", value: "inactive", displayed: false)

to

if (newMode != "Office") events << sendEvent(name: "Office", value: "inactive", displayed: false)

def modeHome() {
    sendChangedMode("Home")
}

to

def modeOffice() {
    sendChangedMode("Office")
}

There are 3 tiles for modes and you can increase the number of tiles if you prefer. To add an additional mode (which you have already created through the hamburger menu or elsewhere):

(1) Add a standardTile, for example, add this after the “Night” tile:

    standardTile("Party", "device.Party", decoration: "flat", width: 2, height: 2) {
		state "inactive", label:'Party', action:"modeParty", icon:"st.Entertainment.entertainment2", backgroundColor:"#ffffff"
		state "active", label:'Party', action:"modeParty", icon:"st.Entertainment.entertainment2", backgroundColor:"#dcdcdc"
    }

The icon name comes from http://scripts.3dgo.net/smartthings/icons/ or https://web.archive.org/web/20150825232647/http://scripts.3dgo.net/smartthings/icons


(2) Add the tile to the list of tiles displayed:

	details(["modeCurrent", "Home", "Away", "Night", "Party"])

(3) Add the command for tile:

    command "modeHome"
    command "modeAway"
    command "modeNight"
    command "modeParty"

(4) Add the mode to locationModeChanged:

if (newMode != "Home") events << sendEvent(name: "Home", value: "inactive", displayed: false)
if (newMode != "Away") events << sendEvent(name: "Away", value: "inactive", displayed: false)
if (newMode != "Night") events << sendEvent(name: "Night", value: "inactive", displayed: false)
if (newMode != "Party") events << sendEvent(name: "Party", value: "inactive", displayed: false)

(5) Define the command:

def modeParty() {
    sendChangedMode("Party")
}
2 Likes

Great instructions. I modified it for my four modes like this. I finally renamed it to .Mode Indicator (with the period in front) which causes it display first in the Things page view.

1 Like

If displaying:
2 mode tiles -> use mode tile width and height of 3
3 mode tiles -> width and height of 2
4 mode tiles (as per @dalec) -> width and height of 3
5 mode tiles -> use 3 tiles of width/height 2, followed by 2 tiles of width/height 3 (or vice versa)
6 mode tiles -> use width/height of 2

Does this still work? Having issues with the smartapp giving me an error.

Just tried it. Still works for me. Let me know what error you’re getting (log).

@gkl_sf

How would I parse this code in order to literally just add a value tile to another DH that I have which simply displays the current location mode of the hub? Is there a way for the DH to pull current mode and display it in a standalone tile?

I literally just want to add a tile like yours at the top that displays current location mode on this DH:

Hi. You’ll need to have a helper app which subscribes to location, “mode” and then updates the DH when the mode changes. It’s just a few lines – for example –

DH:

metadata {
command "locationModeChanged", ["string"]
}

tiles(scale: 2) {
valueTile("modeCurrent", "device.modeCurrent", decoration: "flat", width: 6, height: 1) {
       state "default", label:'${currentValue}', backgroundColor:"#00a0dc"
       }
}  

def locationModeChanged(newMode) {
sendEvent(name: "modeCurrent", value: newMode)
}

App:

preferences {
	section {
		input "theDTH", "capability.actuator"
	}
}

def initialize() {
    subscribe(location, "mode", locationModeChanged)
}

def locationModeChanged(evt) { 
        theDTH.locationModeChanged(evt.value)
    }
}

Thanks for this. I am trying to implement this but I’m running in to an issue. I created the SmartApp and added the extra code to the handler for a Minimote. So far I can’t get the current mode to pass to the handler.

I found this in the Live Logging from the SmartApp when the SmartApp is installed:

11:01:17 PM: error Mode Helper DOES NOT RESPOND TO INSTALLED HANDLER:

I’m no expert but it looks to me like I have something wrong in the SmartApp code:

definition(
    name: "Mode Helper",
    namespace: "Nezmo68",
    author: "Nezmo",
    description: "Mode helper",
    category: "Mode Magic",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png",
    iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")


preferences {
	section {
		input "theDTH", "capability.actuator"
	}
}

def initialize() {
    subscribe(location, "mode", locationModeChanged)
}

def locationModeChanged(evt) { 
        theDTH.locationModeChanged(evt.value)
    }
1 Like

Did you go into the smartapp settings and select the device?

I did. I had to do something different in the SmartApp in the end to get it working. I’ll post everything once I’ve got the DTH exactly how I want it.

Thank you again for your help as I needed the basics to help me along.

1 Like

Might need to add

locationModeChanged(location.mode)

to initialize()

otherwise the DTH won’t display a mode until mode changes

Edit: actually, add it to updated() not initialize()

1 Like

Here’s what I ended-up with and it seems to be working well.

preferences {
	section {
		input "theDTH", "capability.actuator"
	}
}

def installed() {
	log.debug "Installed with settings: ${settings}"

	initialize()
}

def updated() {
	log.debug "Updated with settings: ${settings}"

	unsubscribe()
	initialize()
}
def initialize() {
    subscribe(location, "mode", locationModeChanged)
}

def locationModeChanged(evt) { //send mode change to device
    theDTH.locationModeChanged(evt.value)
    log.debug "current device mode is ${currentDeviceMode}, system mode changed to ${evt.value}"
}
1 Like

Helpful, thanks! First time installing a virtual device and selecting the handler myself; it took me way too long to realize that self-published device handlers show up at the bottom instead of alphabetically in the “Type” list…

George, are you still out there? I tried using your code. I can see the mode change status if I change it via a piston or IDE but it’s not working the other way. When I click a mode nothing happens. No log, no error no mode change. I was wondering if you could help me out?

Helper

/**

  • mode_switch_helper v1 for mode_switch virtual device
  • Copyright 2016 gkl_sf
  • 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.

*/

definition(
name: “Mode Switch Helper”,
namespace: “gkl-sf”,
author: “gkl_sf”,
description: “Mode switch helper”,
category: “Mode Magic”,
iconUrl: “https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png”,
iconX2Url: “https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png”,
iconX3Url: “https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png”)

preferences {
section {
input “modeSwitcher”, “capability.actuator”
}
}

def installed() {
log.debug “Installed with settings: ${settings}”

initialize()

}

def updated() {
log.debug “Updated with settings: ${settings}”

unsubscribe()
initialize()

}

def initialize() {
subscribe(modeSwitcher, “modeChange”, deviceModeChanged)
subscribe(location, “mode”, locationModeChanged)
}

def deviceModeChanged(evt) { //device sent new mode to helper
log.debug “current system mode is {location.mode}, device requests mode change to {evt.value}”
if (location.mode != evt.value) {
setLocationMode(evt.value)
}
}

def locationModeChanged(evt) { //send mode change to device
def currentDeviceMode = modeSwitcher.currentValue(“modeCurrent”)
log.debug “current device mode is {currentDeviceMode}, system mode changed to {evt.value}”
if (currentDeviceMode != evt.value) {
modeSwitcher.locationModeChanged(evt.value)
}
}

Device Handler

/*

  • mode_switch virtual device v1, requires mode_switch_helper smartapp
  • Copyright 2016 gkl_sf
  • 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: “Mode Switch”, namespace: “gkl-sf”, author: “gkl_sf”) {
capability “Actuator” //capability without built-in commands

    //these are needed for tile actions
    command "Morning"
    command "LateNight"
    command "Sleep"       
    
    //this is for the helper app to inform the device that system mode was changed
    command "locationModeChanged", ["string"]
    
    attribute "modeCurrent", "string"
    attribute "modeChange", "string"
    
	fingerprint inClusters: "0x91"
    
}

tiles(scale: 2) {

    valueTile("modeCurrent", "device.modeCurrent", decoration: "flat", width: 6, height: 1) {
		state "default", label:'${currentValue}', backgroundColor:"#999999"
    }

    standardTile("Morning", "device.Morning", decoration: "flat", width: 2, height: 2) {
		state "inactive", label:'Morning', action:"modeMorning", icon:"st.Home.home2", backgroundColor:"#ffffff"
		state "active", label:'Morning', action:"modeMorning", icon:"st.Home.home2", backgroundColor:"#dcdcdc"
    } 
    
    standardTile("LateNight", "device.LateNight", decoration: "flat", width: 2, height: 2) {
		state "inactive", label:'Late Night', action:"modeLateNight", icon:"st.nest.nest-away", backgroundColor:"#ffffff"
		state "active", label:'Late Night', action:"modeLateNight", icon:"st.nest.nest-away", backgroundColor:"#dcdcdc"
    }

    standardTile("Sleep", "device.Sleep", decoration: "flat", width: 2, height: 2) {
		state "inactive", label:'Sleep', action:"modeSleep", icon:"st.Weather.weather4", backgroundColor:"#ffffff"
		state "active", label:'Sleep', action:"modeSleep", icon:"st.Weather.weather4", backgroundColor:"#dcdcdc"
    }
    
	main(["modeCurrent"]) //modeCurrent is primary so that list of Things in mobile app shows the current mode
	details(["modeCurrent", "Morning", "LateNight", "Sleep"])
}     

}

//received new mode from helper
def locationModeChanged(newMode) {
log.debug “received system mode change to ${newMode}”
def events =
events << sendEvent(name: “modeCurrent”, value: newMode, displayed: false)
events << sendEvent(name: newMode, value: “active”, displayed: false)
if (newMode != “Morning”) events << sendEvent(name: “Morning”, value: “inactive”, displayed: false)
if (newMode != “LateNight”) events << sendEvent(name: “LateNight”, value: “inactive”, displayed: false)
if (newMode != “Sleep”) events << sendEvent(name: “Sleep”, value: “inactive”, displayed: false)
events
}

//send events for new mode to helper

def modeMorning() {
sendChangedMode(“Morning”)
}

def modeLateNight() {
sendChangedMode(“LateNight”)
}

def modeSleep() {
sendChangedMode(“Sleep”)
}

private sendChangedMode(newMode) {
log.debug “send new mode to helper, current system mode {location.mode}, new mode {newMode}”
if (newMode != location.mode) {
sendEvent(name: “modeChange”, value: newMode, descriptionText: “Change Mode to ${newMode}”, isStateChange: true)
}
}

Does this work on the new app? I find it, nicely put, rather stupid to have to make 3 clicks to set the mode, and then not be able to see what it is.

This does not work with the new ST app. I’ve seen multiple threads with this request but still haven’t found a way to display or change the mode with a smart switch/tile.

Since this is a Groovy smartapp, its days are numbered no matter what since the Groovy IDE will be shut down in the not too distant future.

My suggestion would be to create a virtual switch using an Edge driver (there are two options that are frequently discussed in the community). Then create an Automation to set location mode when the switch is toggled.

Edge drivers and Automations will both survive the Groovy shutdown, so you won’t have to worry about rebuilding any of this in the near future.

1 Like