Last active
April 11, 2019 23:33
-
-
Save pcaddict/4eb13ecfc3451b5a0cda5694742eaffa to your computer and use it in GitHub Desktop.
GT_MultiSensor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2018 SmartThings | |
* | |
* 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. | |
*/ | |
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus | |
import physicalgraph.zigbee.zcl.DataType | |
metadata { | |
definition(name: "Multi Sensor", namespace: "multiSensor", author: "Patrick Grindstaff", runLocally: true) { | |
capability "Configuration" | |
capability "Battery" | |
capability "Temperature Measurement" | |
capability "Relative Humidity Measurement" | |
capability "Refresh" | |
capability "Health Check" | |
capability "Sensor" | |
//command "enrollResponse" | |
fingerprint inClusters: "0000,0003,0402,0403,0405", outClusters: "0003", manufacturer: "Grindstaff Technologies", model: "Multi Sensor" | |
} | |
simulator { | |
status "active": "zone report :: type: 19 value: 0031" | |
status "inactive": "zone report :: type: 19 value: 0030" | |
} | |
preferences { | |
section { | |
input title: "Temperature Offset", 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 "tempOffset", "decimal", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false | |
} | |
section { | |
input title: "Humidity Offset", description: "This feature allows you to correct any humidity variations by selecting an offset. Ex: If your sensor consistently reports a humidity that's 6% higher then a similiar calibrated sensor, you'd enter \"-6\".", displayDuringSetup: false, type: "paragraph", element: "paragraph" | |
input "humidityOffset", "decimal", title: "Humidity Offset in Percent", description: "Adjust humidity by this percentage", range: "*..*", displayDuringSetup: false | |
} | |
} | |
tiles(scale: 2) { | |
valueTile("temperature", "device.temperature", width: 2, height: 2) { | |
state("temperature", label: '${currentValue}°', unit: "F", | |
backgroundColors: [ | |
[value: 31, color: "#153591"], | |
[value: 44, color: "#1e9cbb"], | |
[value: 59, color: "#90d2a7"], | |
[value: 74, color: "#44b621"], | |
[value: 84, color: "#f1d801"], | |
[value: 95, color: "#d04e00"], | |
[value: 96, color: "#bc2323"] | |
] | |
) | |
} | |
valueTile("humidity", "device.humidity", decoration: "flat", inactiveLabel: false, width: 2, height: 2) { | |
state "humidity", label: '${currentValue}% humidity', unit: "" | |
} | |
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { | |
state "default", action: "refresh.refresh", icon: "st.secondary.refresh" | |
} | |
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { | |
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure" | |
} | |
main("temperature", "humidity") | |
details(["temperature", "humidity", "pressure", "refresh", "configure"]) | |
} | |
} | |
private List<Map> collectAttributes(Map descMap) { | |
List<Map> descMaps = new ArrayList<Map>() | |
descMaps.add(descMap) | |
if (descMap.additionalAttrs) { | |
descMaps.addAll(descMap.additionalAttrs) | |
} | |
return descMaps | |
} | |
/* | |
def parse(String description) { | |
log.debug "description: $description" | |
Map map = zigbee.getEvent(description) | |
if (!map) { | |
if (description?.startsWith('zone status')) { | |
map = parseIasMessage(description) | |
} else { | |
Map descMap = zigbee.parseDescriptionAsMap(description) | |
if (descMap?.clusterInt == zigbee.POWER_CONFIGURATION_CLUSTER && descMap.commandInt != 0x07 && descMap.value) { | |
log.info "BATT METRICS - attr: ${descMap?.attrInt}, value: ${descMap?.value}, decValue: ${Integer.parseInt(descMap.value, 16)}, currPercent: ${device.currentState("battery")?.value}, device: ${device.getDataValue("manufacturer")} ${device.getDataValue("model")}" | |
List<Map> descMaps = collectAttributes(descMap) | |
def battMap = descMaps.find { it.attrInt == 0x0020 } | |
if (battMap) { | |
map = getBatteryResult(Integer.parseInt(battMap.value, 16)) | |
} | |
} else if (descMap?.clusterInt == 0x0500 && descMap.attrInt == 0x0002) { | |
def zs = new ZoneStatus(zigbee.convertToInt(descMap.value, 16)) | |
map = translateZoneStatus(zs) | |
} else if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) { | |
if (descMap.data[0] == "00") { | |
log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap" | |
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) | |
} else { | |
log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}" | |
} | |
} else if (descMap?.clusterInt == zigbee.IAS_ZONE_CLUSTER && descMap.attrInt == zigbee.ATTRIBUTE_IAS_ZONE_STATUS && descMap?.value) { | |
map = translateZoneStatus(new ZoneStatus(zigbee.convertToInt(descMap?.value))) | |
} | |
} | |
} else if (map.name == "temperature") { | |
if (tempOffset) { | |
map.value = ((float) map.value + (float) tempOffset) as Float | |
} | |
map.descriptionText = temperatureScale == 'C' ? "${device.displayName} temperature was ${map.value}°C" : "${device.displayName} temperature was ${map.value}°F" | |
map.translatable = true | |
} else if (map.name == "humidity") { | |
if (humidityOffset) { | |
map.value = (int) map.value + (int) humidityOffset | |
} | |
map.descriptionText = "${device.displayName} humidity was ${map.value}%" | |
} | |
log.debug "Parse returned $map" | |
def result = map ? createEvent(map) : [:] | |
if (description?.startsWith('enroll request')) { | |
List cmds = zigbee.enrollResponse() | |
log.debug "enroll response: ${cmds}" | |
result = cmds?.collect { new physicalgraph.device.HubAction(it) } | |
} | |
return result | |
}*/ | |
def parse(String description) { | |
log.debug "description: $description" | |
//Map map = zigbee.getEvent(description) | |
Map map = [:] | |
if (description?.startsWith('catchall: ')) { | |
parseCatchAllMessage(description) | |
} else if (description?.startsWith('temperature')) { | |
map = parseCustomMessage(description) | |
} else if (description?.startsWith('humidity')) { | |
map = parseCustomMessage(description) | |
} | |
log.debug "Parse returned $map" | |
def result = map ? createEvent(map) : [:] | |
if (description?.startsWith('enroll request')) { | |
List cmds = zigbee.enrollResponse() | |
log.debug "enroll response: ${cmds}" | |
result = cmds?.collect { new physicalgraph.device.HubAction(it) } | |
} | |
return result | |
} | |
private Map parseCatchAllMessage(String description) { | |
Map resultMap = [:] | |
Map descMap = zigbee.parseDescriptionAsMap(description) | |
switch (descMap.clusterInt) { | |
case zigbee.POWER_CONFIGURATION_CLUSTER: | |
if (descMap.commandInt != 0x07) { | |
resultMap = getBatteryResult(descMap.data.last()); // Will need to figure out correct data source once battery reporting is implemented in sensor firmware. | |
} | |
break | |
case zigbee.TEMPERATURE_MEASUREMENT_CLUSTER: | |
if (descMap.clusterInt == 0x07) { | |
if (descMap.data[0] == "00") { | |
log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap" | |
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) | |
} else { | |
log.warn "TEMP REPORTING CONFIG FAILED. ERROR CODE: ${descMap.data[0]}" | |
} | |
} | |
break | |
case zigbee.RELATIVE_HUMIDITY_CLUSTER: | |
if (descMap.clusterInt == 0x07) { | |
if (descMap.data[0] == "00") { | |
log.debug "HUMIDITY REPORTING CONFIG RESPONSE: $descMap" | |
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) | |
} else { | |
log.warn "HUMIDITY REPORTING CONFIG FAILED. ERROR CODE: ${descMap.data[0]}" | |
} | |
} | |
break | |
} | |
} | |
private Map parseCustomMessage(String description) { | |
Map resultMap = [:] | |
if(description?.startsWith('temperature')) { | |
def value = (description - "temperature: ").trim() | |
if(value.isNumber()) { | |
if(getTemperatureScale() == "F") { | |
value = celsiusToFahrenheit(value.toFloat()) as Float | |
} | |
resultMap = getTemperatureResult(value) | |
return resultMap | |
} else { | |
log.error "Invalid Temperature ${value}" | |
} | |
} else if (description?.startsWith('humidity')) { | |
def value = (description - "humidity: ").trim() | |
if(value.isNumber()) { | |
value = value.toFloat() as Float | |
resultMap = getHumidityResult(value) | |
return resultMap | |
} | |
} | |
} | |
private Map getTemperatureResult(value) { | |
log.debug "Get Temperature Result: ${value}" | |
def linkText = getLinkText(device) | |
if(tempOffset) { | |
value += tempOffset as Float | |
} | |
def descriptionText = "${linkText} was ${value}°${temperatureScale}" | |
return [ | |
name: 'temperature', | |
value: value, | |
descriptionText: descriptionText, | |
translatable: true, | |
unit: temperatureScale | |
] | |
} | |
private Map getHumidityResult(value) { | |
log.debug "Get Humidity Result: ${value}" | |
def linkText = getLinkText(device) | |
if(humidOffset) { | |
value += humidOffset as Float | |
} | |
def descriptionText = "${linkText} was ${value}% Humidity" | |
return [ | |
name: 'humidity', | |
value: value, | |
descriptionText: descriptionText, | |
translatable: true, | |
unit: % | |
] | |
} | |
private Map getBatteryResult(rawValue) { | |
log.debug "Battery rawValue = ${rawValue}" | |
def linkText = getLinkText(device) | |
def result = [:] | |
def volts = rawValue / 10 | |
if (!(rawValue == 0 || rawValue == 255)) { | |
result.name = 'battery' | |
result.translatable = true | |
def minVolts = 2.4 | |
def maxVolts = 2.7 | |
// Get the current battery percentage as a multiplier 0 - 1 | |
def curValVolts = Integer.parseInt(device.currentState("battery")?.value ?: "100") / 100.0 | |
// Find the corresponding voltage from our range | |
curValVolts = curValVolts * (maxVolts - minVolts) + minVolts | |
// Round to the nearest 10th of a volt | |
curValVolts = Math.round(10 * curValVolts) / 10.0 | |
// Only update the battery reading if we don't have a last reading, | |
// OR we have received the same reading twice in a row | |
// OR we don't currently have a battery reading | |
// OR the value we just received is at least 2 steps off from the last reported value | |
if (state?.lastVolts == null || state?.lastVolts == volts || device.currentState("battery")?.value == null || Math.abs(curValVolts - volts) > 0.1) { | |
def pct = (volts - minVolts) / (maxVolts - minVolts) | |
def roundedPct = Math.round(pct * 100) | |
if (roundedPct <= 0) | |
roundedPct = 1 | |
result.value = Math.min(100, roundedPct) | |
} else { | |
// Don't update as we want to smooth the battery values, but do report the last battery state for record keeping purposes | |
result.value = device.currentState("battery").value | |
} | |
result.descriptionText = "${device.displayName} battery was ${result.value}%" | |
state.lastVolts = volts | |
} | |
return result | |
} | |
/*private Map getBatteryPercentageResult(rawValue) { | |
log.debug "Battery Percentage rawValue = ${rawValue} -> ${rawValue / 2}%" | |
def result = [:] | |
if (0 <= rawValue && rawValue <= 200) { | |
result.name = 'battery' | |
result.translatable = true | |
result.value = Math.round(rawValue / 2) | |
result.descriptionText = "${device.displayName} battery was ${result.value}%" | |
} | |
return result | |
}*/ | |
/* | |
private Map getMotionResult(value) { | |
log.debug 'motion' | |
String descriptionText = value == 'active' ? "${device.displayName} detected motion" : "${device.displayName} motion has stopped" | |
return [ | |
name : 'motion', | |
value : value, | |
descriptionText: descriptionText, | |
translatable : true | |
] | |
}*/ | |
/** | |
* PING is used by Device-Watch in attempt to reach the Device | |
* */ | |
def ping() { | |
zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) | |
} | |
def refresh() { | |
log.debug "Refreshing Values" | |
def refreshCmds = [] | |
refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) + | |
zigbee.readAttribute(zigbee.RELATIVE_HUMIDITY_CLUSTER, 0x0000) + | |
zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) + | |
zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + | |
zigbee.enrollResponse() | |
return refreshCmds | |
} | |
def configure() { | |
// Device-Watch allows 2 check-in misses from device + ping (plus 1 min lag time) | |
// enrolls with default periodic reporting until newer 5 min interval is confirmed | |
//sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) | |
log.debug "Configuring Reporting" | |
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity | |
// battery minReport 30 seconds, maxReportTime 6 hrs by default | |
// humidity minReportTime 30 seconds, maxReportTime 60 min | |
def configCmds = [] | |
configCmds += zigbee.batteryConfig() + | |
//zigbee.temperatureConfig(30, 300) + | |
zigbee.configureReporting(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000, DataType.INT16, 30, 300, 0x01) + | |
zigbee.configureReporting(zigbee.RELATIVE_HUMIDITY_CLUSTER, 0x0000, DataType.UINT16, 30, 3600, 150) | |
//zigbee.configureReporting(0x0403, 0x0000, DataType.INT16, 30, 600, 1) | |
return refresh() + configCmds | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright 2018 SmartThings | |
* | |
* 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. | |
*/ | |
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus | |
import physicalgraph.zigbee.zcl.DataType | |
metadata { | |
definition(name: "Multi Sensor", namespace: "multiSensorTest", author: "Patrick Grindstaff", runLocally: true) { | |
capability "Configuration" | |
capability "Battery" | |
capability "Temperature Measurement" | |
capability "Relative Humidity Measurement" | |
capability "Refresh" | |
capability "Health Check" | |
capability "Sensor" | |
//command "enrollResponse" | |
fingerprint inClusters: "0000,0003,0402,0403,0405", outClusters: "0003", manufacturer: "Grindstaff Technologies", model: "Multi Sensor" | |
} | |
simulator { | |
status "active": "zone report :: type: 19 value: 0031" | |
status "inactive": "zone report :: type: 19 value: 0030" | |
} | |
preferences { | |
section { | |
input title: "Temperature Offset", 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 "tempOffset", "decimal", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false | |
} | |
section { | |
input title: "Humidity Offset", description: "This feature allows you to correct any humidity variations by selecting an offset. Ex: If your sensor consistently reports a humidity that's 6% higher then a similiar calibrated sensor, you'd enter \"-6\".", displayDuringSetup: false, type: "paragraph", element: "paragraph" | |
input "humidityOffset", "decimal", title: "Humidity Offset in Percent", description: "Adjust humidity by this percentage", range: "*..*", displayDuringSetup: false | |
} | |
} | |
tiles(scale: 2) { | |
valueTile("temperature", "device.temperature", width: 2, height: 2) { | |
state("temperature", label: '${currentValue}°', unit: "F", | |
backgroundColors: [ | |
[value: 31, color: "#153591"], | |
[value: 44, color: "#1e9cbb"], | |
[value: 59, color: "#90d2a7"], | |
[value: 74, color: "#44b621"], | |
[value: 84, color: "#f1d801"], | |
[value: 95, color: "#d04e00"], | |
[value: 96, color: "#bc2323"] | |
] | |
) | |
} | |
valueTile("humidity", "device.humidity", decoration: "flat", inactiveLabel: false, width: 2, height: 2) { | |
state "humidity", label: '${currentValue}% humidity', unit: "" | |
} | |
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { | |
state "default", action: "refresh.refresh", icon: "st.secondary.refresh" | |
} | |
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { | |
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure" | |
} | |
main("temperature", "humidity") | |
details(["temperature", "humidity", "pressure", "refresh", "configure"]) | |
} | |
} | |
private List<Map> collectAttributes(Map descMap) { | |
List<Map> descMaps = new ArrayList<Map>() | |
descMaps.add(descMap) | |
if (descMap.additionalAttrs) { | |
descMaps.addAll(descMap.additionalAttrs) | |
} | |
return descMaps | |
} | |
def parse(String description) { | |
log.debug "description: $description" | |
Map map = zigbee.getEvent(description) | |
if (!map) { | |
if (description?.startsWith('zone status')) { | |
map = parseIasMessage(description) | |
} else { | |
Map descMap = zigbee.parseDescriptionAsMap(description) | |
if (descMap?.clusterInt == zigbee.POWER_CONFIGURATION_CLUSTER && descMap.commandInt != 0x07 && descMap.value) { | |
log.info "BATT METRICS - attr: ${descMap?.attrInt}, value: ${descMap?.value}, decValue: ${Integer.parseInt(descMap.value, 16)}, currPercent: ${device.currentState("battery")?.value}, device: ${device.getDataValue("manufacturer")} ${device.getDataValue("model")}" | |
List<Map> descMaps = collectAttributes(descMap) | |
def battMap = descMaps.find { it.attrInt == 0x0020 } | |
if (battMap) { | |
map = getBatteryResult(Integer.parseInt(battMap.value, 16)) | |
} | |
} else if (descMap?.clusterInt == 0x0500 && descMap.attrInt == 0x0002) { | |
def zs = new ZoneStatus(zigbee.convertToInt(descMap.value, 16)) | |
map = translateZoneStatus(zs) | |
} else if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) { | |
if (descMap.data[0] == "00") { | |
log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap" | |
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) | |
} else { | |
log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}" | |
} | |
} else if (descMap?.clusterInt == zigbee.IAS_ZONE_CLUSTER && descMap.attrInt == zigbee.ATTRIBUTE_IAS_ZONE_STATUS && descMap?.value) { | |
map = translateZoneStatus(new ZoneStatus(zigbee.convertToInt(descMap?.value))) | |
} | |
} | |
} else if (map.name == "temperature") { | |
if (tempOffset) { | |
map.value = map.value + tempOffset | |
} else { | |
map.value = map.value | |
} | |
map.descriptionText = temperatureScale == 'C' ? "${device.displayName} temperature was ${map.value}°C" : "${device.displayName} temperature was ${map.value}°F" | |
map.translatable = true | |
} else if (map.name == "humidity") { | |
if (humidityOffset) { | |
map.value = (int) map.value + (int) humidityOffset | |
} | |
map.descriptionText = "${device.displayName} humidity was ${map.value}%" | |
} | |
log.debug "Parse returned $map" | |
def result = map ? createEvent(map) : [:] | |
if (description?.startsWith('enroll request')) { | |
List cmds = zigbee.enrollResponse() | |
log.debug "enroll response: ${cmds}" | |
result = cmds?.collect { new physicalgraph.device.HubAction(it) } | |
} | |
return result | |
} | |
private Map parseIasMessage(String description) { | |
ZoneStatus zs = zigbee.parseZoneStatus(description) | |
translateZoneStatus(zs) | |
} | |
private Map translateZoneStatus(ZoneStatus zs) { | |
// Some sensor models that use this DTH use alarm1 and some use alarm2 to signify motion | |
return (zs.isAlarm1Set() || zs.isAlarm2Set()) ? getMotionResult('active') : getMotionResult('inactive') | |
} | |
private Map getBatteryResult(rawValue) { | |
log.debug "Battery rawValue = ${rawValue}" | |
def linkText = getLinkText(device) | |
def result = [:] | |
def volts = rawValue / 10 | |
if (!(rawValue == 0 || rawValue == 255)) { | |
result.name = 'battery' | |
result.translatable = true | |
def minVolts = 2.4 | |
def maxVolts = 2.7 | |
// Get the current battery percentage as a multiplier 0 - 1 | |
def curValVolts = Integer.parseInt(device.currentState("battery")?.value ?: "100") / 100.0 | |
// Find the corresponding voltage from our range | |
curValVolts = curValVolts * (maxVolts - minVolts) + minVolts | |
// Round to the nearest 10th of a volt | |
curValVolts = Math.round(10 * curValVolts) / 10.0 | |
// Only update the battery reading if we don't have a last reading, | |
// OR we have received the same reading twice in a row | |
// OR we don't currently have a battery reading | |
// OR the value we just received is at least 2 steps off from the last reported value | |
if (state?.lastVolts == null || state?.lastVolts == volts || device.currentState("battery")?.value == null || Math.abs(curValVolts - volts) > 0.1) { | |
def pct = (volts - minVolts) / (maxVolts - minVolts) | |
def roundedPct = Math.round(pct * 100) | |
if (roundedPct <= 0) | |
roundedPct = 1 | |
result.value = Math.min(100, roundedPct) | |
} else { | |
// Don't update as we want to smooth the battery values, but do report the last battery state for record keeping purposes | |
result.value = device.currentState("battery").value | |
} | |
result.descriptionText = "${device.displayName} battery was ${result.value}%" | |
state.lastVolts = volts | |
} | |
return result | |
} | |
/*private Map getBatteryPercentageResult(rawValue) { | |
log.debug "Battery Percentage rawValue = ${rawValue} -> ${rawValue / 2}%" | |
def result = [:] | |
if (0 <= rawValue && rawValue <= 200) { | |
result.name = 'battery' | |
result.translatable = true | |
result.value = Math.round(rawValue / 2) | |
result.descriptionText = "${device.displayName} battery was ${result.value}%" | |
} | |
return result | |
}*/ | |
/** | |
* PING is used by Device-Watch in attempt to reach the Device | |
* */ | |
def ping() { | |
zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) | |
} | |
def refresh() { | |
log.debug "Refreshing Values" | |
def refreshCmds = [] | |
refreshCmds += zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) + | |
zigbee.readAttribute(zigbee.RELATIVE_HUMIDITY_CLUSTER, 0x0000) + | |
zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) + | |
zigbee.readAttribute(zigbee.IAS_ZONE_CLUSTER, zigbee.ATTRIBUTE_IAS_ZONE_STATUS) + | |
zigbee.enrollResponse() | |
return refreshCmds | |
} | |
def configure() { | |
// Device-Watch allows 2 check-in misses from device + ping (plus 1 min lag time) | |
// enrolls with default periodic reporting until newer 5 min interval is confirmed | |
//sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID, offlinePingable: "1"]) | |
log.debug "Configuring Reporting" | |
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity | |
// battery minReport 30 seconds, maxReportTime 6 hrs by default | |
// humidity minReportTime 30 seconds, maxReportTime 60 min | |
def configCmds = [] | |
configCmds += zigbee.batteryConfig() + | |
zigbee.temperatureConfig(30, 300) + | |
//zigbee.configureReporting(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000, DataType.INT16, 30, 300, 0x0A) + | |
zigbee.configureReporting(zigbee.RELATIVE_HUMIDITY_CLUSTER, 0x0000, DataType.UINT16, 60, 300, 100) | |
//zigbee.configureReporting(0x0403, 0x0000, DataType.INT16, 30, 600, 1) | |
return refresh() + configCmds | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
53f24213-62db-45d4-8889-0c036c0798b0 7:27:37 PM: debug Parse returned [name:temperature, value:81.734, descriptionText:Multi Sensor was 81.734°F, translatable:true, unit:F] | |
53f24213-62db-45d4-8889-0c036c0798b0 7:27:37 PM: debug Get Temperature Result: 81.734 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:27:37 PM: debug description: temperature: 27.63 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:22:37 PM: debug Parse returned [name:temperature, value:81.698, descriptionText:Multi Sensor was 81.698°F, translatable:true, unit:F] | |
53f24213-62db-45d4-8889-0c036c0798b0 7:22:37 PM: debug Get Temperature Result: 81.698 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:22:37 PM: debug description: temperature: 27.61 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:22:37 PM: debug Parse returned [name:temperature, value:81.698, descriptionText:Multi Sensor was 81.698°F, translatable:true, unit:F] | |
53f24213-62db-45d4-8889-0c036c0798b0 7:22:37 PM: debug Get Temperature Result: 81.698 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:22:37 PM: debug description: temperature: 27.61 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:17:51 PM: debug Parse returned [name:temperature, value:81.662, descriptionText:Multi Sensor was 81.662°F, translatable:true, unit:F] | |
53f24213-62db-45d4-8889-0c036c0798b0 7:17:51 PM: debug Get Temperature Result: 81.662 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:17:51 PM: debug description: temperature: 27.59 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:17:51 PM: debug Parse returned [name:temperature, value:81.662, descriptionText:Multi Sensor was 81.662°F, translatable:true, unit:F] | |
53f24213-62db-45d4-8889-0c036c0798b0 7:17:51 PM: debug Get Temperature Result: 81.662 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:17:51 PM: debug description: temperature: 27.59 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:12:35 PM: debug Parse returned [name:temperature, value:81.608, descriptionText:Multi Sensor was 81.608°F, translatable:true, unit:F] | |
53f24213-62db-45d4-8889-0c036c0798b0 7:12:35 PM: debug Get Temperature Result: 81.608 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:12:35 PM: debug description: temperature: 27.56 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:12:35 PM: debug Parse returned [name:temperature, value:81.608, descriptionText:Multi Sensor was 81.608°F, translatable:true, unit:F] | |
53f24213-62db-45d4-8889-0c036c0798b0 7:12:35 PM: debug Get Temperature Result: 81.608 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:12:35 PM: debug description: temperature: 27.56 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:10:31 PM: debug Parse returned [name:humidity, value:42.0, descriptionText:Multi Sensor was 42.0% Humidity] | |
53f24213-62db-45d4-8889-0c036c0798b0 7:10:31 PM: debug Get Humidity Result: 42.0 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:10:31 PM: debug description: humidity: 42 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:09:30 PM: debug Parse returned [name:humidity, value:44.0, descriptionText:Multi Sensor was 44.0% Humidity] | |
53f24213-62db-45d4-8889-0c036c0798b0 7:09:30 PM: debug Get Humidity Result: 44.0 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:09:30 PM: debug description: humidity: 44 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:09:30 PM: debug Parse returned [name:humidity, value:44.0, descriptionText:Multi Sensor was 44.0% Humidity] | |
53f24213-62db-45d4-8889-0c036c0798b0 7:09:30 PM: debug Get Humidity Result: 44.0 | |
53f24213-62db-45d4-8889-0c036c0798b0 7:09:30 PM: debug description: humidity: 44 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment