New Things view Forces you to see what they want you to see in multi tile at top

The new multi tile feature and new App feature locks you into only the first option for the Main section.

So if you have a multi sensor, or anything with more than one display tile, the first in the main will be shown only.

The old app used to allow you to tap a small circle in each tile to set it as the default tile.

Now, that option is gone.

I will be putting together some alternative devicetypes for the new ones to display other tiles in the multitile view.

For example:

Moisture sensor shows dry/wet as the default, but frankly I really want to see the temp setting. This was possible in old app, now impossible with the updated devicetype.

I will make available one that shows temp as the default.

Same thing for multi sensors.

If you want to fix these your self, the new devicetypes are in the IDE in the browse examples. You can make your own versions.

As soon as the IDE allows me to save and test things… Ahhhhh… I feel for these guys.

10 Likes

I miss this feature too.
Also, It would be good to have the ability to have the state of multiple devices rather than just one device on the top tile. I feel we are wasting a lot of real estate by showing the state of one device.

Yeah, as soon as I figure out how to do that, I will try. The docs are up but right now nothing really is working in the IDE.

It will work in time…

@pstuart, I believe you just need to remove the new code that uses the multiattributetile code, plus the width/height =2 setting for each smaller tile, if I remember right.

yeah, but I like the multiattributetile :smile: Just don’t like that I can’t choose what I want to be there.

It is a bit more complicated, but it is totally doable.

What isn’t clear is if I do a custom devicetype will things still run local on hub v2. Time will tell.

Yep, I do like that agreed. I guess it will take a little bit of time to get use to the newness of the app and new features, as well as stuff I wish we still had.

I saved a copy of the smartsense multi a while back, and looking at the code between that and what’s there now, the difference is only in these lines:

tiles(scale: 2) {
	multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){
		tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
			attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e"
			attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821"
		}
	}

Every other line is exactly the same (except the other tiles specifying size). I don’t think that wouldn’t impact running locally. Do you think that the tileAttribute statement is key to tweaking? I’ll go look at the documentstion as well. I’m really curious to see how this can be done.

Yeah, it isn’t exactly, cause the contact open/closed is now missing as a standard tile.

Here was an interesting statement in the docs:

Execution Location

With the original SmartThings hub, all Device handlers execute in the SmartThings cloud. With the new Samsung SmartThings hub, certain Device handlers may run locally on the hub or in the SmartThings cloud. Execution location varies depending on a variety of factors, and is managed by the SmartThings internal team.

As a SmartThings developer, you should write your device handlers to satisfy their specific use cases, regardless of where the handler executes. There is currently no way to specify or force a certain execution location.

Yeah, can’t find it right now, but it was stated somewhere that custom / user devicetypes would not be allowed to run locally unless submitted for approval by ST. This has yet to be clarified.

If we modify these devicetypes and use our own, will that prevent these from working locally? Time will tell.

I think @Ben further clarified that this is not going to be some committee, but a set of criteria that the smartapp has to meet. I don’t think they have the criteria or the automation to handle this yet. He said they want as much as possible to run locally.

1 Like

Smartapps yes, but it is still vague how devicetypes are handled. I realize the goal is to run everything local that can be local.

First one “fixed” to my desired view.

Moisture Sensor now shows Temp as default and the secondary BigTile is the status of the dry/wet

2 Likes

Fixed Zen Thermostat to add multi tile and some text to indicate what is running.

Nice, I like the thermostat changes. I wrote a device type for my use case to update tiles for the same thing for the old app. I’ll take a look at your code to update mine and simplify it.

If you figure out the VALUE_CONTROL stuff, that would be pretty sweet as well. Do you have to change “type” from lighting to thermostat?

the type lighting is the only one so far that supports the secondary and slider controls.

thermostat type doesn’t seem to do anything, yet.

1 Like

Here’s a VALUE_CONTROL use that maybe you can help with. It’s for the fan control. The up arrow always works, but the down arrow has an issue where it looks to be triggering the correct method (debug log shows message), but the zwave command doesn’t fire and there’s no speed change.

Sorry, it’s not in GitHub. Tossed it together quickly making use of an adapted setLevel() that enables fan speed control from my Harmony remote.

@pstuart I think you could update your Zen for the VALUE_CONTROL by making the action setSetpoint. It looks to increment by 1 as a default, so you might have to work around that if you want finer control.

metadata {
	// Automatically generated. Make future change here.
	definition (name: "My GE Fan Control Switch v2", namespace: "jscgs350", author: "SmartThings") {
		capability "Switch Level"
		capability "Actuator"
		capability "Indicator"
		capability "Switch"
		capability "Polling"
		capability "Refresh"
		capability "Sensor"
        
        command "lowSpeed"
        command "medSpeed"
        command "highSpeed"

        attribute "currentSpeed", "string"

//		fingerprint inClusters: "0x26"
	}

	tiles(scale: 2) {

                multiAttributeTile(name:"richSwitch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
                 tileAttribute("device.switch", key: "PRIMARY_CONTROL"){
                   attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821"
		           attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff"
                   attributeState "turningOn", label:'${name}', icon:"st.switches.switch.on", backgroundColor:"#79b821"
  			       attributeState "turningOff", label:'${name}', icon:"st.switches.switch.off", backgroundColor:"#ffffff"
                 }
                 tileAttribute("device.currentSpeed", key: "SECONDARY_CONTROL"){
                   attributeState "currentSpeed", label:'${currentValue}'
                 }
                 tileAttribute("device.level", key: "VALUE_CONTROL"){
                   attributeState "level", action: "switch level.setLevel"
                 }
                }
//		standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
//			state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821"
//			state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff"
//			state "turningOn", label:'${name}', icon:"st.switches.switch.on", backgroundColor:"#79b821"
//			state "turningOff", label:'${name}', icon:"st.switches.switch.off", backgroundColor:"#ffffff"
//		}
		standardTile("indicator", "device.indicatorStatus", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "when off", action:"indicator.indicatorWhenOn", icon:"st.indicators.lit-when-off"
			state "when on", action:"indicator.indicatorNever", icon:"st.indicators.lit-when-on"
			state "never", action:"indicator.indicatorWhenOff", icon:"st.indicators.never-lit"
		}
		standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
		}
		controlTile("levelSliderControl", "device.level", "slider", height: 2, width: 6, inactiveLabel: false) {
			state "level", action:"switch level.setLevel"
		}
        valueTile("currentSpeed", "device.currentSpeed", canChangeIcon: false, inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
            state ("default", label:'${currentValue}')
        }

//Speed control row
        standardTile("lowSpeed", "device.level", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
            state "lowSpeed", label:'LOW', action:"lowSpeed", icon:"st.Home.home30"
        }
        standardTile("medSpeed", "device.level", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
            state "medSpeed", label:'MED', action:"medSpeed", icon:"st.Home.home30"
        }
        standardTile("highSpeed", "device.level", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
            state "highSpeed", label:'HIGH', action:"highSpeed", icon:"st.Home.home30"
        }

		main(["richSwitch"])
		details(["richSwitch", "lowSpeed", "medSpeed", "highSpeed",  "indicator", "currentSpeed",  "refresh"])
	}
}

def parse(String description) {
	def item1 = [
		canBeCurrentState: false,
		linkText: getLinkText(device),
		isStateChange: false,
		displayed: false,
		descriptionText: description,
		value:  description
	]
	def result
	def cmd = zwave.parse(description, [0x20: 1, 0x26: 1, 0x70: 1])
	if (cmd) {
		result = createEvent(cmd, item1)
	}
	else {
		item1.displayed = displayed(description, item1.isStateChange)
		result = [item1]
	}
	log.debug "Parse returned ${result?.descriptionText}"
	result
}

def createEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	for (int i = 0; i < result.size(); i++) {
		result[i].type = "physical"
	}
	result
}

def createEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	for (int i = 0; i < result.size(); i++) {
		result[i].type = "physical"
	}
	result
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStartLevelChange cmd, Map item1) {
	[]
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStopLevelChange cmd, Map item1) {
	[response(zwave.basicV1.basicGet())]
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelSet cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	for (int i = 0; i < result.size(); i++) {
		result[i].type = "physical"
	}
	result
}

def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd, Map item1) {
	def result = doCreateEvent(cmd, item1)
	result[0].descriptionText = "${item1.linkText} is ${item1.value}"
	result[0].handlerName = cmd.value ? "statusOn" : "statusOff"
	for (int i = 0; i < result.size(); i++) {
		result[i].type = "digital"
	}
	result
}

def doCreateEvent(physicalgraph.zwave.Command cmd, Map item1) {
	def result = [item1]

	item1.name = "switch"
	item1.value = cmd.value ? "on" : "off"
    if (item1.value == "off") {
     	sendEvent(name: "currentSpeed", value: "OFF" as String)
    }
	item1.handlerName = item1.value
	item1.descriptionText = "${item1.linkText} was turned ${item1.value}"
	item1.canBeCurrentState = true
	item1.isStateChange = isStateChange(device, item1.name, item1.value)
	item1.displayed = item1.isStateChange

	if (cmd.value >= 5) {
		def item2 = new LinkedHashMap(item1)
		item2.name = "level"
		item2.value = cmd.value as String
		item2.unit = "%"
		item2.descriptionText = "${item1.linkText} dimmed ${item2.value} %"
		item2.canBeCurrentState = true
		item2.isStateChange = isStateChange(device, item2.name, item2.value)
		item2.displayed = false
        if (item2.value == "30") {
        	sendEvent(name: "currentSpeed", value: "LOW" as String)
        }
        if (item2.value == "62") {
        	sendEvent(name: "currentSpeed", value: "MEDIUM" as String)
        }
        if (item2.value == "99") {
        	sendEvent(name: "currentSpeed", value: "HIGH" as String)
        }        
		result << item2
	}
	result
}

def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
	def value = "when off"
	if (cmd.configurationValue[0] == 1) {value = "when on"}
	if (cmd.configurationValue[0] == 2) {value = "never"}
	[name: "indicatorStatus", value: value, display: false]
}

def createEvent(physicalgraph.zwave.Command cmd,  Map map) {
	// Handles any Z-Wave commands we aren't interested in
	log.debug "UNHANDLED COMMAND $cmd"
}

def on() {
	log.info "on"
	delayBetween([zwave.basicV1.basicSet(value: 0xFF).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def off() {
	log.info "off"
    delayBetween ([zwave.basicV1.basicSet(value: 0x00).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def setLevel(value) {    
    log.debug "New speed is ${value}"
    
	if (value < device.currentValue("level")) {
    	log.debug "Speed decrease"
    	switch(device.currentValue("currentSpeed")) {
        	case "HIGH":
            	medSpeed()
                break
            case "MEDIUM":
            	lowSpeed()
                break
            case "LOW":
            	off()
                break
            default:
            	break
        }
    }
    
    if (value > device.currentValue("level")) {
        log.debug "Speed increase"
        switch(device.currentValue("currentSpeed"))  {
        	case "HIGH":
                break
            case "MEDIUM":
            	highSpeed()
                break
            case "LOW":
            	medSpeed()
                break
            case "OFF":
            	lowSpeed()
                break
            default:
            	break
        }
   
    }

	//def level = Math.min(value as Integer, 99)
	//delayBetween ([zwave.basicV1.basicSet(value: level).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def setLevel(value, duration) {
    def level = Math.min(value as Integer, 99)
	def dimmingDuration = duration < 128 ? duration : 128 + Math.round(duration / 60)
	zwave.switchMultilevelV2.switchMultilevelSet(value: level, dimmingDuration: dimmingDuration).format()
}

def lowSpeed() {
	log.debug "Low speed settings"
    delayBetween ([zwave.basicV1.basicSet(value: 30).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def medSpeed() {
	log.debug "Medium speed settings"
    delayBetween ([zwave.basicV1.basicSet(value: 62).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}

def highSpeed() {
	log.debug "High speed settings"
    delayBetween ([zwave.basicV1.basicSet(value: 99).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}


def poll() {
	zwave.switchMultilevelV1.switchMultilevelGet().format()
}

def refresh() {
	zwave.switchMultilevelV1.switchMultilevelGet().format()
}

def indicatorWhenOn() {
	sendEvent(name: "indicatorStatus", value: "when on", display: false)
	zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format()
}

def indicatorWhenOff() {
	sendEvent(name: "indicatorStatus", value: "when off", display: false)
	zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format()
}

def indicatorNever() {
	sendEvent(name: "indicatorStatus", value: "never", display: false)
	zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 3, size: 1).format()
}

def invertSwitch(invert=true) {
	if (invert) {
		zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 4, size: 1).format()
	}
	else {
		zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 4, size: 1).format()
	}
}
1 Like

Cool, thanks @Sticks18. As soon as I can get done with a few honey-do stuff I’ll be working on this tonight. Stay tuned!

Hmmm, no matter what I do I can’t get the up / down arrows to show up on Android. are you on android or iOS?

EDIT, confirmed. OMG, they don’t even have the up down arrows in the Android code.

Funny… iOS only then… Maybe this was a bit rushed?

1 Like

iOS. Wow! That’s a big bug. I guess they had a date to hit.

1 Like

@pstuart and @Sticks18 , That explains why my thermos didn’t see the arrow, holy cow. I was beating myself up trying to figure out what I was doing wrong…

Did the up/down arrows both work as expected?