An update on this one. I was inspired by @tony.fleisher and his work on zwave tools (git hub link So, I set out to find a better solution. And...here it is:
The process flow works like this:
- A device pre-exists that has child devices attached to it
- In an app, select the parent device (note that HE doesn't allow you to navigate from parent device to child device in the object model)
- The scheme below can be used to automatically find all the child devices of that selected parent device in the app, and thus have device objects for the parent, and the children without having the user select all the child devices.
First, by setting multiple:true and offerAll:true on the input, you get an option to toggle all on or off on a device list in an app.
input(name: "DimmerDevices",
type:"capability.switchLevel",
title: "Display Dimmers<br><span style='font-style:italic;color:grey;font-size:.8em;'>If Unsure Which Belong to This Device, Select All</span>",
width:4,
multiple:true,
offerAll:true)
Note that by switching to type:"capability.*" you could find all the child devices and not just the ones with the specified capability.
And then, with some javascript (sorry...I'm really not a pro at that, so this is a little ugly), upon the page loading, I hide the input button and automate the clicking of the select all button.
paragraph(title:"script","""
<span id='toggleBtn' onclick='toggleDisplay()' style='background-color:lightgrey; padding:5px 5px 5px 5px;'>Show Child Device List</span>
<script id="mainScript">
function toggleDisplay(){
var btn=\$('[data-elemname="DimmerDevices"').parent();
if(btn.css('display')==='none'){
btn.css({display:'block'});
\$('#toggleBtn').text("Hide Child Device List")
}else{
btn.css({display:'none'});
\$('#toggleBtn').text("Show Child Device List")
}
}
function dropList(){
//click the device selection button to drop down the list to select
\$('[data-elemname="DimmerDevices"').trigger('click');
//wait for .1s and then select the button to "select all"
setTimeout(function(){selectAll()},100); // This is really not clean, but I don't know a better way to do this.
}
function selectAll(){
\$('#DimmerDevices-checkbox-0').trigger('click');
}
\$(document).ready(loadFun);
function loadFun(){
var btn=\$('[data-elemname="DimmerDevices"').parent();
btn.css({display: "none"});
dropList();
};
</script>
""")
Where you see "DimmerDevices" in the jquery, that is the name of my input in the groovy app. I haven't thoroughly tested it, but I'd assume that it would track perfectly to just replace "DimmerDevices" with what ever you input element is.
Now, to be fair, there are some really odd things in here. First, there is some odd loading issue. If I initiate the click on the select all too fast after the click on the drop list button, it will click the button and check it, but not actually select everything. Further, I actually have to click on the button to drop the list, or I can't get the select all to work. Oddly, this sequence is still required if the whole series of HTML elements is display:none. I couldn't figure out what I was supposed to wait for to go from the drop click to the select click, and couldn't find a cleaner way to do this. So, waiting .1s between functions was fast enough and it worked. Also, I was expecting to have to click the "update" button, but magically, it takes care of itself. (Yes, I know, this doesn't sound robust, but maybe someone smarter can figure out the why's in here and make this idea really work.)
The last step was just some nice little groovy code to search the selected devices and compare their parent id to the id of the main device that you selected in another input element.
def childDimmers=settings.DimmerDevices.findAll(){it.getParentDeviceId()==settings.mondoDevice.getIdAsLong()}
It all seems to be working great. I still consider this issue of not having references to the children in the parent device object to be a flaw in the object model, but I suspect the developers are looking at this as a security issue. They seem to want the user to explicitly select everything device the reference. I'd argue that by selecting the parent device, you are selecting the child devices and making that link in the object model is no riskier than burying child devices inside app code, like you can do now.
If anyone has improvements to this, I'd love to hear them.