OK, so I probably did a little more than I needed to, but I couldn't stand how non-Hubitat-ty the logging looked, so I added options and cleaned it up a bit (and added info logging they were lacking). I also fixed everything I could that looks like it would have broken if the sensor supports (and was included with) S2 security. I left a lot of oddities that might be normal in ST DTHs (been a while...) but should be harmless on Hubitat.
Most of the other modifications I did were just the usual: the physicalgraph namespace becomes hubitat, the tiles and simulator sections are not used (so can be removed), and whatnot: App and driver porting to Hubitat
If this was too much, I can try again and not try as hard in case that messed something up. I haven't tested this with any real sensors. Hope it works for you!
/**
* Copyright 2015 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.
*
* Z-Wave Reversed Contact Sensor. Does the opposite of the regular door/window sensor. Built specifically for the
* Aeotec Aeon Dry Contact Sensor for @Boatman (John Lee).
*
* Author: SmartThings
* Date: 2013-11-3
* Version: v2
*
* Updates:
* -------
* 04-17-2016 : Initial commit
* 12-07-2020 : Modified for Hubitat
*
*/
metadata {
definition (name: "My Z-Wave Reversed Contact Sensor", namespace: "jscgs350", author: "jscgs350") {
capability "ContactSensor"
capability "Sensor"
capability "Battery"
capability "Configuration"
// fingerprint deviceId: "0x2001", inClusters: "0x30,0x80,0x84,0x85,0x86,0x72"
// fingerprint deviceId: "0x07", inClusters: "0x30"
// fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x98", outClusters: "0x5A,0x82"
}
preferences {
input name: "enableDebug", type: "bool", title: "Enable debug logging", defaultValue: true
input name: "enableDesc", type: "bool", title: "Enable descriptionText logging", defaultValue: true
}
}
void logsOff(){
log.warn "Auto-disabling debug logging..."
device.updateSetting("enableDebug", [value:"false", type:"bool"])
}
def parse(String description) {
if (enableDebug) log.debug "parse: $description"
def result = null
if (description.startsWith("Err 106")) {
if (getDataValue("S2")) {
if (enableDebug) log.debug description
} else {
log.warn "This sensor failed to complete the network security key exchange. If you are unable to control it, you must remove it from your network and add it again."
result = createEvent(
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it, you must remove it from your network and add it again.",
eventType: "ALERT",
name: "secureInclusion",
value: "failed",
isStateChange: true,
)
}
} else if (description != "updated") {
def cmd = zwave.parse(description, [0x20: 1, 0x25: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
if (enableDebug) log.debug "parsed '$description' to $result"
return result
}
def updated() {
if (enableDebug != false) runIn(1800, logsOff)
def cmds = []
if (!state.MSR) {
cmds = [
zwave.manufacturerSpecificV2.manufacturerSpecificGet().format(),
"delay 1200",
zwaveSecureEncap(zwave.wakeUpV1.wakeUpNoMoreInformation())
]
} else if (!state.lastbat) {
cmds = []
} else {
cmds = [zwaveSecureEncap(zwave.wakeUpV1.wakeUpNoMoreInformation())]
}
response(cmds)
}
def configure() {
delayBetween([
zwaveSecureEncap(zwave.manufacturerSpecificV2.manufacturerSpecificGet()),
batteryGetCommand()
], 6000)
}
def sensorValueEvent(value) {
if (enableDesc && device.currentValue("contact") != (value ? "closed" : "open")) log.info "$device.displayName is ${value ? 'closed' : 'open'}"
if (value) {
createEvent(name: "contact", value: "closed", descriptionText: "$device.displayName is closed")
} else {
createEvent(name: "contact", value: "open", descriptionText: "$device.displayName is open")
}
}
def zwaveEvent(hubitat.zwave.commands.basicv1.BasicReport cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(hubitat.zwave.commands.basicv1.BasicSet cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(hubitat.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(hubitat.zwave.commands.sensorbinaryv1.SensorBinaryReport cmd)
{
sensorValueEvent(cmd.sensorValue)
}
def zwaveEvent(hubitat.zwave.commands.sensoralarmv1.SensorAlarmReport cmd)
{
sensorValueEvent(cmd.sensorState)
}
def zwaveEvent(hubitat.zwave.commands.notificationv3.NotificationReport cmd)
{
def result = []
if (cmd.notificationType == 0x06 && cmd.event == 0x16) {
result << sensorValueEvent(1)
} else if (cmd.notificationType == 0x06 && cmd.event == 0x17) {
result << sensorValueEvent(0)
} else if (cmd.notificationType == 0x07) {
if (cmd.v1AlarmType == 0x07) { // special case for nonstandard messages from Monoprice door/window sensors
result << sensorValueEvent(cmd.v1AlarmLevel)
} else if (cmd.event == 0x01 || cmd.event == 0x02) {
result << sensorValueEvent(1)
} else if (cmd.event == 0x03) {
if (enableDesc) log.info "$device.displayName covering was removed"
result << createEvent(descriptionText: "$device.displayName covering was removed", isStateChange: true)
result << response(zwave.wakeUpV1.wakeUpIntervalSet(seconds:4*3600, nodeid:zwaveHubNodeId))
if(!state.MSR) result << response(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
} else if (cmd.event == 0x05 || cmd.event == 0x06) {
result << createEvent(descriptionText: "$device.displayName detected glass breakage", isStateChange: true)
} else if (cmd.event == 0x07) {
if(!state.MSR) result << response(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
result << createEvent(name: "motion", value: "active", descriptionText:"$device.displayName detected motion")
}
} else if (cmd.notificationType) {
def text = "Notification $cmd.notificationType: event ${([cmd.event] + cmd.eventParameter).join(", ")}"
result << createEvent(name: "notification$cmd.notificationType", value: "$cmd.event", descriptionText: text, displayed: false)
} else {
def value = cmd.v1AlarmLevel == 255 ? "active" : cmd.v1AlarmLevel ?: "inactive"
result << createEvent(name: "alarm $cmd.v1AlarmType", value: value, displayed: false)
}
result
}
def zwaveEvent(hubitat.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
def event = createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)
def cmds = []
if (!state.MSR) {
cmds << zwaveSecureEncap(zwave.wakeUpV1.wakeUpIntervalSet(seconds:4*3600, nodeid:zwaveHubNodeId))
cmds << zwaveSecureEncap(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
cmds << "delay 1200"
}
if (!state.lastbat || now() - state.lastbat > 53*60*60*1000) {
cmds << batteryGetCommand()
} else {
cmds << zwaveSecureEncap(zwave.wakeUpV1.wakeUpNoMoreInformation())
}
[event, response(cmds)]
}
def zwaveEvent(hubitat.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) {
map.value = 1
map.descriptionText = "${device.displayName} has a low battery"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
state.lastbat = now()
if (enableDesc) log.info "$device.displayName battery is ${map.value}%"
[createEvent(map), response(zwave.wakeUpV1.wakeUpNoMoreInformation())]
}
def zwaveEvent(hubitat.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
def result = []
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
if (enableDebug) log.debug "msr: $msr"
updateDataValue("MSR", msr)
result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)
if (msr == "011A-0601-0901") { // Enerwave motion doesn't always get the associationSet that the hub sends on join
result << response(zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId))
} else if (!device.currentState("battery")) {
if (msr == "0086-0102-0059") {
result << response(zwave.securityV1.securityMessageEncapsulation().encapsulate(zwave.batteryV1.batteryGet()).format())
} else {
result << response(batteryGetCommand())
}
}
result
}
def zwaveEvent(hubitat.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
hubitat.zwave.Command encapCmd = cmd.encapsulatedCommand([0x20: 1, 0x85: 2, 0x70: 1])
if (encapCmd) {
zwaveEvent(encapCmd)
}
}
def zwaveEvent(hubitat.zwave.Command cmd) {
createEvent(descriptionText: "$device.displayName: $cmd", displayed: false)
}
def batteryGetCommand() {
zwaveSecureEncap(zwave.batteryV1.batteryGet())
}