Skip to content

Instantly share code, notes, and snippets.

@adamkempenich
Last active February 24, 2022 00:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save adamkempenich/1c102cc360c76fe783a88a899cdb54e6 to your computer and use it in GitHub Desktop.
Save adamkempenich/1c102cc360c76fe783a88a899cdb54e6 to your computer and use it in GitHub Desktop.
metadata {
definition (name: "Binding Driver", namespace: "Inovelli", author: "AdamKempenich", importUrl: "") {
capability "Configuration"
command "bind", ["string"]
}
preferences {
section("Device Settings:") {
}
}
}
def configure(anything){
}
void parse( data ){
log.debug "Parse: ${data}"
}
def bind(cmds){ return cmds }
/**
* Zigbee Bindings
*
* Author:
* Adam Kempenich
*
* Add
* [X] Bind
* [X] Unbind
* [X] Allow multiple device selections
* [X] Make sure child device list doesn't include master device
* [X] Read device capabilities and only show possible outcomes
* [ ] Read binding Table
* [X] LogDebug
*
* Documentation:
*
* Changelog:
* 0.965 (Feb 23, 2022)
* - Requires the master device to use the binding driver
* - Doesn't validate master device capabilities
* - Works to bind/unbind
* 0.96 (Feb 2, 2022)
* - Initial build
ADD THE FOLLOWING LINE TO THE BOTTOM OF YOUR DRIVER (yes, it's so silly...)
def bind(cmds){ return cmds }
*/
import hubitat.device.HubAction
import hubitat.device.HubMultiAction
definition(
name: "Zigbee Bindings",
namespace: "inovelli",
author: "Adam Kempenich",
importURL: "",
description: "",
category: "",
iconUrl: "",
iconX2Url: ""
)
preferences {
section("Options:") {
//Master
input "bindMaster", "capability.configuration", title: "Bind this device", multiple:false, required: false, submitOnChange: true
input "masterEndpoint", "string", title: "Use this endpoint from the master (0x__)", defaultValue: "0x01", required: true
// Get endpoint from master?
// Get outClusters and hide depending on what's available
if(bindMaster != null){
// if(bindMaster.hasCapability("Switch")){
input "bindPower", "bool", title: "Bind power", defaultValue: true
// }
// if(bindMaster.hasCapability("SwitchLevel")){
input "bindLevel", "bool", title: "Bind level", defaultValue: true
// }
// if(bindMaster.hasCapability("ColorControl")){
input "bindColor", "bool", title: "Bind color", defaultValue: true
//}
}
// Slave
input "bindSlave", "capability.configuration", title: "To these devieces...", multiple:true, required: false
input "slaveEndpoint", "string", title: "Use this endpoint for the slave (0x__)", defaultValue: "0x01", required: true
// Get endpoint from slaves, or multiple fields?
def unbindSelectedTrue = "<div class='ignoreRequired enclosure'><span class='left'>Bind</span><span class='right-selected'><b>Unbind</b></span></div>"
def unbindSelectedFalse = "<div class='ignoreRequired enclosure'><span class='left-selected'><b>Bind</b></span><span class='right'>Unbind</span></div>"
input "unbindSelected", "bool", title: "${unbindSelected && unbindSelected != null ? unbindSelectedTrue : unbindSelectedFalse}", submitOnChange: true, defaultValue: false
input(name:"logDebug", type:"bool", title: "Log debug information?",
description: "Logs data for debugging. (Default: On)", defaultValue: true,
required: true, displayDuringSetup: true)
label title: "<h2>Enter a name for this app (optional)</h2>", required: false
paragraph """<style>
#formApp > div > div:nth-child(9) > div.mdl-grid > div:nth-child(14) > label > div.mdl-switch__track, #formApp > div > div:nth-child(9) > div.mdl-grid > div:nth-child(14) > label > div.mdl-switch__thumb{
display: none !important;
}
/**.mdl-switch__track, .mdl-switch__thumb, .mdl-switch__ripple-container{display:none;}**/
.left-selected{
background:#3498db;
border-top-left-radius:25px;
border-bottom-left-radius:25px;
padding: 1em; color:#ecf0f1
}
.left{
background:#ecf0f1;
border-top-left-radius:25px;
border-bottom-left-radius:25px;
padding: 1em;
color: #95a5a6;
}
.right-selected{
background:#e74c3c;
border-top-right-radius:25px;
border-bottom-right-radius:25px;
padding: 1em; color:#ecf0f1;
}
.right{
background:#ecf0f1;
border-top-right-radius:25px;
border-bottom-right-radius:25px;
padding: 1em;
color: #95a5a6;
}
.enclosure{
margin: 1.5em -44px !important;
}
.ignoreRequired + span{
display:none;
}
</style>"""
}
}
def installed() {
unsubscribe()
unschedule()
initialize()
}
def updated() {
unsubscribe()
unschedule()
initialize()
}
def initialize() {
unsubscribe()
unschedule()
List<String> cmds = []
if(unbindSelected){
bindText = 'unbind'
} else {
bindText = 'bind'
}
for(slaveDevice in bindSlave){
// I definitely didn't cause an infinite loop by binding a device to itself...
if(bindMaster.zigbeeId != slaveDevice.zigbeeId){
if(bindPower){
cmds << "zdo ${bindText} 0x${bindMaster.deviceNetworkId} ${masterEndpoint} ${slaveEndpoint} 0x0006 {${bindMaster.zigbeeId}} {${slaveDevice.zigbeeId}}"
cmds << "delay 200"
}
if(bindLevel){
cmds << "zdo ${bindText} 0x${bindMaster.deviceNetworkId} ${masterEndpoint} ${slaveEndpoint} 0x0008 {${bindMaster.zigbeeId}} {${slaveDevice.zigbeeId}}"
cmds << "delay 200"
}
if(bindColor){
cmds << "zdo ${bindText} 0x${bindMaster.deviceNetworkId} ${masterEndpoint} ${slaveEndpoint} 0x0300 {${bindMaster.zigbeeId}} {${slaveDevice.zigbeeId}}"
cmds << "delay 200"
}
} else {
log.warn "BING BONG! You tried to bind a device to itself. Ignoring that device and moving along."
}
}
logDebug "Sending ${cmds}"
bindMaster.bind(cmds) // I hate having to rely on the device for now...
//def params = [request: "${cmds}", protocol: hubitat.device.Protocol.ZIGBEE ]
//sendHubCommand(new HubAction(params, "0x${bindMaster.deviceNetworkId}", [callback: parse]))
//sendHubCommand(new HubMultiAction(cmds, hubitat.device.Protocol.ZIGBEE, "0x${bindMaster.deviceNetworkId}"))
}
def parse(String description) {
log.debug "Parse description $description"
def descMap = zigbee.parseDescriptionAsMap(description)
log.info "map is ${descMap}"
}
def logDebug(text){
if(settings.logDebug){
log.debug(text)
}
}
///**
//* Zigbee Bindings
//*
//* Author:
//* Adam Kempenich
//*
//* Add
//* [X] Bind
//* [X] Unbind
//* [X] Allow multiple device selections
//* [X] Make sure child device list doesn't include master device
//* [X] Read device capabilities and only show possible outcomes
//* [ ] Read binding Table
//* [ ] LogDebug
//* [ ] LogDescriptionText
//*
//* Documentation:
//*
//* Changelog:
//* 0.96 (Feb 2, 2022)
//* - Initial build
//*/
//
//
//
//import hubitat.device.HubAction
//import hubitat.device.HubMultiAction
//import hubitat.device.Protocol
//
//
//definition(
// name: "Zigbee Bindings",
// namespace: "inovelli",
// author: "Adam Kempenich",
// importURL: "",
// description: "",
// category: "",
// iconUrl: "",
// iconX2Url: ""
//)
//
//preferences {
// section("Options:") {
//
// //Master
// input "bindMaster", "capability.configuration", title: "Bind this device", multiple:false, required: false
// input "masterEndpoint", "string", title: "Use this endpoint from the master (0x__)", defaultValue: "0x01", required: true
// // Get endpoint from master?
//
//
//
// // Get outClusters and hide depending on what's available
// if(bindMaster != null){
//
// if(bindMaster.hasCapability("Switch")){
// input "bindPower", "bool", title: "Bind power", defaultValue: true
// }
// if(bindMaster.hasCapability("SwitchLevel")){
// input "bindLevel", "bool", title: "Bind level", defaultValue: true
// }
// if(bindMaster.hasCapability("ColorControl")){
// input "bindColor", "bool", title: "Bind color", defaultValue: true
// }
// }
//
//
//
// // Slave
// input "bindSlave", "capability.configuration", title: "To these devieces...", multiple:true, required: false
// input "slaveEndpoint", "string", title: "Use this endpoint for the slave (0x__)", defaultValue: "0x01", required: true
// // Get endpoint from slaves, or multiple fields?
//
// input "unbindSelected", "bool", title: "Enable this to <b>UNBIND</b> the above selected clusters/devices", defaultValue: false
//
//
//
// input(name:"logDebug", type:"bool", title: "Log debug information?",
// description: "Logs data for debugging. (Default: On)", defaultValue: true,
// required: true, displayDuringSetup: true)
//
// label title: "<h2>Enter a name for this app (optional)</h2>", required: false
//
// }
//}
//
//def installed() {
// unsubscribe()
// unschedule()
// initialize()
//}
//
//def updated() {
// unsubscribe()
// unschedule()
// initialize()
//}
//
//def initialize() {
// unsubscribe()
// unschedule()
//
// bind()
//}
//
//
//def bind(){
//
// def cmds = []
//
// if(unbindSelected){
// bindText = 'unbind'
// } else {
// bindText = 'bind'
// }
//
// for(slaveDevice in bindSlave){
//
// // I definitely didn't cause an infinite loop by binding a device to itself...
// if(bindMaster.zigbeeId != slaveDevice.zigbeeId){
// if(bindPower){
// cmds << "zdo ${bindText} 0x${bindMaster.deviceNetworkId} ${masterEndpoint} ${slaveEndpoint} 0x0006 {${bindMaster.zigbeeId}} {${slaveDevice.zigbeeId}}"
// cmds << "delay 200"
// }
// if(bindLevel){
// cmds << "zdo ${bindText} 0x${bindMaster.deviceNetworkId} ${masterEndpoint} ${slaveEndpoint} 0x0008 {${bindMaster.zigbeeId}} {${slaveDevice.zigbeeId}}"
// cmds << "delay 200"
// }
// if(bindColor){
// cmds << "zdo ${bindText} 0x${bindMaster.deviceNetworkId} ${masterEndpoint} ${slaveEndpoint} 0x0300 {${bindMaster.zigbeeId}} {${slaveDevice.zigbeeId}}"
// cmds << "delay 200"
// }
// } else {
// log.warn "BING BONG! You tried to bind a device to itself. Ignoring that device and moving along."
// }
// }
//
// logDebug "Sending ${cmds}"
//
// bindMaster.bind(cmds)
// //cmds << "he rattr 0x${bindMaster.deviceNetworkId} 0x${bindMaster.endpointId} 0x0006 0 {}"
// //"zdo bind 0x1D6E 0x02 0x01 0x0006 {000D6F000FC74D13} {000D6F00053AC67A}"
// //cmds << "zdo bind 0x${bindMaster.deviceNetworkId} 1 1 6 {${bindMaster.zigbeeId}} {}"
// // cmds << "zdo bind ${bindMaster.deviceNetworkId} 1 1 0x0006 {${bindMaster.zigbeeId}} {${bindSlave[0].zigbeeId}}"
// //bindMaster.refresh()
// //sendHubCommand(new HubMultiAction(cmds, hubitat.device.Protocol.ZIGBEE, "0x${bindMaster.deviceNetworkId}"))
// // def hubAction = new HubMultiAction(cmds, hubitat.device.Protocol.ZIGBEE, "0x${bindMaster.deviceNetworkId}")
// // log.warn "${bindMaster.hubAction}"
// //cmds << "he cmd 0x${bindMaster.deviceNetworkId} 1 0x0006 1 {}"
// //def hubAction = new hubitat.device.HubAction("zdo bind 0xCCD2 0x02 0x01 0x0006 {000D6F00053AC67A} {000D6F0003325A24}", hubitat.device.Protocol.ZIGBEE, bindMaster.deviceNetworkid)
// //log.trace "${hubAction}"
// //sendHubCommand(hubAction)
// //String cmd = "zdo bind 0x1D6E 0x01 0x01 0x0006 {000D6F000FC74D13} {000D6F00053AC67A}"
// //sendHubCommand(new HubAction(cmd, hubitat.device.Protocol.ZIGBEE, "0x${bindMaster.deviceNetworkId}"))
//
// //try{
// // addChildDevice("Inovelli", "Zigbee Bindings", "ZigbeeBindingBuddy")
// // pauseExecution(1000)
// //} catch(gatewayCreationError){
// // if($gatewayCreationError != "java.lang.IllegalArgumentException: A device with the same device network ID exists, Please use a different DNI"){
// // logDebug "Something went wrong when creating a child gateway: ${gatewayCreationError}"
// // }
// //}
// //def childDevice = getChildDevice("ZigbeeBindingBuddy")
// ////
// ////
// //childDevice.bind(cmds)
//
// //log.trace "${unbindSelected ? 'Unbinding' : 'Binding'} with ${cmds} master DNI: 0x${bindMaster.deviceNetworkId}"
//
//
//}
//
//
//def parse(String description) {
// log.debug "Parse description $description"
// def descMap = zigbee.parseDescriptionAsMap(description)
// log.info "map is ${descMap}"
//}
//
//def logDebug(text){
// if(settings.logDebug){
// log.debug(text)
// }
//}
//
//
//
//
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment