Syntax for a basic SmartApp toggle tile?

Please feel free to skip the italicized section to go directly to the problem.

Background
I have a window unit (AC/heat) that doesn’t regulate temperature very well, and doesn’t have any smart features. My ideal solution would work as follows:

* Able to turn the unit on/off and switch modes (AC/heat) by voice (Google Home, Alexa).
* Able to adjust the temperature by voice by either saying “turn the thermostat up/down by [x] degrees” or “set the thermostat to [x] degress.”
* The thermostat variable should check against a SmartThings multipurpose sensor and adjust accordingly, turning the unit on or off and switching modes as needed.

Tools:
* SmartThings Multipurpose sensor (detects temperature)
* Broadlink RM Pro (sends infrared signals to window unit)
* Android TV device running RM Bridge app (necessary to send commands to RM Pro via URL)

Using Becky Richa’s absolutely fantastic guide and resources (https://github.com/beckyricha/Broadlink-RM-SmartThings-Alexa) I’ve managed to create a device called “Window Unit” in SmartThings that has a simple On/Off toggle. It works well, and I’d like to create a similar toggle in the same device that switches modes (cool/heat). As far as I can tell, I’ve copied her code exactly, and then changed it in all the corresponding places to do what I want to do. But it does not toggle from one to the other like the on/off switch does. I’d really appreciate if someone more knowledgeable than myself could take a look at this and tell me why it isn’t working. I’m sure I’ll have more questions as I progress on this project, but for the time being, all I need to do is get the image/text/color of the icon to toggle when tapped. Please note that I’m very new to SmartThings, and while I have some general programming knowledge, I am by no means an expert. Any suggestions would probably be more helpful if they are explained in a way that a beginner could understand. The code is below, along with some screenshots for reference. Thanks!

/**
 *  Broadlink Switch
 *
 *  Copyright 2016 BeckyR
 *
 *  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.
 *
 *  1/7/17 - updated with better switch displays and use of device ID from user itsamti
 */
 
 
// 09/01/2016 - itsamti - Added new switch definition below 
metadata {
	
    definition (name: "RM Bridge Switch LAN", namespace: "beckyricha", author: "BeckyR") {
		capability "Switch"
	}

	tiles {
		// This section of code works!!
        standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
			state "off", label: 'Off', action: "switch.on", icon: "st.switches.switch.on", backgroundColor: "#ffffff"
			state "on", label: 'On', action: "switch.off", icon: "st.switches.switch.off", backgroundColor: "#00a0dc"
		}
        /* This section of code does not :( Also, please note that although this example uses action: cool and action: heat, I did also try action: mode.heat and action: mode.cool with the same results. */
		standardTile("mode", "device.mode", width: 1, height: 1) {
			state "heat", label: 'Heat', action: "cool", icon: "st.Home.home29", backgroundColor: "#d04e00"
            state "cool", label: 'Cool', action: "heat", icon: "st.Appliances.appliances11", backgroundColor: "#1e9cbb"
		}
        // The valueTile will eventually show the current temperature as read by the Multipurpose Sensor
        valueTile("tempValue", "device.power", decoration: "flat", width: 1, height: 1) {
            state "power", label:'78 degrees', icon: "st.Weather.weather2" 
        }
        // The controlTile will eventually allow the user to use a slider to pick a temperature to set
        controlTile("tinySlider", "device.level", "slider", height: 2, width: 1, inactiveLabel: false) {
			state "level", action:"switch level.setLevel"
		}
        main "switch"
		details(["switch","switch2","tinySlider","mode","tempValue"])
	}
}

def parse(String description) {
	def pair = description.split(":")
	createEvent(name: pair[0].trim(), value: pair[1].trim())
}

def on() {
	sendEvent(name: "switch", value: "on")
	put('on')
}

def off() {
	sendEvent(name: "switch", value: "off")
	put('off')
}

def heat() {
	sendEvent(name: "mode", value: "heat")
	put('heat')
}

def cool() {
	sendEvent(name: "mode", value: "cool")
	put('cool')
}

private put(toggle) {
    // IP address changed for privacy, and this section can be disregarded, as I'm only focused on fixing toggle functionality of the tile right now
    def url1="XXX.XXX.XX.XX:7474"
    def userpassascii= "yourusername:yourpassword"
    def userpass = "Basic " + userpassascii.encodeAsBase64().toString()
    def toReplace = device.deviceNetworkId
	def replaced = toReplace.replaceAll(' ', '%20')
 	def hubaction = new physicalgraph.device.HubAction(
				method: "GET",
               path: "/code/$replaced%20$toggle",
               headers: [HOST: "${url1}", AUTHORIZATION: "${userpass}"],
               )
   			return hubaction
   }

At the risk of not being super helpful (because I haven’t run your code nor examined super closely)… These notes may help:

  1. A Tile will only change when it receives a State change event for the associated Attribute or if the “nextState” parameter is used. nextState is recommended when used properly to indicate a transition state (eg. “Turning On”).

  2. Yes… Your code is running sendEvent(), but in my experience, sendEvent to affect a Tile in the current Device Handler is unreliable / inconsistent.

  3. The “proper” behavior is for the new State to be sent by the physical device and subsequently received by the parse() method which calls sendEvent implicitly upon exit.

I believe #1 + #2 is the path to a solution.

1 Like

I’m sorry, some of that is a bit over my head, but I appreciate the reply! A few questions - how would I go about changing the state? If I understand correctly I would need to use nextState to toggle it from heat to cool, but what would the proper syntax be (or where could I find it)? Also, I’m just curious about this one, but why do you suppose her bit of code works and mine doesn’t? The only parts of it that I’ve changed are the ones that apply to the images/colors/text. Do you see any areas where I made a modification that should interfere with the way the button functions? Thanks again.

Well… Normally I’d point you to the Developer Docs, but they seem to be incomplete and don’t list the “nextState” option… grrr :confused: http://docs.smartthings.com/en/latest/ref-docs/device-handler-ref.html#standardtile … maybe the parameter is deprecated or hidden…

The next best option is to look at popular standard DTH’s like a Switch:


Welcome to SmartThings. Inconsistent behavior is to be expected.

  1. Revert your code to the exact original and see if it behaves correctly.
  2. Modify it one change at a time until it breaks, then go back and avoid that modification.
1 Like

Thanks, I’ll take a look at that! In the mean time, I’ve been trying to troubleshoot it as you suggested, but I’m quite stumped. It appears that device.switch is something I can’t change (I had previously changed it to device.mode because I wanted it to represent the mode of the window unit). So I changed it back to device.switch. I’ve gotten it now so that both toggles are working, the problem is that when I press either, they both toggle both buttons. This seems like something that should be really simple, I’m sure I’m missing something obvious. But I’ve been at it for hours and it’s looking like it may be more trouble than it’s worth. Thanks for your help!

I’d avoid the word “mode” because that has a lot of meanings in SmartThings.

Regardless of what you call it, you need to declare the custom Attribute in your metadata{}.

http://docs.smartthings.com/en/latest/ref-docs/device-handler-ref.html#attribute

(PS: Please read all the docs. Yes… all the docs :wink: ).

1 Like

Awesome! That looks promising. I will update if I’m able to work this out. Thanks for your patience. :relaxed:

1 Like

Finally got it! After browsing the forums here and playing around with it a bit more, I was able to get to a solution. Your suggestion about attributes helped me work it out. I’ll post the code in case it may help anyone having a similar problem. Thanks again for all your help.

/**
 *  Broadlink Switch
 *
 *  Copyright 2016 BeckyR
 *
 *  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.
 *
 *  1/7/17 - updated with better switch displays and use of device ID from user itsamti
 */
 
 
// 09/01/2016 - itsamti - Added new switch definition below 
metadata {
	
    definition (name: "RM Bridge Switch LAN", namespace: "beckyricha", author: "BeckyR") {
		capability "Switch"
        	attribute "thermostatMode", "string"
            	command "heat"
            	command "cool"
	}

	tiles {
        standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
			state "off", label: 'Off', action: "switch.on", icon: "st.switches.switch.on", backgroundColor: "#ffffff"
			state "on", label: 'On', action: "switch.off", icon: "st.switches.switch.off", backgroundColor: "#00a0dc"
		}
		standardTile("thermostatMode", "device.thermostatMode", width: 1, height: 1) {
			state "off", label: 'Heat', action: "heat", icon: "st.Home.home29", backgroundColor: "#d04e00"
            state "on", label: 'Cool', action: "cool", icon: "st.Appliances.appliances11", backgroundColor: "#1e9cbb"
		}

        main "switch"
		details(["switch","tinySlider","thermostatMode","tempValue"])
	}
}

def parse(String description) {
	def pair = description.split(":")
	createEvent(name: pair[0].trim(), value: pair[1].trim())
}

def on() {
	sendEvent(name: "switch", value: "on")
	put('on')
}

def off() {
	sendEvent(name: "switch", value: "off")
	put('off')
}

def heat() {
	sendEvent(name: "thermostatMode", value: "on")
	put('heat')
}

def cool() {
	sendEvent(name: "thermostatMode", value: "off")
	put('cool')
}

private put(toggle) {
    // IP address changed for privacy, and this section can be disregarded, as I'm only focused on fixing toggle functionality of the tile right now
    def url1="XXX.XXX.XX.XX:7474"
    def userpassascii= "yourusername:yourpassword"
    def userpass = "Basic " + userpassascii.encodeAsBase64().toString()
    def toReplace = device.deviceNetworkId
	def replaced = toReplace.replaceAll(' ', '%20')
 	def hubaction = new physicalgraph.device.HubAction(
				method: "GET",
               path: "/code/$replaced%20$toggle",
               headers: [HOST: "${url1}", AUTHORIZATION: "${userpass}"],
               )
   			return hubaction
   }
}
1 Like