Showing preview only (630K chars total). Download the full file or copy to clipboard to get everything.
Repository: robertvandervoort/SmartThings
Branch: master
Commit: fd0e7fd4fa09
Files: 41
Total size: 606.3 KB
Directory structure:
gitextract_nx5lanog/
├── .gitattributes
├── .gitignore
├── .idea/
│ └── misc.xml
├── Aeon Door and Window Sensor DSB04100-ZWUS/
│ └── Aeon_Door_and_Window_Sensor-DSB04100-ZWUS.groovy
├── Aeon Doorbell/
│ ├── aeon-doorbell-v04.groovy
│ ├── device_type-aeon-doorbell-v0.1
│ ├── device_type-aeon-doorbell-v0.2
│ └── device_type-aeon-doorbell-v0.3
├── Aeon Garage Door/
│ └── device_type-aeon-garage-door-v0.1
├── Aeon Multisensor 6/
│ ├── device_type-aeon-multisensor6-v1.1
│ ├── device_type-aeon-multisensor6-v1.2
│ ├── device_type-aeon-multisensor6-v1.3
│ ├── device_type-aeon-multisensor6-v1.4
│ ├── device_type-aeon-multisensor6-v1.5
│ ├── device_type-aeon-multisensor6-v2.0
│ ├── device_type-aeon-multisensor6-v2.1
│ ├── device_type-aeon-multisensor6-v2.2
│ ├── device_type-aeon-multisensor6-v2.3
│ └── device_type-aeon-multisensor6-v2.3.1
├── Aeon SmartDimmer 6/
│ ├── device_type-aeon-smartdimmer6-v0.1
│ ├── device_type-aeon-smartdimmer6-v0.1-ANDROID
│ └── device_type-aeon-smartdimmer6-v0.2.groovy
├── Aeon SmartSwitch 6/
│ ├── device_type-aeon-smartswitch6-v0.1
│ ├── device_type-aeon-smartswitch6-v0.2
│ ├── device_type-aeon-smartswitch6-v0.4
│ └── device_type-aeon-smartswitch6-v0.4-ANDROID
├── GE Z-Wave Switch - Improved/
│ └── device_type-GE-Z-Wave-Switch-Improved
├── zooZ-4-in-1-Sensor-ZSE40/
│ ├── device_type-zooZ-4-in-1-Sensor-ZSE40_v1.2
│ └── device_type-zooZ-4-in-1-Sensor-ZSE40_v1.2_motion_primary
├── zooZ-Indoor-Siren-ZSE01/
│ ├── device_type-zooZ-indoor-siren-v1
│ ├── device_type-zooZ-indoor-siren-v1.1
│ └── device_type-zooZ-indoor-siren-v1.2
├── zooZ-MiniPlug-ZEN07/
│ ├── device_type-zooZ-4-in-1-Sensor-ZSE40_v1.2.groovy
│ ├── device_type-zooZ-MiniPlug-ZEN07-v1.1.groovy
│ ├── device_type-zooZ-MiniPlug-ZEN07-v1.2.groovy
│ ├── device_type-zooZ-MiniPlug-ZEN07-v1.3.groovy
│ └── device_type-zooZ-MiniPlug-ZEN07-v1.4.groovy
├── zooZ-Motion-Sensor-ZSE02/
│ ├── device_type-zooZ-Motion-Sensor-ZSE02_v1
│ ├── device_type-zooZ-Motion-Sensor-ZSE02_v1.1
│ └── device_type-zooZ-Motion-Sensor-ZSE02_v1.2
└── zooZ-Strip-ZEN20/
└── device_type-zooZ-strip-ZEN20_v1.0
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto
# Custom for Visual Studio
*.cs diff=csharp
# Standard to msysgit
*.doc diff=astextplain
*.DOC diff=astextplain
*.docx diff=astextplain
*.DOCX diff=astextplain
*.dot diff=astextplain
*.DOT diff=astextplain
*.pdf diff=astextplain
*.PDF diff=astextplain
*.rtf diff=astextplain
*.RTF diff=astextplain
================================================
FILE: .gitignore
================================================
Aeon Doorbell/device_type-aeon-doorbell-v0.4
zooZ-MiniPlug-ZEN07/device_type-zooZ-MiniPlug-ZEN07.groovy
================================================
FILE: .idea/misc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
================================================
FILE: Aeon Door and Window Sensor DSB04100-ZWUS/Aeon_Door_and_Window_Sensor-DSB04100-ZWUS.groovy
================================================
/**
* Copyright 2015 SmartThings and 2016 Robert Vandervoort
*
* 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.
*
* Aeon Labs DSB04100-ZWUS - Z-Wave Door & Window Sensor
*
* Author: SmartThings and Robert Vandervoort
* Date: 7-17-2016
*/
metadata {
definition (name: "Aeon Labs DSB04100-ZWUS - Z-Wave Door & Window Sensor - RV", namespace: "robertvandervoort", author: "Robert Vandervoort") {
capability "Contact Sensor"
capability "Tamper Alert"
capability "Sensor"
capability "Battery"
capability "Configuration"
// RAW ID 0 0 0x0701 0 0 0 f 0x5E 0x86 0x72 0x85 0x59 0x73 0x71 0x84 0x30 0x80 0x70 0x98 0x7A 0xEF 0x5A
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x85,0x59,0x73,0x71,0x84,0x30,0x80,0x70,0x98,0x7A,0xEF,0x5A"
}
simulator {
// status messages
status "open": "command: 2001, payload: FF"
status "closed": "command: 2001, payload: 00"
status "wake up": "command: 8407, payload: "
status "detected": "command: 7105, payload: 000000FF07030000"
status "clear": "command: 7105, payload: 000000FF07000000"
}
tiles {
standardTile("contact", "device.contact", width: 2, height: 2) {
state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821"
}
standardTile("tamper", "device.tamper", width: 2, height: 2) {
state "detected", label: '${currentValue}', icon: "st.motion.acceleration.active", backgroundColor: "#ff0000"
state "clear", label: '${currentValue}', icon: "st.motion.acceleration.inactive", backgroundColor: "#00ff00"
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""
}
main "contact"
details(["contact", "tamper", "battery"])
}
}
def parse(String description) {
def result = null
if (description.startsWith("Err 106")) {
if (state.sec) {
log.debug description
} else {
result = createEvent(
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, 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)
}
}
log.debug "parsed '$description' to $result"
return result
}
def updated() {
def cmds = []
if (!state.MSR) {
cmds = [
command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()),
"delay 1200",
zwave.wakeUpV1.wakeUpNoMoreInformation().format()
]
} else if (!state.lastbat) {
cmds = []
} else {
cmds = [zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
}
response(cmds)
}
def configure() {
commands([
zwave.manufacturerSpecificV2.manufacturerSpecificGet(),
zwave.batteryV1.batteryGet()
], 6000)
}
def sensorValueEvent(value) {
if (value) {
createEvent(name: "contact", value: "open", descriptionText: "$device.displayName is open")
} else {
createEvent(name: "contact", value: "closed", descriptionText: "$device.displayName is closed")
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
sensorValueEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd)
{
def result = []
if (cmd.notificationType == 0x07) {
if (cmd.event == 0x03) {
result << createEvent(name: "tamper", value: "detected", descriptionText: "$device.displayName was removed.", isStateChange: true)
if(!state.MSR) result << response(command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()))
} else if (cmd.event == 0x00) {
result << createEvent(name: "tamper", value: "clear", descriptionText: "$device.displayName was replaced.", isStateChange: true)
if(!state.MSR) result << response(command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()))
} else if (cmd.notificationType == 0x06 && cmd.event == 0x16) {
result << sensorValueEvent(1)
} else if (cmd.notificationType == 0x06 && cmd.event == 0x17) {
result << sensorValueEvent(0)
}
result
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
def event = createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)
def cmds = []
if (!state.MSR) {
cmds << command(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
cmds << "delay 1200"
}
if (!state.lastbat || now() - state.lastbat > 53*60*60*1000) {
cmds << command(zwave.batteryV1.batteryGet())
} else {
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
}
[event, response(cmds)]
}
def zwaveEvent(physicalgraph.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()
[createEvent(map), response(zwave.wakeUpV1.wakeUpNoMoreInformation())]
}
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
def result = []
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
log.debug "msr: $msr"
updateDataValue("MSR", msr)
result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x25: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1])
// log.debug "encapsulated: $encapsulatedCommand"
if (encapsulatedCommand) {
state.sec = 1
zwaveEvent(encapsulatedCommand)
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
createEvent(descriptionText: "$device.displayName: $cmd", displayed: false)
}
private command(physicalgraph.zwave.Command cmd) {
if (state.sec == 1) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=200) {
delayBetween(commands.collect{ command(it) }, delay)
}
================================================
FILE: Aeon Doorbell/aeon-doorbell-v04.groovy
================================================
/*
* V 0.4 of Aeon Doorbell code 10/4/2017
* 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.
*
* Changelog:
* v 0.1 - initial push of device type, ability to change ring tone, volume and number of rings, basic set reporting
* for use as a switch to trigger stuff, and ability to trigger as an alarm
* v 0.2 - added separate preference for alarm triggering so a different ringtone can be used for alarm VS doorbell. created
* separate test buttons for doorbell and alarm
* v 0.3 - added firmware version and checksum reporting as part of the config command, modifed the way the battery check works, may need to redress it later
* v 0.4 - added motion activation capability when doorbell or alerm is rung. you can use this to trigger smart home monitor by adding the doorbell as a motion
* sensor and have this trigger a siren or another doorbell's alrm tone for multi doorbell houses
*/
metadata {
definition (name: "Aeon Doorbell - RV v0.4", namespace: "robertvandervoort", author: "Robert Vandervoort") {
capability "Actuator"
capability "Alarm"
capability "Battery"
capability "Switch"
capability "Configuration"
capability "Refresh"
capability "Music Player"
capability "Motion Sensor"
command "atest"
command "btest"
command "getbatt"
command "setRingtone"
fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98"
}
// simulator metadata
simulator {
/*status "battery good": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
zwave.configurationV1.configurationReport(
parameterNumber: 42, configurationValue: 0
)
).incomingMessage()
status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
zwave.configurationV1.configurationReport(
parameterNumber: 42, configurationValue: 255
)
).incomingMessage()
*/
reply "9881002001FF,9881002002": "command: 9881, payload: 002003FF"
reply "988100200100,9881002002": "command: 9881, payload: 00200300"
reply "9881002001FF,delay 3000,988100200100,9881002002": "command: 9881, payload: 00200300"
}
// tile definitions
tiles (scale: 2) {
multiAttributeTile(name:"alarm", type:"generic", width:6, height:4, canChangeIcon: true, canChangeBackground: true) {
tileAttribute("device.alarm", key: "PRIMARY_CONTROL") {
attributeState "off", label:'OFF', action:'alarm.on', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff"
attributeState "on", label:'RINGING', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
}
}
standardTile("btest", "device.alarm", inactiveLabel: false, width: 2, height: 2) {
state "default", label:'bell', action:"btest", icon:"st.Electronics.electronics14"
}
standardTile("atest", "device.alarm", inactiveLabel: false, width: 2, height: 2) {
state "default", label:'alarm', action:"atest", icon:"st.Electronics.electronics14"
}
standardTile("off", "device.alarm", inactiveLabel: false, width: 2, height: 2) {
state "default", label:'', action:"off", icon:"st.secondary.off"
}
valueTile("battery", "device.battery", decoration: "flat", width: 2, height: 2) {
state "battery", label:'Battery', action:"getbatt", backgroundColors:[
[value: 0, color: "#FF0000"],
[value: 100, color: "#00FF00"]
]
}
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
valueTile("testSoundLabel", "device.battery", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
state "battery", label:'Test Sound:', unit:""
}
controlTile("testSoundSlider", "device.playTrack", "slider", width: 4, height: 2, inactiveLabel: false, range:"(1..99)") {
state "testSound", action:"playTrack", backgroundColor: "#1e9cbb"
}
standardTile("motion","device.motion", width: 2, height: 2) {
state "active",label:'motion',icon:"st.motion.motion.active",backgroundColor:"#53a7c0"
state "inactive",label:'no motion',icon:"st.motion.motion.inactive",backgroundColor:"#ffffff"
}
main "alarm"
details(["alarm","btest","atest","off","testSoundLabel","testSoundSlider","battery","setRingtone","setVolume","refresh","motion","configure"])
}
preferences {
input "debugOutput", "boolean",
title: "Enable debug logging?",
defaultValue: false,
displayDuringSetup: true
input "prefRingtone", "integer",
title: "Doorbell tone:",
description: "Pick the ringtone, 1-100",
defaultValue: 1,
range: "1..100",
required: false,
displayduringSetup: true
input "prefAlarmtone", "integer",
title: "Alarm tone:",
description: "Pick the alarm tone, 1-100",
defaultValue: 6,
range: "1..100",
required: false,
displayduringSetup: true
input "prefVolume", "integer",
title: "Doorbell volume:",
description: "Set the volume of the doorbell",
defaultValue: 10,
range: "0..10",
required: false,
displayduringSetup: true
input "prefNumrings", "integer",
title: "Ring repetitions:",
description: "How many times to ring per push of the doorbell",
defaultValue: 1,
range: "1..100",
required: false,
displayduringSetup: true
input "motionEnabled", "boolean",
title: "Motion event on ring?",
description: "Generate motion for triggering other doorbells or alarm",
defaultValue: false,
required: false,
displayduringSetup: true
}
}
def updated()
{
state.debug = ("true" == debugOutput)
if (state.sec && !isConfigured()) {
// in case we miss the SCSR
response(configure())
}
}
def parse(String description)
{
def result = null
if (description.startsWith("Err 106")) {
state.sec = 0
result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true,
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.")
} else if (description != "updated") {
def cmd = zwave.parse(description, [0x25: 1, 0x26: 1, 0x27: 1, 0x32: 3, 0x33: 3, 0x59: 1, 0x70: 1, 0x72: 2, 0x73: 1, 0x7A: 2, 0x82: 1, 0x85: 2, 0x86: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x25: 1, 0x26: 1, 0x27: 1, 0x32: 3, 0x33: 3, 0x59: 1, 0x70: 1, 0x72: 2, 0x73: 1, 0x7A: 2, 0x82: 1, 0x85: 2, 0x86: 1])
state.sec = 1
// if (state.debug) log.debug "encapsulated: ${encapsulatedCommand}"
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
response(configure())
}
def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) {
if (state.debug) log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}"
def request = [
physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet()
]
response(commands(request))
}
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionCommandClassReport cmd) {
if (state.debug) log.debug "---COMMAND CLASS VERSION REPORT V1--- ${device.displayName} has command class version: ${cmd.commandClassVersion} - payload: ${cmd.payload}"
}
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
def fw = "${cmd.applicationVersion}.${cmd.applicationSubVersion}"
updateDataValue("fw", fw)
if (state.debug) log.debug "---VERSION REPORT V1--- ${device.displayName} is running firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}"
}
def zwaveEvent(physicalgraph.zwave.commands.firmwareupdatemdv2.FirmwareMdReport cmd) {
if (state.debug) log.debug "---FIRMWARE MD REPORT V2--- ${device.displayName} has Checksum of ${cmd.checksum} firmwareId: ${cmd.firmwareId}, manufacturerId: ${cmd.firmwareId}"
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) {
if (state.debug) log.debug "---CONFIGURATION REPORT V2--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
if (state.debug) log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
def map = [ name: "battery", value: 100]
if (cmd.parameterNumber == 42) {
if (cmd.configurationValue == [255]) {
map.value = 0
map.descriptionText = "${device.displayName} remote battery is low"
if (state.debug) log.debug "${device.displayName} remote battery is low"
map.isStateChange = true
} else {
map.value = 100
map.descriptionText = "${device.displayName} remote battery is good"
if (state.debug) log.debug "${device.displayName} remote battery is good"
map.isStateChange = true
}
}
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) {
cmd.nodeId.each({log.debug "AssociationReport: '${cmd}', hub: '$zwaveHubNodeId' reports nodeId: '$it' is associated in group: '${cmd.groupingIdentifier}'"})
}
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
if (state.debug) log.debug "Hail received: ${cmd}"
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
if (state.debug) log.debug "doorbell value:${cmd.value}";
sendEvent(name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true, descriptiontext: "doorbell");
sendEvent(name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true);
if (motionEnabled == "true") {
if (cmd.value == 255) {
sendEvent(name: "motion", value: "active", displayed: true, isStateChange: true)
} else {
sendEvent(name: "motion", value: "inactive", displayed: true, isStateChange: true)
}
}
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
if (state.debug) log.debug cmd
createEvent(name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true)
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
if (state.debug) log.debug cmd
createEvent(name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true)
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd) {
if (state.debug) log.debug cmd
createEvent(name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true)
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
if (state.debug) log.debug "Unhandled: $cmd sent to ${device.displayName}"
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
def getbatt() {
if (state.debug) log.debug "Getting battery level for remote control on ${device.displayName}"
def request = [
zwave.configurationV1.configurationGet(parameterNumber: 42)
]
commands(request)
}
def btest() {
if (state.debug) log.debug "Testing doorbell ring ${prefRingtone} on ${device.displayName}"
on()
}
def atest() {
if (state.debug) log.debug "Testing alarm sound ${prefAlarmtone} on ${device.displayName}"
both()
}
def playTrack(track) {
disableNotifications()
def request = [
zwave.configurationV1.configurationSet(parameterNumber: 6, size: 1, scaledConfigurationValue: track.toInteger())
]
commands(request)
}
def disableNotifications() {
state.notification = false
}
def setRingtone(track) {
def request = [
zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: track)
]
commands(request)
}
def strobe() {
if (state.debug) log.debug "Strobe command received"
on()
}
def siren() {
if (state.debug) log.debug "Siren command received"
on()
}
def both() {
if (state.debug) log.debug "Alarm test command received"
def request = [
zwave.configurationV1.configurationSet(parameterNumber: 6, size: 1, scaledConfigurationValue: prefAlarmtone.toInteger())
]
commands(request)
}
def on() {
if (state.debug) log.debug "Ringing ${device.displayName}"
def request = [
zwave.basicV1.basicSet(value: 0xFF)
]
commands(request)
if (state.notification) {
sendEvent(name: "switch", value: "on", type: "physical", displayed: true, isStateChange: true)
if (state.debug) log.debug "${device.displayName} has been rung from button."
} else {
if (state.debug) log.debug "${device.displayName} has been rung from playTrack."
}
}
def off() {
if (state.debug) log.debug "turning off ${device.displayName}"
def request = [
zwave.basicV1.basicSet(value: 0x00),
zwave.basicV1.basicGet()
]
commands(request)
if (state.notification) sendEvent(name: "switch", value: "off", type: "physical", displayed: true, isStateChange: true)
state.notification = true
}
def refresh() {
if (state.debug) log.debug "refresh request sent to ${device.displayName}"
def request = [
zwave.basicV1.basicGet(),
zwave.switchBinaryV1.switchBinaryGet()
]
commands(request)
}
def configure() {
if (state.debug) {
log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}"
if (state.sec) {
log.debug "secure configuration being sent to ${device.displayName}"
}
else
if (state.debug) log.debug "configuration being sent to ${device.displayName}"
}
if (!state.prefRingtone) state.prefRingtone = 1
if (!state.prefAlarmtone) state.prefAlarmtone = 6
if (!state.prefVolume) state.prefVolume = 10
if (!state.prefNumrings) state.prefNumrings = 1
log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}"
def request = [
//associate with group 1 and remove any group 2 association
//zwave.associationV1.associationRemove(groupingIdentifier:2, nodeId:zwaveHubNodeId),
//zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId),
zwave.associationV1.associationGet(groupingIdentifier:1),
zwave.associationV1.associationGet(groupingIdentifier:2),
// Get Version information
zwave.versionV1.versionGet(),
zwave.firmwareUpdateMdV2.firmwareMdGet(),
// Enable to send notifications to associated devices (Group 1) (0=nothing, 1=hail CC, 2=basic CC report)
zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, scaledConfigurationValue: 2),
zwave.configurationV1.configurationGet(parameterNumber: 80),
// send low battery notifications
zwave.configurationV1.configurationSet(parameterNumber: 81, size: 1, scaledConfigurationValue: 1),
zwave.configurationV1.configurationGet(parameterNumber: 81),
// Set the repetitions for playing doorbell ringtone
zwave.configurationV1.configurationSet(parameterNumber: 2, size: 1, scaledConfigurationValue: prefNumrings.toInteger()),
zwave.configurationV1.configurationGet(parameterNumber: 2),
// Set the default doorbell ringtone
zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: prefRingtone.toInteger()),
zwave.configurationV1.configurationGet(parameterNumber: 5),
// Set the volume of ringtone
zwave.configurationV1.configurationSet(parameterNumber: 8, size: 1, scaledConfigurationValue: prefVolume.toInteger()),
zwave.configurationV1.configurationGet(parameterNumber: 8),
// define +- button function
zwave.configurationV1.configurationSet(parameterNumber: 10, size: 1, scaledConfigurationValue: 0),
zwave.configurationV1.configurationGet(parameterNumber: 10),
zwave.configurationV1.configurationSet(parameterNumber: 11, size: 1, scaledConfigurationValue: 0),
zwave.configurationV1.configurationGet(parameterNumber: 11),
// Get last known remote battery health
zwave.configurationV1.configurationGet(parameterNumber: 42)
]
commands(request)
}
private setConfigured() {
updateDataValue("configured", "true")
}
private isConfigured() {
getDataValue("configured") == "true"
}
private command(physicalgraph.zwave.Command cmd) {
if (state.sec) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=500) {
delayBetween(commands.collect{ command(it) }, delay)
}
================================================
FILE: Aeon Doorbell/device_type-aeon-doorbell-v0.1
================================================
/*
* V 0.1 of Aeon Doorbell code 11/24/2015
* 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.
*
*/
metadata {
definition (name: "Aeon Doorbell - RV v0.1", namespace: "robertvandervoort", author: "Robert Vandervoort") {
capability "Actuator"
capability "Alarm"
capability "Switch"
capability "Configuration"
capability "Refresh"
command "test"
fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98"
}
// simulator metadata
simulator {
for (int i in [0, 5, 10, 15, 50, 99, 100]) {
status "battery ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: i
)
).incomingMessage()
}
status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: 255
)
).incomingMessage()
reply "9881002001FF,9881002002": "command: 9881, payload: 002003FF"
reply "988100200100,9881002002": "command: 9881, payload: 00200300"
reply "9881002001FF,delay 3000,988100200100,9881002002": "command: 9881, payload: 00200300"
}
// tile definitions
tiles (scale: 2) {
multiAttributeTile(name:"alarm", type:"generic", width:6, height:4, canChangeIcon: true) {
tileAttribute("device.alarm", key: "PRIMARY_CONTROL") {
attributeState "off", label:'off', action:'alarm.siren', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff"
attributeState "on", label:'alarm!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
}
}
standardTile("test", "device.alarm", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'', action:"test", icon:"st.secondary.test"
}
standardTile("off", "device.alarm", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'', action:"off", icon:"st.secondary.off"
}
valueTile("battery", "device.battery", decoration: "flat", width: 2, height: 2) {
state "battery", label:'${currentValue}% battery', unit:""
}
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
main "alarm"
details(["alarm","test","off","battery","setRingtone","setVolume","refresh","configure"])
}
preferences {
input "debugOutput", "boolean",
title: "Enable debug logging?",
defaultValue: false,
displayDuringSetup: true
input "prefRingtone", "integer",
title: "Doorbell tone:",
description: "Pick the ringtone, 1-100",
defaultValue: 1,
range: "1..100",
required: false,
displayduringSetup: true
input "prefVolume", "integer",
title: "Doorbell volume:",
description: "Set the volume of the doorbell",
defaultValue: 10,
range: "1..10",
required: false,
displayduringSetup: true
input "prefNumrings", "integer",
title: "Ring repetitions:",
description: "How many times to ring per push of the doorbell",
defaultValue: 1,
range: "1..100",
required: false,
displayduringSetup: true
}
}
def updated()
{
state.debug = ("true" == debugOutput)
if (state.sec && !isConfigured()) {
// in case we miss the SCSR
response(configure())
}
}
def parse(String description)
{
def result = null
if (description.startsWith("Err 106")) {
state.sec = 0
result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true,
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.")
} else if (description != "updated") {
def cmd = zwave.parse(description, [0x25: 1, 0x26: 1, 0x27: 1, 0x32: 3, 0x33: 3, 0x59: 1, 0x70: 1, 0x72: 2, 0x73: 1, 0x82: 1, 0x85: 2, 0x86: 2])
if (cmd) {
result = zwaveEvent(cmd)
}
}
// if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x25: 1, 0x26: 1, 0x27: 1, 0x32: 3, 0x33: 3, 0x59: 1, 0x70: 1, 0x72: 2, 0x73: 1, 0x82: 1, 0x85: 2, 0x86: 2])
state.sec = 1
if (state.debug) log.debug "encapsulated: ${encapsulatedCommand}"
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
response(configure())
}
def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) {
if (state.debug) log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}"
def request = [
physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet()
]
response(commands(request))
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) {
if (state.debug) log.debug "---CONFIGURATION REPORT V2--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
if (state.debug) log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}
def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) {
cmd.nodeId.each({log.debug "AssociationReport: '${cmd}', hub: '$zwaveHubNodeId' reports nodeId: '$it' is associated in group: '${cmd.groupingIdentifier}'"})
[:]
}
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
if (state.debug) log.debug "Hail received: ${cmd}"
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
if (state.debug) log.debug "doorbell value:${cmd.value}"
[
createEvent([name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]),
createEvent([name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true])
]
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
if (state.debug) log.debug cmd
[name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
if (state.debug) log.debug cmd
[name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd)
{
if (state.debug) log.debug cmd
[name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
if (state.debug) log.debug "Unhandled: $cmd sent to ${device.displayName}"
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
def test() {
if (state.debug) log.debug "Ringing ${device.displayName}"
def request = [
zwave.basicV1.basicSet(value: 0xFF),
zwave.basicV1.basicGet()
]
commands(request)
}
def strobe() {
if (state.debug) log.debug "Strobe command received"
on()
}
def siren() {
if (state.debug) log.debug "Siren command received"
on()
}
def both() {
if (state.debug) log.debug "Both command received"
on()
}
def on() {
if (state.debug) log.debug "Ringing ${device.displayName}"
def request = [
zwave.basicV1.basicSet(value: 0xFF),
zwave.basicV1.basicGet()
]
commands(request)
}
def off() {
if (state.debug) log.debug "turning off ${device.displayName}"
def request = [
zwave.basicV1.basicSet(value: 0x00),
zwave.basicV1.basicGet()
]
commands(request)
}
def refresh() {
if (state.debug) log.debug "refresh request sent to ${device.displayName}"
def request = [
zwave.basicV1.basicGet(),
zwave.switchBinaryV1.switchBinaryGet()
]
commands(request)
}
def configure() {
if (state.debug) {
if (state.sec) {
log.debug "secure configuration being sent to ${device.displayName}"
}
else
if (state.debug) log.debug "configuration being sent to ${device.displayName}"
}
if (!state.prefRingtone) state.prefRingtone = 1
if (!state.prefVolume) state.prefVolume = 10
if (!state.prefNumrings) state.prefNumrings = 1
log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}"
def request = [
//associate with group 1 and remove any group 2 association
zwave.associationV1.associationRemove(groupingIdentifier:2, nodeId:zwaveHubNodeId),
zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId),
zwave.associationV1.associationGet(groupingIdentifier:1),
zwave.associationV1.associationGet(groupingIdentifier:2),
// Enable to send notifications to associated devices (Group 1) (0=nothing, 1=hail CC, 2=basic CC report)
zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, scaledConfigurationValue: 2),
zwave.configurationV1.configurationGet(parameterNumber: 80),
// send low battery notifications
zwave.configurationV1.configurationSet(parameterNumber: 81, size: 1, scaledConfigurationValue: 1),
zwave.configurationV1.configurationGet(parameterNumber: 81),
// Set the repetitions for playing doorbell ringtone
zwave.configurationV1.configurationSet(parameterNumber: 2, size: 1, scaledConfigurationValue: prefNumrings.toInteger()),
zwave.configurationV1.configurationGet(parameterNumber: 2),
// Set the default doorbell ringtone
zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: prefRingtone.toInteger()),
zwave.configurationV1.configurationGet(parameterNumber: 5),
// Set the volume of ringtone
zwave.configurationV1.configurationSet(parameterNumber: 8, size: 1, scaledConfigurationValue: prefVolume.toInteger()),
zwave.configurationV1.configurationGet(parameterNumber: 8),
// define +- button function
zwave.configurationV1.configurationSet(parameterNumber: 10, size: 1, scaledConfigurationValue: 0),
zwave.configurationV1.configurationGet(parameterNumber: 10),
zwave.configurationV1.configurationSet(parameterNumber: 11, size: 1, scaledConfigurationValue: 0),
zwave.configurationV1.configurationGet(parameterNumber: 11)
]
commands(request)
}
private setConfigured() {
updateDataValue("configured", "true")
}
private isConfigured() {
getDataValue("configured") == "true"
}
private command(physicalgraph.zwave.Command cmd) {
if (state.sec) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=500) {
delayBetween(commands.collect{ command(it) }, delay)
}
================================================
FILE: Aeon Doorbell/device_type-aeon-doorbell-v0.2
================================================
/*
* V 0.2 of Aeon Doorbell code 11/24/2015
* 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.
*
* Changelog:
* v 0.1 - initial push of device type, ability to change ring tone, volume and number of rings, basic set reporting
* for use as a switch to trigger stuff, and ability to trigger as an alarm
* v 0.2 - added separate preference for alarm triggering so a different ringtone can be used for alarm VS doorbell. created
* separate test buttons for doorbell and alarm, battery tile now gets last known remote battery state and displays red or green for bad / good
*/
metadata {
definition (name: "Aeon Doorbell - RV v0.2", namespace: "robertvandervoort", author: "Robert Vandervoort") {
capability "Actuator"
capability "Alarm"
capability "Battery"
capability "Switch"
capability "Configuration"
capability "Refresh"
command "atest"
command "btest"
command "getbatt"
fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98"
}
// simulator metadata
simulator {
/*status "battery good": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
zwave.configurationV1.configurationReport(
parameterNumber: 42, configurationValue: 0
)
).incomingMessage()
status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
zwave.configurationV1.configurationReport(
parameterNumber: 42, configurationValue: 255
)
).incomingMessage()
*/
reply "9881002001FF,9881002002": "command: 9881, payload: 002003FF"
reply "988100200100,9881002002": "command: 9881, payload: 00200300"
reply "9881002001FF,delay 3000,988100200100,9881002002": "command: 9881, payload: 00200300"
}
// tile definitions
tiles (scale: 2) {
multiAttributeTile(name:"alarm", type:"generic", width:6, height:4, canChangeIcon: true, canChangeBackground: true) {
tileAttribute("device.alarm", key: "PRIMARY_CONTROL") {
attributeState "off", label:'OFF', action:'alarm.on', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff"
attributeState "on", label:'RINGING', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
}
}
standardTile("btest", "device.alarm", inactiveLabel: false, width: 2, height: 2) {
state "default", label:'bell', action:"btest", icon:"st.Electronics.electronics14"
}
standardTile("atest", "device.alarm", inactiveLabel: false, width: 2, height: 2) {
state "default", label:'alarm', action:"atest", icon:"st.Electronics.electronics14"
}
standardTile("off", "device.alarm", inactiveLabel: false, width: 2, height: 2) {
state "default", label:'', action:"off", icon:"st.secondary.off"
}
valueTile("battery", "device.battery", decoration: "flat", width: 2, height: 2) {
state "battery", label:'Battery', action:"getbatt", backgroundColors:[
[value: 0, color: "#FF0000"],
[value: 100, color: "#00FF00"]
]
}
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
main "alarm"
details(["alarm","btest","atest","off","battery","setRingtone","setVolume","refresh","configure"])
}
preferences {
input "debugOutput", "boolean",
title: "Enable debug logging?",
defaultValue: false,
displayDuringSetup: true
input "prefRingtone", "integer",
title: "Doorbell tone:",
description: "Pick the ringtone, 1-100",
defaultValue: 1,
range: "1..100",
required: false,
displayduringSetup: true
input "prefAlarmtone", "integer",
title: "Alarm tone:",
description: "Pick the alarm tone, 1-100",
defaultValue: 6,
range: "1..100",
required: false,
displayduringSetup: true
input "prefVolume", "integer",
title: "Doorbell volume:",
description: "Set the volume of the doorbell",
defaultValue: 10,
range: "1..10",
required: false,
displayduringSetup: true
input "prefNumrings", "integer",
title: "Ring repetitions:",
description: "How many times to ring per push of the doorbell",
defaultValue: 1,
range: "1..100",
required: false,
displayduringSetup: true
}
}
def updated()
{
state.debug = ("true" == debugOutput)
if (state.sec && !isConfigured()) {
// in case we miss the SCSR
response(configure())
}
}
def parse(String description)
{
def result = null
if (description.startsWith("Err 106")) {
state.sec = 0
result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true,
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.")
} else if (description != "updated") {
def cmd = zwave.parse(description, [0x25: 1, 0x26: 1, 0x27: 1, 0x32: 3, 0x33: 3, 0x59: 1, 0x70: 1, 0x72: 2, 0x73: 1, 0x82: 1, 0x85: 2, 0x86: 2])
if (cmd) {
result = zwaveEvent(cmd)
}
}
// if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x25: 1, 0x26: 1, 0x27: 1, 0x32: 3, 0x33: 3, 0x59: 1, 0x70: 1, 0x72: 2, 0x73: 1, 0x82: 1, 0x85: 2, 0x86: 2])
state.sec = 1
if (state.debug) log.debug "encapsulated: ${encapsulatedCommand}"
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
response(configure())
}
def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) {
if (state.debug) log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}"
def request = [
physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet()
]
response(commands(request))
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) {
if (state.debug) log.debug "---CONFIGURATION REPORT V2--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
if (state.debug) log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
def map = [ name: "battery"]
if (cmd.parameterNumber == 42 && cmd.configurationValue == 0xFF) {
map.value = 0
map.descriptionText = "${device.displayName} remote battery is low"
if (state.debug) log.debug "${device.displayName} remote battery is low"
map.isStateChange = true
} else {
map.value = 100
map.descriptionText = "${device.displayName} remote battery is good"
if (state.debug) log.debug "${device.displayName} remote battery is good"
map.isStateChange = true
}
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) {
cmd.nodeId.each({log.debug "AssociationReport: '${cmd}', hub: '$zwaveHubNodeId' reports nodeId: '$it' is associated in group: '${cmd.groupingIdentifier}'"})
[:]
}
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
if (state.debug) log.debug "Hail received: ${cmd}"
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
if (state.debug) log.debug "doorbell value:${cmd.value}"
[
createEvent([name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]),
createEvent([name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true])
]
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
if (state.debug) log.debug cmd
[name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
if (state.debug) log.debug cmd
[name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd)
{
if (state.debug) log.debug cmd
[name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
if (state.debug) log.debug "Unhandled: $cmd sent to ${device.displayName}"
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
def getbatt() {
if (state.debug) log.debug "Getting battery level for remote control on ${device.displayName}"
def request = [
zwave.configurationV1.configurationGet(parameterNumber: 42)
]
commands(request)
}
def btest() {
if (state.debug) log.debug "Testing doorbell ring ${prefRingtone} on ${device.displayName}"
on()
}
def atest() {
if (state.debug) log.debug "Testing alarm sound ${prefAlarmtone} on ${device.displayName}"
both()
}
def strobe() {
if (state.debug) log.debug "Strobe command received"
on()
}
def siren() {
if (state.debug) log.debug "Siren command received"
on()
}
def both() {
if (state.debug) log.debug "Alarm test command received"
def request = [
zwave.configurationV1.configurationSet(parameterNumber: 6, size: 1, scaledConfigurationValue: prefAlarmtone.toInteger())
]
commands(request)
}
def on() {
if (state.debug) log.debug "Ringing ${device.displayName}"
def request = [
zwave.basicV1.basicSet(value: 0xFF)
]
commands(request)
}
def off() {
if (state.debug) log.debug "turning off ${device.displayName}"
def request = [
zwave.basicV1.basicSet(value: 0x00),
zwave.basicV1.basicGet()
]
commands(request)
}
def refresh() {
if (state.debug) log.debug "refresh request sent to ${device.displayName}"
def request = [
zwave.basicV1.basicGet(),
zwave.switchBinaryV1.switchBinaryGet()
]
commands(request)
}
def configure() {
if (state.debug) {
if (state.sec) {
log.debug "secure configuration being sent to ${device.displayName}"
}
else
if (state.debug) log.debug "configuration being sent to ${device.displayName}"
}
if (!state.prefRingtone) state.prefRingtone = 1
if (!state.prefRingtone) state.prefAlarmtone = 1
if (!state.prefVolume) state.prefVolume = 10
if (!state.prefNumrings) state.prefNumrings = 1
log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}"
def request = [
//associate with group 1 and remove any group 2 association
//zwave.associationV1.associationRemove(groupingIdentifier:2, nodeId:zwaveHubNodeId),
//zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId),
zwave.associationV1.associationGet(groupingIdentifier:1),
zwave.associationV1.associationGet(groupingIdentifier:2),
// Enable to send notifications to associated devices (Group 1) (0=nothing, 1=hail CC, 2=basic CC report)
zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, scaledConfigurationValue: 2),
zwave.configurationV1.configurationGet(parameterNumber: 80),
// send low battery notifications
zwave.configurationV1.configurationSet(parameterNumber: 81, size: 1, scaledConfigurationValue: 1),
zwave.configurationV1.configurationGet(parameterNumber: 81),
// Set the repetitions for playing doorbell ringtone
zwave.configurationV1.configurationSet(parameterNumber: 2, size: 1, scaledConfigurationValue: prefNumrings.toInteger()),
zwave.configurationV1.configurationGet(parameterNumber: 2),
// Set the default doorbell ringtone
zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: prefRingtone.toInteger()),
zwave.configurationV1.configurationGet(parameterNumber: 5),
// Set the volume of ringtone
zwave.configurationV1.configurationSet(parameterNumber: 8, size: 1, scaledConfigurationValue: prefVolume.toInteger()),
zwave.configurationV1.configurationGet(parameterNumber: 8),
// define +- button function
zwave.configurationV1.configurationSet(parameterNumber: 10, size: 1, scaledConfigurationValue: 0),
zwave.configurationV1.configurationGet(parameterNumber: 10),
zwave.configurationV1.configurationSet(parameterNumber: 11, size: 1, scaledConfigurationValue: 0),
zwave.configurationV1.configurationGet(parameterNumber: 11)
]
commands(request)
}
private setConfigured() {
updateDataValue("configured", "true")
}
private isConfigured() {
getDataValue("configured") == "true"
}
private command(physicalgraph.zwave.Command cmd) {
if (state.sec) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=500) {
delayBetween(commands.collect{ command(it) }, delay)
}
================================================
FILE: Aeon Doorbell/device_type-aeon-doorbell-v0.3
================================================
/*
* V 0.3 of Aeon Doorbell code 11/24/2015
* 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.
*
* Changelog:
* v 0.1 - initial push of device type, ability to change ring tone, volume and number of rings, basic set reporting
* for use as a switch to trigger stuff, and ability to trigger as an alarm
* v 0.2 - added separate preference for alarm triggering so a different ringtone can be used for alarm VS doorbell. created
* separate test buttons for doorbell and alarm
* v 0.3 - added firmware version and checksum reporting as part of the config command, modifed the way the battery check works, may need to redress it later
*/
metadata {
definition (name: "Aeon Doorbell - RV v0.3", namespace: "robertvandervoort", author: "Robert Vandervoort") {
capability "Actuator"
capability "Alarm"
capability "Battery"
capability "Switch"
capability "Configuration"
capability "Refresh"
command "atest"
command "btest"
command "getbatt"
fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98"
}
// simulator metadata
simulator {
/*status "battery good": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
zwave.configurationV1.configurationReport(
parameterNumber: 42, configurationValue: 0
)
).incomingMessage()
status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
zwave.configurationV1.configurationReport(
parameterNumber: 42, configurationValue: 255
)
).incomingMessage()
*/
reply "9881002001FF,9881002002": "command: 9881, payload: 002003FF"
reply "988100200100,9881002002": "command: 9881, payload: 00200300"
reply "9881002001FF,delay 3000,988100200100,9881002002": "command: 9881, payload: 00200300"
}
// tile definitions
tiles (scale: 2) {
multiAttributeTile(name:"alarm", type:"generic", width:6, height:4, canChangeIcon: true, canChangeBackground: true) {
tileAttribute("device.alarm", key: "PRIMARY_CONTROL") {
attributeState "off", label:'OFF', action:'alarm.on', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff"
attributeState "on", label:'RINGING', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13"
}
}
standardTile("btest", "device.alarm", inactiveLabel: false, width: 2, height: 2) {
state "default", label:'bell', action:"btest", icon:"st.Electronics.electronics14"
}
standardTile("atest", "device.alarm", inactiveLabel: false, width: 2, height: 2) {
state "default", label:'alarm', action:"atest", icon:"st.Electronics.electronics14"
}
standardTile("off", "device.alarm", inactiveLabel: false, width: 2, height: 2) {
state "default", label:'', action:"off", icon:"st.secondary.off"
}
valueTile("battery", "device.battery", decoration: "flat", width: 2, height: 2) {
state "battery", label:'Battery', action:"getbatt", backgroundColors:[
[value: 0, color: "#FF0000"],
[value: 100, color: "#00FF00"]
]
}
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
main "alarm"
details(["alarm","btest","atest","off","battery","setRingtone","setVolume","refresh","configure"])
}
preferences {
input "debugOutput", "boolean",
title: "Enable debug logging?",
defaultValue: false,
displayDuringSetup: true
input "prefRingtone", "integer",
title: "Doorbell tone:",
description: "Pick the ringtone, 1-100",
defaultValue: 1,
range: "1..100",
required: false,
displayduringSetup: true
input "prefAlarmtone", "integer",
title: "Alarm tone:",
description: "Pick the alarm tone, 1-100",
defaultValue: 6,
range: "1..100",
required: false,
displayduringSetup: true
input "prefVolume", "integer",
title: "Doorbell volume:",
description: "Set the volume of the doorbell",
defaultValue: 10,
range: "1..10",
required: false,
displayduringSetup: true
input "prefNumrings", "integer",
title: "Ring repetitions:",
description: "How many times to ring per push of the doorbell",
defaultValue: 1,
range: "1..100",
required: false,
displayduringSetup: true
}
}
def updated()
{
state.debug = ("true" == debugOutput)
if (state.sec && !isConfigured()) {
// in case we miss the SCSR
response(configure())
}
}
def parse(String description)
{
def result = null
if (description.startsWith("Err 106")) {
state.sec = 0
result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true,
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.")
} else if (description != "updated") {
def cmd = zwave.parse(description, [0x25: 1, 0x26: 1, 0x27: 1, 0x32: 3, 0x33: 3, 0x59: 1, 0x70: 1, 0x72: 2, 0x73: 1, 0x7A: 2, 0x82: 1, 0x85: 2, 0x86: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
// if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x25: 1, 0x26: 1, 0x27: 1, 0x32: 3, 0x33: 3, 0x59: 1, 0x70: 1, 0x72: 2, 0x73: 1, 0x7A: 2, 0x82: 1, 0x85: 2, 0x86: 1])
state.sec = 1
// if (state.debug) log.debug "encapsulated: ${encapsulatedCommand}"
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
response(configure())
}
def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) {
if (state.debug) log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}"
def request = [
physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet()
]
response(commands(request))
}
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionCommandClassReport cmd) {
if (state.debug) log.debug "---COMMAND CLASS VERSION REPORT V1--- ${device.displayName} has command class version: ${cmd.commandClassVersion} - payload: ${cmd.payload}"
}
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
def fw = "${cmd.applicationVersion}.${cmd.applicationSubVersion}"
updateDataValue("fw", fw)
if (state.debug) log.debug "---VERSION REPORT V1--- ${device.displayName} is running firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}"
}
def zwaveEvent(physicalgraph.zwave.commands.firmwareupdatemdv2.FirmwareMdReport cmd) {
if (state.debug) log.debug "---FIRMWARE MD REPORT V2--- ${device.displayName} has Checksum of ${cmd.checksum} firmwareId: ${cmd.firmwareId}, manufacturerId: ${cmd.firmwareId}"
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) {
if (state.debug) log.debug "---CONFIGURATION REPORT V2--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
if (state.debug) log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
def map = [ name: "battery"]
if (cmd.parameterNumber == 42) {
if (cmd.configurationValue == [255]) {
map.value = 0
map.descriptionText = "${device.displayName} remote battery is low"
if (state.debug) log.debug "${device.displayName} remote battery is low"
map.isStateChange = true
} else {
map.value = 100
map.descriptionText = "${device.displayName} remote battery is good"
if (state.debug) log.debug "${device.displayName} remote battery is good"
map.isStateChange = true
}
}
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) {
cmd.nodeId.each({log.debug "AssociationReport: '${cmd}', hub: '$zwaveHubNodeId' reports nodeId: '$it' is associated in group: '${cmd.groupingIdentifier}'"})
}
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
if (state.debug) log.debug "Hail received: ${cmd}"
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
if (state.debug) log.debug "doorbell value:${cmd.value}"
[
createEvent([name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]),
createEvent([name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true])
]
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
if (state.debug) log.debug cmd
[name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
if (state.debug) log.debug cmd
[name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd)
{
if (state.debug) log.debug cmd
[name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
if (state.debug) log.debug "Unhandled: $cmd sent to ${device.displayName}"
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
def getbatt() {
if (state.debug) log.debug "Getting battery level for remote control on ${device.displayName}"
def request = [
zwave.configurationV1.configurationGet(parameterNumber: 42)
]
commands(request)
}
def btest() {
if (state.debug) log.debug "Testing doorbell ring ${prefRingtone} on ${device.displayName}"
on()
}
def atest() {
if (state.debug) log.debug "Testing alarm sound ${prefAlarmtone} on ${device.displayName}"
both()
}
def strobe() {
if (state.debug) log.debug "Strobe command received"
on()
}
def siren() {
if (state.debug) log.debug "Siren command received"
on()
}
def both() {
if (state.debug) log.debug "Alarm test command received"
def request = [
zwave.configurationV1.configurationSet(parameterNumber: 6, size: 1, scaledConfigurationValue: prefAlarmtone.toInteger())
]
commands(request)
}
def on() {
if (state.debug) log.debug "Ringing ${device.displayName}"
def request = [
zwave.basicV1.basicSet(value: 0xFF)
]
commands(request)
}
def off() {
if (state.debug) log.debug "turning off ${device.displayName}"
def request = [
zwave.basicV1.basicSet(value: 0x00),
zwave.basicV1.basicGet()
]
commands(request)
}
def refresh() {
if (state.debug) log.debug "refresh request sent to ${device.displayName}"
def request = [
zwave.basicV1.basicGet(),
zwave.switchBinaryV1.switchBinaryGet()
]
commands(request)
}
def configure() {
if (state.debug) {
if (state.sec) {
log.debug "secure configuration being sent to ${device.displayName}"
}
else
if (state.debug) log.debug "configuration being sent to ${device.displayName}"
}
if (!state.prefRingtone) state.prefRingtone = 1
if (!state.prefRingtone) state.prefAlarmtone = 1
if (!state.prefVolume) state.prefVolume = 10
if (!state.prefNumrings) state.prefNumrings = 1
log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}"
def request = [
//associate with group 1 and remove any group 2 association
//zwave.associationV1.associationRemove(groupingIdentifier:2, nodeId:zwaveHubNodeId),
//zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId),
zwave.associationV1.associationGet(groupingIdentifier:1),
zwave.associationV1.associationGet(groupingIdentifier:2),
// Get Version information
zwave.versionV1.versionGet(),
zwave.firmwareUpdateMdV2.firmwareMdGet(),
// Enable to send notifications to associated devices (Group 1) (0=nothing, 1=hail CC, 2=basic CC report)
zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, scaledConfigurationValue: 2),
zwave.configurationV1.configurationGet(parameterNumber: 80),
// send low battery notifications
zwave.configurationV1.configurationSet(parameterNumber: 81, size: 1, scaledConfigurationValue: 1),
zwave.configurationV1.configurationGet(parameterNumber: 81),
// Set the repetitions for playing doorbell ringtone
zwave.configurationV1.configurationSet(parameterNumber: 2, size: 1, scaledConfigurationValue: prefNumrings.toInteger()),
zwave.configurationV1.configurationGet(parameterNumber: 2),
// Set the default doorbell ringtone
zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: prefRingtone.toInteger()),
zwave.configurationV1.configurationGet(parameterNumber: 5),
// Set the volume of ringtone
zwave.configurationV1.configurationSet(parameterNumber: 8, size: 1, scaledConfigurationValue: prefVolume.toInteger()),
zwave.configurationV1.configurationGet(parameterNumber: 8),
// define +- button function
zwave.configurationV1.configurationSet(parameterNumber: 10, size: 1, scaledConfigurationValue: 0),
zwave.configurationV1.configurationGet(parameterNumber: 10),
zwave.configurationV1.configurationSet(parameterNumber: 11, size: 1, scaledConfigurationValue: 0),
zwave.configurationV1.configurationGet(parameterNumber: 11),
// Get last known remote battery health
zwave.configurationV1.configurationGet(parameterNumber: 42)
]
commands(request)
}
private setConfigured() {
updateDataValue("configured", "true")
}
private isConfigured() {
getDataValue("configured") == "true"
}
private command(physicalgraph.zwave.Command cmd) {
if (state.sec) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=500) {
delayBetween(commands.collect{ command(it) }, delay)
}
================================================
FILE: Aeon Garage Door/device_type-aeon-garage-door-v0.1
================================================
/*
* V 0.1 of Aeon Garage Door code 12/15/2015
* 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.
*
* some code used from various SmartThings device type and metering code from ElasticDev
*
* change log:
* v 0.1
*/
metadata {
definition (name: "Aeon Garage Door - RV v0.1", namespace: "robertvandervoort", author: "Robert Vandervoort") {
capability "Alarm" // 0x71 Notification v4
capability "Battery"
capability "Switch" // 0x25 Switch Binary v1
capability "Configuration" // 0x70 Configuration v1
capability "Actuator"
capability "Door Control"
capability "Garage Door Control"
capability "Contact Sensor"
capability "Refresh"
capability "Sensor"
command "calibrate"
/*
0x22 Application Status v1
0x5E Zwave Gen 5 v2
0x85 Association v2
0x59 Association Grp Info v1
0x72 Manufacturer Specific v2
0x86 Version v1
0x7A Firmware Update Md v2
0x73 Powerlevel v1
0x98 Security v1
0x66 BARRIER_OPERATOR v1
0xEF Mark v1
0x5A Device Reset Locally v1
0x82 Hail v1
*/
// Raw description
// 0 0 0x4007 0 0 0 10 0x5E 0x25 0x70 0x85 0x59 0x72 0x86 0x7A 0x73 0x98 0x66 0xEF 0x22 0x5A 0x82
fingerprint deviceId: "0x10", inClusters: "0x98"
fingerprint inClusters: "0x5E, 0x25, 0x70, 0x85, 0x59, 0x72, 0x86, 0x7A, 0x73, 0x98, 0x66, 0x71, 0xEF, 0x22, 0x5A", outClusters: "0x82"
}
// simulator metadata
simulator {
status "on": "command: 2003, payload: FF"
status "off": "command: 2003, payload: 00"
// reply messages
reply "2001FF,delay 100,2502": "command: 2503, payload: FF"
reply "200100,delay 100,2502": "command: 2503, payload: 00"
}
// tile definitions
tiles (scale: 2) {
multiAttributeTile(name:"main", type:"generic", width:6, height:4, canChangeIcon: true) {
tileAttribute("device.door", key: "PRIMARY_CONTROL") {
attributeState "unknown", label:'${name}', action:"refresh.refresh", icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e"
attributeState "closed", label:'${name}', action:"door control.open", icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821", nextState:"opening"
attributeState "open", label:'${name}', action:"door control.close", icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e", nextState:"closing"
attributeState "opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#ffe71e"
attributeState "closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#ffe71e"
}
}
standardTile("open", "device.door", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'open', action:"door control.open", icon:"st.doors.garage.garage-opening"
}
standardTile("close", "device.door", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'close', action:"door control.close", icon:"st.doors.garage.garage-closing"
}
standardTile("configure", "device.door", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
standardTile("refresh", "device.door", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'', action:"refresh", icon:"st.secondary.refresh"
}
main "main"
details(["main","open","close","refresh","configure"])
}
preferences {
input "debugOutput", "boolean",
title: "Enable debug logging?",
defaultValue: false,
displayDuringSetup: true
}
}
def updated()
{
state.debug = ("true" == debugOutput)
if (state.sec && !isConfigured()) {
// in case we miss the SCSR
response(configure())
}
}
import physicalgraph.zwave.commands.barrieroperatorv1.*
def parse(String description)
{
def result = null
if (description.startsWith("Err 106")) {
state.sec = 0
result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true,
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.")
} else if (description != "updated") {
def cmd = zwave.parse(description, [0x5E: 2, 0x25: 1, 0x70: 1, 0x85: 2, 0x59: 1, 0x72: 2, 0x86: 1, 0x7A: 2, 0x73: 1, 0x98: 1, 0x66: 1, 0x71: 4, 0xEF: 1, 0x22: 1, 0x5A: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
// if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x5E: 2, 0x25: 1, 0x70: 1, 0x85: 2, 0x59: 1, 0x72: 2, 0x86: 1, 0x7A: 2, 0x73: 1, 0x98: 1, 0x66: 1, 0x71: 4, 0xEF: 1, 0x22: 1, 0x5A: 1])
state.sec = 1
// if (state.debug) log.debug "encapsulated: ${encapsulatedCommand}"
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
response(configure())
}
def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) {
if (state.debug) log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}"
def request = [
physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet()
]
response(commands(request))
}
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionCommandClassReport cmd) {
if (state.debug) log.debug "---COMMAND CLASS VERSION REPORT V1--- ${device.displayName} has command class version: ${cmd.commandClassVersion} - payload: ${cmd.payload}"
}
def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) {
def fw = "${cmd.applicationVersion}.${cmd.applicationSubVersion}"
updateDataValue("fw", fw)
if (state.debug) log.debug "---VERSION REPORT V1--- ${device.displayName} is running firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}"
}
def zwaveEvent(physicalgraph.zwave.commands.firmwareupdatemdv2.FirmwareMdReport cmd) {
if (state.debug) log.debug "---FIRMWARE MD REPORT V2--- ${device.displayName} has Checksum of ${cmd.checksum} firmwareId: ${cmd.firmwareId}, manufacturerId: ${cmd.firmwareId}"
}
def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) {
cmd.nodeId.each({log.debug "AssociationReport: '${cmd}', hub: '$zwaveHubNodeId' reports nodeId: '$it' is associated in group: '${cmd.groupingIdentifier}'"})
}
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
if (state.debug) log.debug "Hail received: ${cmd}"
}
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
def result = []
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
log.debug "msr: $msr"
updateDataValue("MSR", msr)
result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false)
result
}
def zwaveEvent(physicalgraph.zwave.commands.applicationstatusv1.ApplicationBusy cmd) {
def msg = cmd.status == 0 ? "try again later" :
cmd.status == 1 ? "try again in $cmd.waitTime seconds" :
cmd.status == 2 ? "request queued" : "sorry"
createEvent(displayed: true, descriptionText: "$device.displayName is busy, $msg")
}
def zwaveEvent(physicalgraph.zwave.commands.applicationstatusv1.ApplicationRejectedRequest cmd) {
createEvent(displayed: true, descriptionText: "$device.displayName rejected the last request")
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) {
if (state.debug) log.debug "---CONFIGURATION REPORT V2--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
if (state.debug) log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}
def zwaveEvent(BarrierOperatorReport cmd) {
def result = []
def map = [ name: "door" ]
switch (cmd.barrierState) {
case BarrierOperatorReport.BARRIER_STATE_CLOSED:
map.descriptionText = "$device.displayName door is closed"
map.value = "closed"
result << createEvent(name: "contact", value: "closed", displayed: false)
break
case BarrierOperatorReport.BARRIER_STATE_UNKNOWN_POSITION_MOVING_TO_CLOSE:
map.descriptionText = "$device.displayName door is closing"
map.value = "closing"
break
case BarrierOperatorReport.BARRIER_STATE_UNKNOWN_POSITION_STOPPED:
map.descriptionText = "$device.displayName door state is unknown"
map.value = "unknown"
break
case BarrierOperatorReport.BARRIER_STATE_UNKNOWN_POSITION_MOVING_TO_OPEN:
map.descriptionText = "$device.displayName door is opening"
map.value = "opening"
result << createEvent(name: "contact", value: "open", displayed: false)
break
case BarrierOperatorReport.BARRIER_STATE_OPEN:
map.descriptionText = "$device.displayName door is open"
map.value = "open"
result << createEvent(name: "contact", value: "open", displayed: false)
break
}
if (state.debug) log.debug "---BARRIER OPERATOR REPORT--- ${map.descriptionText}"
result + createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
def result = []
def map = [:]
if (cmd.notificationType == 6) {
map.displayed = true
switch(cmd.event) {
case 0x40:
if (cmd.eventParameter[0]) {
map.descriptionText = "$device.displayName performing initialization process"
} else {
map.descriptionText = "$device.displayName initialization process complete"
}
break
case 0x41:
map.descriptionText = "$device.displayName door operation force has been exceeded"
break
case 0x42:
map.descriptionText = "$device.displayName motor has exceeded operational time limit"
break
case 0x43:
map.descriptionText = "$device.displayName has exceeded physical mechanical limits"
break
case 0x44:
map.descriptionText = "$device.displayName unable to perform requested operation (UL requirement)"
break
case 0x45:
map.descriptionText = "$device.displayName remote operation disabled (UL requirement)"
break
case 0x46:
map.descriptionText = "$device.displayName failed to perform operation due to device malfunction"
break
case 0x47:
if (cmd.eventParameter[0]) {
map.descriptionText = "$device.displayName vacation mode enabled"
} else {
map.descriptionText = "$device.displayName vacation mode disabled"
}
break
case 0x48:
if (cmd.eventParameter[0]) {
map.descriptionText = "$device.displayName safety beam obstructed"
} else {
map.descriptionText = "$device.displayName safety beam obstruction cleared"
}
break
case 0x49:
if (cmd.eventParameter[0]) {
map.descriptionText = "$device.displayName door sensor ${cmd.eventParameter[0]} not detected"
} else {
map.descriptionText = "$device.displayName door sensor not detected"
}
break
case 0x4A:
if (cmd.eventParameter[0]) {
map.descriptionText = "$device.displayName door sensor ${cmd.eventParameter[0]} has a low battery"
} else {
map.descriptionText = "$device.displayName door sensor has a low battery"
}
result << createEvent(name: "battery", value: 1, unit: "%", descriptionText: map.descriptionText)
break
case 0x4B:
map.descriptionText = "$device.displayName detected a short in wall station wires"
break
case 0x4C:
map.descriptionText = "$device.displayName is associated with non-Z-Wave remote control"
break
default:
map.descriptionText = "$device.displayName: access control alarm $cmd.event"
map.displayed = false
break
}
} else if (cmd.notificationType == 7) {
switch (cmd.event) {
case 1:
case 2:
map.descriptionText = "$device.displayName detected intrusion"
break
case 3:
map.descriptionText = "$device.displayName tampering detected: product cover removed"
break
case 4:
map.descriptionText = "$device.displayName tampering detected: incorrect code"
break
case 7:
case 8:
map.descriptionText = "$device.displayName detected motion"
break
default:
map.descriptionText = "$device.displayName: security alarm $cmd.event"
map.displayed = false
}
} else if (cmd.notificationType){
map.descriptionText = "$device.displayName: alarm type $cmd.notificationType event $cmd.event"
} else {
map.descriptionText = "$device.displayName: alarm $cmd.v1AlarmType is ${cmd.v1AlarmLevel == 255 ? 'active' : cmd.v1AlarmLevel ?: 'inactive'}"
}
result ? [createEvent(map), *result] : createEvent(map)
if (state.debug) log.debug result
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd)
{
[name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd)
{
[name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
[name: "switch", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd)
{
[name: "switch", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true]
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
if (state.debug) log.debug "Unhandled: $cmd"
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
def on() {
def request = [
zwave.basicV1.basicSet(value: 0xFF),
zwave.basicV1.basicGet(),
zwave.switchBinaryV1.switchBinaryGet()
]
commands(request)
}
def off() {
def request = [
zwave.basicV1.basicSet(value: 0x00),
zwave.basicV1.basicGet(),
zwave.switchBinaryV1.switchBinaryGet()
]
commands(request)
}
def open() {
def request = [
zwave.barrierOperatorV1.barrierOperatorSet(requestedBarrierState: BarrierOperatorSet.REQUESTED_BARRIER_STATE_OPEN)
]
commands(request)
}
def close() {
def request = [
zwave.barrierOperatorV1.barrierOperatorSet(requestedBarrierState: BarrierOperatorSet.REQUESTED_BARRIER_STATE_CLOSE)
]
commands(request)
}
def refresh() {
def request = [
// get battery state
zwave.configurationV1.configurationGet(parameterNumber: 42),
zwave.basicV1.basicGet(),
zwave.switchBinaryV1.switchBinaryGet(),
zwave.barrierOperatorV1.barrierOperatorGet()
]
commands(request)
}
def configure() {
if (state.debug) log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}, zwaveHubNodeId: ${zwaveHubNodeId}}"
def request = [
//associate with group 1 and 2
//zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId),
//zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId),
zwave.associationV1.associationGet(groupingIdentifier:1),
zwave.associationV1.associationGet(groupingIdentifier:2),
// Get Version information
zwave.versionV1.versionGet(),
zwave.firmwareUpdateMdV2.firmwareMdGet(),
// Enable to send notifications to associated devices (Group 1) when the state of Micro Switch’s load changed (0=nothing, 1=hail CC, 2=basic CC report)
zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, configurationValue: [2]),
zwave.configurationV1.configurationGet(parameterNumber: 80),
//set startup tone
zwave.configurationV1.configurationSet(parameterNumber: 32, size: 1, configurationValue: [1]),
zwave.configurationV1.configurationGet(parameterNumber: 32),
//get number of alarm tone
zwave.configurationV1.configurationGet(parameterNumber: 36),
// Set blink, sound, volume of opening action
zwave.configurationV1.configurationSet(parameterNumber: 37, size: 4, configurationValue: [5,1,1,1]),
zwave.configurationV1.configurationGet(parameterNumber: 37),
// set blink, sound, volume of closing action
zwave.configurationV1.configurationSet(parameterNumber: 38, size: 4, configurationValue: [10,2,1,1]),
zwave.configurationV1.configurationGet(parameterNumber: 38),
// set blink, sound, volume of unknown state
zwave.configurationV1.configurationSet(parameterNumber: 39, size: 4, configurationValue: [1,3,1,0]),
zwave.configurationV1.configurationGet(parameterNumber: 39),
// set blink, sound, volume of CLOSED state
zwave.configurationV1.configurationSet(parameterNumber: 40, size: 4, configurationValue: [1,3,1,0]),
zwave.configurationV1.configurationGet(parameterNumber: 40),
// get battery state
zwave.configurationV1.configurationGet(parameterNumber: 42),
// Can use the zwaveHubNodeId variable to add the hub to the device's associations:
zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)
]
commands(request)
}
private setConfigured() {
updateDataValue("configured", "true")
}
private isConfigured() {
getDataValue("configured") == "true"
}
private command(physicalgraph.zwave.Command cmd) {
if (state.sec) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=500) {
delayBetween(commands.collect{ command(it) }, delay)
}
================================================
FILE: Aeon Multisensor 6/device_type-aeon-multisensor6-v1.1
================================================
/**
* V 1.1 of Multisensor 6 code
* known issues : preferences do not seem to affect configuration, secure pairing is the most tested method at the moment. when clicking the action button on * the sensor, click two times quickly to pair secured. Still not seeing anything other than 0 for ultraviolet. Also, temp and humidity seem to be off about 6 * degrees warmer and 7 percent humidity lower than actual, though your sensor may vary.
* Original code for gen5 Copyright 2015 SmartThings, modified for use on gen 6 by Robert Vandervoort
*
* 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.
*
*/
metadata {
definition (name: "Aeon Multisensor 6", namespace: "robertvandervoort", author: "Robert Vandervoort") {
capability "Motion Sensor"
capability "Temperature Measurement"
capability "Relative Humidity Measurement"
capability "Illuminance Measurement"
capability "Configuration"
capability "Sensor"
capability "Battery"
fingerprint deviceId: "0x2101", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x7A,0xEF,0x5A,0x98,0x7A"
}
simulator {
status "no motion" : "command: 9881, payload: 00300300"
status "motion" : "command: 9881, payload: 003003FF"
status "no vibration" : " command: 9881, payload: 0071050000000007030000"
status "vibration" : "command: 9881, payload: 007105000000FF07030000"
for (int i = 0; i <= 100; i += 20) {
status "temperature ${i}F": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
precision: 1,
sensorType: 1,
scale: 1
)
).incomingMessage()
}
for (int i = 0; i <= 100; i += 20) {
status "RH ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 5
)
).incomingMessage()
}
for (int i in [0, 20, 89, 100, 200, 500, 1000]) {
status "illuminance ${i} lux": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 3
)
).incomingMessage()
}
for (int i = 0; i <= 11; i += 1) {
status "ultraviolet ${i}": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 27
)
).incomingMessage()
}
for (int i in [0, 5, 10, 15, 50, 99, 100]) {
status "battery ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: i
)
).incomingMessage()
}
status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: 255
)
).incomingMessage()
status "wake up": "command: 8407, payload:"
}
tiles {
standardTile("motion","device.motion") {
state "active",label:'motion',icon:"st.motion.motion.active",backgroundColor:"#53a7c0"
state "inactive",label:'no motion',icon:"st.motion.motion.inactive",backgroundColor:"#ffffff"
}
valueTile("temperature","device.temperature",inactiveLabel: false) {
state "temperature",label:'${currentValue}°',backgroundColors:[
[value: 32, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 92, color: "#d04e00"],
[value: 98, color: "#bc2323"]
]
}
valueTile(
"humidity","device.humidity",inactiveLabel: false) {
state "humidity",label:'RH ${currentValue} %',unit:""
}
valueTile(
"illuminance","device.illuminance",inactiveLabel: false) {
state "luminosity",label:'${currentValue} ${unit}',unit:"lux"
}
valueTile(
"ultraviolet","device.ultraviolet",inactiveLabel: false) {
state "ultraviolet",label:'UV ${currentValue} ${unit}',unit:""
}
standardTile(
"vibration","device.vibration") {
state "active",label:'vibration',icon:"st.motion.motion.active",backgroundColor:"#ff0000"
state "inactive",label:'calm',icon:"st.motion.motion.inactive",backgroundColor:"#00ff00"
}
valueTile(
"battery", "device.battery", inactiveLabel: false, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""
}
standardTile(
"configureAfterSecure","device.configure",inactiveLabel: false,decoration: "flat") {
state "configure",label:'',action:"configureAfterSecure",icon:"st.secondary.configure"
}
main([
"motion","temperature","humidity","illuminance","ultraviolet"
])
details([
"motion","temperature","humidity","illuminance","ultraviolet","battery","configureAfterSecure"
])
}
preferences {
input "tempoffset",
"number",
title: "Temperature offset",
description: "negative values reduce the monitored value positive ones add to it",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "humidityoffset",
"number",
title: "Humidity offset",
description: "negative values reduce the monitored value positive ones add to it",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "luminanceoffset",
"number",
title: "Luminance offset",
description: "negative values reduce the monitored value positive ones add to it",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "ultravioletoffset",
"number",
title: "Ultraviolet offset",
description: "negative values reduce the monitored value positive ones add to it",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "PIRsensitivity",
"number",
title: "PIR motion sensitivity",
description: "A value from 0-127 low to high sensitivity",
defaultValue: 64,
required: true,
displayDuringSetup: true
input "ReportingInterval",
"number",
title: "Report data every X seconds",
description: "A value in seconds, default is 60 / 8 minutes",
defaultValue: 4,
required: true,
displayDuringSetup: true
}
}
def parse(String description) {
def result = null
if (description == "updated") {
result = null
}
else {
def cmd = zwave.parse(description, [0x31: 5, 0x30: 2, 0x84: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
log.debug "Parsed '${description}' to ${result.inspect()}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)]
if (!isConfigured()) {
// we're still in the process of configuring a newly joined device
log.debug("not sending wakeUpNoMoreInformation yet")
result += response(configureAfterSecure())
} else {
result += response(zwave.wakeUpV1.wakeUpNoMoreInformation())
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x31: 5, 0x30: 2, 0x84: 1])
log.debug "encapsulated: ${encapsulatedCommand}"
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
log.debug "Received SecurityCommandsSupportedReport"
response(configureAfterSecure())
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) {
map.value = 1
map.descriptionText = "${device.displayName} battery is low"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
state.lastbatt = new Date().time
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd)
{
def map = [:]
switch (cmd.sensorType) {
case 1:
map.name = "temperature"
def cmdScale = cmd.scale == 1 ? "F" : "C"
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
map.unit = getTemperatureScale()
break;
case 3:
map.name = "illuminance"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = "lux"
break;
case 5:
map.name = "humidity"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = "%"
break;
case 27:
map.name = "ultraviolet"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = ""
break;
default:
map.descriptionText = cmd.toString()
}
createEvent(map)
}
def motionEvent(value) {
def map = [name: "motion"]
if (value == 255) {
map.value = "active"
map.descriptionText = "$device.displayName detected motion"
} else {
map.value = "inactive"
map.descriptionText = "$device.displayName motion has stopped"
}
createEvent(map)
}
def vibrationEvent(value) {
def map = [name: "vibration"]
if (value == 255) {
map.value = "active"
map.descriptionText = "$device.displayName detected vibration"
} else {
log.debug "-------------Vibration inactive------------------"
map.value = "inactive"
map.descriptionText = "$device.displayName vibration has stopped"
}
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv2.SensorBinaryReport cmd) {
motionEvent(cmd.sensorValue)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
log.debug "Basic Set 255 triggered motion event"
motionEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
if (cmd.notificationType == 7 && cmd.event == 8) {
log.debug "notification type 7 event 8 triggered motion event"
motionEvent(cmd.notificationStatus)
} else if (cmd.notificationType == 7 && cmd.event == 0) {
log.debug "notification type 7 event 0 motion and vibration cleared"
motionEvent(cmd.notificationStatus)
vibrationEvent(cmd.notificationStatus)
} else if (cmd.notificationType == 7 && cmd.event == 3) {
log.debug "notification type 7 event 3 triggered vibration event"
vibrationEvent(cmd.notificationStatus)
} else {
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
def configureAfterSecure() {
log.debug "configureAfterSecure()"
//log.debug "PIRsensitivity: $PIRsensitivity, Reporting Interval: $ReportingInterval, Temp offset: $tempoffset, Humidity offset: $humidityoffset, Luminance offset: $luminanceoffset, UV offset: $ultravioletoffset"
def PIRsens = 64
if (PIRsensitivity) {
PIRsens=PIRsensitivity.toInteger()
}
def ReportingInt = 4
if (ReportingInterval) {
ReportingInt=ReportingInterval.toInteger()
}
def tempoff = 0
if (tempoffset) {
tempoff=tempoffset.toInteger()
}
def humidityoff = 0
if (humidityoffset) {
humidityoff=humidityoffset.toInteger()
}
def luminanceoff = 0
if (luminanceoffset) {
luminanceoff=luminanceoffset.toInteger()
}
def ultravioletoff = 0
if (ultravioletoffset) {
ultravioletoff=ultravioletoffset.toInteger()
}
//log.debug "PIRsens: $PIRsens, ReportingInt: $ReportingInt, Tempoffset: $tempoff, Humidityoff: $humidityoff, Luminanceoff: $luminanceoff, UVoff: $ultravioletoff"
def request = [
// send temperature, humidity, illuminance, ultraviolet and battery
zwave.configurationV1.configurationSet(parameterNumber: 0x65, size: 4, scaledConfigurationValue: 128|64|32|16|1),
// configure frequency of reporting
zwave.configurationV1.configurationSet(parameterNumber: 0x6F,size: 4, scaledConfigurationValue: ReportingInt),
// configure PIR sensitivity
zwave.configurationV1.configurationSet(parameterNumber: 0x06,size: 1, scaledConfigurationValue: PIRsens),
// send battery every 20 hours
zwave.configurationV1.configurationSet(parameterNumber: 0x66, size: 4, scaledConfigurationValue: 1),
zwave.configurationV1.configurationSet(parameterNumber: 0x70, size: 4, scaledConfigurationValue: 20*60*60),
// send no-motion report 60 seconds after motion stops
zwave.configurationV1.configurationSet(parameterNumber: 0x03, size: 2, scaledConfigurationValue: 60),
// enable motion sensor
zwave.configurationV1.configurationSet(parameterNumber: 0x04, size: 1, scaledConfigurationValue: 0),
// send binary sensor report instead of basic set for motion
zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 2),
// Enable the function of vibration sensor
zwave.configurationV1.configurationSet(parameterNumber: 0x07, size: 1, scaledConfigurationValue: 1),
// disable notification-style motion events
zwave.notificationV3.notificationSet(notificationType: 7, notificationStatus: 0),
// configure temp offset
zwave.configurationV1.configurationSet(parameterNumber: 0xC9, size: 2, scaledConfigurationValue: tempoff),
// configure humidity offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCA, size: 2, scaledConfigurationValue: humidityoff),
// configure luminance offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCB, size: 2, scaledConfigurationValue: luminanceoff),
// configure ultraviolet offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCC, size: 2, scaledConfigurationValue: ultravioletoff),
zwave.batteryV1.batteryGet(),
zwave.sensorBinaryV2.sensorBinaryGet(),
// Can use the zwaveHubNodeId variable to add the hub to the device's associations:
zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)
]
setConfigured()
//log.debug request
secureSequence(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
}
def configure() {
//["delay 30000"] + secure(zwave.securityV1.securityCommandsSupportedGet())
log.debug "configure()"
def reportIntervalSecs = 4;
if (reportInterval) {
reportIntervalSecs = reportInterval.toInteger()
}
delayBetween([
// send temperature, humidity, illuminance, ultraviolet and battery every 8 minutes or as defined by preference
zwave.configurationV1.configurationSet(parameterNumber: 0x65, size: 4, scaledConfigurationValue: 128|64|32|16|1).format(),
zwave.configurationV1.configurationSet(parameterNumber: 0x6F, size: 4, scaledConfigurationValue: reportIntervalSecs).format(),
// send battery every 20 hours
zwave.configurationV1.configurationSet(parameterNumber: 0x66, size: 4, scaledConfigurationValue: 1).format(),
zwave.configurationV1.configurationSet(parameterNumber: 0x70, size: 4, scaledConfigurationValue: 20*60*60).format(),
// send no-motion report 60 seconds after motion stops
zwave.configurationV1.configurationSet(parameterNumber: 0x03, size: 2, scaledConfigurationValue: 60).format(),
// enable motion sensor
zwave.configurationV1.configurationSet(parameterNumber: 0x04, size: 1, scaledConfigurationValue: 0).format(),
// send binary sensor report instead of basic set for motion
zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 2).format(),
// configure PIR sensitivity for multisensor 6 min to max 0-127 default 64
zwave.configurationV1.configurationSet(parameterNumber: 0x06, size: 1, scaledConfigurationValue: 64).format(),
// Enable the function of vibration sensor
zwave.configurationV1.configurationSet(parameterNumber: 0x07, size: 1, scaledConfigurationValue: 1).format(),
// disable notification-style motion events
zwave.notificationV3.notificationSet(notificationType: 7, notificationStatus: 0).format(),
// configure temp offset
zwave.configurationV1.configurationSet(parameterNumber: 0xC9, size: 2, scaledConfigurationValue: 20).format(),
// configure humidity offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCA, size: 2, scaledConfigurationValue: 20).format(),
// configure luminance offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCB, size: 2, scaledConfigurationValue: 0).format(),
// configure ultraviolet offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCC, size: 2, scaledConfigurationValue: 5).format(),
zwave.batteryV1.batteryGet(),
zwave.sensorBinaryV2.sensorBinaryGet(),
// Can use the zwaveHubNodeId variable to add the hub to the device's associations:
zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)
])
setConfigured()
zwave.wakeUpV1.wakeUpNoMoreInformation().format()
}
def setConfigured() {
device.updateDataValue("configured", "true")
}
def isConfigured() {
Boolean configured = device.getDataValue(["configured"]) as Boolean
return configured
}
private secure(physicalgraph.zwave.Command cmd) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
}
private secureSequence(commands, delay=200) {
delayBetween(commands.collect{ secure(it) }, delay)
}
def updated() {
log.debug "updated()"
log.debug "PIRsensitivity: $PIRsensitivity, Reporting Interval: $ReportingInterval, Temp offset: $tempoffset, Humidity offset: $humidityoffset, Luminance offset: $luminanceoffset, UV offset: $ultravioletoffset"
configureAfterSecure()
}
================================================
FILE: Aeon Multisensor 6/device_type-aeon-multisensor6-v1.2
================================================
/**
* V 1.2 of Multisensor 6 code
* known issues : preferences do not seem to affect configuration,
* Not seeing anything other than 0 for ultraviolet.
* temp and humidity seem to be off about 6 * degrees warmer and 7 percent humidity lower than actual
* FIXED: battery tile added, vibration tile removed and touch capability and tile added and status updates are working, thanks TIM YUHL for the code review and sanity check!
* Original code for gen5 Copyright 2015 SmartThings, modified for use on gen 6 by Robert Vandervoort
*
* 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.
*
*/
metadata {
definition (name: "Aeon Multisensor 6", namespace: "robertvandervoort", author: "Robert Vandervoort") {
capability "Motion Sensor"
capability "Touch Sensor"
capability "Temperature Measurement"
capability "Relative Humidity Measurement"
capability "Illuminance Measurement"
capability "Ultraviolet Index"
capability "Configuration"
capability "Sensor"
capability "Battery"
fingerprint deviceId: "0x2101", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x7A,0xEF,0x5A,0x98,0x7A"
}
simulator {
status "no motion" : "command: 9881, payload: 00300300"
status "motion" : "command: 9881, payload: 003003FF"
status "no touch" : " command: 9881, payload: 0071050000000007030000"
status "touch" : "command: 9881, payload: 007105000000FF07030000"
for (int i = 0; i <= 100; i += 20) {
status "temperature ${i}F": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
precision: 1,
sensorType: 1,
scale: 1
)
).incomingMessage()
}
for (int i = 0; i <= 100; i += 20) {
status "RH ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 5
)
).incomingMessage()
}
for (int i in [0, 20, 89, 100, 200, 500, 1000]) {
status "illuminance ${i} lux": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 3
)
).incomingMessage()
}
for (int i = 0; i <= 11; i += 1) {
status "ultraviolet ${i}": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 27
)
).incomingMessage()
}
for (int i in [0, 5, 10, 15, 50, 99, 100]) {
status "battery ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: i
)
).incomingMessage()
}
status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: 255
)
).incomingMessage()
status "wake up": "command: 8407, payload:"
}
tiles {
standardTile("motion","device.motion") {
state "active",label:'motion',icon:"st.motion.motion.active",backgroundColor:"#53a7c0"
state "inactive",label:'no motion',icon:"st.motion.motion.inactive",backgroundColor:"#ffffff"
}
valueTile("temperature","device.temperature",inactiveLabel: false) {
state "temperature",label:'${currentValue}°',backgroundColors:[
[value: 32, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 92, color: "#d04e00"],
[value: 98, color: "#bc2323"]
]
}
valueTile(
"humidity","device.humidity",inactiveLabel: false) {
state "humidity",label:'RH ${currentValue} %',unit:""
}
valueTile(
"illuminance","device.illuminance",inactiveLabel: false) {
state "luminosity",label:'${currentValue} ${unit}', unit:"lux", backgroundColors:[
[value: 0, color: "#000000"],
[value: 47, color: "#1A1A0A"],
[value: 94, color: "#333314"],
[value: 141, color: "#4C4C1F"],
[value: 188, color: "#666629"],
[value: 235, color: "#808033"],
[value: 282, color: "#99993D"],
[value: 329, color: "#B2B247"],
[value: 376, color: "#CCCC52"],
[value: 423, color: "#E6E65C"],
[value: 470, color: "#FFFF66"],
[value: 517, color: "#FFFF75"],
[value: 564, color: "#FFFF85"],
[value: 611, color: "#FFFF94"],
[value: 658, color: "#FFFFA3"],
[value: 705, color: "#FFFFB2"],
[value: 752, color: "#FFFFC2"],
[value: 799, color: "#FFFFD1"],
[value: 846, color: "#FFFFE0"],
[value: 900, color: "#FFFFF0"],
[value: 1000, color: "#FFFFFF"]
]
}
valueTile(
"ultraviolet","device.ultraviolet",inactiveLabel: false) {
state "ultraviolet",label:'${currentValue} UV',unit:"UV"
}
standardTile(
"touch","device.touch") {
state "touched",label:'touched',icon:"st.motion.motion.active",backgroundColor:"#ff0000"
state "inactive",label:'calm',icon:"st.motion.motion.inactive",backgroundColor:"#00ff00"
}
valueTile(
"battery", "device.battery", inactiveLabel: false, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""
}
standardTile(
"configure","device.configure",inactiveLabel: false,decoration: "flat") {
state "configure",label:'',action:"configure",icon:"st.secondary.configure"
}
main([
"motion","touch","temperature","humidity","illuminance","ultraviolet"
])
details([
"motion","touch","temperature","humidity","illuminance","ultraviolet","battery","configureAfterSecure"
])
}
preferences {
input "tempoffset",
"number",
title: "Temperature offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "..",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "humidityoffset",
"number",
title: "Humidity offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "..",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "luminanceoffset",
"number",
title: "Luminance offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "..",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "ultravioletoffset",
"number",
title: "Ultraviolet offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "..",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "PIRsensitivity",
"number",
title: "PIR motion sensitivity",
description: "A value from 0-5, from disabled to high sensitivity",
defaultValue: 1,
required: true,
displayDuringSetup: true
input "ReportingInterval",
"number",
title: "Report data interval",
description: "A value in seconds for mains power, you can't go shorter than 3600 on battery power.",
defaultValue: 60,
required: true,
displayDuringSetup: true
}
}
def parse(String description) {
def result = null
if (description == "updated") {
result = null
}
else {
def cmd = zwave.parse(description, [0x31: 5, 0x30: 2, 0x84: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
log.debug "Parsed '${description}' to ${result.inspect()}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)]
if (!isConfigured()) {
// we're still in the process of configuring a newly joined device
log.debug("not sending wakeUpNoMoreInformation yet")
result += response(configureAfterSecure())
} else {
result += response(zwave.wakeUpV1.wakeUpNoMoreInformation())
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x31: 5, 0x30: 2, 0x84: 1])
log.debug "encapsulated: ${encapsulatedCommand}"
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
log.debug "Received SecurityCommandsSupportedReport"
response(configureAfterSecure())
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) {
map.value = 1
map.descriptionText = "${device.displayName} battery is low"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
state.lastbatt = new Date().time
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd)
{
def map = [:]
switch (cmd.sensorType) {
case 1:
map.name = "temperature"
def cmdScale = cmd.scale == 1 ? "F" : "C"
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
map.unit = getTemperatureScale()
break;
case 3:
map.name = "illuminance"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = "lux"
break;
case 5:
map.name = "humidity"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = "%"
break;
case 27:
map.name = "ultraviolet"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = ""
break;
default:
map.descriptionText = cmd.toString()
}
createEvent(map)
}
def motionEvent(value) {
def map = [name: "motion"]
if (value == 255) {
map.value = "active"
map.descriptionText = "$device.displayName detected motion"
} else {
map.value = "inactive"
map.descriptionText = "$device.displayName motion has stopped"
}
createEvent(map)
}
def touchEvent(value) {
def map = [name: "touch"]
if (value == 255) {
log.debug "-------------touched------------------"
map.value = "touched"
map.descriptionText = "$device.displayName detected touch"
} else {
log.debug "-------------touch inactive-----------"
map.value = "inactive"
map.descriptionText = "$device.displayName touch has stopped"
}
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv2.SensorBinaryReport cmd) {
motionEvent(cmd.sensorValue)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
log.debug "Basic Set 255 triggered motion event"
motionEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
if (cmd.notificationType == 7 && cmd.event == 8) {
log.debug "notification type 7 event 8 triggered motion event"
motionEvent(cmd.notificationStatus)
} else if (cmd.notificationType == 7 && cmd.event == 0) {
log.debug "notification type 7 event 0 motion and touch cleared"
motionEvent(0)
touchEvent(0)
} else if (cmd.notificationType == 7 && cmd.event == 3) {
log.debug "notification type 7 event 3 triggered touch event"
touchEvent(cmd.notificationStatus)
} else {
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
def configureAfterSecure() {
log.debug "configureAfterSecure()"
//log.debug "PIRsensitivity: $PIRsensitivity, Reporting Interval: $ReportingInterval, Temp offset: $tempoffset, Humidity offset: $humidityoffset, Luminance offset: $luminanceoffset, UV offset: $ultravioletoffset"
def PIRsens = 1
if (PIRsensitivity) {
PIRsens=PIRsensitivity.toInteger()
}
def ReportingInt = 60
if (ReportingInterval) {
ReportingInt=ReportingInterval.toInteger()
}
def tempoff = 0
if (tempoffset) {
if(tempoffset < 0) {
tempoff=(255-tempoffset.tointeger())
}
if(tempoffset > 0) {
tempoff=(0+tempoffset.tointeger())
}
}
def humidityoff = 0
if (humidityoffset) {
humidityoff=humidityoffset.toInteger()
}
def luminanceoff = 0
if (luminanceoffset) {
luminanceoff=luminanceoffset.toInteger()
}
def ultravioletoff = 0
if (ultravioletoffset) {
ultravioletoff=ultravioletoffset.toInteger()
}
//log.debug "PIRsens: $PIRsens, ReportingInt: $ReportingInt, Tempoffset: $tempoff, Humidityoff: $humidityoff, Luminanceoff: $luminanceoff, UVoff: $ultravioletoff"
def request = [
// send temperature, humidity, illuminance, ultraviolet and battery
zwave.configurationV1.configurationSet(parameterNumber: 0x65, size: 4, scaledConfigurationValue: 128|64|32|16),
// configure frequency of reporting
zwave.configurationV1.configurationSet(parameterNumber: 0x6F,size: 4, scaledConfigurationValue: ReportingInt),
// send battery every 20 hours
zwave.configurationV1.configurationSet(parameterNumber: 0x66, size: 4, scaledConfigurationValue: 1),
zwave.configurationV1.configurationSet(parameterNumber: 0x70, size: 4, scaledConfigurationValue: 20*60*60),
// send no-motion report 20 seconds after motion stops
zwave.configurationV1.configurationSet(parameterNumber: 0x03, size: 2, scaledConfigurationValue: 20),
// enable motion sensor and set sensitivity
zwave.configurationV1.configurationSet(parameterNumber: 0x04, size: 1, scaledConfigurationValue: PIRsens),
// send binary sensor report for motion
zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 2),
// Enable the function of touch sensor
// zwave.configurationV1.configurationSet(parameterNumber: 0x07, size: 1, scaledConfigurationValue: 1),
// disable notification-style motion events
zwave.notificationV3.notificationSet(notificationType: 7, notificationStatus: 0),
// configure temp offset
zwave.configurationV1.configurationSet(parameterNumber: 0xC9, size: 2, scaledConfigurationValue: tempoff),
// configure humidity offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCA, size: 2, scaledConfigurationValue: humidityoff),
// configure luminance offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCB, size: 2, scaledConfigurationValue: luminanceoff),
// configure ultraviolet offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCC, size: 2, scaledConfigurationValue: ultravioletoff),
zwave.batteryV1.batteryGet(),
zwave.sensorBinaryV2.sensorBinaryGet(),
// Can use the zwaveHubNodeId variable to add the hub to the device's associations:
zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)
]
setConfigured()
//log.debug request
secureSequence(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
}
def configure() {
//["delay 20000"] + secure(zwave.securityV1.securityCommandsSupportedGet())
log.debug "configure()"
def PIRsens = 1
if (PIRsensitivity) {
PIRsens=PIRsensitivity.toInteger()
}
def ReportingInt = 60
if (ReportingInterval) {
ReportingInt=ReportingInterval.toInteger()
}
def tempoff = 0
if (tempoffset) {
if(tempoffset < 0) {
tempoff=(255-tempoffset.tointeger())
}
if(tempoffset > 0) {
tempoff=(0+tempoffset.tointeger())
}
}
def humidityoff = 0
if (humidityoffset) {
humidityoff=humidityoffset.toInteger()
}
def luminanceoff = 0
if (luminanceoffset) {
luminanceoff=luminanceoffset.toInteger()
}
def ultravioletoff = 0
if (ultravioletoffset) {
ultravioletoff=ultravioletoffset.toInteger()
}
log.debug "PIRsens: $PIRsens, ReportingInt: $ReportingInt, Tempoffset: $tempoff, Humidityoff: $humidityoff, Luminanceoff: $luminanceoff, UVoff: $ultravioletoff"
delayBetween([
// send temperature, humidity, illuminance, ultraviolet and battery every 60 minutes or seconds depending on power state
zwave.configurationV1.configurationSet(parameterNumber: 0x65, size: 4, scaledConfigurationValue: 128|64|32|16).format(),
zwave.configurationV1.configurationSet(parameterNumber: 0x6F, size: 4, scaledConfigurationValue: ReportingInt).format(),
// send battery every 20 hours
zwave.configurationV1.configurationSet(parameterNumber: 0x66, size: 4, scaledConfigurationValue: 1).format(),
zwave.configurationV1.configurationSet(parameterNumber: 0x70, size: 4, scaledConfigurationValue: 20*60*60).format(),
// send no-motion report 20 seconds after motion stops
zwave.configurationV1.configurationSet(parameterNumber: 0x03, size: 2, scaledConfigurationValue: 20).format(),
// enable motion sensor and set min sensitivity
zwave.configurationV1.configurationSet(parameterNumber: 0x04, size: 1, scaledConfigurationValue: PIRsens).format(),
// send binary sensor report for motion
zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 2).format(),
// Enable the function of touch sensor
//zwave.configurationV1.configurationSet(parameterNumber: 0x07, size: 1, scaledConfigurationValue: 1).format(),
// disable notification-style motion events
zwave.notificationV3.notificationSet(notificationType: 7, notificationStatus: 0).format(),
// configure temp offset
zwave.configurationV1.configurationSet(parameterNumber: 0xC9, size: 2, scaledConfigurationValue: tempoff).format(),
// configure humidity offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCA, size: 2, scaledConfigurationValue: humidityoff).format(),
// configure luminance offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCB, size: 2, scaledConfigurationValue: luminanceoff).format(),
// configure ultraviolet offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCC, size: 2, scaledConfigurationValue: ultravioletoff).format(),
zwave.batteryV1.batteryGet(),
zwave.sensorBinaryV2.sensorBinaryGet(),
// Can use the zwaveHubNodeId variable to add the hub to the device's associations:
zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)
])
setConfigured()
zwave.wakeUpV1.wakeUpNoMoreInformation().format()
}
def setConfigured() {
device.updateDataValue("configured", "true")
}
def isConfigured() {
Boolean configured = device.getDataValue(["configured"]) as Boolean
return configured
}
private secure(physicalgraph.zwave.Command cmd) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
}
private secureSequence(commands, delay=200) {
delayBetween(commands.collect{ secure(it) }, delay)
}
def updated() {
log.debug "updated()"
log.debug "PIRsensitivity: $PIRsensitivity, Reporting Interval: $ReportingInterval, Temp offset: $tempoffset, Humidity offset: $humidityoffset, Luminance offset: $luminanceoffset, UV offset: $ultravioletoffset"
configure()
}
================================================
FILE: Aeon Multisensor 6/device_type-aeon-multisensor6-v1.3
================================================
/**
* V 1.3 of Multisensor 6 code 9/14/2015
* Original code for gen5 Copyright 2015 SmartThings, modified for use on Multisensor 6 by Robert Vandervoort 6/19/2015
*
* 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.
*
*/
metadata {
definition (name: "rv Aeon Multisensor 6", namespace: "robertvandervoort", author: "Robert Vandervoort") {
capability "Motion Sensor"
capability "Touch Sensor"
capability "Temperature Measurement"
capability "Relative Humidity Measurement"
capability "Illuminance Measurement"
capability "Ultraviolet Index"
capability "Configuration"
capability "Sensor"
capability "Battery"
attribute "tamper", "enum", ["detected", "clear"]
// CC supported 94, 134, 114, 132, 89, 133, 115, 113, 128, 48, 49, 112, 152, 122
fingerprint deviceId: "0x2101", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0xEF,0x5A,0x98,0x7A"
}
simulator {
status "no motion" : "command: 9881, payload: 00300300"
status "motion" : "command: 9881, payload: 003003FF"
status "clear" : " command: 9881, payload: 0071050000000007030000"
status "tamper" : "command: 9881, payload: 007105000000FF07030000"
for (int i = 0; i <= 100; i += 20) {
status "temperature ${i}F": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
precision: 1,
sensorType: 1,
scale: 1
)
).incomingMessage()
}
for (int i = 0; i <= 100; i += 20) {
status "RH ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 5
)
).incomingMessage()
}
for (int i in [0, 20, 89, 100, 200, 500, 1000]) {
status "illuminance ${i} lux": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 3
)
).incomingMessage()
}
for (int i = 0; i <= 11; i += 1) {
status "ultravioletultravioletIndex ${i}": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 27
)
).incomingMessage()
}
for (int i in [0, 5, 10, 15, 50, 99, 100]) {
status "battery ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: i
)
).incomingMessage()
}
status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: 255
)
).incomingMessage()
status "wake up": "command: 8407, payload:"
}
tiles {
standardTile("motion","device.motion") {
state "active",label:'motion',icon:"st.motion.motion.active",backgroundColor:"#53a7c0"
state "inactive",label:'no motion',icon:"st.motion.motion.inactive",backgroundColor:"#ffffff"
}
valueTile("temperature","device.temperature",inactiveLabel: false) {
state "temperature",label:'${currentValue}°',backgroundColors:[
[value: 32, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 92, color: "#d04e00"],
[value: 98, color: "#bc2323"]
]
}
valueTile(
"humidity","device.humidity",inactiveLabel: false) {
state "humidity",label:'RH ${currentValue} %',unit:""
}
valueTile(
"illuminance","device.illuminance",inactiveLabel: false) {
state "luminosity",label:'${currentValue} ${unit}', unit:"lux", backgroundColors:[
[value: 0, color: "#000000"],
[value: 47, color: "#1A1A0A"],
[value: 94, color: "#333314"],
[value: 141, color: "#4C4C1F"],
[value: 188, color: "#666629"],
[value: 235, color: "#808033"],
[value: 282, color: "#99993D"],
[value: 329, color: "#B2B247"],
[value: 376, color: "#CCCC52"],
[value: 423, color: "#E6E65C"],
[value: 470, color: "#FFFF66"],
[value: 517, color: "#FFFF75"],
[value: 564, color: "#FFFF85"],
[value: 611, color: "#FFFF94"],
[value: 658, color: "#FFFFA3"],
[value: 705, color: "#FFFFB2"],
[value: 752, color: "#FFFFC2"],
[value: 799, color: "#FFFFD1"],
[value: 846, color: "#FFFFE0"],
[value: 900, color: "#FFFFF0"],
[value: 1000, color: "#FFFFFF"]
]
}
valueTile(
"ultravioletIndex","device.ultravioletIndex",inactiveLabel: false) {
state "ultravioletIndex",label:'${currentValue} UV INDEX',unit:""
}
standardTile(
"tamper","device.tamper") {
state "tamper",label:'tamper',icon:"st.motion.motion.active",backgroundColor:"#ff0000"
state "clear",label:'clear',icon:"st.motion.motion.inactive",backgroundColor:"#00ff00"
}
valueTile(
"battery", "device.battery", inactiveLabel: false, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""
}
standardTile(
"configure","device.configure",inactiveLabel: false, decoration: "flat") {
state "configure", label:'insecure config', action:"configure", icon:"st.secondary.tools"
}
standardTile(
"configureAfterSecure", "device.configure", inactiveLabel: false, decoration: "flat") {
state "configure", label:'secure config', action:"configureAfterSecure", icon:"st.secondary.tools"
}
main([
"motion","tamper","temperature","humidity","illuminance","ultravioletIndex"
])
details([
"motion","tamper","temperature","humidity","illuminance","ultravioletIndex","battery","configure","configureAfterSecure"
])
}
preferences {
input "tempoffset",
"number",
title: "Temperature offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "..",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "humidityoffset",
"number",
title: "Humidity offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "..",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "luminanceoffset",
"number",
title: "Luminance offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "..",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "ultravioletoffset",
"number",
title: "Ultraviolet offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "..",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "PIRsensitivity",
"number",
title: "PIR motion sensitivity",
description: "A value from 0-5, from disabled to high sensitivity",
defaultValue: 1,
required: true,
displayDuringSetup: true
input "ReportingInterval",
"number",
title: "Report data interval",
description: "A value in seconds.",
defaultValue: 300,
required: true,
displayDuringSetup: true
}
}
def parse(String description) {
def result = null
if (description == "updated") {
result = null
}
else {
def cmd = zwave.parse(description, [0x31: 5, 0x30: 2, 0x84: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
log.debug "Parsed '${description}' to ${result.inspect()}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)]
if (!isConfigured()) {
// we're still in the process of configuring a newly joined device
log.debug("have not sent config yet - not sending wakeUpNoMoreInformation yet")
result += response(configureAfterSecure())
result += response(configure())
} else {
result += response(zwave.wakeUpV1.wakeUpNoMoreInformation())
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x31: 5, 0x30: 2, 0x84: 1])
log.debug "encapsulated: ${encapsulatedCommand}"
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
log.debug "Received SecurityCommandsSupportedReport"
// response(configureAfterSecure())
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) {
map.value = 1
map.descriptionText = "${device.displayName} battery is low"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
state.lastbatt = new Date().time
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd)
{
def map = [:]
switch (cmd.sensorType) {
case 1:
map.name = "temperature"
def cmdScale = cmd.scale == 1 ? "F" : "C"
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
map.unit = getTemperatureScale()
break;
case 3:
map.name = "illuminance"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = "lux"
break;
case 5:
map.name = "humidity"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = "%"
break;
case 27:
map.name = "ultravioletIndex"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = ""
break;
default:
map.descriptionText = cmd.toString()
}
createEvent(map)
}
def motionEvent(value) {
def map = [name: "motion"]
if (value) {
map.value = "active"
map.descriptionText = "$device.displayName detected motion"
} else {
map.value = "inactive"
map.descriptionText = "$device.displayName motion has stopped"
}
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv2.SensorBinaryReport cmd) {
// setConfigured()
motionEvent(cmd.sensorValue)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
motionEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
def result = []
if (cmd.notificationType == 7) {
switch (cmd.event) {
case 0:
result << motionEvent(0)
result << createEvent(name: "tamper", value: "clear", descriptionText: "$device.displayName tamper cleared")
break
case 3:
result << createEvent(name: "tamper", value: "detected", descriptionText: "$device.displayName was moved")
break
case 7:
result << motionEvent(1)
break
}
} else {
result << createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
result
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
def configureAfterSecure() {
log.debug "configureAfterSecure"
log.debug "PIRsensitivity: $PIRsensitivity, Reporting Interval: $ReportingInterval, Temp offset: $tempoffset, Humidity offset: $humidityoffset, Luminance offset: $luminanceoffset, UV offset: $ultravioletoffset"
def PIRsens = 1
if (PIRsensitivity) {
PIRsens=PIRsensitivity.toInteger()
}
def ReportingInt = 300
if (ReportingInterval) {
ReportingInt=ReportingInterval.toInteger()
}
def tempoff = 0
if (tempoffset) {
if(tempoffset < 0) {
tempoff=(255-tempoffset)
}
if(tempoffset > 0) {
tempoff=(0+tempoffset)
}
}
def humidityoff = 0
if (humidityoffset) {
humidityoff=humidityoffset.toInteger()
}
def luminanceoff = 0
if (luminanceoffset) {
luminanceoff=luminanceoffset.toInteger()
}
def ultravioletoff = 0
if (ultravioletoffset) {
ultravioletoff=ultravioletoffset.toInteger()
}
//log.debug "PIRsens: $PIRsens, ReportingInt: $ReportingInt, Tempoffset: $tempoff, Humidityoff: $humidityoff, Luminanceoff: $luminanceoff, UVoff: $ultravioletoff"
def request = [
// set wakeup interval to 5 mins
zwave.wakeUpV1.wakeUpIntervalSet(seconds:300, nodeid:zwaveHubNodeId),
// send temperature, humidity, illuminance, ultraviolet based on reporting interval preference default 5 mins
zwave.configurationV1.configurationSet(parameterNumber: 0x65, size: 4, scaledConfigurationValue: 128|64|32|16),
// configure frequency of reporting
zwave.configurationV1.configurationSet(parameterNumber: 0x6F,size: 4, scaledConfigurationValue: ReportingInt),
// send battery every 20 hours
zwave.configurationV1.configurationSet(parameterNumber: 0x66, size: 4, scaledConfigurationValue: 1),
zwave.configurationV1.configurationSet(parameterNumber: 0x70, size: 4, scaledConfigurationValue: 20*60*60),
// send no-motion report 20 seconds after motion stops
zwave.configurationV1.configurationSet(parameterNumber: 0x03, size: 2, scaledConfigurationValue: 20),
// enable motion sensor and set sensitivity
zwave.configurationV1.configurationSet(parameterNumber: 0x04, size: 1, scaledConfigurationValue: PIRsens),
// send binary sensor report for motion
zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 2),
// Enable the function of touch sensor
// zwave.configurationV1.configurationSet(parameterNumber: 0x07, size: 1, scaledConfigurationValue: 1),
// disable notification-style motion events
zwave.notificationV3.notificationSet(notificationType: 7, notificationStatus: 0),
// configure temp offset
zwave.configurationV1.configurationSet(parameterNumber: 0xC9, size: 2, scaledConfigurationValue: tempoff),
// configure humidity offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCA, size: 2, scaledConfigurationValue: humidityoff),
// configure luminance offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCB, size: 2, scaledConfigurationValue: luminanceoff),
// configure ultraviolet offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCC, size: 2, scaledConfigurationValue: ultravioletoff),
zwave.batteryV1.batteryGet(),
zwave.sensorBinaryV2.sensorBinaryGet(),
// Can use the zwaveHubNodeId variable to add the hub to the device's associations:
zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)
]
//log.debug request
secureSequence(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
setConfigured()
}
def configure() {
//["delay 20000"] + secure(zwave.securityV1.securityCommandsSupportedGet())
log.debug "configure"
log.debug "PIRsensitivity: $PIRsensitivity, Reporting Interval: $ReportingInterval, Temp offset: $tempoffset, Humidity offset: $humidityoffset, Luminance offset: $luminanceoffset, UV offset: $ultravioletoffset"
def PIRsens = 1
if (PIRsensitivity) {
PIRsens=PIRsensitivity.toInteger()
}
def ReportingInt = 300
if (ReportingInterval) {
ReportingInt=ReportingInterval.toInteger()
}
def tempoff = 0
if (tempoffset) {
if(tempoffset < 0) {
tempoff=(255-tempoffset)
}
if(tempoffset > 0) {
tempoff=(0+tempoffset)
}
}
def humidityoff = 0
if (humidityoffset) {
humidityoff=humidityoffset.toInteger()
}
def luminanceoff = 0
if (luminanceoffset) {
luminanceoff=luminanceoffset.toInteger()
}
def ultravioletoff = 0
if (ultravioletoffset) {
ultravioletoff=ultravioletoffset.toInteger()
}
log.debug "PIRsens: $PIRsens, ReportingInt: $ReportingInt, Tempoffset: $tempoff, Humidityoff: $humidityoff, Luminanceoff: $luminanceoff, UVoff: $ultravioletoff"
delayBetween([
// set wakeup interval to 5 minutes
zwave.wakeUpV1.wakeUpIntervalSet(seconds:300, nodeid:zwaveHubNodeId).format(),
// send temperature, humidity, illuminance, ultraviolet based on reporting interval preference default 5 mins
zwave.configurationV1.configurationSet(parameterNumber: 0x65, size: 4, scaledConfigurationValue: 128|64|32|16).format(),
zwave.configurationV1.configurationSet(parameterNumber: 0x6F, size: 4, scaledConfigurationValue: ReportingInt).format(),
// send battery every 20 hours
zwave.configurationV1.configurationSet(parameterNumber: 0x66, size: 4, scaledConfigurationValue: 1).format(),
zwave.configurationV1.configurationSet(parameterNumber: 0x70, size: 4, scaledConfigurationValue: 20*60*60).format(),
// send no-motion report 20 seconds after motion stops
zwave.configurationV1.configurationSet(parameterNumber: 0x03, size: 2, scaledConfigurationValue: 20).format(),
// enable motion sensor and set min sensitivity
zwave.configurationV1.configurationSet(parameterNumber: 0x04, size: 1, scaledConfigurationValue: PIRsens).format(),
// send binary sensor report for motion
zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 2).format(),
// Enable the function of touch sensor
//zwave.configurationV1.configurationSet(parameterNumber: 0x07, size: 1, scaledConfigurationValue: 1).format(),
// disable notification-style motion events
zwave.notificationV3.notificationSet(notificationType: 7, notificationStatus: 0).format(),
// configure temp offset
zwave.configurationV1.configurationSet(parameterNumber: 0xC9, size: 2, scaledConfigurationValue: tempoff).format(),
// configure humidity offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCA, size: 2, scaledConfigurationValue: humidityoff).format(),
// configure luminance offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCB, size: 2, scaledConfigurationValue: luminanceoff).format(),
// configure ultraviolet offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCC, size: 2, scaledConfigurationValue: ultravioletoff).format(),
zwave.batteryV1.batteryGet(),
zwave.sensorBinaryV2.sensorBinaryGet(),
// Can use the zwaveHubNodeId variable to add the hub to the device's associations:
zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)
])
zwave.wakeUpV1.wakeUpNoMoreInformation().format()
setConfigured()
}
def setConfigured() {
device.updateDataValue("configured", "true")
}
def isConfigured() {
Boolean configured = device.getDataValue(["configured"]) as Boolean
return configured
}
private secure(physicalgraph.zwave.Command cmd) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
}
private secureSequence(commands, delay=200) {
delayBetween(commands.collect{ secure(it) }, delay)
}
def updated() {
log.debug "updated()"
log.debug "PIRsensitivity: $PIRsensitivity, Reporting Interval: $ReportingInterval, Temp offset: $tempoffset, Humidity offset: $humidityoffset, Luminance offset: $luminanceoffset, UV offset: $ultravioletoffset"
//configure()
}
================================================
FILE: Aeon Multisensor 6/device_type-aeon-multisensor6-v1.4
================================================
/*
* V 1.4 of Multisensor 6 code 9/14/2015
* Uses some original code from @Duncan Aeon Multisensor 6 code for secure configuration, Copyright 2015 SmartThings, modified for setting
* preferences around configuration and the reporting of tampering and ultraviolet index, and reconfiguration after pairing.
* Robert Vandervoort 6/19/2015 - 9/20/2015
*
* 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.
*
* INSTRUCTIONS: Pair device to SmartThings by double tapping the inclusion button. Allow it to join with SmartThings device type. After
* adding, go to device entry in the website, edit it, change type to Aeon Multisensor 6 - RV, open device in SmartThings app, edit
* edit preferences to your liking but do not save yet, short press action button on sensor one time and the light should go blue, hit save
* in the app, a couple seconds later the light should go out (you can verify in live logging that it says it woke up and settings were sent
* over).. Now on device screen, short press the action button one more time and hit secure configure button on the app screen... Your sensor
* should now follow your polling interval, but will go no lower than 5 minute intervals unless a large enough change happens to warrant it.
* motion activates immediately and clears after 20 seconds. tamper activates immediately and also clears after 20 seconds. Currently tamper
* is just used for logging and as an indicator on the screen. If requests for functionality outside of that are required please message me.
*/
metadata {
definition (name: "Aeon Multisensor 6 - RV", namespace: "robertvandervoort", author: "Robert Vandervoort") {
capability "Motion Sensor"
capability "Temperature Measurement"
capability "Relative Humidity Measurement"
capability "Illuminance Measurement"
capability "Ultraviolet Index"
capability "Configuration"
capability "Sensor"
capability "Battery"
// CCs supported - 94, 134, 114, 132, 89, 133, 115, 113, 128, 48, 49, 112, 152, 122
attribute "tamper", "enum", ["detected", "clear"]
fingerprint deviceId: "0x2101", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0xEF,0x5A,0x98,0x7A"
}
simulator {
status "no motion" : "command: 9881, payload: 00300300"
status "motion" : "command: 9881, payload: 003003FF"
status "clear" : " command: 9881, payload: 0071050000000007030000"
status "tamper" : "command: 9881, payload: 007105000000FF07030000"
for (int i = 0; i <= 100; i += 20) {
status "temperature ${i}F": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
precision: 1,
sensorType: 1,
scale: 1
)
).incomingMessage()
}
for (int i = 0; i <= 100; i += 20) {
status "RH ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 5
)
).incomingMessage()
}
for (int i in [0, 1, 2, 8, 12, 16, 20, 24, 30, 64, 82, 100, 200, 500, 1000]) {
status "illuminance ${i} lux": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 3
)
).incomingMessage()
}
for (int i = 0; i <= 11; i += 1) {
status "ultravioletultravioletIndex ${i}": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 27
)
).incomingMessage()
}
for (int i in [0, 5, 10, 15, 50, 99, 100]) {
status "battery ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: i
)
).incomingMessage()
}
status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: 255
)
).incomingMessage()
status "wake up": "command: 8407, payload:"
}
tiles {
standardTile("motion","device.motion") {
state "active",label:'motion',icon:"st.motion.motion.active",backgroundColor:"#53a7c0"
state "inactive",label:'no motion',icon:"st.motion.motion.inactive",backgroundColor:"#ffffff"
}
valueTile("temperature","device.temperature") {
state "temperature",label:'${currentValue}°',backgroundColors:[
[value: 32, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 92, color: "#d04e00"],
[value: 98, color: "#bc2323"]
]
}
valueTile(
"humidity","device.humidity") {
state "humidity",label:'RH ${currentValue} %',unit:""
}
valueTile(
"illuminance","device.illuminance") {
state "luminosity",label:'${currentValue} ${unit}', unit:"lux", backgroundColors:[
[value: 0, color: "#000000"],
[value: 1, color: "#060053"],
[value: 3, color: "#3E3900"],
[value: 12, color: "#8E8400"],
[value: 24, color: "#C5C08B"],
[value: 36, color: "#DAD7B6"],
[value: 128, color: "#F3F2E9"],
[value: 1000, color: "#FFFFFF"]
]
}
valueTile(
"ultravioletIndex","device.ultravioletIndex") {
state "ultravioletIndex",label:'${currentValue} UV INDEX',unit:""
}
standardTile(
"tamper","device.tamper") {
state "tamper",label:'tamper',icon:"st.motion.motion.active",backgroundColor:"#ff0000"
state "clear",label:'clear',icon:"st.motion.motion.inactive",backgroundColor:"#00ff00"
}
valueTile(
"battery", "device.battery", decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""
}
standardTile(
"configure","device.configure", decoration: "flat") {
state "configure", label:'config', action:"configure", icon:"st.secondary.tools"
}
main([
"temperature","humidity","illuminance","motion","tamper","ultravioletIndex"
])
details([
"temperature","humidity","illuminance","motion","tamper","ultravioletIndex","battery","configure"
])
}
preferences {
input "tempoffset",
"number",
title: "Temperature offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "..",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "humidityoffset",
"number",
title: "Humidity offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "..",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "luminanceoffset",
"number",
title: "Luminance offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "..",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "ultravioletoffset",
"number",
title: "Ultraviolet offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "..",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "PIRsensitivity",
"number",
title: "PIR motion sensitivity",
description: "A value from 0-5, from disabled to high sensitivity",
defaultValue: 1,
required: true,
displayDuringSetup: true
input "ReportingInterval",
"number",
title: "Report data interval",
description: "A value in seconds.",
defaultValue: 300,
required: true,
displayDuringSetup: true
}
}
def updated()
{
if (state.sec && !isConfigured()) {
// in case we miss the SCSR
response(configure())
}
}
def parse(String description)
{
def result = null
if (description.startsWith("Err 106")) {
state.sec = 0
result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true,
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.")
} else if (description != "updated") {
def cmd = zwave.parse(description, [0x31: 5, 0x30: 2, 0x84: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
log.debug "Parsed '${description}' to ${result.inspect()}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)]
if (!isConfigured()) {
// we're still in the process of configuring a newly joined device
log.debug("late configure")
result += response(configure())
} else {
result += response(zwave.wakeUpV1.wakeUpNoMoreInformation())
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x31: 5, 0x30: 2, 0x84: 1])
state.sec = 1
log.debug "encapsulated: ${encapsulatedCommand}"
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
response(configure())
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) {
map.value = 1
map.descriptionText = "${device.displayName} battery is low"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
state.lastbatt = now()
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd)
{
def map = [:]
switch (cmd.sensorType) {
case 1:
map.name = "temperature"
def cmdScale = cmd.scale == 1 ? "F" : "C"
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
map.unit = getTemperatureScale()
break;
case 3:
map.name = "illuminance"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = "lux"
break;
case 5:
map.name = "humidity"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = "%"
break;
case 27:
map.name = "ultravioletIndex"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = ""
break;
default:
map.descriptionText = cmd.toString()
}
createEvent(map)
}
def motionEvent(value) {
def map = [name: "motion"]
if (value) {
map.value = "active"
map.descriptionText = "$device.displayName detected motion"
} else {
map.value = "inactive"
map.descriptionText = "$device.displayName motion has stopped"
}
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv2.SensorBinaryReport cmd) {
setConfigured()
motionEvent(cmd.sensorValue)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
motionEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
def result = []
if (cmd.notificationType == 7) {
switch (cmd.event) {
case 0:
result << motionEvent(0)
result << createEvent(name: "tamper", value: "clear", descriptionText: "$device.displayName tamper cleared")
break
case 3:
result << createEvent(name: "tamper", value: "detected", descriptionText: "$device.displayName was moved")
break
case 7:
result << motionEvent(1)
break
}
} else {
result << createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
result
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
def configure() {
// This sensor joins as a secure device if you double-click the button to include it
//if (device.device.rawDescription =~ /98/ && !state.sec) {
// log.debug "Multi 6 not sending configure until secure"
// return []
//}
log.debug "--Sending configuration command to Multisensor 6--"
//log.debug "Prefernces settings: PIRsensitivity: $PIRsensitivity, Reporting Interval: $ReportingInterval, Temp offset: $tempoffset, Humidity offset: $humidityoffset, Luminance offset: $luminanceoffset, UV offset: $ultravioletoffset"
def PIRsens = 1
if (PIRsensitivity) {
PIRsens=PIRsensitivity.toInteger()
}
def ReportingInt = 300
if (ReportingInterval) {
ReportingInt=ReportingInterval.toInteger()
}
def tempoff = 0
if (tempoffset) {
if(tempoffset < 0) {
tempoff=(255-tempoffset)
}
if(tempoffset > 0) {
tempoff=(0+tempoffset)
}
}
def humidityoff = 0
if (humidityoffset) {
if(humidityoffset < 0) {
humidityoff=(255-humidityoffset)
}
if(humidityoffset > 0) {
humidityoff=(0+humidityoffset)
}
}
def luminanceoff = 0
if (luminanceoffset) {
if(luminanceoffset < 0) {
luminanceoff=(255-luminanceoffset)
}
if(luminanceoffset > 0) {
luminanceoff=(0+luminanceoffset)
}
}
def ultravioletoff = 0
if (ultravioletoffset) {
if(ultravioletoffset < 0) {
ultravioletoff=(255-ultravioletoffset)
}
if(ultravioletoffset > 0) {
ultravioletoff=(0 + ultravioletoffset)
}
}
//log.debug "Setting - PIRsens: $PIRsens, ReportingInt: $ReportingInt, Tempoffset: $tempoff, Humidityoff: $humidityoff, Luminanceoff: $luminanceoff, UVoff: $ultravioletoff"
def request = [
// set wakeup interval to 5 mins
zwave.wakeUpV1.wakeUpIntervalSet(seconds:300, nodeid:zwaveHubNodeId),
// send temperature, humidity, illuminance, ultraviolet based on reporting interval preference default 5 mins
zwave.configurationV1.configurationSet(parameterNumber: 0x65, size: 4, scaledConfigurationValue: 128|64|32|16),
// configure frequency of reporting
zwave.configurationV1.configurationSet(parameterNumber: 0x6F,size: 4, scaledConfigurationValue: ReportingInt),
// send battery every 20 hours
zwave.configurationV1.configurationSet(parameterNumber: 0x66, size: 4, scaledConfigurationValue: 1),
zwave.configurationV1.configurationSet(parameterNumber: 0x70, size: 4, scaledConfigurationValue: 20*60*60),
// send no-motion report 20 seconds after motion stops
zwave.configurationV1.configurationSet(parameterNumber: 0x03, size: 2, scaledConfigurationValue: 20),
// enable motion sensor and set sensitivity
zwave.configurationV1.configurationSet(parameterNumber: 0x04, size: 1, scaledConfigurationValue: PIRsens),
// send binary sensor report for motion
zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 2),
// Enable the function of touch sensor
zwave.configurationV1.configurationSet(parameterNumber: 0x07, size: 1, scaledConfigurationValue: 1),
// disable notification-style motion events
// zwave.notificationV3.notificationSet(notificationType: 7, notificationStatus: 0),
// configure temp offset
zwave.configurationV1.configurationSet(parameterNumber: 0xC9, size: 1, scaledConfigurationValue: tempoff),
// configure humidity offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCA, size: 1, scaledConfigurationValue: humidityoff),
// configure luminance offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCB, size: 2, scaledConfigurationValue: luminanceoff),
// configure ultraviolet offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCC, size: 1, scaledConfigurationValue: ultravioletoff),
zwave.batteryV1.batteryGet(),
zwave.sensorBinaryV2.sensorBinaryGet(),
// Can use the zwaveHubNodeId variable to add the hub to the device's associations:
zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)
]
commands(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
}
private setConfigured() {
updateDataValue("configured", "true")
}
private isConfigured() {
getDataValue("configured") == "true"
}
private command(physicalgraph.zwave.Command cmd) {
if (state.sec) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=200) {
delayBetween(commands.collect{ command(it) }, delay)
}
================================================
FILE: Aeon Multisensor 6/device_type-aeon-multisensor6-v1.5
================================================
/*
* V 1.5 of Multisensor 6 code 9/14/2015
* Uses some original code from @Duncan Aeon Multisensor 6 code for secure configuration, Copyright 2015 SmartThings, modified for setting
* preferences around configuration and the reporting of tampering and ultraviolet index, and reconfiguration after pairing.
* Robert Vandervoort 6/19/2015 - 9/20/2015
*
* 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.
*
* INSTRUCTIONS: Pair device to SmartThings by double tapping the inclusion button. Allow it to join with SmartThings device type. After
* adding, go to device entry in the website, edit it, change type to Aeon Multisensor 6 - RV, open device in SmartThings app, edit
* edit preferences to your liking but do not save yet, short press action button on sensor one time and the light should go blue, hit save
* in the app, a couple seconds later the light should go out (you can verify in live logging that it says it woke up and settings were sent
* over).. Now on device screen, short press the action button one more time and hit secure configure button on the app screen... Your sensor
* should now follow your polling interval, but will go no lower than 5 minute intervals unless a large enough change happens to warrant it.
* motion activates immediately and clears after 20 seconds. tamper activates immediately and also clears after 20 seconds. Currently tamper
* is just used for logging and as an indicator on the screen. If requests for functionality outside of that are required please message me.
*/
metadata {
definition (name: "Aeon Multisensor 6 - RV 1.5", namespace: "robertvandervoort", author: "Robert Vandervoort") {
capability "Motion Sensor"
capability "Temperature Measurement"
capability "Relative Humidity Measurement"
capability "Illuminance Measurement"
capability "Ultraviolet Index"
capability "Configuration"
capability "Sensor"
capability "Battery"
// CCs supported - 94, 134, 114, 132, 89, 133, 115, 113, 128, 48, 49, 112, 152, 122
attribute "tamper", "enum", ["detected", "clear"]
fingerprint deviceId: "0x2101", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0xEF,0x5A,0x98,0x7A"
}
simulator {
status "no motion" : "command: 9881, payload: 00300300"
status "motion" : "command: 9881, payload: 003003FF"
status "clear" : " command: 9881, payload: 0071050000000007030000"
status "tamper" : "command: 9881, payload: 007105000000FF07030000"
for (int i = 0; i <= 100; i += 20) {
status "temperature ${i}F": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
precision: 1,
sensorType: 1,
scale: 1
)
).incomingMessage()
}
for (int i = 0; i <= 100; i += 20) {
status "RH ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 5
)
).incomingMessage()
}
for (int i in [0, 1, 2, 8, 12, 16, 20, 24, 30, 64, 82, 100, 200, 500, 1000]) {
status "illuminance ${i} lux": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 3
)
).incomingMessage()
}
for (int i = 0; i <= 11; i += 1) {
status "ultravioletultravioletIndex ${i}": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 27
)
).incomingMessage()
}
for (int i in [0, 5, 10, 15, 50, 99, 100]) {
status "battery ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: i
)
).incomingMessage()
}
status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: 255
)
).incomingMessage()
status "wake up": "command: 8407, payload:"
}
tiles {
standardTile("motion","device.motion") {
state "active",label:'motion',icon:"st.motion.motion.active",backgroundColor:"#53a7c0"
state "inactive",label:'no motion',icon:"st.motion.motion.inactive",backgroundColor:"#ffffff"
}
valueTile("temperature","device.temperature") {
state "temperature",label:'${currentValue}°',backgroundColors:[
[value: 32, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 92, color: "#d04e00"],
[value: 98, color: "#bc2323"]
]
}
valueTile(
"humidity","device.humidity") {
state "humidity",label:'RH ${currentValue} %',unit:""
}
valueTile(
"illuminance","device.illuminance") {
state "luminosity",label:'${currentValue} ${unit}', unit:"lux", backgroundColors:[
[value: 0, color: "#000000"],
[value: 1, color: "#060053"],
[value: 3, color: "#3E3900"],
[value: 12, color: "#8E8400"],
[value: 24, color: "#C5C08B"],
[value: 36, color: "#DAD7B6"],
[value: 128, color: "#F3F2E9"],
[value: 1000, color: "#FFFFFF"]
]
}
valueTile(
"ultravioletIndex","device.ultravioletIndex") {
state "ultravioletIndex",label:'${currentValue} UV INDEX',unit:""
}
standardTile(
"tamper","device.tamper") {
state "tamper",label:'tamper',icon:"st.motion.motion.active",backgroundColor:"#ff0000"
state "clear",label:'clear',icon:"st.motion.motion.inactive",backgroundColor:"#00ff00"
}
valueTile(
"battery", "device.battery", decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""
}
standardTile(
"configure","device.configure", decoration: "flat") {
state "configure", label:'config', action:"configure", icon:"st.secondary.tools"
}
main([
"temperature","humidity","illuminance","motion","tamper","ultravioletIndex"
])
details([
"temperature","humidity","illuminance","motion","tamper","ultravioletIndex","battery","configure"
])
}
preferences {
input "tempoffset",
"number",
title: "Temperature offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "-11..11",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "humidityoffset",
"number",
title: "Humidity offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "-50..50",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "luminanceoffset",
"number",
title: "Luminance offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "-1000..1000",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "ultravioletoffset",
"number",
title: "Ultraviolet offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "-10..10",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "PIRsensitivity",
"number",
title: "PIR motion sensitivity",
description: "A value from 0-5, from disabled to high sensitivity",
range: "0..5",
defaultValue: 1,
required: true,
displayDuringSetup: true
input "MotionReset",
"number",
title: "PIR reset time",
description: "Number of seconds to wait to report motion cleared after a motion event if there is no motion detected.",
defaultValue: 20,
required: true,
displayDuringSetup: true
input "ReportingInterval",
"number",
title: "Report data interval",
description: "A value in seconds.",
defaultValue: 300,
required: true,
displayDuringSetup: true
}
}
def updated()
{
if (state.sec && !isConfigured()) {
// in case we miss the SCSR
response(configure())
}
}
def parse(String description)
{
def result = null
if (description.startsWith("Err 106")) {
state.sec = 0
result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true,
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.")
} else if (description != "updated") {
def cmd = zwave.parse(description, [0x31: 5, 0x30: 2, 0x84: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
log.debug "Parsed '${description}' to ${result.inspect()}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)]
if (!isConfigured()) {
// we're still in the process of configuring a newly joined device
log.debug("late configure")
result += response(configure())
} else {
result += response(zwave.wakeUpV1.wakeUpNoMoreInformation())
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x31: 5, 0x30: 2, 0x84: 1])
state.sec = 1
log.debug "encapsulated: ${encapsulatedCommand}"
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
response(configure())
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) {
log.debug "---CONFIGURATION REPORT V2--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) {
map.value = 1
map.descriptionText = "${device.displayName} battery is low"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
state.lastbatt = now()
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd)
{
def map = [:]
switch (cmd.sensorType) {
case 1:
map.name = "temperature"
def cmdScale = cmd.scale == 1 ? "F" : "C"
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
map.unit = getTemperatureScale()
break;
case 3:
map.name = "illuminance"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = "lux"
break;
case 5:
map.name = "humidity"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = "%"
break;
case 27:
map.name = "ultravioletIndex"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = ""
break;
default:
map.descriptionText = cmd.toString()
}
createEvent(map)
}
def motionEvent(value) {
def map = [name: "motion"]
if (value) {
map.value = "active"
map.descriptionText = "$device.displayName detected motion"
} else {
map.value = "inactive"
map.descriptionText = "$device.displayName motion has stopped"
}
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv2.SensorBinaryReport cmd) {
setConfigured()
motionEvent(cmd.sensorValue)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
motionEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
def result = []
if (cmd.notificationType == 7) {
switch (cmd.event) {
case 0:
result << motionEvent(0)
result << createEvent(name: "tamper", value: "clear", descriptionText: "$device.displayName tamper cleared")
break
case 3:
result << createEvent(name: "tamper", value: "detected", descriptionText: "$device.displayName was moved")
break
case 7:
result << motionEvent(1)
break
}
} else {
result << createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
result
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
def configure() {
// This sensor joins as a secure device if you double-click the button to include it
//if (device.device.rawDescription =~ /98/ && !state.sec) {
// log.debug "Multi 6 not sending configure until secure"
// return []
//}
log.debug "--Sending configuration command to Multisensor 6--"
log.debug "Prefernces settings: PIRsensitivity: $PIRsensitivity, Reporting Interval: $ReportingInterval, Temp offset: $tempoffset, Humidity offset: $humidityoffset, Luminance offset: $luminanceoffset, UV offset: $ultravioletoffset"
def PIRsens = 1
if (PIRsensitivity) {
PIRsens=PIRsensitivity.toInteger()
}
def MotionRst = 20
if (MotionReset) {
MotionRst=MotionReset.toInteger()
}
def ReportingInt = 300
if (ReportingInterval) {
ReportingInt=ReportingInterval.toInteger()
}
def tempoff = 0
if (tempoffset) {
tempoff=tempoffset*10
}
def humidityoff = 0
if (humidityoffset) {
humidityoff=humidityoffset
}
def luminanceoff = 0
if (luminanceoffset) {
luminanceoff=luminanceoffset
}
def ultravioletoff = 0
if (ultravioletoffset) {
ultravioletoff=ultravioletoffset
}
log.debug "Setting - PIRsens: $PIRsens, ReportingInt: $ReportingInt, Tempoffset: $tempoff, Humidityoff: $humidityoff, Luminanceoff: $luminanceoff, UVoff: $ultravioletoff"
def request = [
// set wakeup interval to 5 mins
zwave.wakeUpV1.wakeUpIntervalSet(seconds:300, nodeid:zwaveHubNodeId),
// send temperature, humidity, illuminance, ultraviolet based on reporting interval preference default 5 mins
zwave.configurationV1.configurationSet(parameterNumber: 0x65, size: 4, scaledConfigurationValue: 128|64|32|16),
// configure frequency of reporting
zwave.configurationV1.configurationSet(parameterNumber: 0x6F,size: 4, scaledConfigurationValue: ReportingInt),
// send battery every 20 hours
zwave.configurationV1.configurationSet(parameterNumber: 0x66, size: 4, scaledConfigurationValue: 1),
zwave.configurationV1.configurationSet(parameterNumber: 0x70, size: 4, scaledConfigurationValue: 20*60*60),
// send no-motion report 20 seconds after motion stops
zwave.configurationV1.configurationSet(parameterNumber: 0x03, size: 2, scaledConfigurationValue: MotionRst),
// enable motion sensor and set sensitivity
zwave.configurationV1.configurationSet(parameterNumber: 0x04, size: 1, scaledConfigurationValue: PIRsens),
// send binary sensor report for motion
zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 2),
// Enable the function of touch sensor
zwave.configurationV1.configurationSet(parameterNumber: 0x07, size: 1, scaledConfigurationValue: 1),
// disable notification-style motion events
// zwave.notificationV3.notificationSet(notificationType: 7, notificationStatus: 0),
// configure temp offset
zwave.configurationV1.configurationSet(parameterNumber: 0xC9, size: 1, scaledConfigurationValue: tempoff),
// configure humidity offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCA, size: 1, scaledConfigurationValue: humidityoff),
// configure luminance offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCB, size: 2, scaledConfigurationValue: luminanceoff),
// configure ultraviolet offset
zwave.configurationV1.configurationSet(parameterNumber: 0xCC, size: 1, scaledConfigurationValue: ultravioletoff),
zwave.configurationV1.configurationGet(parameterNumber: 0x6F),
zwave.configurationV1.configurationGet(parameterNumber: 0x03),
zwave.configurationV1.configurationGet(parameterNumber: 0x04),
zwave.configurationV1.configurationGet(parameterNumber: 0x28),
zwave.configurationV1.configurationGet(parameterNumber: 0xC9),
zwave.configurationV1.configurationGet(parameterNumber: 0xCA),
zwave.configurationV1.configurationGet(parameterNumber: 0xCB),
zwave.configurationV1.configurationGet(parameterNumber: 0xCC),
zwave.batteryV1.batteryGet(),
zwave.sensorBinaryV2.sensorBinaryGet(),
// Can use the zwaveHubNodeId variable to add the hub to the device's associations:
zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId)
]
commands(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
}
private setConfigured() {
updateDataValue("configured", "true")
}
private isConfigured() {
getDataValue("configured") == "true"
}
private command(physicalgraph.zwave.Command cmd) {
if (state.sec) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay=200) {
delayBetween(commands.collect{ command(it) }, delay)
}
================================================
FILE: Aeon Multisensor 6/device_type-aeon-multisensor6-v2.0
================================================
/*
* V 2.0 of Multisensor 6 code 9/14/2015
* Uses some original code from @Duncan Aeon Multisensor 6 code for secure configuration, Copyright 2015 SmartThings, modified for setting
* preferences around configuration and the reporting of tampering and ultraviolet index, and reconfiguration after pairing.
* 2.0 brings about the new style look with multiattribute tile for temp and humidity
* Robert Vandervoort 6/19/2015 - 11/5/2015
*
* 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.
*
* INSTRUCTIONS: Pair device to SmartThings by double tapping the inclusion button. Allow it to join with SmartThings device type. After
* adding, go to device entry in the website, edit it, change type to Aeon Multisensor 6 - RV, open device in SmartThings app, edit
* edit preferences to your liking but do not save yet, short press action button on sensor one time and the light should go blue, hit save
* in the app, a couple seconds later the light should go out (you can verify in live logging that it says it woke up and settings were sent
* over).. Now on device screen, short press the action button one more time and hit secure configure button on the app screen... Your sensor
* should now follow your polling interval, but will go no lower than 5 minute intervals unless a large enough change happens to warrant it.
* motion activates immediately and clears after 20 seconds. tamper activates immediately and also clears after 20 seconds. Currently tamper
* is just used for logging and as an indicator on the screen. If requests for functionality outside of that are required please message me.
*/
metadata {
definition (name: "Aeon Multisensor 6 - RV 2.0", namespace: "robertvandervoort", author: "Robert Vandervoort") {
capability "Motion Sensor"
capability "Temperature Measurement"
capability "Relative Humidity Measurement"
capability "Illuminance Measurement"
capability "Ultraviolet Index"
capability "Configuration"
capability "Sensor"
capability "Battery"
// CCs supported - 94, 134, 114, 132, 89, 133, 115, 113, 128, 48, 49, 112, 152, 122
attribute "tamper", "enum", ["detected", "clear"]
fingerprint deviceId: "0x2101", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0xEF,0x5A,0x98,0x7A"
}
simulator {
status "no motion" : "command: 9881, payload: 00300300"
status "motion" : "command: 9881, payload: 003003FF"
status "clear" : " command: 9881, payload: 0071050000000007030000"
status "tamper" : "command: 9881, payload: 007105000000FF07030000"
for (int i = 0; i <= 100; i += 20) {
status "temperature ${i}F": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
precision: 1,
sensorType: 1,
scale: 1
)
).incomingMessage()
}
for (int i = 0; i <= 100; i += 20) {
status "RH ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 5
)
).incomingMessage()
}
for (int i in [0, 1, 2, 8, 12, 16, 20, 24, 30, 64, 82, 100, 200, 500, 1000]) {
status "illuminance ${i} lux": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 3
)
).incomingMessage()
}
for (int i = 0; i <= 11; i += 1) {
status "ultravioletultravioletIndex ${i}": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().sensorMultilevelV2.sensorMultilevelReport(
scaledSensorValue: i,
sensorType: 27
)
).incomingMessage()
}
for (int i in [0, 5, 10, 15, 50, 99, 100]) {
status "battery ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: i
)
).incomingMessage()
}
status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate(
new physicalgraph.zwave.Zwave().batteryV1.batteryReport(
batteryLevel: 255
)
).incomingMessage()
status "wake up": "command: 8407, payload:"
}
tiles (scale: 2) {
multiAttributeTile(name:"main", type:"generic", width:6, height:4) {
tileAttribute("device.temperature", key: "PRIMARY_CONTROL") {
attributeState "temperature",label:'${currentValue}°',backgroundColors:[
[value: 32, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 92, color: "#d04e00"],
[value: 98, color: "#bc2323"]
]
}
tileAttribute("device.humidity", key: "SECONDARY_CONTROL") {
attributeState "humidity",label:'RH ${currentValue} %',unit:""
}
}
standardTile("motion","device.motion", width: 2, height: 2) {
state "active",label:'motion',icon:"st.motion.motion.active",backgroundColor:"#53a7c0"
state "inactive",label:'no motion',icon:"st.motion.motion.inactive",backgroundColor:"#ffffff"
}
valueTile("temperature","device.temperature", width: 2, height: 2) {
state "temperature",label:'${currentValue}°',backgroundColors:[
[value: 32, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
[value: 74, color: "#44b621"],
[value: 84, color: "#f1d801"],
[value: 92, color: "#d04e00"],
[value: 98, color: "#bc2323"]
]
}
valueTile(
"illuminance","device.illuminance", width: 2, height: 2) {
state "luminosity",label:'${currentValue} ${unit}', unit:"lux", backgroundColors:[
[value: 0, color: "#000000"],
[value: 1, color: "#060053"],
[value: 3, color: "#3E3900"],
[value: 12, color: "#8E8400"],
[value: 24, color: "#C5C08B"],
[value: 36, color: "#DAD7B6"],
[value: 128, color: "#F3F2E9"],
[value: 1000, color: "#FFFFFF"]
]
}
valueTile(
"ultravioletIndex","device.ultravioletIndex", width: 2, height: 2) {
state "ultravioletIndex",label:'${currentValue} UV INDEX',unit:""
}
standardTile(
"tamper","device.tamper", width: 2, height: 2) {
state "tamper",label:'tamper',icon:"st.motion.motion.active",backgroundColor:"#ff0000"
state "clear",label:'clear',icon:"st.motion.motion.inactive",backgroundColor:"#00ff00"
}
valueTile(
"battery", "device.battery", decoration: "flat", width: 2, height: 2) {
state "battery", label:'${currentValue}% battery', unit:""
}
standardTile(
"configure","device.configure", decoration: "flat", width: 2, height: 2) {
state "configure", label:'config', action:"configure", icon:"st.secondary.tools"
}
main([
"main"
])
details([
"main","illuminance","ultravioletIndex","motion","tamper","battery","configure"
])
}
preferences {
input "tempoffset",
"number",
title: "Temperature offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "-11..11",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "humidityoffset",
"number",
title: "Humidity offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "-50..50",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "luminanceoffset",
"number",
title: "Luminance offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "-1000..1000",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "ultravioletoffset",
"number",
title: "Ultraviolet offset",
description: "negative values reduce the monitored value positive ones add to it",
range: "-10..10",
defaultValue: 0,
required: false,
displayDuringSetup: false
input "PIRsensitivity",
"number",
title: "PIR motion sensitivity",
description: "A value from 0-5, from disabled to high sensitivity",
range: "0..5",
defaultValue: 1,
required: true,
displayDuringSetup: true
input "MotionReset",
"number",
title: "PIR reset time",
description: "Number of seconds to wait to report motion cleared after a motion event if there is no motion detected.",
defaultValue: 20,
required: true,
displayDuringSetup: true
input "ReportingInterval",
"number",
title: "Report data interval",
description: "A value in seconds.",
defaultValue: 300,
required: true,
displayDuringSetup: true
}
}
def updated()
{
if (state.sec && !isConfigured()) {
// in case we miss the SCSR
response(configure())
}
}
def parse(String description)
{
def result = null
if (description.startsWith("Err 106")) {
state.sec = 0
result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true,
descriptionText: "This sensor failed to complete the network security key exchange. If you are unable to control it via SmartThings, you must remove it from your network and add it again.")
} else if (description != "updated") {
def cmd = zwave.parse(description, [0x31: 5, 0x30: 2, 0x84: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
log.debug "Parsed '${description}' to ${result.inspect()}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
{
def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)]
if (!isConfigured()) {
// we're still in the process of configuring a newly joined device
log.debug("late configure")
result += response(configure())
} else {
result += response(zwave.wakeUpV1.wakeUpNoMoreInformation())
}
result
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
def encapsulatedCommand = cmd.encapsulatedCommand([0x31: 5, 0x30: 2, 0x84: 1])
state.sec = 1
log.debug "encapsulated: ${encapsulatedCommand}"
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
response(configure())
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) {
log.debug "---CONFIGURATION REPORT V2--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}"
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) {
map.value = 1
map.descriptionText = "${device.displayName} battery is low"
map.isStateChange = true
} else {
map.value = cmd.batteryLevel
}
state.lastbatt = now()
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelReport cmd)
{
def map = [:]
switch (cmd.sensorType) {
case 1:
map.name = "temperature"
def cmdScale = cmd.scale == 1 ? "F" : "C"
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
map.unit = getTemperatureScale()
break;
case 3:
map.name = "illuminance"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = "lux"
break;
case 5:
map.name = "humidity"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = "%"
break;
case 27:
map.name = "ultravioletIndex"
map.value = cmd.scaledSensorValue.toInteger()
map.unit = ""
break;
default:
map.descriptionText = cmd.toString()
}
createEvent(map)
}
def motionEvent(value) {
def map = [name: "motion"]
if (value) {
map.value = "active"
map.descriptionText = "$device.displayName detected motion"
} else {
map.value = "inactive"
map.descriptionText = "$device.displayName motion has stopped"
}
createEvent(map)
}
def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv2.SensorBinaryReport cmd) {
setConfigured()
motionEvent(cmd.sensorValue)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
motionEvent(cmd.value)
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
def result = []
if (cmd.notificationType == 7) {
switch (cmd.event) {
case 0:
result << motionEvent(0)
result << createEvent(name: "tamper", value: "clear", descriptionText: "$device.displayName tamper cleared")
break
case 3:
result << createEvent(name: "tamper", value: "detected", descriptionText: "$device.displayName was moved")
break
case 7:
result << motionEvent(1)
break
}
} else {
result << cre
gitextract_nx5lanog/
├── .gitattributes
├── .gitignore
├── .idea/
│ └── misc.xml
├── Aeon Door and Window Sensor DSB04100-ZWUS/
│ └── Aeon_Door_and_Window_Sensor-DSB04100-ZWUS.groovy
├── Aeon Doorbell/
│ ├── aeon-doorbell-v04.groovy
│ ├── device_type-aeon-doorbell-v0.1
│ ├── device_type-aeon-doorbell-v0.2
│ └── device_type-aeon-doorbell-v0.3
├── Aeon Garage Door/
│ └── device_type-aeon-garage-door-v0.1
├── Aeon Multisensor 6/
│ ├── device_type-aeon-multisensor6-v1.1
│ ├── device_type-aeon-multisensor6-v1.2
│ ├── device_type-aeon-multisensor6-v1.3
│ ├── device_type-aeon-multisensor6-v1.4
│ ├── device_type-aeon-multisensor6-v1.5
│ ├── device_type-aeon-multisensor6-v2.0
│ ├── device_type-aeon-multisensor6-v2.1
│ ├── device_type-aeon-multisensor6-v2.2
│ ├── device_type-aeon-multisensor6-v2.3
│ └── device_type-aeon-multisensor6-v2.3.1
├── Aeon SmartDimmer 6/
│ ├── device_type-aeon-smartdimmer6-v0.1
│ ├── device_type-aeon-smartdimmer6-v0.1-ANDROID
│ └── device_type-aeon-smartdimmer6-v0.2.groovy
├── Aeon SmartSwitch 6/
│ ├── device_type-aeon-smartswitch6-v0.1
│ ├── device_type-aeon-smartswitch6-v0.2
│ ├── device_type-aeon-smartswitch6-v0.4
│ └── device_type-aeon-smartswitch6-v0.4-ANDROID
├── GE Z-Wave Switch - Improved/
│ └── device_type-GE-Z-Wave-Switch-Improved
├── zooZ-4-in-1-Sensor-ZSE40/
│ ├── device_type-zooZ-4-in-1-Sensor-ZSE40_v1.2
│ └── device_type-zooZ-4-in-1-Sensor-ZSE40_v1.2_motion_primary
├── zooZ-Indoor-Siren-ZSE01/
│ ├── device_type-zooZ-indoor-siren-v1
│ ├── device_type-zooZ-indoor-siren-v1.1
│ └── device_type-zooZ-indoor-siren-v1.2
├── zooZ-MiniPlug-ZEN07/
│ ├── device_type-zooZ-4-in-1-Sensor-ZSE40_v1.2.groovy
│ ├── device_type-zooZ-MiniPlug-ZEN07-v1.1.groovy
│ ├── device_type-zooZ-MiniPlug-ZEN07-v1.2.groovy
│ ├── device_type-zooZ-MiniPlug-ZEN07-v1.3.groovy
│ └── device_type-zooZ-MiniPlug-ZEN07-v1.4.groovy
├── zooZ-Motion-Sensor-ZSE02/
│ ├── device_type-zooZ-Motion-Sensor-ZSE02_v1
│ ├── device_type-zooZ-Motion-Sensor-ZSE02_v1.1
│ └── device_type-zooZ-Motion-Sensor-ZSE02_v1.2
└── zooZ-Strip-ZEN20/
└── device_type-zooZ-strip-ZEN20_v1.0
Condensed preview — 41 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (669K chars).
[
{
"path": ".gitattributes",
"chars": 378,
"preview": "# Auto detect text files and perform LF normalization\n* text=auto\n\n# Custom for Visual Studio\n*.cs diff=csharp\n\n# St"
},
{
"path": ".gitignore",
"chars": 103,
"preview": "Aeon Doorbell/device_type-aeon-doorbell-v0.4\nzooZ-MiniPlug-ZEN07/device_type-zooZ-MiniPlug-ZEN07.groovy"
},
{
"path": ".idea/misc.xml",
"chars": 172,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n <component name=\"ProjectRootManager\">\n <output url=\"fi"
},
{
"path": "Aeon Door and Window Sensor DSB04100-ZWUS/Aeon_Door_and_Window_Sensor-DSB04100-ZWUS.groovy",
"chars": 6980,
"preview": "/**\n * Copyright 2015 SmartThings and 2016 Robert Vandervoort\n *\n * Licensed under the Apache License, Version 2.0 (th"
},
{
"path": "Aeon Doorbell/aeon-doorbell-v04.groovy",
"chars": 19270,
"preview": "/*\n * V 0.4 of Aeon Doorbell code 10/4/2017\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may "
},
{
"path": "Aeon Doorbell/device_type-aeon-doorbell-v0.1",
"chars": 12165,
"preview": "/*\n * V 0.1 of Aeon Doorbell code 11/24/2015\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may"
},
{
"path": "Aeon Doorbell/device_type-aeon-doorbell-v0.2",
"chars": 14272,
"preview": "/*\n * V 0.2 of Aeon Doorbell code 11/24/2015\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may"
},
{
"path": "Aeon Doorbell/device_type-aeon-doorbell-v0.3",
"chars": 15510,
"preview": "/*\n * V 0.3 of Aeon Doorbell code 11/24/2015\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may"
},
{
"path": "Aeon Garage Door/device_type-aeon-garage-door-v0.1",
"chars": 18350,
"preview": "/*\n * V 0.1 of Aeon Garage Door code 12/15/2015\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you "
},
{
"path": "Aeon Multisensor 6/device_type-aeon-multisensor6-v1.1",
"chars": 18882,
"preview": "/**\n * V 1.1 of Multisensor 6 code\n *\tknown issues : preferences do not seem to affect configuration, secure pairing is "
},
{
"path": "Aeon Multisensor 6/device_type-aeon-multisensor6-v1.2",
"chars": 20441,
"preview": "/**\n * V 1.2 of Multisensor 6 code\n *\tknown issues : preferences do not seem to affect configuration,\n *\tNot seeing anyt"
},
{
"path": "Aeon Multisensor 6/device_type-aeon-multisensor6-v1.3",
"chars": 20469,
"preview": "/**\n * V 1.3 of Multisensor 6 code 9/14/2015\n * Original code for gen5 Copyright 2015 SmartThings, modified for use on "
},
{
"path": "Aeon Multisensor 6/device_type-aeon-multisensor6-v1.4",
"chars": 17597,
"preview": "/*\n * V 1.4 of Multisensor 6 code 9/14/2015\n * Uses some original code from @Duncan Aeon Multisensor 6 code for secure c"
},
{
"path": "Aeon Multisensor 6/device_type-aeon-multisensor6-v1.5",
"chars": 18674,
"preview": "/*\n * V 1.5 of Multisensor 6 code 9/14/2015\n * Uses some original code from @Duncan Aeon Multisensor 6 code for secure c"
},
{
"path": "Aeon Multisensor 6/device_type-aeon-multisensor6-v2.0",
"chars": 19416,
"preview": "/*\n * V 2.0 of Multisensor 6 code 9/14/2015\n * Uses some original code from @Duncan Aeon Multisensor 6 code for secure c"
},
{
"path": "Aeon Multisensor 6/device_type-aeon-multisensor6-v2.1",
"chars": 19927,
"preview": "/*\n * V 2.1 of Multisensor 6 code 10/10/2015\n * Uses some original code from @Duncan Aeon Multisensor 6 code for secure "
},
{
"path": "Aeon Multisensor 6/device_type-aeon-multisensor6-v2.2",
"chars": 20839,
"preview": "/*\n * V 2.2 of Multisensor 6 code 10/10/2015\n * Uses some original code from @Duncan Aeon Multisensor 6 code for secure "
},
{
"path": "Aeon Multisensor 6/device_type-aeon-multisensor6-v2.3",
"chars": 21105,
"preview": "/*\n * V 2.3 of Multisensor 6 code 5/18/2016\n * Uses some original code from @Duncan Aeon Multisensor 6 code for secure c"
},
{
"path": "Aeon Multisensor 6/device_type-aeon-multisensor6-v2.3.1",
"chars": 21107,
"preview": "/*\n * V 2.3 of Multisensor 6 code 5/18/2016\n * Uses some original code from @Duncan Aeon Multisensor 6 code for secure c"
},
{
"path": "Aeon SmartDimmer 6/device_type-aeon-smartdimmer6-v0.1",
"chars": 18473,
"preview": "/*\n * V 0.1 of Aeon Smart Dimmer 6 code 10/6/2015\n * Licensed under the Apache License, Version 2.0 (the \"License\"); yo"
},
{
"path": "Aeon SmartDimmer 6/device_type-aeon-smartdimmer6-v0.1-ANDROID",
"chars": 18513,
"preview": "/*\n * V 0.1 of Aeon Smart Dimmer 6 code 10/6/2015\n * Licensed under the Apache License, Version 2.0 (the \"License\"); yo"
},
{
"path": "Aeon SmartDimmer 6/device_type-aeon-smartdimmer6-v0.2.groovy",
"chars": 18563,
"preview": "/*\n * V 0.2 of Aeon Smart Dimmer 6 code 9/24/2017\n * Licensed under the Apache License, Version 2.0 (the \"License\"); yo"
},
{
"path": "Aeon SmartSwitch 6/device_type-aeon-smartswitch6-v0.1",
"chars": 14091,
"preview": "/*\n * V 0.1 of Aeon Smart Switch 6 code 10/5/2015\n * Licensed under the Apache License, Version 2.0 (the \"License\"); yo"
},
{
"path": "Aeon SmartSwitch 6/device_type-aeon-smartswitch6-v0.2",
"chars": 14285,
"preview": "/*\n * V 0.2 of Aeon Smart Switch 6 code 10/5/2015\n * Licensed under the Apache License, Version 2.0 (the \"License\"); yo"
},
{
"path": "Aeon SmartSwitch 6/device_type-aeon-smartswitch6-v0.4",
"chars": 15409,
"preview": "/*\n * V 0.4 of Aeon Smart Switch 6 code 10/5/2015\n * Licensed under the Apache License, Version 2.0 (the \"License\"); yo"
},
{
"path": "Aeon SmartSwitch 6/device_type-aeon-smartswitch6-v0.4-ANDROID",
"chars": 15450,
"preview": "/*\n * V 0.4 of Aeon Smart Switch 6 code 10/5/2015\n * Licensed under the Apache License, Version 2.0 (the \"License\"); yo"
},
{
"path": "GE Z-Wave Switch - Improved/device_type-GE-Z-Wave-Switch-Improved",
"chars": 6658,
"preview": "/**\n * Created from code Copyright 2015 SmartThings\n *\tmodified by Robert Vandervoort 6/12/2016\n *\n * Licensed under t"
},
{
"path": "zooZ-4-in-1-Sensor-ZSE40/device_type-zooZ-4-in-1-Sensor-ZSE40_v1.2",
"chars": 21085,
"preview": "/*\n * V 1.2 of zooZ 4-in-1 sensor code 6/12/2016\n * by Robert Vandervoort\n *\n * Licensed under the Apache License, Vers"
},
{
"path": "zooZ-4-in-1-Sensor-ZSE40/device_type-zooZ-4-in-1-Sensor-ZSE40_v1.2_motion_primary",
"chars": 20912,
"preview": "/*\n * V 1.2 of zooZ 4-in-1 sensor code 6/12/2016\n * by Robert Vandervoort\n *\n * Licensed under the Apache License, Vers"
},
{
"path": "zooZ-Indoor-Siren-ZSE01/device_type-zooZ-indoor-siren-v1",
"chars": 10217,
"preview": "/*\n * V 1.0 of zooZ Indoor Siren ZSE01\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not u"
},
{
"path": "zooZ-Indoor-Siren-ZSE01/device_type-zooZ-indoor-siren-v1.1",
"chars": 10236,
"preview": "/*\n * V 1.1 of zooZ Indoor Siren ZSE01\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not u"
},
{
"path": "zooZ-Indoor-Siren-ZSE01/device_type-zooZ-indoor-siren-v1.2",
"chars": 8503,
"preview": "/*\n * V 1.2 of zooZ Indoor Siren ZSE01\n * Licensed under the Apache License, Version 2.0 (the \"License\"); you may not u"
},
{
"path": "zooZ-MiniPlug-ZEN07/device_type-zooZ-4-in-1-Sensor-ZSE40_v1.2.groovy",
"chars": 21085,
"preview": "/*\n * V 1.2 of zooZ 4-in-1 sensor code 6/12/2016\n * by Robert Vandervoort\n *\n * Licensed under the Apache License, Vers"
},
{
"path": "zooZ-MiniPlug-ZEN07/device_type-zooZ-MiniPlug-ZEN07-v1.1.groovy",
"chars": 15779,
"preview": "/*\nzooZ MiniPlug ZEN07 device handler for SmartThings version 1.0 by Robert Vandervoort 10/10/2016\nLicensed under the Ap"
},
{
"path": "zooZ-MiniPlug-ZEN07/device_type-zooZ-MiniPlug-ZEN07-v1.2.groovy",
"chars": 19421,
"preview": "/*\nzooZ MiniPlug ZEN07 device handler for SmartThings version 1.0 by Robert Vandervoort 10/10/2016\nLicensed under the Ap"
},
{
"path": "zooZ-MiniPlug-ZEN07/device_type-zooZ-MiniPlug-ZEN07-v1.3.groovy",
"chars": 19818,
"preview": "/*\nzooZ MiniPlug ZEN07 device handler for SmartThings version 1.0 by Robert Vandervoort 10/10/2016\nLicensed under the Ap"
},
{
"path": "zooZ-MiniPlug-ZEN07/device_type-zooZ-MiniPlug-ZEN07-v1.4.groovy",
"chars": 23663,
"preview": "/*\nzooZ MiniPlug ZEN07 device handler for SmartThings version 1.0 by Robert Vandervoort 10/10/2016\nLicensed under the Ap"
},
{
"path": "zooZ-Motion-Sensor-ZSE02/device_type-zooZ-Motion-Sensor-ZSE02_v1",
"chars": 15582,
"preview": "/*\n * V 1.0 of zooZ motion sensor ZSE-02 code 5/7/2016\n * by Robert Vandervoort\n *\n * Licensed under the Apache License"
},
{
"path": "zooZ-Motion-Sensor-ZSE02/device_type-zooZ-Motion-Sensor-ZSE02_v1.1",
"chars": 11336,
"preview": "/*\n * V 1.1 of zooZ motion sensor ZSE-02 code 5/13/16\n * by Robert Vandervoort\n *\n * Licensed under the Apache License,"
},
{
"path": "zooZ-Motion-Sensor-ZSE02/device_type-zooZ-Motion-Sensor-ZSE02_v1.2",
"chars": 9604,
"preview": "/*\n * V 1.2 of zooZ motion sensor ZSE-02 code 5/14/16\n * by Robert Vandervoort\n *\n * Licensed under the Apache License,"
},
{
"path": "zooZ-Strip-ZEN20/device_type-zooZ-strip-ZEN20_v1.0",
"chars": 6526,
"preview": "/**\n * Derived from Aeon Smart Strip code Copyright 2015 SmartThings\n *\treworked 6/2016 by Robert Vandervoort\n *\n * Li"
}
]
About this extraction
This page contains the full source code of the robertvandervoort/SmartThings GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 41 files (606.3 KB), approximately 171.5k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.