The results are surprising.
I’ve created a dummy plugin to test parent-child relationship (1 parent with handleChildren and 2 childs with specific implementation file).
The startup sequence :
09 10/18/15 17:45:40.193 JobHandler_LuaUPnP::Run device 274 Test Child 1 room 0 type urn:schemas-vosmont-github-io:device:TestChildChild:1 cat 0:-1 id parent 273/0xf8aec0 upnp: 0 plugin:0 pnp:0 mac: ip:
09 10/18/15 17:45:40.194 JobHandler_LuaUPnP::Run device 275 Test Child 2 room 0 type urn:schemas-vosmont-github-io:device:TestChildChild:1 cat 0:-1 id parent 273/0xf8c8f0 upnp: 0 plugin:0 pnp:0 mac: ip:
09 10/18/15 17:45:40.194 JobHandler_LuaUPnP::Run device 273 Test Master room 0 type urn:schemas-vosmont-github-io:device:TestChildMaster:1 cat 0:-1 id parent 0/0xf8aaf8 upnp: 0 plugin:0 pnp:0 mac: ip:
50 10/18/15 17:45:47.362 luup_log:273: TestChild_Master#273 - startup
50 10/18/15 17:45:47.363 luup_log:273: TestChild_Master#273 - myLocalDeviceId:MasterId
50 10/18/15 17:45:47.363 luup_log:273: TestChild_Master#273 - globalVar:Child
50 10/18/15 17:45:47.364 luup_log:273: TestChild_Master#273 - localVar:Master
50 10/18/15 17:45:47.365 luup_log:273: TestChild_Master#273 - localChildVar:nil
50 10/18/15 17:45:47.366 luup_log:273: TestChild_Child#273 - startup
50 10/18/15 17:45:47.367 luup_log:273: TestChild_Child#273 - myLocalDeviceId:ChildId
50 10/18/15 17:45:47.377 luup_log:273: TestChild_Child#273 - globalVar:Child
50 10/18/15 17:45:47.378 luup_log:273: TestChild_Child#273 - localVar:Child
50 10/18/15 17:45:47.379 luup_log:273: TestChild_Child#273 - localChildVar:DeclaredJustInChild
→ the startup function declared in childs is called just one time with the id of the parent (and seems to be launched before the startup function of the parent).
→ local variables are really local: parent doesn’t see local variables of its childs.
→ global variables are shared between parent and childs (and child variable initialisation seems to be the last)
EDIT: the order of initialisation between parent and child is random.
EDIT: startup functions of parent and child HAVE to have different names (to avoid collision because they are global)
Call action :
08 10/18/15 17:50:21.181 JobHandler_LuaUPnP::HandleActionRequest device: 275 service: urn:upnp-vosmont-github-io:serviceId:TestChildChild1 action: SetStatus
08 10/18/15 17:50:21.182 JobHandler_LuaUPnP::HandleActionRequest argument serviceId=urn:upnp-vosmont-github-io:serviceId:TestChildChild1
50 10/18/15 17:50:21.186 luup_log:273: TestChild_Child#275 - set status '1'
50 10/18/15 17:50:21.187 luup_log:273: TestChild_Child#275 - myLocalDeviceId:273
50 10/18/15 17:50:21.187 luup_log:273: TestChild_Child#275 - globalVar:Child
50 10/18/15 17:50:21.190 luup_log:273: TestChild_Child#275 - localVar:Child
50 10/18/15 17:50:21.190 luup_log:273: TestChild_Child#275 - localChildVar:DeclaredJustInChild
06 10/18/15 17:50:21.191 Device_Variable::m_szValue_set device: 275 service: urn:upnp-vosmont-github-io:serviceId:TestChildChild1 variable: Status was: EMPTY now: 1 #hooks: 0 upnp: 0 skip: 0 v:0x11ea880/NONE duplicate:0
→ The action implementation called is the function of the child (with the id of the child)
EDIT:
I’ve done the same tests with actions which return values : the behavior is the same.
Some additional tests:
If the action is not present in the parent implementation file :
ERROR: No implementation
→ The action has to be present in the implementation file of the parent (but its code is not used)
If the action is not present in the child implementation file :
08 10/18/15 17:58:25.262 JobHandler_LuaUPnP::HandleActionRequest device: 275 service: urn:upnp-vosmont-github-io:serviceId:TestChildChild1 action: SetStatus
08 10/18/15 17:58:25.262 JobHandler_LuaUPnP::HandleActionRequest argument serviceId=urn:upnp-vosmont-github-io:serviceId:TestChildChild1
02 10/18/15 17:58:25.265 JobHandler_LuaUPnP::RunAction device 275 action urn:upnp-vosmont-github-io:serviceId:TestChildChild1/SetStatus failed with 501/No implementation
08 10/18/15 18:09:59.746 JobHandler_LuaUPnP::HandleActionRequest device: 275 service: urn:upnp-vosmont-github-io:serviceId:TestChildChild1 action: SetStatus
08 10/18/15 18:09:59.748 JobHandler_LuaUPnP::HandleActionRequest argument serviceId=urn:upnp-vosmont-github-io:serviceId:TestChildChild1 <0x709eb520>
50 10/18/15 18:09:59.750 luup_log:273: TestChild_Master#275 - set status '3' <0x772d9320>
50 10/18/15 18:09:59.751 luup_log:273: TestChild_Master#275 - myLocalDeviceId:273 <0x772d9320>
50 10/18/15 18:09:59.751 luup_log:273: TestChild_Master#275 - globalVar:Child <0x772d9320>
50 10/18/15 18:09:59.752 luup_log:273: TestChild_Master#275 - localVar:Master <0x772d9320>
50 10/18/15 18:09:59.752 luup_log:273: TestChild_Master#275 - localChildVar:nil <0x772d9320>
01 10/18/15 18:09:59.753 LuaInterface::CallFunction_Job device 275 function STestChildChild1_TestChildChild1_SetStatus_job failed [string "..."]:22: attempt to index global 'TestChild' (a nil value)
→ If the action is not present in the implementation file of the child, the linked function in the implementation file of the parent is used (with the id of the child, but local variables of the child are not reachable, like module declaration for example)
So… BartE is right
and I now understand the remark “with dummy debug log”