mirror of
https://github.com/mtan93/SmartThingsPublic.git
synced 2026-03-08 05:31:56 +00:00
custom device types for the CoopBoss hardware version 3
Prepping for submission to SmartThings. Removed extra comments. Submitting to public store for approval Updated for new SmartThings interface Release Candidate for CoopBoss H3V9 save Update to fix invalid temperature reporting and added maxCurrentNE methods and attributes. Made changes to defalutState:true to state "default" on smart tiles that had only one default state. This was causing the Android version of the app to crash. Updated comments Added test for null values that were causing errors during join process Fixed log errors during join process by testing for null values before init process. Update fingerprint with Manufacturer data SmartApps for CoopBoss hardware version 3 Updated Icons. 1 Updates to Prep for RC Clean up save
This commit is contained in:
committed by
Donald Kirker
parent
810f3645d9
commit
dd99a024c2
795
devicetypes/johnrucker/coopboss-h3vx.src/coopboss-h3vx.groovy
Normal file
795
devicetypes/johnrucker/coopboss-h3vx.src/coopboss-h3vx.groovy
Normal file
@@ -0,0 +1,795 @@
|
||||
/**
|
||||
* CoopBoss H3Vx
|
||||
* 02/29/16 Fixed app crash with Android by changing the syntax of default state in tile definition.
|
||||
* Fixed null value errors during join process. Added 3 new commands to refresh data.
|
||||
*
|
||||
* 01/18/16 Masked invalid temperature reporting when TempProbe1 is below 0C
|
||||
* Added setBaseCurrentNE, readBaseCurrentNE, commands as well as baseCurrentNE attribute.
|
||||
*
|
||||
* Copyright 2016 John Rucker
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
||||
* in compliance with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
|
||||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing permissions and limitations under the License.
|
||||
* Icon location = http://scripts.3dgo.net/smartthings/icons/
|
||||
*/
|
||||
metadata {
|
||||
definition (name: "CoopBoss H3Vx", namespace: "JohnRucker", author: "John.Rucker@Solar-Current.com") {
|
||||
capability "Refresh"
|
||||
capability "Polling"
|
||||
capability "Sensor"
|
||||
capability "Actuator"
|
||||
capability "Configuration"
|
||||
capability "Temperature Measurement"
|
||||
capability "Door Control"
|
||||
capability "Switch"
|
||||
|
||||
command "closeDoor"
|
||||
command "closeDoorHiI"
|
||||
command "openDoor"
|
||||
command "autoCloseOn"
|
||||
command "autoCloseOff"
|
||||
command "autoOpenOn"
|
||||
command "autoOpenOff"
|
||||
command "setCloseLevelTo"
|
||||
command "setOpenLevelTo"
|
||||
command "setSensitivityLevel"
|
||||
command "Aux1On"
|
||||
command "Aux1Off"
|
||||
command "Aux2On"
|
||||
command "Aux2Off"
|
||||
command "updateTemp1"
|
||||
command "updateTemp2"
|
||||
command "updateSun"
|
||||
command "setNewBaseCurrent"
|
||||
command "setNewPhotoCalibration"
|
||||
command "readNewPhotoCalibration"
|
||||
command "readBaseCurrentNE"
|
||||
command "setBaseCurrentNE"
|
||||
command "updateSensitivity"
|
||||
command "updateCloseLightLevel"
|
||||
command "updateOpenLightLevel"
|
||||
|
||||
attribute "doorState","string"
|
||||
attribute "currentLightLevel","number"
|
||||
attribute "closeLightLevel","number"
|
||||
attribute "openLightLevel","number"
|
||||
attribute "autoCloseEnable","string"
|
||||
attribute "autoOpenEnable","string"
|
||||
attribute "TempProb1","number"
|
||||
attribute "TempProb2","number"
|
||||
attribute "dayOrNight","string"
|
||||
attribute "doorSensitivity","number"
|
||||
attribute "doorCurrent","number"
|
||||
attribute "doorVoltage","number"
|
||||
attribute "Aux1","string"
|
||||
attribute "Aux2","string"
|
||||
attribute "coopStatus","string"
|
||||
attribute "baseDoorCurrent","number"
|
||||
attribute "photoCalibration","number"
|
||||
attribute "baseCurrentNE","string"
|
||||
|
||||
fingerprint profileId: "0104", inClusters: "0000,0101,0402", manufacturer: "Solar-Current", model: "Coop Boss"
|
||||
|
||||
}
|
||||
|
||||
// simulator metadata
|
||||
simulator {
|
||||
}
|
||||
|
||||
|
||||
preferences {
|
||||
input description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
|
||||
input "tempOffsetCoop", "number", title: "Coop Temperature Offset", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
|
||||
input "tempOffsetOutside", "number", title: "Outside Temperature Offset", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
|
||||
}
|
||||
|
||||
|
||||
// UI tile definitions
|
||||
tiles(scale: 2){
|
||||
multiAttributeTile(name:"doorCtrl", type:"generic", width:6, height:4) {tileAttribute("device.doorState", key: "PRIMARY_CONTROL")
|
||||
{
|
||||
attributeState "unknown", label: '${name}', action:"openDoor", icon: "st.Outdoor.outdoor20", nextState:"Sent"
|
||||
attributeState "open", label: '${name}', action:"closeDoor", icon: "st.Outdoor.outdoor20", backgroundColor: "#0000ff" , nextState:"Sent"
|
||||
attributeState "opening", label: '${name}', action:"closeDoor", icon: "st.Outdoor.outdoor20", backgroundColor: "#ffa81e"
|
||||
attributeState "closed", label: '${name}', action:"openDoor", icon: "st.Outdoor.outdoor20", backgroundColor: "#79b821", nextState:"Sent"
|
||||
attributeState "closing", label: '${name}', action:"openDoor", icon: "st.Outdoor.outdoor20", backgroundColor: "#ffa81e"
|
||||
attributeState "jammed", label: '${name}', action:"closeDoorHiI", icon: "st.Outdoor.outdoor20", backgroundColor: "#ff0000", nextState:"Sent"
|
||||
attributeState "forced close", label: 'forced\rclose', action:"openDoor", icon: "st.Outdoor.outdoor20", backgroundColor: "#ff8000", nextState:"Sent"
|
||||
attributeState "fault", label: 'FAULT', action:"openDoor", icon: "st.Outdoor.outdoor20", backgroundColor: "#ff0000", nextState:"Sent"
|
||||
attributeState "Sent", label: 'wait', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
|
||||
}
|
||||
tileAttribute ("device.coopStatus", key: "SECONDARY_CONTROL") {
|
||||
attributeState "device.coopStatus", label:'${currentValue}'
|
||||
}
|
||||
}
|
||||
|
||||
multiAttributeTile(name:"dtlsDoorCtrl", type:"generic", width:6, height:4) {tileAttribute("device.doorState", key: "PRIMARY_CONTROL")
|
||||
{
|
||||
attributeState "unknown", label: '${name}', action:"openDoor", icon: "st.secondary.tools", nextState:"Sent"
|
||||
attributeState "open", label: '${name}', action:"closeDoor", icon: "st.doors.garage.garage-open", backgroundColor: "#0000ff", nextState:"Sent"
|
||||
attributeState "opening", label: '${name}', action:"closeDoor", icon: "st.doors.garage.garage-opening", backgroundColor: "#ffa81e"
|
||||
attributeState "closed", label: '${name}', action:"openDoor", icon: "st.doors.garage.garage-closed", backgroundColor: "#79b821", nextState:"Sent"
|
||||
attributeState "closing", label: '${name}', action:"openDoor", icon: "st.doors.garage.garage-closing", backgroundColor: "#ffa81e"
|
||||
attributeState "jammed", label: '${name}', action:"closeDoorHiI", icon: "st.doors.garage.garage-open", backgroundColor: "#ff0000", nextState:"Sent"
|
||||
attributeState "forced close", label: "forced", action:"openDoor", icon: "st.doors.garage.garage-closed", backgroundColor: "#ff8000", nextState:"Sent"
|
||||
attributeState "fault", label: 'FAULT', action:"openDoor", icon: "st.secondary.tools", backgroundColor: "#ff0000", nextState:"Sent"
|
||||
attributeState "Sent", label: 'wait', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
|
||||
}
|
||||
tileAttribute ("device.doorState", key: "SECONDARY_CONTROL") {
|
||||
attributeState "unknown", label: 'Door is in unknown state. Push to open.'
|
||||
attributeState "open", label: 'Coop door is open. Push to close.'
|
||||
attributeState "opening", label: 'Caution, door is opening!'
|
||||
attributeState "closed", label: 'Coop door is closed. Push to open.'
|
||||
attributeState "closing", label: 'Caution, door is closing!'
|
||||
attributeState "jammed", label: 'Door open! Push for high-force close'
|
||||
attributeState "forced close", label: "Door is closed. Push to open."
|
||||
attributeState "fault", label: 'Door fault check electrical connection.'
|
||||
attributeState "Sent", label: 'Command sent to CoopBoss...'
|
||||
}
|
||||
}
|
||||
|
||||
standardTile("autoClose", "device.autoCloseEnable", width: 2, height: 2){
|
||||
state "on", label: 'Auto', action:"autoCloseOff", icon: "st.doors.garage.garage-closing", backgroundColor: "#79b821", nextState:"Sent"
|
||||
state "off", label: 'Auto', action:"autoCloseOn", icon: "st.doors.garage.garage-closing", nextState:"Sent"
|
||||
state "Sent", label: 'wait', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
|
||||
}
|
||||
|
||||
standardTile("autoOpen", "device.autoOpenEnable", width: 2, height: 2){
|
||||
state "on", label: 'Auto', action:"autoOpenOff", icon: "st.doors.garage.garage-opening", backgroundColor: "#79b821", nextState:"Sent"
|
||||
state "off", label: 'Auto', action:"autoOpenOn", icon: "st.doors.garage.garage-opening", nextState:"Sent"
|
||||
state "Sent", label: 'wait', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
|
||||
}
|
||||
|
||||
valueTile("TempProb1", "device.TempProb1", width: 2, height: 2, decoration: "flat"){
|
||||
state "default", label:'Coop\r${currentValue}°', unit:"F", action:"updateTemp1"}
|
||||
|
||||
valueTile("TempProb2", "device.TempProb2", width: 2, height: 2, decoration: "flat"){
|
||||
state "default", label:'Outside\r${currentValue}°', unit:"F", action:"updateTemp2"}
|
||||
|
||||
valueTile("currentLevel", "device.currentLightLevel", width: 2, height: 2, decoration: "flat") {
|
||||
state "default", label:'Sun\r${currentValue}', action:"updateSun"}
|
||||
|
||||
valueTile("dayOrNight", "device.dayOrNight", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
|
||||
state "default", label:'${currentValue}.'
|
||||
}
|
||||
|
||||
controlTile("SetClSlider", "device.closeLightLevel", "slider", height: 2, width: 4, inactiveLabel: false, range:"(1..100)") {
|
||||
state "closeLightLevel", action:"setCloseLevelTo", backgroundColor:"#d04e00"
|
||||
}
|
||||
|
||||
valueTile("SetClValue", "device.closeLightLevel", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
|
||||
state "default", label:'Close\nSunlight\n${currentValue}', action:'updateCloseLightLevel'
|
||||
}
|
||||
|
||||
controlTile("SetOpSlider", "device.openLightLevel", "slider", height: 2, width: 4, inactiveLabel: false, range:"(1..100)") {
|
||||
state "openLightLevel", action:"setOpenLevelTo", backgroundColor:"#d04e00"
|
||||
}
|
||||
|
||||
valueTile("SetOpValue", "device.openLightLevel", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
|
||||
state "default", label:'Open\nSunlight\n${currentValue}', action:'updateOpenLightLevel'
|
||||
}
|
||||
|
||||
controlTile("SetSensitivitySlider", "device.doorSensitivity", "slider", height: 2, width: 4, inactiveLabel: false, range:"(1..100)") {
|
||||
state "openLightLevel", action:"setSensitivityLevel", backgroundColor:"#d04e00"
|
||||
}
|
||||
|
||||
valueTile("SetSensitivityValue", "device.doorSensitivity", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
|
||||
state "default", label:'Door\nSensitivity\n${currentValue}', action:'updateSensitivity'
|
||||
}
|
||||
|
||||
standardTile("refresh", "device.refresh", width: 2, height: 2, decoration: "flat", inactiveLabel: false) {
|
||||
state "default", label:'All', action:"refresh.refresh", icon:"st.secondary.refresh-icon"
|
||||
}
|
||||
|
||||
standardTile("aux1", "device.Aux1", width: 2, height: 2, canChangeIcon: true) {
|
||||
state "off", label:'Aux 1', action:"Aux1On", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"Sent"
|
||||
state "on", label:'Aux 1', action:"Aux1Off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"Sent"
|
||||
state "Sent", label: 'wait', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
|
||||
}
|
||||
|
||||
standardTile("aux2", "device.Aux2", width: 2, height: 2, canChangeIcon: true) {
|
||||
state "off", label:'Aux 2', action:"Aux2On", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"Sent"
|
||||
state "on", label:'Aux 2', action:"Aux2Off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"Sent"
|
||||
state "Sent", label: 'wait', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
|
||||
}
|
||||
|
||||
main "doorCtrl"
|
||||
details (["dtlsDoorCtrl", "TempProb1", "TempProb2", "currentLevel", "autoClose", "autoOpen", "dayOrNight",
|
||||
"SetClSlider", "SetClValue", "SetOpSlider", "SetOpValue", "SetSensitivitySlider", "SetSensitivityValue",
|
||||
"aux1", "aux2", "refresh"])
|
||||
}
|
||||
}
|
||||
|
||||
// Parse incoming device messages to generate events def parse(String description) {
|
||||
def parse(String description) {
|
||||
log.debug "description: $description"
|
||||
Map map = [:]
|
||||
if (description?.startsWith('catchall:')) {
|
||||
map = parseCatchAllMessage(description)
|
||||
}
|
||||
else if (description?.startsWith('read attr -')) {
|
||||
map = parseReportAttributeMessage(description)
|
||||
}
|
||||
else if (description?.startsWith('temperature: ') || description?.startsWith('humidity: ')) {
|
||||
map = parseCustomMessage(description)
|
||||
}
|
||||
log.debug map
|
||||
//return map ? createEvent(map) : null
|
||||
sendEvent(map)
|
||||
callUpdateStatusTxt()
|
||||
}
|
||||
|
||||
private Map parseCatchAllMessage(String description) {
|
||||
Map resultMap = [:]
|
||||
def cluster = zigbee.parse(description)
|
||||
log.debug cluster
|
||||
if (cluster.clusterId == 0x0402) {
|
||||
switch(cluster.sourceEndpoint) {
|
||||
|
||||
case 0x39: // Endpoint 0x39 is the temperature of probe 1
|
||||
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
|
||||
resultMap.name = "TempProb1"
|
||||
def celsius = Integer.valueOf(temp,16).shortValue()
|
||||
if (celsius == -32768){ // This number is used to indicate an error in the temperature reading
|
||||
resultMap.value = "---"
|
||||
}else{
|
||||
celsius = celsius / 100 // Temperature value is sent X 100.
|
||||
resultMap.value = celsiusToFahrenheit(celsius)
|
||||
if (tempOffsetOutside) {
|
||||
def offset = tempOffsetOutside as int
|
||||
resultMap.value = resultMap.value + offset
|
||||
}
|
||||
}
|
||||
sendEvent(name: "temperature", value: resultMap.value, displayed: false) // set the temperatureMeasurment capability to temperature
|
||||
break
|
||||
|
||||
case 0x40: // Endpoint 0x40 is the temperature of probe 2
|
||||
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
|
||||
resultMap.name = "TempProb2"
|
||||
def celsius = Integer.valueOf(temp,16).shortValue()
|
||||
//resultMap.descriptionText = "Prob2 celsius value = ${celsius}"
|
||||
if (celsius == -32768){ // This number is used to indicate an error in the temperature reading
|
||||
resultMap.value = "---"
|
||||
}else{
|
||||
celsius = celsius / 100 // Temperature value is sent X 100.
|
||||
resultMap.value = celsiusToFahrenheit(celsius)
|
||||
if (tempOffsetCoop) {
|
||||
def offset = tempOffsetCoop as int
|
||||
resultMap.value = resultMap.value + offset
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if (cluster.clusterId == 0x0101 && cluster.command == 0x0b) { // This is a default response to a command sent to cluster 0x0101 door control
|
||||
//log.debug "Default Response Data = $cluster.data"
|
||||
switch(cluster.data) {
|
||||
|
||||
case "[10, 0]": // 0x0a turn auto close on command verified
|
||||
resultMap.name = "autoCloseEnable"
|
||||
resultMap.value = "on"
|
||||
break
|
||||
|
||||
case "[11, 0]": // 0x0b turn auto close off command verified
|
||||
resultMap.name = "autoCloseEnable"
|
||||
resultMap.value = "off"
|
||||
break
|
||||
|
||||
case "[12, 0]": // 0x0C turn auto open on command verified
|
||||
resultMap.name = "autoOpenEnable"
|
||||
resultMap.value = "on"
|
||||
break
|
||||
|
||||
case "[13, 0]": // 0x0d turn auto open off command verified
|
||||
resultMap.name = "autoOpenEnable"
|
||||
resultMap.value = "off"
|
||||
break
|
||||
|
||||
|
||||
case "[20, 0]": // 0x14 Aux1 On command verified
|
||||
log.info "verified Aux1 On"
|
||||
sendEvent(name: "switch", value: "on", displayed: false)
|
||||
resultMap.name = "Aux1"
|
||||
resultMap.value = "on"
|
||||
break
|
||||
|
||||
case "[21, 0]": // 0x15 Aux1 Off command verified
|
||||
log.info "verified Aux1 Off"
|
||||
sendEvent(name: "switch", value: "off", displayed: false)
|
||||
resultMap.name = "Aux1"
|
||||
resultMap.value = "off"
|
||||
break
|
||||
|
||||
case "[22, 0]": // 0x16 Aux2 On command verified
|
||||
log.info "verified Aux2 On"
|
||||
resultMap.name = "Aux2"
|
||||
resultMap.value = "on"
|
||||
break
|
||||
|
||||
case "[23, 0]": // 0x17 Aux2 Off command verified
|
||||
log.info "verified Aux2 Off"
|
||||
resultMap.name = "Aux2"
|
||||
resultMap.value = "off"
|
||||
break
|
||||
|
||||
}
|
||||
}
|
||||
return resultMap
|
||||
}
|
||||
|
||||
private Map parseReportAttributeMessage(String description) {
|
||||
Map resultMap = [:]
|
||||
def descMap = parseDescriptionAsMap(description)
|
||||
//log.debug "read attr descMap --> $descMap"
|
||||
if (descMap.cluster == "0101" && descMap.attrId == "0003") {
|
||||
resultMap.name = "doorState"
|
||||
if (descMap.value == "00"){
|
||||
resultMap.value = "unknown"
|
||||
sendEvent(name: "door", value: "unknown", displayed: false)
|
||||
}else if(descMap.value == "01"){
|
||||
resultMap.value = "closed"
|
||||
sendEvent(name: "door", value: "closed", displayed: false)
|
||||
}else if(descMap.value == "02"){
|
||||
resultMap.value = "open"
|
||||
sendEvent(name: "door", value: "open", displayed: false)
|
||||
}else if(descMap.value == "03"){
|
||||
resultMap.value = "jammed"
|
||||
}else if(descMap.value == "04"){
|
||||
resultMap.value = "forced close"
|
||||
}else if(descMap.value == "05"){
|
||||
resultMap.value = "forced close"
|
||||
}else if(descMap.value == "06"){
|
||||
resultMap.value = "closing"
|
||||
sendEvent(name: "door", value: "closing", displayed: false)
|
||||
}else if(descMap.value == "07"){
|
||||
resultMap.value = "opening"
|
||||
sendEvent(name: "door", value: "opening", displayed: false)
|
||||
}else if(descMap.value == "08"){
|
||||
resultMap.value = "fault"
|
||||
}else {
|
||||
resultMap.value = "unknown"
|
||||
}
|
||||
resultMap.descriptionText = "Door State Changed to ${resultMap.value}"
|
||||
|
||||
} else if (descMap.cluster == "0101" && descMap.attrId == "0400") {
|
||||
resultMap.name = "currentLightLevel"
|
||||
resultMap.value = (Integer.parseInt(descMap.value, 16))
|
||||
resultMap.displayed = false
|
||||
|
||||
} else if (descMap.cluster == "0101" && descMap.attrId == "0401") {
|
||||
resultMap.name = "closeLightLevel"
|
||||
resultMap.value = (Integer.parseInt(descMap.value, 16))
|
||||
|
||||
} else if (descMap.cluster == "0101" && descMap.attrId == "0402") {
|
||||
resultMap.name = "openLightLevel"
|
||||
resultMap.value = (Integer.parseInt(descMap.value, 16))
|
||||
|
||||
} else if (descMap.cluster == "0101" && descMap.attrId == "0403") {
|
||||
resultMap.name = "autoCloseEnable"
|
||||
if (descMap.value == "01"){resultMap.value = "on"}
|
||||
else{resultMap.value = "off"}
|
||||
|
||||
} else if (descMap.cluster == "0101" && descMap.attrId == "0404") {
|
||||
resultMap.name = "autoOpenEnable"
|
||||
if (descMap.value == "01"){resultMap.value = "on"}
|
||||
else{resultMap.value = "off"}
|
||||
|
||||
} else if (descMap.cluster == "0101" && descMap.attrId == "0405") {
|
||||
resultMap.name = "doorCurrent"
|
||||
resultMap.value = (Integer.parseInt(descMap.value, 16))
|
||||
resultMap.value = resultMap.value * 0.001
|
||||
|
||||
} else if (descMap.cluster == "0101" && descMap.attrId == "0408") {
|
||||
resultMap.name = "doorSensitivity"
|
||||
resultMap.value = (100 - Integer.parseInt(descMap.value, 16))
|
||||
|
||||
} else if (descMap.cluster == "0101" && descMap.attrId == "0409") {
|
||||
resultMap.name = "baseDoorCurrent"
|
||||
resultMap.value = (Integer.parseInt(descMap.value, 16))
|
||||
resultMap.value = resultMap.value * 0.001
|
||||
|
||||
} else if (descMap.cluster == "0101" && descMap.attrId == "040a") {
|
||||
resultMap.name = "doorVoltage"
|
||||
resultMap.value = (Integer.parseInt(descMap.value, 16))
|
||||
resultMap.value = resultMap.value * 0.001
|
||||
|
||||
} else if (descMap.cluster == "0101" && descMap.attrId == "040b") {
|
||||
resultMap.name = "Aux1"
|
||||
if(descMap.value == "01"){
|
||||
resultMap.value = "on"
|
||||
sendEvent(name: "switch", value: "on", displayed: false)
|
||||
}else{
|
||||
resultMap.value = "off"
|
||||
sendEvent(name: "switch", value: "off", displayed: false)
|
||||
}
|
||||
|
||||
} else if (descMap.cluster == "0101" && descMap.attrId == "040c") {
|
||||
resultMap.name = "Aux2"
|
||||
if(descMap.value == "01"){
|
||||
resultMap.value = "on"
|
||||
}else{
|
||||
resultMap.value = "off"
|
||||
}
|
||||
} else if (descMap.cluster == "0101" && descMap.attrId == "040d") {
|
||||
resultMap.name = "photoCalibration"
|
||||
resultMap.value = (Integer.parseInt(descMap.value, 16))
|
||||
} else if (descMap.cluster == "0101" && descMap.attrId == "040e") {
|
||||
resultMap.name = "baseCurrentNE"
|
||||
resultMap.value = (Integer.parseInt(descMap.value, 16))
|
||||
}
|
||||
return resultMap
|
||||
}
|
||||
|
||||
private Map parseCustomMessage(String description) {
|
||||
//log.info "ParseCustomMessage called with ${description}"
|
||||
Map resultMap = [:]
|
||||
if (description?.startsWith('temperature: ')) {
|
||||
resultMap.name = "temperature"
|
||||
def rawT = (description - "temperature: ").trim()
|
||||
resultMap.descriptionText = "Temperature celsius value = ${rawT}"
|
||||
def rawTint = Float.parseFloat(rawT)
|
||||
if (rawTint > 65){
|
||||
resultMap.name = null
|
||||
resultMap.value = null
|
||||
resultMap.descriptionText = "Temperature celsius value = ${rawT} is invalid not updating"
|
||||
log.warn "Invalid temperature value detected! rawT = ${rawT}, description = ${description}"
|
||||
}else if (rawT == -32768){ // This number is used to indicate an error in the temperature reading
|
||||
resultMap.value = "ERR"
|
||||
}else{
|
||||
resultMap.value = celsiusToFahrenheit(rawT.toFloat()) as Float
|
||||
sendEvent(name: "TempProb1", value: resultMap.value, displayed: false) // Workaround for lack of access to endpoint information for Temperature report
|
||||
}
|
||||
}
|
||||
resultMap.displayed = false
|
||||
log.info "Temperature reported = ${resultMap.value}"
|
||||
return resultMap
|
||||
}
|
||||
|
||||
def parseDescriptionAsMap(description) {
|
||||
(description - "read attr - ").split(",").inject([:]) { map, param ->
|
||||
def nameAndValue = param.split(":")
|
||||
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
|
||||
}
|
||||
}
|
||||
|
||||
// Added for Temeperature parse
|
||||
def getFahrenheit(value) {
|
||||
def celsius = Integer.parseInt(value, 16)
|
||||
return celsiusToFahrenheit(celsius) as Integer
|
||||
}
|
||||
|
||||
// Private methods
|
||||
def callUpdateStatusTxt(){
|
||||
def cTemp = device.currentState("TempProb1")?.value
|
||||
def cLight = 0
|
||||
def testNull = device.currentState("currentLightLevel")?.value
|
||||
if (testNull != null){
|
||||
cLight = device.currentState("currentLightLevel")?.value as int
|
||||
}
|
||||
updateStatusTxt(cTemp, cLight)
|
||||
}
|
||||
|
||||
def updateStatusTxt(currentTemp, currentLight){
|
||||
//log.info "called updateStatusTxt with ${currentTemp}, ${currentLight}"
|
||||
def cTmp = currentTemp
|
||||
def cLL = 10
|
||||
def oLL = 10
|
||||
|
||||
def testNull = device.currentState("closeLightLevel")?.value
|
||||
if (testNull != null){
|
||||
cLL = device.currentState("closeLightLevel")?.value as int
|
||||
}
|
||||
|
||||
testNull = device.currentState("openLightLevel")?.value
|
||||
if (testNull != null){
|
||||
oLL = device.currentState("openLightLevel")?.value as int
|
||||
}
|
||||
|
||||
def aOpnEn = device.currentState("autoOpenEnable")?.value
|
||||
def aClsEn = device.currentState("autoCloseEnable")?.value
|
||||
|
||||
if (currentLight < cLL){
|
||||
if (aOpnEn == "on"){
|
||||
sendEvent(name: "dayOrNight", value: "Sun must be > ${oLL} to auto open", displayed: false)
|
||||
sendEvent(name: "coopStatus", value: "Sunlight ${currentLight} open at ${oLL}. Coop ${cTmp}°", displayed: false)
|
||||
}else{
|
||||
sendEvent(name: "dayOrNight", value: "Auto Open is turned off.", displayed: false)
|
||||
sendEvent(name: "coopStatus", value: "Sunlight ${currentLight} auto open off. Coop ${cTmp}°", displayed: false)
|
||||
}
|
||||
}else {
|
||||
if (aClsEn == "on"){
|
||||
sendEvent(name: "dayOrNight", value: "Sun must be < ${cLL} to auto close", displayed: false)
|
||||
sendEvent(name: "coopStatus", value: "Sunlight ${currentLight} close at ${cLL}. Coop ${cTmp}°", displayed: false)
|
||||
}else{
|
||||
sendEvent(name: "dayOrNight", value: "Auto Close is turned off.", displayed: false)
|
||||
sendEvent(name: "coopStatus", value: "Sunlight ${currentLight} auto close off. Coop ${cTmp}°", displayed: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Commands to device
|
||||
def on() {
|
||||
log.debug "on calling Aux1On"
|
||||
Aux1On()
|
||||
}
|
||||
|
||||
def off() {
|
||||
log.debug "off calling Aux1Off"
|
||||
Aux1Off()
|
||||
}
|
||||
|
||||
def close() {
|
||||
log.debug "close calling closeDoor"
|
||||
closeDoor()
|
||||
}
|
||||
|
||||
def open() {
|
||||
log.debug "open calling openDoor"
|
||||
openDoor()
|
||||
}
|
||||
|
||||
def Aux1On(){
|
||||
log.debug "Sending Aux1 = on command"
|
||||
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x14 {}"
|
||||
}
|
||||
|
||||
def Aux1Off(){
|
||||
log.debug "Sending Aux1 = off command"
|
||||
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x15 {}"
|
||||
}
|
||||
|
||||
def Aux2On(){
|
||||
log.debug "Sending Aux2 = on command"
|
||||
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x16 {}"
|
||||
}
|
||||
|
||||
def Aux2Off(){
|
||||
log.debug "Sending Aux2 = off command"
|
||||
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x17 {}"
|
||||
}
|
||||
|
||||
def openDoor() {
|
||||
log.debug "Sending Open command"
|
||||
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x1 {}"
|
||||
}
|
||||
|
||||
def closeDoor() {
|
||||
log.debug "Sending Close command"
|
||||
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x0 {}"
|
||||
}
|
||||
|
||||
def closeDoorHiI() {
|
||||
log.debug "Sending High Current Close command"
|
||||
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x4 {}"
|
||||
}
|
||||
|
||||
def autoOpenOn() {
|
||||
log.debug "Setting Auto Open On"
|
||||
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x0C {}"
|
||||
}
|
||||
|
||||
def autoOpenOff() {
|
||||
log.debug "Setting Auto Open Off"
|
||||
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x0D {}"
|
||||
}
|
||||
|
||||
def autoCloseOn() {
|
||||
log.debug "Setting Auto Close On"
|
||||
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x0A {}"
|
||||
}
|
||||
|
||||
def autoCloseOff() {
|
||||
log.debug "Setting Auto Close Off"
|
||||
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x0B {}"
|
||||
}
|
||||
|
||||
def setOpenLevelTo(cValue) {
|
||||
def cX = cValue
|
||||
log.debug "Setting Open Light Level to ${cX} Hex = 0x${Integer.toHexString(cX)}"
|
||||
|
||||
def cmd = []
|
||||
cmd << "st wattr 0x${device.deviceNetworkId} 0x38 0x0101 0x402 0x23 {${Integer.toHexString(cX)}}"
|
||||
cmd << "delay 150"
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x402" // Read light value
|
||||
cmd
|
||||
}
|
||||
|
||||
def setCloseLevelTo(cValue) {
|
||||
def cX = cValue
|
||||
log.debug "Setting Close Light Level to ${cX} Hex = 0x${Integer.toHexString(cX)}"
|
||||
|
||||
def cmd = []
|
||||
cmd << "st wattr 0x${device.deviceNetworkId} 0x38 0x0101 0x401 0x23 {${Integer.toHexString(cX)}}"
|
||||
cmd << "delay 150"
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x401" // Read light value
|
||||
cmd
|
||||
|
||||
}
|
||||
|
||||
def setSensitivityLevel(cValue) {
|
||||
def cX = 100 - cValue
|
||||
log.debug "Setting Door sensitivity level to ${cX} Hex = 0x${Integer.toHexString(cX)}"
|
||||
|
||||
def cmd = []
|
||||
cmd << "st wattr 0x${device.deviceNetworkId} 0x38 0x0101 0x408 0x23 {${Integer.toHexString(cX)}}" // Write attribute. 0x23 is a 32 bit integer value.
|
||||
cmd << "delay 150"
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x408" // Read attribute
|
||||
cmd
|
||||
}
|
||||
|
||||
def setNewBaseCurrent(cValue) {
|
||||
def cX = cValue as int
|
||||
log.info "Setting new BaseCurrent to ${cX} Hex = 0x${Integer.toHexString(cX)}"
|
||||
|
||||
def cmd = []
|
||||
cmd << "st wattr 0x${device.deviceNetworkId} 0x38 0x0101 0x409 0x23 {${Integer.toHexString(cX)}}" // Write attribute. 0x23 is a 32 bit integer value.
|
||||
cmd << "delay 150"
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x409" // Read attribute
|
||||
cmd
|
||||
}
|
||||
|
||||
def setNewPhotoCalibration(cValue) {
|
||||
def cX = cValue as int
|
||||
log.info "Setting new Photoresister calibration to ${cX} Hex = 0x${Integer.toHexString(cX)}"
|
||||
|
||||
def cmd = []
|
||||
cmd << "st wattr 0x${device.deviceNetworkId} 0x38 0x0101 0x40D 0x2B {${Integer.toHexString(cX)}}" // Write attribute. 0x2B is a 32 bit signed integer value.
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x40D" // Read attribute
|
||||
cmd
|
||||
}
|
||||
|
||||
def readNewPhotoCalibration() {
|
||||
log.info "Requesting current Photoresister calibration "
|
||||
|
||||
def cmd = []
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x40D" // Read attribute
|
||||
cmd
|
||||
}
|
||||
|
||||
def readBaseCurrentNE() {
|
||||
log.info "Requesting base current never exceed setting "
|
||||
|
||||
def cmd = []
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x40E" // Read attribute
|
||||
cmd
|
||||
}
|
||||
|
||||
def setBaseCurrentNE(cValue) {
|
||||
def cX = cValue as int
|
||||
log.info "Setting new base Current Never Exceed to ${cX} Hex = 0x${Integer.toHexString(cX)}"
|
||||
|
||||
def cmd = []
|
||||
cmd << "st wattr 0x${device.deviceNetworkId} 0x38 0x0101 0x40E 0x23 {${Integer.toHexString(cX)}}" // Write attribute. 0x23 is a 32 bit unsigned integer value.
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x40E" // Read attribute
|
||||
cmd
|
||||
}
|
||||
|
||||
def poll(){
|
||||
log.debug "Polling Device"
|
||||
def cmd = []
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0003" // Read Door State
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0400" // Read Current Light Level
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x39 0x0402 0x0000" // Read probe 1 Temperature
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x40 0x0402 0x0000" // Read probe 2 Temperature
|
||||
|
||||
cmd
|
||||
}
|
||||
|
||||
def updateTemp1() {
|
||||
log.debug "Sending attribute read request for Temperature Probe1"
|
||||
def cmd = []
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x39 0x0402 0x0000" // Read Current Temperature from Coop Probe 1
|
||||
cmd
|
||||
}
|
||||
|
||||
def updateTemp2() {
|
||||
log.debug "Sending attribute read request for Temperature Probe2"
|
||||
def cmd = []
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x40 0x0402 0x0000" // Read Current Temperature from Coop Probe 2
|
||||
cmd
|
||||
}
|
||||
|
||||
|
||||
def updateSun() {
|
||||
log.debug "Sending attribute read request for Sun Light Level"
|
||||
def cmd = []
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0400" // Read Current Light Level
|
||||
cmd
|
||||
}
|
||||
|
||||
def updateSensitivity() {
|
||||
log.debug "Sending attribute read request for door sensitivity"
|
||||
def cmd = []
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0408" // Read Door sensitivity
|
||||
cmd
|
||||
}
|
||||
|
||||
def updateCloseLightLevel() {
|
||||
log.debug "Sending attribute read close light level"
|
||||
def cmd = []
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0401"
|
||||
cmd
|
||||
}
|
||||
|
||||
def updateOpenLightLevel() {
|
||||
log.debug "Sending attribute read open light level"
|
||||
def cmd = []
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0402"
|
||||
cmd
|
||||
}
|
||||
|
||||
def refresh() {
|
||||
log.debug "sending refresh command"
|
||||
def cmd = []
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0003" // Read Door State
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0400" // Read Current Light Level
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0401" // Read Door Close Light Level
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0402" // Read Door Open Light Level
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0403" // Read Auto Door Close Settings
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0404" // Read Auto Door Open Settings
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x39 0x0402 0x0000" // Read Current Temperature from Coop Probe 1
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0408" // Object detection sensitivity
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x40 0x0402 0x0000" // Read Current Temperature from Coop Probe 2
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0405" // Current required to close door
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x040B" // Aux1 Status
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x040C" // Aux2 Status
|
||||
cmd << "delay 150"
|
||||
|
||||
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x409" // Read Base current
|
||||
|
||||
cmd
|
||||
}
|
||||
|
||||
def configure() {
|
||||
log.debug "Binding SEP 0x38 DEP 0x01 Cluster 0x0101 Lock cluster to hub"
|
||||
log.debug "Binding SEP 0x39 DEP 0x01 Cluster 0x0402 Temperature cluster to hub"
|
||||
log.debug "Binding SEP 0x40 DEP 0x01 Cluster 0x0402 Temperature cluster to hub"
|
||||
|
||||
def cmd = []
|
||||
cmd << "zdo bind 0x${device.deviceNetworkId} 0x38 0x01 0x0101 {${device.zigbeeId}} {}" // Bind to end point 0x38 and the lock cluster
|
||||
cmd << "delay 150"
|
||||
cmd << "zdo bind 0x${device.deviceNetworkId} 0x39 0x01 0x0402 {${device.zigbeeId}} {}" // Bind to end point 0x39 and the temperature cluster
|
||||
cmd << "delay 150"
|
||||
cmd << "zdo bind 0x${device.deviceNetworkId} 0x40 0x01 0x0402 {${device.zigbeeId}} {}" // Bind to end point 0x40 and the temperature cluster
|
||||
cmd << "delay 1500"
|
||||
|
||||
log.info "Sending ZigBee Configuration Commands to Coop Control"
|
||||
return cmd + refresh()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user