When adding a generic child device driver, developers currently have two choices:
addChildDevice("hubitat", "Generic Component Dimmer", "data": [label: "Dimmer", isComponent: true])
addChildDevice("hubitat", "Generic Component Dimmer", "data": [label: "Dimmer", isComponent: false])
When isComponent: true, then the child device can't be changed by the user.
When isComponent: false, then the child device can changed by the user but the user can select any device .
I'd like to add a third option that I've named uses:
addChildDevice("hubitat", "Generic Component Dimmer", "data": [label: "Dimmer", uses: "parent.componentSetLevel"])
addChildDevice("hubitat", "Generic Component Dimmer", "data": [label: "Switch", uses: "parent.componentOn"])
This could be a string or a list of strings.
addChildDevice("hubitat", "Generic Component Dimmer", "data": [label: "Dimmer", uses: ["parent.componentOn", "parent.componentSetLevel"])
This option would allow the user to chose a child device but with a restriction that the child device declares that it uses a specific API. In the last case, I would be able to select any device that declares the use of 'parent.componentOn' or 'parent.componentSetLevel'.
Some context about the use case(s), I have several Zen16, Zen17 relays and recently purchased the Fibaro Smart Implant.
My first issue was controlling a magnetic lock using a Zen16 relay:
This appears as a 'switch' and not a lock. Since 'isComponent: true', I can't modify the device to a 'generic lock'.
Let's take example of the code from @jtp10181 for the Zen17:
/Handle Sensor Child Devices
if (inputType != null) {
epName = "Sensor ${endPoint}"
// properties.type = "S"
switch (inputType) {
case 4: deviceType.typeName = "Generic Component Water Sensor"; break
case 5: deviceType.typeName = "Generic Component Switch"; break
case 6: deviceType.typeName = "Generic Component Motion Sensor"; break
case 7: deviceType.typeName = "Generic Component Contact Sensor"; break
case 8: deviceType.typeName = "Generic Component Carbon Monoxide Detector"; break
case 9: deviceType.typeName = "Generic Component Carbon Dioxide Detector"; break
case 10: deviceType.typeName = "Generic Component Switch"; break
case 11: deviceType.typeName = "Generic Component Contact Sensor"; break
default: deviceType.typeName = "Generic Component Switch"
}
}
properties.name = "${device.name} - ${epName}"
logDebug "Creating '${epName}' Child Device"
def childDev
try {
childDev = addChildDevice(deviceType.namespace, deviceType.typeName, dni, properties)
}
If this code was changed to:
//Handle Sensor Child Devices
if (inputType != null) {
epName = "Sensor ${endPoint}"
// properties.type = "S"
switch (inputType) {
case 4: deviceType.typeName = "Generic Component Water Sensor"; break
case 5: deviceType.typeName = "Generic Component Switch";
properties.uses = 'parent.componentOn'
break
case 6: deviceType.typeName = "Generic Component Motion Sensor"; break
case 7: deviceType.typeName = "Generic Component Contact Sensor"; break
case 8: deviceType.typeName = "Generic Component Carbon Monoxide Detector"; break
case 9: deviceType.typeName = "Generic Component Carbon Dioxide Detector"; break
case 10: deviceType.typeName = "Generic Component Switch";
properties.uses = 'parent.componentOn'
break
case 11: deviceType.typeName = "Generic Component Contact Sensor"; break
default: deviceType.typeName = "Generic Component Switch"
properties.uses = 'parent.componentOn'
}
}
properties.name = "${device.name} - ${epName}"
logDebug "Creating '${epName}' Child Device"
def childDev
try {
childDev = addChildDevice(deviceType.namespace, deviceType.typeName, dni, properties)
}
I could then select any child device that uses a 'parent.componentOn', most surely the Generic Component Lock, yay!
All generic components could use an extra declaration:
https://github.com/hubitat/HubitatPublic/blob/master/examples/drivers/genericComponentDimmer.groovy
definition(name: "Generic Component Dimmer", namespace: "hubitat", author: "mike maxwell", component: true) {
capability "Light"
capability "Switch"
capability "Switch Level"
capability "ChangeLevel"
capability "Refresh"
capability "Actuator"
uses 'parent.componentOn'
uses 'parent.componentSetLevel'
}
The meaning of 'uses' = "parent.componentOn" is this driver is expected to call componentOn() for the switch on/off capabilities . "parent.componentSetLevel" the componentLevel() functions. There's no compile-time checks at all, it acts like a tag/category.
I think it should be fairly easy to implement and help simplify parent/child issues.
Right now, I have this wonky setup where every "Generic Component Switch" has a lock capability. I think it was a suggestion in the forums and has grown into a mess.