How to pass parameters in href?


(Alex) #39

15 characters in the documentation are worth about 3 days of development efforts!


(Patrick Stuart [@pstuart]) #41

Why? This is redundant since all the devices and their states are subscribed in the settings array.

You can always get a device capability status in the settings.[inputname] list and route what you want to a state variable if you want, but just seems like a waste of memory to duplicate what is already there.


(Mike Maxwell) #42

Yea, I’m aware of that. This question came up in another thread when another dev was trying to not call getChildDevice(s) repedetly and was attempting to stuff them into a state structure.
As I mentioned, I use some of the info in the deviceInput arrays as a key to a state map structure to store everything else…
You assumed by “deviceList”, i meant those devices associated with preference selection variables.


(Alex) #43

Anyone knows what the memory limit is?

We have limit of execution duration at 20 sec, scheduled jobs at 4. Any memory cap?


(Todd Wackford) #44

@Mike_Maxwell,

instead of storing the device object in the state var, I store it’s id. Then when I need to, I enum through the devices and find the matching ID. Not elegant, but it works.

Also, here’s a bit of code that may help you manage the settings a little better:

//remove the child from settings. Unselects from list of devices, not delete
log.debug "Settings size = ${settings['devices']}"

if (!settings['devices']) //empty list, bail
	return

def newDeviceList = settings['devices'] - childDevice.device.deviceNetworkId
app.updateSetting("devices", newDeviceList)

(Mike Maxwell) #45

Thanks Todd, but I’m not storing the device object or child devices in a state variable, even if you wanted to for some insane reason, it is not possible.
I use the device.Id as a key into a map in the state variable, as you describe.

Now that settings snippet?, that bad boy is gold!

So If I read the above correctly:
childDevice is a map you created in state, that was previously populated via getChildDevices() or the like…
You’re creating a new list of devices which are the user selected devices without any child devices the user may have selected…
And then updating the page device list…
Is that a correct understanding?

Where do you find these?


(Todd Wackford) #46

Actually this is how I handled the user deleting the child device down in the device (thing) itself and I needed to reflect that in the service manager app UI. It “un-selects” the child device without deleting it from the device list.

I probably should have added this to the snip:

def deviceData = state.deviceDataArr.findAll { it.id == childDevice.device.deviceNetworkId }

(Alex) #47

Jim, so what’s the difference between the two examples that are listed at the above URL?

Neither of them opens a link in external browser. They both open links in some sort of embedded browsers.

I’m on Android 5 with latest ST app.


(Jim Anderson) #48

external: true opens the link in a web browser (Safari) in iOS. I’ll have to follow-up about Android not behaving that way.


(Alex) #49

Yes please. For half a year I’ve been going out of my way with SmartTiles to output a URL.

  • Printing to the logs
  • Sending as a text message
  • Building an embedded web app for the sole purpose of displaying it!

Nothing beats opening a URL in a web browser!!!


(Jim Anderson) #50

Just want to follow up and correct some information here:

style: external has been replaced with using the style: "external" parameter. I’ve updated the documentation around it.

Android does not currently support opening URLs in the browser; a bug report has been filed.


(Alex) #51

Darn. I had such high hopes! This would really liberate SmartTiles from ridiculous workarounds.

Keep me posted please.


(www.rboyapps.com - Make your home your butler!) #52

When passing parameters via the href command when there is more than one section, it’s broken in Android.
This is difficult to explain but the end result is if you have a loop for input parameters and you want to pass the parameters to the href page it doesn’t work on Android. It works perfectly on iOS.

Try this simple test example

definition(
    name: "Test HREF App",
    namespace: "smartthings",
    author: "SmartThings",
    description: "Test HREF Pages",
    category: "SmartThings Labs",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/App-LightUpMyWorld.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/App-LightUpMyWorld@2x.png"
)

preferences {
    page(name: "main")
    page(name: "testPage")
}


def main() {
    dynamicPage(name: "main", title: "HREF Test", uninstall: true, install: true) {
        for (int i = 1; i <= 5; i++) {
            def priorName = settings."userNames${i}" 
            section("User #${i}") { 
                if (priorName) {
                    input name: "userNames${i}", description: "${priorName}", title: "Name", defaultValue: priorName, type: "text", multiple: false, required: false, submitOnChange: true
                } else {
                    input name: "userNames${i}", description: "Tap to set", title: "Name", type: "text", multiple: false, required: false, submitOnChange: true
                }

                def hrefParams = [
                    user: i as String, 
                    passed: true 
                ]
                log.trace "$i Params: $hrefParams"
                href(name: "testPage", params: hrefParams, title: "Click here to define actions for ${settings."userNames${i}"}", page: "testPage", description: "", required: false)
            }
        }

        section("Mode Change Open Door/Window/Switch Notification") {
            def modes = location.modes
            for (mode in modes) {
                // Unlock actions for each mode
                def hrefParams1 = [
                    user: mode as String, 
                    passed: true 
                ]
                href(name: "modeDoorMonitor", params: hrefParams1, title: "When switching to mode ${mode}", page: "testPage", description: "", required: false)
            }
        }
    }
}

def testPage(params) {
    //  params is broken, after doing a submitOnChange on this page, params is lost. So as a work around when this page is called with params save it to state and if the page is called with no params we know it's the bug and use the last state instead
    if (params.passed) {
        atomicState.params = params // We got something, so save it otherwise it's a page refresh for submitOnChange
    }

    def user = atomicState.params?.user ?: ""
    def name = user ? settings."userNames${user}" : ""

    log.trace "Actions Page, user:$user, name:$name, passed params: $params, saved params:$atomicState.params"

    dynamicPage(name:"testPage", title: "Setup actions for each door" + (user ? " for user $name." : ""), uninstall: false, install: false) {
        section {
            input "userOverrideUnlockActions${user}", "bool", title: "Define specific actions for $name", required: true,  submitOnChange: true
        }
    }
}

def initialize() {
}

def updated() {
}

@slagle @jody.albritton I’ve reported this to support ticket number 195968

Am I doing this incorrectly or is just a broken Android behavior?


Android 2.1.5 - Release Notes
[RELEASE] Open/Close Door/Window/Switch/Lock/Valve/Shade Notification and Actions on Mode Change
[RELEASE] Lock User Management: Door lock code manager (create, delete and schedule codes) with automatic lock/unlock, custom user actions and SHM/ADT integration
(Tim Slagle) #53

Does it get to your log.trace, or just fail upon entry into that code block?


(www.rboyapps.com - Make your home your butler!) #54

No I get to the trace, the page load fine, just the the parameter being passed is always the last user in case of Android, no matter what section you click on.
e.g Click on section 1 -> user passed 5
e.g Click on section 2 -> user passed 5
e.g Click on section 3 -> user passed 5
e.g Click on section 4 -> user passed 5
e.g Click on section 5 -> user passed 5

It passes the parameter of the section always with Android (with iOS it passes the correct number).

Is there a different/better way to handle this?


(www.rboyapps.com - Make your home your butler!) #55

This was fixed in the last Android version and THEY BROKE IT AGAIN WITH 2.1.5

@alex an classic example ST never learning from their mistakes. I can see this issue being reported and fixed over and over since March 2015. How’s that for QA.


(Kyle LeNeau) #56

Are you sure that your app updated to 2.1.5. We just tested this and are not seeing the same issue. Can you provide some more information about your phone model and OS version. There might be something odd there but w’ll keep taking a look.


(Patrick Musselman) #57

Continuing the discussion from [RELEASE] Open Door/Window/Switch Notification on Mode Change:

@kleneau I believe this in reference to the issues the I was having after installing the Open Door Window/Switch Notification on Mode Change app. I am using a Samsung S6+ and my OS is 5.1.1. Thanks!


(www.rboyapps.com - Make your home your butler!) #58

###Update the sample test code, two scenario’s one with for inside the section and other outside.

When passing parameters via the href command when there is more than one section, it’s broken in Android.
This is difficult to explain but the end result is if you have a loop for input parameters and you want to pass the parameters to the href page it doesn’t work on Android. It works perfectly on iOS.

Try this simple test example

definition(
    name: "Test HREF App",
    namespace: "smartthings",
    author: "SmartThings",
    description: "Test HREF Pages",
    category: "SmartThings Labs",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/App-LightUpMyWorld.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/App-LightUpMyWorld@2x.png"
)

preferences {
    page(name: "main")
    page(name: "testPage")
}


def main() {
    dynamicPage(name: "main", title: "HREF Test", uninstall: true, install: true) {
        for (int i = 1; i <= 5; i++) {
            def priorName = settings."userNames${i}" 
            section("User #${i}") { 
                if (priorName) {
                    input name: "userNames${i}", description: "${priorName}", title: "Name", defaultValue: priorName, type: "text", multiple: false, required: false, submitOnChange: true
                } else {
                    input name: "userNames${i}", description: "Tap to set", title: "Name", type: "text", multiple: false, required: false, submitOnChange: true
                }

                def hrefParams = [
                    user: i as String, 
                    passed: true 
                ]
                log.trace "$i Params: $hrefParams"
                href(name: "testPage", params: hrefParams, title: "Click here to define actions for ${settings."userNames${i}"}", page: "testPage", description: "", required: false)
            }
        }

        section("Mode Change Notification") {
            def modes = location.modes
            for (mode in modes) {
                // Unlock actions for each mode
                def hrefParams1 = [
                    user: mode as String, 
                    passed: true 
                ]
                href(name: "modeDoorMonitor", params: hrefParams1, title: "When switching to mode ${mode}", page: "testPage", description: "", required: false)
            }
        }
    }
}

def testPage(params) {
    //  params is broken, after doing a submitOnChange on this page, params is lost. So as a work around when this page is called with params save it to state and if the page is called with no params we know it's the bug and use the last state instead
    if (params.passed) {
        atomicState.params = params // We got something, so save it otherwise it's a page refresh for submitOnChange
    }

    def user = atomicState.params?.user ?: ""
    def name = user ? settings."userNames${user}" : ""

    log.trace "Actions Page, user:$user, name:$name, passed params: $params, saved params:$atomicState.params"

    dynamicPage(name:"testPage", title: "Setup actions for each door" + (user ? " for user $name." : ""), uninstall: false, install: false) {
        section {
            input "userOverrideUnlockActions${user}", "bool", title: "Define specific actions for $name", required: true,  submitOnChange: true
        }
    }
}

def initialize() {
}

def updated() {
}

(Patrick Musselman) #59

This resolved my issue Open Door Window/Switch Notification on Mode Change app.