Bug in Parent Child Devices

Then I’m out of ideas. Seems to me that there is a platform issue where the context to access the “state” (atomic or otherwise) seems to be broken when dealing with a new thread (call from a child app).

Did you guys see this?

http://docs.smartthings.com/en/latest/smartapp-developers-guide/parent-child-smartapps.html#tips-best-practices

Tips & Best Practices

  • Think carefully about creating more than one level of parent-to-child relationships, as it may negatively impact usability and create unneeded complications.
  • Sharing state or atomicState between parent and child SmartApps is not currently supported.

Without seeing some sample code I can’t replicate what you guys are seeing. I do this currently with a device I wrote but put it in a method and return it.

1 Like

Yes, have seen this.

I interpreted the “Sharing state or atomicState between parent and child SmartApps” part as meaning that they don’t use the same context, but not that changes to the state variables made by the parent when called by a child wouldn’t work.

Btw, I had this same set of problems within the same app, no parent/child apps involved for me. (For me it was a child device calling a parent app). And all of my state variable handling was directly in the parent app (no direct calls to the state variables from the child device). I ended up having to switch from state to atomicState to fix part of it, but then I had problems with creating lists on atomicState.

Something isn’t right here.

Rule Machine makes extensive use of state variables in the parent. It used to use more, but I changed something. It used to be that every Rule reported its truth state to the parent, who kept it in a state variable. That worked with 100% reliability. Now, I simply have the parent call the child in question to get the truth state, and report it back to which ever child is asking for it. I still keep “subscriptions” in the parent, in a state variable, and that has been 100% reliable also.

And, whenever I put log.debug statements in the parent in methods called by child apps, they show up just fine, in the child app log stream.

So, @RBoy, something is messed up with your parent-child setup! More than the bug you think you’re seeing. In fact, it could be that whatever is messed up is the reason for the problem. Just setting a state variable in the parent, and then seeing it later, work fine for me, and I’ve banged the heck out of it. So have a lot of users. Except for the bugs that I’ve introduced along the way, that all works as expected.

1 Like

That never worked for me, just like RBoy, so I also use a custom LOG method to be able to show the debug information in the child logs.

Yes I did but these are 2 different things. This is taking about sharing the State/AtomicState variables - which isn’t what I’m trying to do.

I expect the State variable to be valid in the context of the Smartapp. I.e. I can access that variable anywhere in the SmartApp. In this case when the SmartApp is called the State variable always starts with null

If you have a child parent just try this, in your SmartApp method called by the child try this:
Device Handler (inside your refresh() command)

callAppMethod(this)

Also define this in your Device Handler to help see what’s going on

 def log(message) {
    log.trace message
}

SmartApp

def callAppMethod(child) {
    child.log "BEFORE State: $state.testVar"
    if (state.testVar == null) {
        child.log "EMTPTY!!"
        state.testVar = []
    }
    state.testVar << ["testing", "testing2"]
    child.log "AFTER State: $state.testVar"
}

Try it out and see what happens. Call it a few times and the state.testVar should keep increasing in size but you’ll see it’s ALWAYS empty.

What? Look at this example below, parent and child. Child calls parent, parent logs it, child logs it, all show up in child’s log. This worked first time. Are you guys using singleInstance: true in your parent definition?

definition(
	name: "Test Parent",
	singleInstance: true,
	namespace: "bravenel",
	author: "Bruce Ravenel",
	description: "Test Parent",
	category: "My Apps",
	iconUrl: "https://raw.githubusercontent.com/bravenel/Rule-Trigger/master/smartapps/bravenel/RuleMachine.png",
	iconX2Url: "https://raw.githubusercontent.com/bravenel/Rule-Trigger/master/smartapps/bravenel/RuleMachine%402x.png",
	iconX3Url: "https://raw.githubusercontent.com/bravenel/Rule-Trigger/master/smartapps/bravenel/RuleMachine%402x.png"
)

preferences {
	page(name: "mainPage")
}

def mainPage() {
    dynamicPage(name: "mainPage", title: "Installed Children ", install: true, uninstall: false) {
        section {
            app(name: "childApps", appName: "testChild", namespace: "bravenel", title: "Create New Child...", multiple: true)
        }
    }
}

def testMethod(param) {
	log.debug "testMethod: $param"
    return param
}

def installed() {
}

def updated() {
}

Here is the child:

definition(
	name: "testChild",
	namespace: "bravenel",
	author: "Bruce Ravenel",
	description: "testChild",
	category: "Convenience",
	parent: "bravenel:Test Parent",
	iconUrl: "https://raw.githubusercontent.com/bravenel/Rule-Trigger/master/smartapps/bravenel/RuleMachine.png",
	iconX2Url: "https://raw.githubusercontent.com/bravenel/Rule-Trigger/master/smartapps/bravenel/RuleMachine%402x.png",
)

preferences {
	page(name: "mainPage")

}

def installed() {
	log.debug "Installed"
}

def updated() {
	log.debug "Called Parent: ${parent.testMethod("Hello")}"
}

def mainPage() {
	dynamicPage(name: "mainPage", title: "New child test app", uninstall: true, install: true) {
    	section() {
			label title: "Name the Trigger", required: true
            log.debug "Hi from child"
        }
    }
}

Yes I am

(20 characters needed)

Yes and

I tried your code and nothing happens. It’s not installing any children when I click on Create new child nor is there any output in the debugger, nothing at al…

Truly strange. Take a look in the IDE in installed apps.

The first time I installed it, I omitted the page in the child. Then clicking on new child didn’t do anything. Once I used the code above, worked fine.

What’s different between your situation and mine???

I wonder if this could be a namespace problem. Try changing the namespace in both parent and child to your own namespace.

Did you hit Done in the parent when you opened it in the Marketplace? If not, no children.

Yep, I tried clicking it, hitting done, no children and surprisingly no logging either.

@bravenel could you explain this line? I don’t see this anywhere in the ST docs. For creating new child devices as I understand the API is

addChildDevice

@bravenel hang on, does your code create a child SmartApp (installed the child a device not a smart app)? I’m referring to a child Device type and the child device calls the parent smartapp.

EDIT: Yep when I set it up as an SmartApp to SmartApp (Parent to Child it works fine), but that’s not what I’m tring. It’s a SmartApp to Device Parent Child relationship and that’s completely broken for State variable.

@slagle point to note please, the issue is with App to Device

1 Like

Okay, you had me all confused too since the title says “Parent Child Apps”…

So I tested a few things when I got home tonight:
@bravenel’s code: this worked, but not in the way that I was thinking it was being explained. I did see all the log messages, but all in the Child App. The Test Parent never showed up in the logs at all. This can be very confusing when debugging as I am generally looking for the log messages in the app that generates them. But I suspect this is working as intended (or at least they aren’t likely to change things).

I also went back and tested my own app and realized my situation was also different that what is described here. I actually generate both Child Apps and Child Devices, so I was mixing a little of the two in the thread.

Here is what I have:
Ecobee (Connect) App --> Ecobee Thermostat (Device)
|----> Ecobee Sensors (Device)
`----> Helper SmartApps (Child SmartApp)

So, what I was actually doing was calling functions inside the Ecobee Thermostat (Device) from the Helper SmartApp (Child SmartApp). The Ecobee Thermostat then calls functions within the Ecobee (Connect) SmartApp. So the flow of various log messages can be very convoluted. What I end up seeing is log messages show up in the Helper SmartApp, they show up in the Thermostat Device logs but nothing shows up under the Ecobee (Connect) Parent SmartApp.

Could you replicate the issue of not being able to save the State variable in your parent app method when called from your child device?

I need to revisit all that to remind myself what all was going on again. When I gave up on using state (after 3-4 hrs troubleshooting) I just switched over to atomicState. So not sure how easy it will be to recreate.

But that will likely have to wait until tomorrow night… I need sleep now.

1 Like

yeah we all need some :slightly_smiling:
Try atomicState with a list or map and see what happens…

1 Like

So here’s an interesting one:
When a child call calls a parent app, the parent app can access the state variable but it’s read only! It cannot update it and retain the value outside of the scope of the function

So from child device:

parent.someFunc()

In parent app

def someFunc() {
def r = state.someVar // Works great!
state.someVar = XX // Works ONLY within the scope of this function
def k = state.someVar // Returns XX
callSome()
}

def callSome() {
def h = state.someVar // DOES NOT return XX, someVar return the value BEFORE someFunc was called
}

Anyone seen this?

EDIT: However atomicState works fine, just State doesn’t work.