├── .gitattributes ├── .gitignore ├── .idea └── misc.xml ├── Aeon Door and Window Sensor 6 └── 15 Door Window Sensor 6.pdf ├── Aeon Door and Window Sensor DSB04100-ZWUS └── Aeon_Door_and_Window_Sensor-DSB04100-ZWUS.groovy ├── Aeon Doorbell ├── 11 Doorbell Gen5.pdf ├── 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 ├── Engineering Spec - Aeon Labs Garage Door Controller Gen5.pdf └── device_type-aeon-garage-door-v0.1 ├── Aeon LED Strip └── 19 LED Strip.pdf ├── Aeon Multisensor 6 ├── 9 Multisensor 6 V1.07 - ES.pdf ├── Engineering Spec - Aeon Labs MultiSensor 6.pdf ├── archived code │ └── Aeon Multisensor 6.zip ├── 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 Multisensor Gen 5 └── 8 MultiSensor Gen5.pdf ├── Aeon Nano Dimmer ├── Engineering Spec - Aeon Labs Nano Dimmer.pdf └── Instructions - Aeon Labs Nano Dimmer.pdf ├── Aeon SmartDimmer 6 ├── Engineering Spec - Aeon Labs Smart Dimmer 6.pdf ├── device_type-aeon-smartdimmer6-v0.1 ├── device_type-aeon-smartdimmer6-v0.1-ANDROID └── device_type-aeon-smartdimmer6-v0.2.groovy ├── Aeon SmartSwitch 6 ├── Engineering Spec - Aeon Labs Smart Switch 6.pdf ├── 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 ├── Aeon Wallmote Quad ├── Engineering Spec - Aeon Labs WallMote Quad.pdf └── Instructions - Aeon Labs WallMote Quad.pdf ├── GE Z-Wave Switch - Improved └── device_type-GE-Z-Wave-Switch-Improved ├── zooZ-4-in-1-Sensor-ZSE40 ├── ZSE40-tech-info.pdf ├── 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 ├── Z-Wave command classes for Siren.pdf ├── device_type-zooZ-indoor-siren-v1 ├── device_type-zooZ-indoor-siren-v1.1 ├── device_type-zooZ-indoor-siren-v1.2 └── zooz-zse01-indoor-siren-manual.pdf ├── 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 ├── Z-Wave command classes for motion sensor.pdf ├── device_type-zooZ-Motion-Sensor-ZSE02_v1 ├── device_type-zooZ-Motion-Sensor-ZSE02_v1.1 ├── device_type-zooZ-Motion-Sensor-ZSE02_v1.2 └── zooz-zse02-motion-sensor-manual.pdf ├── zooZ-Strip-ZEN20 └── device_type-zooZ-strip-ZEN20_v1.0 └── zooZ-Water-Valve └── Z-Wave command classes for valve.pdf /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Aeon Doorbell/device_type-aeon-doorbell-v0.4 2 | zooZ-MiniPlug-ZEN07/device_type-zooZ-MiniPlug-ZEN07.groovy -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Aeon Door and Window Sensor 6/15 Door Window Sensor 6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon Door and Window Sensor 6/15 Door Window Sensor 6.pdf -------------------------------------------------------------------------------- /Aeon Door and Window Sensor DSB04100-ZWUS/Aeon_Door_and_Window_Sensor-DSB04100-ZWUS.groovy: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2015 SmartThings and 2016 Robert Vandervoort 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 | * in compliance with the License. You may obtain a copy of the License at: 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 10 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 11 | * for the specific language governing permissions and limitations under the License. 12 | * 13 | * Aeon Labs DSB04100-ZWUS - Z-Wave Door & Window Sensor 14 | * 15 | * Author: SmartThings and Robert Vandervoort 16 | * Date: 7-17-2016 17 | */ 18 | 19 | metadata { 20 | definition (name: "Aeon Labs DSB04100-ZWUS - Z-Wave Door & Window Sensor - RV", namespace: "robertvandervoort", author: "Robert Vandervoort") { 21 | capability "Contact Sensor" 22 | capability "Tamper Alert" 23 | capability "Sensor" 24 | capability "Battery" 25 | capability "Configuration" 26 | // RAW ID 0 0 0x0701 0 0 0 f 0x5E 0x86 0x72 0x85 0x59 0x73 0x71 0x84 0x30 0x80 0x70 0x98 0x7A 0xEF 0x5A 27 | fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x85,0x59,0x73,0x71,0x84,0x30,0x80,0x70,0x98,0x7A,0xEF,0x5A" 28 | } 29 | 30 | simulator { 31 | // status messages 32 | status "open": "command: 2001, payload: FF" 33 | status "closed": "command: 2001, payload: 00" 34 | status "wake up": "command: 8407, payload: " 35 | status "detected": "command: 7105, payload: 000000FF07030000" 36 | status "clear": "command: 7105, payload: 000000FF07000000" 37 | } 38 | 39 | tiles { 40 | standardTile("contact", "device.contact", width: 2, height: 2) { 41 | state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e" 42 | state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821" 43 | } 44 | standardTile("tamper", "device.tamper", width: 2, height: 2) { 45 | state "detected", label: '${currentValue}', icon: "st.motion.acceleration.active", backgroundColor: "#ff0000" 46 | state "clear", label: '${currentValue}', icon: "st.motion.acceleration.inactive", backgroundColor: "#00ff00" 47 | } 48 | valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") { 49 | state "battery", label:'${currentValue}% battery', unit:"" 50 | } 51 | main "contact" 52 | details(["contact", "tamper", "battery"]) 53 | } 54 | } 55 | 56 | def parse(String description) { 57 | def result = null 58 | if (description.startsWith("Err 106")) { 59 | if (state.sec) { 60 | log.debug description 61 | } else { 62 | result = createEvent( 63 | 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.", 64 | eventType: "ALERT", 65 | name: "secureInclusion", 66 | value: "failed", 67 | isStateChange: true, 68 | ) 69 | } 70 | } else if (description != "updated") { 71 | def cmd = zwave.parse(description, [0x20: 1, 0x25: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1]) 72 | if (cmd) { 73 | result = zwaveEvent(cmd) 74 | } 75 | } 76 | log.debug "parsed '$description' to $result" 77 | return result 78 | } 79 | 80 | def updated() { 81 | def cmds = [] 82 | if (!state.MSR) { 83 | cmds = [ 84 | command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()), 85 | "delay 1200", 86 | zwave.wakeUpV1.wakeUpNoMoreInformation().format() 87 | ] 88 | } else if (!state.lastbat) { 89 | cmds = [] 90 | } else { 91 | cmds = [zwave.wakeUpV1.wakeUpNoMoreInformation().format()] 92 | } 93 | response(cmds) 94 | } 95 | 96 | def configure() { 97 | commands([ 98 | zwave.manufacturerSpecificV2.manufacturerSpecificGet(), 99 | zwave.batteryV1.batteryGet() 100 | ], 6000) 101 | } 102 | 103 | def sensorValueEvent(value) { 104 | if (value) { 105 | createEvent(name: "contact", value: "open", descriptionText: "$device.displayName is open") 106 | } else { 107 | createEvent(name: "contact", value: "closed", descriptionText: "$device.displayName is closed") 108 | } 109 | result 110 | } 111 | 112 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) 113 | { 114 | sensorValueEvent(cmd.value) 115 | } 116 | 117 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) 118 | { 119 | sensorValueEvent(cmd.value) 120 | } 121 | 122 | def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) 123 | { 124 | def result = [] 125 | if (cmd.notificationType == 0x07) { 126 | if (cmd.event == 0x03) { 127 | result << createEvent(name: "tamper", value: "detected", descriptionText: "$device.displayName was removed.", isStateChange: true) 128 | if(!state.MSR) result << response(command(zwave.manufacturerSpecificV2.manufacturerSpecificGet())) 129 | } else if (cmd.event == 0x00) { 130 | result << createEvent(name: "tamper", value: "clear", descriptionText: "$device.displayName was replaced.", isStateChange: true) 131 | if(!state.MSR) result << response(command(zwave.manufacturerSpecificV2.manufacturerSpecificGet())) 132 | } else if (cmd.notificationType == 0x06 && cmd.event == 0x16) { 133 | result << sensorValueEvent(1) 134 | } else if (cmd.notificationType == 0x06 && cmd.event == 0x17) { 135 | result << sensorValueEvent(0) 136 | } 137 | result 138 | } 139 | result 140 | } 141 | 142 | def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd) 143 | { 144 | def event = createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false) 145 | def cmds = [] 146 | if (!state.MSR) { 147 | cmds << command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()) 148 | cmds << "delay 1200" 149 | } 150 | if (!state.lastbat || now() - state.lastbat > 53*60*60*1000) { 151 | cmds << command(zwave.batteryV1.batteryGet()) 152 | } else { 153 | cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format() 154 | } 155 | [event, response(cmds)] 156 | } 157 | 158 | def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) { 159 | def map = [ name: "battery", unit: "%" ] 160 | if (cmd.batteryLevel == 0xFF) { 161 | map.value = 1 162 | map.descriptionText = "${device.displayName} has a low battery" 163 | map.isStateChange = true 164 | } else { 165 | map.value = cmd.batteryLevel 166 | } 167 | state.lastbat = now() 168 | [createEvent(map), response(zwave.wakeUpV1.wakeUpNoMoreInformation())] 169 | } 170 | 171 | def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) { 172 | def result = [] 173 | def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId) 174 | log.debug "msr: $msr" 175 | updateDataValue("MSR", msr) 176 | result << createEvent(descriptionText: "$device.displayName MSR: $msr", isStateChange: false) 177 | } 178 | 179 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) { 180 | def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x25: 1, 0x30: 1, 0x31: 5, 0x80: 1, 0x84: 1, 0x71: 3, 0x9C: 1]) 181 | // log.debug "encapsulated: $encapsulatedCommand" 182 | if (encapsulatedCommand) { 183 | state.sec = 1 184 | zwaveEvent(encapsulatedCommand) 185 | } 186 | } 187 | 188 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 189 | createEvent(descriptionText: "$device.displayName: $cmd", displayed: false) 190 | } 191 | 192 | private command(physicalgraph.zwave.Command cmd) { 193 | if (state.sec == 1) { 194 | zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() 195 | } else { 196 | cmd.format() 197 | } 198 | } 199 | 200 | private commands(commands, delay=200) { 201 | delayBetween(commands.collect{ command(it) }, delay) 202 | } -------------------------------------------------------------------------------- /Aeon Doorbell/11 Doorbell Gen5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon Doorbell/11 Doorbell Gen5.pdf -------------------------------------------------------------------------------- /Aeon Doorbell/device_type-aeon-doorbell-v0.1: -------------------------------------------------------------------------------- 1 | /* 2 | * V 0.1 of Aeon Doorbell code 11/24/2015 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 4 | * in compliance with the License. You may obtain a copy of the License at: 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 9 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 10 | * for the specific language governing permissions and limitations under the License. 11 | * 12 | */ 13 | 14 | metadata { 15 | definition (name: "Aeon Doorbell - RV v0.1", namespace: "robertvandervoort", author: "Robert Vandervoort") { 16 | capability "Actuator" 17 | capability "Alarm" 18 | capability "Switch" 19 | capability "Configuration" 20 | capability "Refresh" 21 | 22 | command "test" 23 | 24 | fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98" 25 | } 26 | // simulator metadata 27 | 28 | simulator { 29 | for (int i in [0, 5, 10, 15, 50, 99, 100]) { 30 | status "battery ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate( 31 | new physicalgraph.zwave.Zwave().batteryV1.batteryReport( 32 | batteryLevel: i 33 | ) 34 | ).incomingMessage() 35 | } 36 | status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate( 37 | new physicalgraph.zwave.Zwave().batteryV1.batteryReport( 38 | batteryLevel: 255 39 | ) 40 | ).incomingMessage() 41 | reply "9881002001FF,9881002002": "command: 9881, payload: 002003FF" 42 | reply "988100200100,9881002002": "command: 9881, payload: 00200300" 43 | reply "9881002001FF,delay 3000,988100200100,9881002002": "command: 9881, payload: 00200300" 44 | } 45 | 46 | // tile definitions 47 | tiles (scale: 2) { 48 | multiAttributeTile(name:"alarm", type:"generic", width:6, height:4, canChangeIcon: true) { 49 | tileAttribute("device.alarm", key: "PRIMARY_CONTROL") { 50 | attributeState "off", label:'off', action:'alarm.siren', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" 51 | attributeState "on", label:'alarm!', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" 52 | } 53 | } 54 | standardTile("test", "device.alarm", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 55 | state "default", label:'', action:"test", icon:"st.secondary.test" 56 | } 57 | standardTile("off", "device.alarm", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 58 | state "default", label:'', action:"off", icon:"st.secondary.off" 59 | } 60 | valueTile("battery", "device.battery", decoration: "flat", width: 2, height: 2) { 61 | state "battery", label:'${currentValue}% battery', unit:"" 62 | } 63 | standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 64 | state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure" 65 | } 66 | standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 67 | state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" 68 | } 69 | main "alarm" 70 | details(["alarm","test","off","battery","setRingtone","setVolume","refresh","configure"]) 71 | } 72 | 73 | preferences { 74 | input "debugOutput", "boolean", 75 | title: "Enable debug logging?", 76 | defaultValue: false, 77 | displayDuringSetup: true 78 | input "prefRingtone", "integer", 79 | title: "Doorbell tone:", 80 | description: "Pick the ringtone, 1-100", 81 | defaultValue: 1, 82 | range: "1..100", 83 | required: false, 84 | displayduringSetup: true 85 | input "prefVolume", "integer", 86 | title: "Doorbell volume:", 87 | description: "Set the volume of the doorbell", 88 | defaultValue: 10, 89 | range: "1..10", 90 | required: false, 91 | displayduringSetup: true 92 | input "prefNumrings", "integer", 93 | title: "Ring repetitions:", 94 | description: "How many times to ring per push of the doorbell", 95 | defaultValue: 1, 96 | range: "1..100", 97 | required: false, 98 | displayduringSetup: true 99 | } 100 | } 101 | 102 | def updated() 103 | { 104 | state.debug = ("true" == debugOutput) 105 | if (state.sec && !isConfigured()) { 106 | // in case we miss the SCSR 107 | response(configure()) 108 | 109 | } 110 | } 111 | 112 | def parse(String description) 113 | { 114 | def result = null 115 | if (description.startsWith("Err 106")) { 116 | state.sec = 0 117 | result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true, 118 | 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.") 119 | } else if (description != "updated") { 120 | 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]) 121 | if (cmd) { 122 | result = zwaveEvent(cmd) 123 | } 124 | } 125 | // if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}" 126 | return result 127 | } 128 | 129 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) { 130 | 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]) 131 | state.sec = 1 132 | if (state.debug) log.debug "encapsulated: ${encapsulatedCommand}" 133 | if (encapsulatedCommand) { 134 | zwaveEvent(encapsulatedCommand) 135 | } else { 136 | log.warn "Unable to extract encapsulated cmd from $cmd" 137 | createEvent(descriptionText: cmd.toString()) 138 | } 139 | } 140 | 141 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) { 142 | response(configure()) 143 | } 144 | 145 | def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) { 146 | if (state.debug) log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}" 147 | def request = [ 148 | physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet() 149 | ] 150 | response(commands(request)) 151 | } 152 | 153 | def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) { 154 | 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}" 155 | } 156 | 157 | def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) { 158 | 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}" 159 | } 160 | 161 | def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) { 162 | cmd.nodeId.each({log.debug "AssociationReport: '${cmd}', hub: '$zwaveHubNodeId' reports nodeId: '$it' is associated in group: '${cmd.groupingIdentifier}'"}) 163 | [:] 164 | } 165 | 166 | def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) { 167 | if (state.debug) log.debug "Hail received: ${cmd}" 168 | } 169 | 170 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) 171 | { 172 | if (state.debug) log.debug "doorbell value:${cmd.value}" 173 | [ 174 | createEvent([name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]), 175 | createEvent([name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]) 176 | ] 177 | } 178 | 179 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) 180 | { 181 | if (state.debug) log.debug cmd 182 | [name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 183 | } 184 | 185 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) 186 | { 187 | if (state.debug) log.debug cmd 188 | [name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 189 | } 190 | 191 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd) 192 | { 193 | if (state.debug) log.debug cmd 194 | [name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 195 | } 196 | 197 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 198 | if (state.debug) log.debug "Unhandled: $cmd sent to ${device.displayName}" 199 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 200 | } 201 | 202 | def test() { 203 | if (state.debug) log.debug "Ringing ${device.displayName}" 204 | def request = [ 205 | zwave.basicV1.basicSet(value: 0xFF), 206 | zwave.basicV1.basicGet() 207 | ] 208 | commands(request) 209 | } 210 | 211 | def strobe() { 212 | if (state.debug) log.debug "Strobe command received" 213 | on() 214 | } 215 | 216 | def siren() { 217 | if (state.debug) log.debug "Siren command received" 218 | on() 219 | } 220 | 221 | def both() { 222 | if (state.debug) log.debug "Both command received" 223 | on() 224 | } 225 | 226 | def on() { 227 | if (state.debug) log.debug "Ringing ${device.displayName}" 228 | def request = [ 229 | zwave.basicV1.basicSet(value: 0xFF), 230 | zwave.basicV1.basicGet() 231 | ] 232 | commands(request) 233 | } 234 | 235 | def off() { 236 | if (state.debug) log.debug "turning off ${device.displayName}" 237 | def request = [ 238 | zwave.basicV1.basicSet(value: 0x00), 239 | zwave.basicV1.basicGet() 240 | ] 241 | commands(request) 242 | } 243 | 244 | def refresh() { 245 | if (state.debug) log.debug "refresh request sent to ${device.displayName}" 246 | def request = [ 247 | zwave.basicV1.basicGet(), 248 | zwave.switchBinaryV1.switchBinaryGet() 249 | ] 250 | commands(request) 251 | } 252 | 253 | def configure() { 254 | if (state.debug) { 255 | if (state.sec) { 256 | log.debug "secure configuration being sent to ${device.displayName}" 257 | } 258 | else 259 | if (state.debug) log.debug "configuration being sent to ${device.displayName}" 260 | } 261 | if (!state.prefRingtone) state.prefRingtone = 1 262 | if (!state.prefVolume) state.prefVolume = 10 263 | if (!state.prefNumrings) state.prefNumrings = 1 264 | log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}" 265 | 266 | def request = [ 267 | //associate with group 1 and remove any group 2 association 268 | zwave.associationV1.associationRemove(groupingIdentifier:2, nodeId:zwaveHubNodeId), 269 | zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId), 270 | zwave.associationV1.associationGet(groupingIdentifier:1), 271 | zwave.associationV1.associationGet(groupingIdentifier:2), 272 | 273 | // Enable to send notifications to associated devices (Group 1) (0=nothing, 1=hail CC, 2=basic CC report) 274 | zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, scaledConfigurationValue: 2), 275 | zwave.configurationV1.configurationGet(parameterNumber: 80), 276 | 277 | // send low battery notifications 278 | zwave.configurationV1.configurationSet(parameterNumber: 81, size: 1, scaledConfigurationValue: 1), 279 | zwave.configurationV1.configurationGet(parameterNumber: 81), 280 | 281 | // Set the repetitions for playing doorbell ringtone 282 | zwave.configurationV1.configurationSet(parameterNumber: 2, size: 1, scaledConfigurationValue: prefNumrings.toInteger()), 283 | zwave.configurationV1.configurationGet(parameterNumber: 2), 284 | 285 | // Set the default doorbell ringtone 286 | zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: prefRingtone.toInteger()), 287 | zwave.configurationV1.configurationGet(parameterNumber: 5), 288 | 289 | // Set the volume of ringtone 290 | zwave.configurationV1.configurationSet(parameterNumber: 8, size: 1, scaledConfigurationValue: prefVolume.toInteger()), 291 | zwave.configurationV1.configurationGet(parameterNumber: 8), 292 | 293 | // define +- button function 294 | zwave.configurationV1.configurationSet(parameterNumber: 10, size: 1, scaledConfigurationValue: 0), 295 | zwave.configurationV1.configurationGet(parameterNumber: 10), 296 | zwave.configurationV1.configurationSet(parameterNumber: 11, size: 1, scaledConfigurationValue: 0), 297 | zwave.configurationV1.configurationGet(parameterNumber: 11) 298 | ] 299 | commands(request) 300 | } 301 | 302 | private setConfigured() { 303 | updateDataValue("configured", "true") 304 | } 305 | 306 | private isConfigured() { 307 | getDataValue("configured") == "true" 308 | } 309 | 310 | private command(physicalgraph.zwave.Command cmd) { 311 | if (state.sec) { 312 | zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() 313 | } else { 314 | cmd.format() 315 | } 316 | } 317 | 318 | private commands(commands, delay=500) { 319 | delayBetween(commands.collect{ command(it) }, delay) 320 | } -------------------------------------------------------------------------------- /Aeon Doorbell/device_type-aeon-doorbell-v0.2: -------------------------------------------------------------------------------- 1 | /* 2 | * V 0.2 of Aeon Doorbell code 11/24/2015 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 4 | * in compliance with the License. You may obtain a copy of the License at: 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 9 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 10 | * for the specific language governing permissions and limitations under the License. 11 | * 12 | * Changelog: 13 | * v 0.1 - initial push of device type, ability to change ring tone, volume and number of rings, basic set reporting 14 | * for use as a switch to trigger stuff, and ability to trigger as an alarm 15 | * v 0.2 - added separate preference for alarm triggering so a different ringtone can be used for alarm VS doorbell. created 16 | * separate test buttons for doorbell and alarm, battery tile now gets last known remote battery state and displays red or green for bad / good 17 | */ 18 | 19 | metadata { 20 | definition (name: "Aeon Doorbell - RV v0.2", namespace: "robertvandervoort", author: "Robert Vandervoort") { 21 | capability "Actuator" 22 | capability "Alarm" 23 | capability "Battery" 24 | capability "Switch" 25 | capability "Configuration" 26 | capability "Refresh" 27 | 28 | command "atest" 29 | command "btest" 30 | command "getbatt" 31 | 32 | fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98" 33 | } 34 | // simulator metadata 35 | 36 | simulator { 37 | /*status "battery good": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate( 38 | zwave.configurationV1.configurationReport( 39 | parameterNumber: 42, configurationValue: 0 40 | ) 41 | ).incomingMessage() 42 | status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate( 43 | zwave.configurationV1.configurationReport( 44 | parameterNumber: 42, configurationValue: 255 45 | ) 46 | ).incomingMessage() 47 | */ 48 | reply "9881002001FF,9881002002": "command: 9881, payload: 002003FF" 49 | reply "988100200100,9881002002": "command: 9881, payload: 00200300" 50 | reply "9881002001FF,delay 3000,988100200100,9881002002": "command: 9881, payload: 00200300" 51 | } 52 | // tile definitions 53 | tiles (scale: 2) { 54 | multiAttributeTile(name:"alarm", type:"generic", width:6, height:4, canChangeIcon: true, canChangeBackground: true) { 55 | tileAttribute("device.alarm", key: "PRIMARY_CONTROL") { 56 | attributeState "off", label:'OFF', action:'alarm.on', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" 57 | attributeState "on", label:'RINGING', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" 58 | } 59 | } 60 | standardTile("btest", "device.alarm", inactiveLabel: false, width: 2, height: 2) { 61 | state "default", label:'bell', action:"btest", icon:"st.Electronics.electronics14" 62 | } 63 | standardTile("atest", "device.alarm", inactiveLabel: false, width: 2, height: 2) { 64 | state "default", label:'alarm', action:"atest", icon:"st.Electronics.electronics14" 65 | } 66 | standardTile("off", "device.alarm", inactiveLabel: false, width: 2, height: 2) { 67 | state "default", label:'', action:"off", icon:"st.secondary.off" 68 | } 69 | valueTile("battery", "device.battery", decoration: "flat", width: 2, height: 2) { 70 | state "battery", label:'Battery', action:"getbatt", backgroundColors:[ 71 | [value: 0, color: "#FF0000"], 72 | [value: 100, color: "#00FF00"] 73 | ] 74 | } 75 | standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 76 | state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure" 77 | } 78 | standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 79 | state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" 80 | } 81 | main "alarm" 82 | details(["alarm","btest","atest","off","battery","setRingtone","setVolume","refresh","configure"]) 83 | } 84 | 85 | preferences { 86 | input "debugOutput", "boolean", 87 | title: "Enable debug logging?", 88 | defaultValue: false, 89 | displayDuringSetup: true 90 | input "prefRingtone", "integer", 91 | title: "Doorbell tone:", 92 | description: "Pick the ringtone, 1-100", 93 | defaultValue: 1, 94 | range: "1..100", 95 | required: false, 96 | displayduringSetup: true 97 | input "prefAlarmtone", "integer", 98 | title: "Alarm tone:", 99 | description: "Pick the alarm tone, 1-100", 100 | defaultValue: 6, 101 | range: "1..100", 102 | required: false, 103 | displayduringSetup: true 104 | input "prefVolume", "integer", 105 | title: "Doorbell volume:", 106 | description: "Set the volume of the doorbell", 107 | defaultValue: 10, 108 | range: "1..10", 109 | required: false, 110 | displayduringSetup: true 111 | input "prefNumrings", "integer", 112 | title: "Ring repetitions:", 113 | description: "How many times to ring per push of the doorbell", 114 | defaultValue: 1, 115 | range: "1..100", 116 | required: false, 117 | displayduringSetup: true 118 | } 119 | } 120 | 121 | def updated() 122 | { 123 | state.debug = ("true" == debugOutput) 124 | if (state.sec && !isConfigured()) { 125 | // in case we miss the SCSR 126 | response(configure()) 127 | 128 | } 129 | } 130 | 131 | def parse(String description) 132 | { 133 | def result = null 134 | if (description.startsWith("Err 106")) { 135 | state.sec = 0 136 | result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true, 137 | 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.") 138 | } else if (description != "updated") { 139 | 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]) 140 | if (cmd) { 141 | result = zwaveEvent(cmd) 142 | } 143 | } 144 | // if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}" 145 | return result 146 | } 147 | 148 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) { 149 | 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]) 150 | state.sec = 1 151 | if (state.debug) log.debug "encapsulated: ${encapsulatedCommand}" 152 | if (encapsulatedCommand) { 153 | zwaveEvent(encapsulatedCommand) 154 | } else { 155 | log.warn "Unable to extract encapsulated cmd from $cmd" 156 | createEvent(descriptionText: cmd.toString()) 157 | } 158 | } 159 | 160 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) { 161 | response(configure()) 162 | } 163 | 164 | def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) { 165 | if (state.debug) log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}" 166 | def request = [ 167 | physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet() 168 | ] 169 | response(commands(request)) 170 | } 171 | 172 | def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) { 173 | 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}" 174 | } 175 | 176 | def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) { 177 | 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}" 178 | def map = [ name: "battery"] 179 | if (cmd.parameterNumber == 42 && cmd.configurationValue == 0xFF) { 180 | map.value = 0 181 | map.descriptionText = "${device.displayName} remote battery is low" 182 | if (state.debug) log.debug "${device.displayName} remote battery is low" 183 | map.isStateChange = true 184 | } else { 185 | map.value = 100 186 | map.descriptionText = "${device.displayName} remote battery is good" 187 | if (state.debug) log.debug "${device.displayName} remote battery is good" 188 | map.isStateChange = true 189 | } 190 | createEvent(map) 191 | } 192 | 193 | def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) { 194 | cmd.nodeId.each({log.debug "AssociationReport: '${cmd}', hub: '$zwaveHubNodeId' reports nodeId: '$it' is associated in group: '${cmd.groupingIdentifier}'"}) 195 | [:] 196 | } 197 | 198 | def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) { 199 | if (state.debug) log.debug "Hail received: ${cmd}" 200 | } 201 | 202 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) 203 | { 204 | if (state.debug) log.debug "doorbell value:${cmd.value}" 205 | [ 206 | createEvent([name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]), 207 | createEvent([name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]) 208 | ] 209 | } 210 | 211 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) 212 | { 213 | if (state.debug) log.debug cmd 214 | [name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 215 | } 216 | 217 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) 218 | { 219 | if (state.debug) log.debug cmd 220 | [name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 221 | } 222 | 223 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd) 224 | { 225 | if (state.debug) log.debug cmd 226 | [name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 227 | } 228 | 229 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 230 | if (state.debug) log.debug "Unhandled: $cmd sent to ${device.displayName}" 231 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 232 | } 233 | 234 | def getbatt() { 235 | if (state.debug) log.debug "Getting battery level for remote control on ${device.displayName}" 236 | def request = [ 237 | zwave.configurationV1.configurationGet(parameterNumber: 42) 238 | ] 239 | commands(request) 240 | } 241 | 242 | def btest() { 243 | if (state.debug) log.debug "Testing doorbell ring ${prefRingtone} on ${device.displayName}" 244 | on() 245 | } 246 | 247 | def atest() { 248 | if (state.debug) log.debug "Testing alarm sound ${prefAlarmtone} on ${device.displayName}" 249 | both() 250 | } 251 | 252 | def strobe() { 253 | if (state.debug) log.debug "Strobe command received" 254 | on() 255 | } 256 | 257 | def siren() { 258 | if (state.debug) log.debug "Siren command received" 259 | on() 260 | } 261 | 262 | def both() { 263 | if (state.debug) log.debug "Alarm test command received" 264 | def request = [ 265 | zwave.configurationV1.configurationSet(parameterNumber: 6, size: 1, scaledConfigurationValue: prefAlarmtone.toInteger()) 266 | ] 267 | commands(request) 268 | } 269 | 270 | def on() { 271 | if (state.debug) log.debug "Ringing ${device.displayName}" 272 | def request = [ 273 | zwave.basicV1.basicSet(value: 0xFF) 274 | ] 275 | commands(request) 276 | } 277 | 278 | def off() { 279 | if (state.debug) log.debug "turning off ${device.displayName}" 280 | def request = [ 281 | zwave.basicV1.basicSet(value: 0x00), 282 | zwave.basicV1.basicGet() 283 | ] 284 | commands(request) 285 | } 286 | 287 | def refresh() { 288 | if (state.debug) log.debug "refresh request sent to ${device.displayName}" 289 | def request = [ 290 | zwave.basicV1.basicGet(), 291 | zwave.switchBinaryV1.switchBinaryGet() 292 | ] 293 | commands(request) 294 | } 295 | 296 | def configure() { 297 | if (state.debug) { 298 | if (state.sec) { 299 | log.debug "secure configuration being sent to ${device.displayName}" 300 | } 301 | else 302 | if (state.debug) log.debug "configuration being sent to ${device.displayName}" 303 | } 304 | if (!state.prefRingtone) state.prefRingtone = 1 305 | if (!state.prefRingtone) state.prefAlarmtone = 1 306 | if (!state.prefVolume) state.prefVolume = 10 307 | if (!state.prefNumrings) state.prefNumrings = 1 308 | log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}" 309 | 310 | def request = [ 311 | //associate with group 1 and remove any group 2 association 312 | //zwave.associationV1.associationRemove(groupingIdentifier:2, nodeId:zwaveHubNodeId), 313 | //zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId), 314 | zwave.associationV1.associationGet(groupingIdentifier:1), 315 | zwave.associationV1.associationGet(groupingIdentifier:2), 316 | 317 | // Enable to send notifications to associated devices (Group 1) (0=nothing, 1=hail CC, 2=basic CC report) 318 | zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, scaledConfigurationValue: 2), 319 | zwave.configurationV1.configurationGet(parameterNumber: 80), 320 | 321 | // send low battery notifications 322 | zwave.configurationV1.configurationSet(parameterNumber: 81, size: 1, scaledConfigurationValue: 1), 323 | zwave.configurationV1.configurationGet(parameterNumber: 81), 324 | 325 | // Set the repetitions for playing doorbell ringtone 326 | zwave.configurationV1.configurationSet(parameterNumber: 2, size: 1, scaledConfigurationValue: prefNumrings.toInteger()), 327 | zwave.configurationV1.configurationGet(parameterNumber: 2), 328 | 329 | // Set the default doorbell ringtone 330 | zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: prefRingtone.toInteger()), 331 | zwave.configurationV1.configurationGet(parameterNumber: 5), 332 | 333 | // Set the volume of ringtone 334 | zwave.configurationV1.configurationSet(parameterNumber: 8, size: 1, scaledConfigurationValue: prefVolume.toInteger()), 335 | zwave.configurationV1.configurationGet(parameterNumber: 8), 336 | 337 | // define +- button function 338 | zwave.configurationV1.configurationSet(parameterNumber: 10, size: 1, scaledConfigurationValue: 0), 339 | zwave.configurationV1.configurationGet(parameterNumber: 10), 340 | zwave.configurationV1.configurationSet(parameterNumber: 11, size: 1, scaledConfigurationValue: 0), 341 | zwave.configurationV1.configurationGet(parameterNumber: 11) 342 | ] 343 | commands(request) 344 | } 345 | 346 | private setConfigured() { 347 | updateDataValue("configured", "true") 348 | } 349 | 350 | private isConfigured() { 351 | getDataValue("configured") == "true" 352 | } 353 | 354 | private command(physicalgraph.zwave.Command cmd) { 355 | if (state.sec) { 356 | zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() 357 | } else { 358 | cmd.format() 359 | } 360 | } 361 | 362 | private commands(commands, delay=500) { 363 | delayBetween(commands.collect{ command(it) }, delay) 364 | } -------------------------------------------------------------------------------- /Aeon Doorbell/device_type-aeon-doorbell-v0.3: -------------------------------------------------------------------------------- 1 | /* 2 | * V 0.3 of Aeon Doorbell code 11/24/2015 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 4 | * in compliance with the License. You may obtain a copy of the License at: 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 9 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 10 | * for the specific language governing permissions and limitations under the License. 11 | * 12 | * Changelog: 13 | * v 0.1 - initial push of device type, ability to change ring tone, volume and number of rings, basic set reporting 14 | * for use as a switch to trigger stuff, and ability to trigger as an alarm 15 | * v 0.2 - added separate preference for alarm triggering so a different ringtone can be used for alarm VS doorbell. created 16 | * separate test buttons for doorbell and alarm 17 | * 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 18 | */ 19 | 20 | metadata { 21 | definition (name: "Aeon Doorbell - RV v0.3", namespace: "robertvandervoort", author: "Robert Vandervoort") { 22 | capability "Actuator" 23 | capability "Alarm" 24 | capability "Battery" 25 | capability "Switch" 26 | capability "Configuration" 27 | capability "Refresh" 28 | 29 | command "atest" 30 | command "btest" 31 | command "getbatt" 32 | 33 | fingerprint deviceId: "0x1005", inClusters: "0x5E,0x98" 34 | } 35 | // simulator metadata 36 | 37 | simulator { 38 | /*status "battery good": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate( 39 | zwave.configurationV1.configurationReport( 40 | parameterNumber: 42, configurationValue: 0 41 | ) 42 | ).incomingMessage() 43 | status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate( 44 | zwave.configurationV1.configurationReport( 45 | parameterNumber: 42, configurationValue: 255 46 | ) 47 | ).incomingMessage() 48 | */ 49 | reply "9881002001FF,9881002002": "command: 9881, payload: 002003FF" 50 | reply "988100200100,9881002002": "command: 9881, payload: 00200300" 51 | reply "9881002001FF,delay 3000,988100200100,9881002002": "command: 9881, payload: 00200300" 52 | } 53 | // tile definitions 54 | tiles (scale: 2) { 55 | multiAttributeTile(name:"alarm", type:"generic", width:6, height:4, canChangeIcon: true, canChangeBackground: true) { 56 | tileAttribute("device.alarm", key: "PRIMARY_CONTROL") { 57 | attributeState "off", label:'OFF', action:'alarm.on', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" 58 | attributeState "on", label:'RINGING', action:'alarm.off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" 59 | } 60 | } 61 | standardTile("btest", "device.alarm", inactiveLabel: false, width: 2, height: 2) { 62 | state "default", label:'bell', action:"btest", icon:"st.Electronics.electronics14" 63 | } 64 | standardTile("atest", "device.alarm", inactiveLabel: false, width: 2, height: 2) { 65 | state "default", label:'alarm', action:"atest", icon:"st.Electronics.electronics14" 66 | } 67 | standardTile("off", "device.alarm", inactiveLabel: false, width: 2, height: 2) { 68 | state "default", label:'', action:"off", icon:"st.secondary.off" 69 | } 70 | valueTile("battery", "device.battery", decoration: "flat", width: 2, height: 2) { 71 | state "battery", label:'Battery', action:"getbatt", backgroundColors:[ 72 | [value: 0, color: "#FF0000"], 73 | [value: 100, color: "#00FF00"] 74 | ] 75 | } 76 | standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 77 | state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure" 78 | } 79 | standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 80 | state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" 81 | } 82 | main "alarm" 83 | details(["alarm","btest","atest","off","battery","setRingtone","setVolume","refresh","configure"]) 84 | } 85 | 86 | preferences { 87 | input "debugOutput", "boolean", 88 | title: "Enable debug logging?", 89 | defaultValue: false, 90 | displayDuringSetup: true 91 | input "prefRingtone", "integer", 92 | title: "Doorbell tone:", 93 | description: "Pick the ringtone, 1-100", 94 | defaultValue: 1, 95 | range: "1..100", 96 | required: false, 97 | displayduringSetup: true 98 | input "prefAlarmtone", "integer", 99 | title: "Alarm tone:", 100 | description: "Pick the alarm tone, 1-100", 101 | defaultValue: 6, 102 | range: "1..100", 103 | required: false, 104 | displayduringSetup: true 105 | input "prefVolume", "integer", 106 | title: "Doorbell volume:", 107 | description: "Set the volume of the doorbell", 108 | defaultValue: 10, 109 | range: "1..10", 110 | required: false, 111 | displayduringSetup: true 112 | input "prefNumrings", "integer", 113 | title: "Ring repetitions:", 114 | description: "How many times to ring per push of the doorbell", 115 | defaultValue: 1, 116 | range: "1..100", 117 | required: false, 118 | displayduringSetup: true 119 | } 120 | } 121 | 122 | def updated() 123 | { 124 | state.debug = ("true" == debugOutput) 125 | if (state.sec && !isConfigured()) { 126 | // in case we miss the SCSR 127 | response(configure()) 128 | 129 | } 130 | } 131 | 132 | def parse(String description) 133 | { 134 | def result = null 135 | if (description.startsWith("Err 106")) { 136 | state.sec = 0 137 | result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true, 138 | 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.") 139 | } else if (description != "updated") { 140 | 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]) 141 | if (cmd) { 142 | result = zwaveEvent(cmd) 143 | } 144 | } 145 | // if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}" 146 | return result 147 | } 148 | 149 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) { 150 | 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]) 151 | state.sec = 1 152 | // if (state.debug) log.debug "encapsulated: ${encapsulatedCommand}" 153 | if (encapsulatedCommand) { 154 | zwaveEvent(encapsulatedCommand) 155 | } else { 156 | log.warn "Unable to extract encapsulated cmd from $cmd" 157 | createEvent(descriptionText: cmd.toString()) 158 | } 159 | } 160 | 161 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) { 162 | response(configure()) 163 | } 164 | 165 | def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) { 166 | if (state.debug) log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}" 167 | def request = [ 168 | physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet() 169 | ] 170 | response(commands(request)) 171 | } 172 | 173 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionCommandClassReport cmd) { 174 | if (state.debug) log.debug "---COMMAND CLASS VERSION REPORT V1--- ${device.displayName} has command class version: ${cmd.commandClassVersion} - payload: ${cmd.payload}" 175 | } 176 | 177 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) { 178 | def fw = "${cmd.applicationVersion}.${cmd.applicationSubVersion}" 179 | updateDataValue("fw", fw) 180 | if (state.debug) log.debug "---VERSION REPORT V1--- ${device.displayName} is running firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}" 181 | } 182 | 183 | def zwaveEvent(physicalgraph.zwave.commands.firmwareupdatemdv2.FirmwareMdReport cmd) { 184 | if (state.debug) log.debug "---FIRMWARE MD REPORT V2--- ${device.displayName} has Checksum of ${cmd.checksum} firmwareId: ${cmd.firmwareId}, manufacturerId: ${cmd.firmwareId}" 185 | } 186 | 187 | def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) { 188 | 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}" 189 | } 190 | 191 | def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) { 192 | 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}" 193 | def map = [ name: "battery"] 194 | if (cmd.parameterNumber == 42) { 195 | if (cmd.configurationValue == [255]) { 196 | map.value = 0 197 | map.descriptionText = "${device.displayName} remote battery is low" 198 | if (state.debug) log.debug "${device.displayName} remote battery is low" 199 | map.isStateChange = true 200 | } else { 201 | map.value = 100 202 | map.descriptionText = "${device.displayName} remote battery is good" 203 | if (state.debug) log.debug "${device.displayName} remote battery is good" 204 | map.isStateChange = true 205 | } 206 | } 207 | createEvent(map) 208 | } 209 | 210 | def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) { 211 | cmd.nodeId.each({log.debug "AssociationReport: '${cmd}', hub: '$zwaveHubNodeId' reports nodeId: '$it' is associated in group: '${cmd.groupingIdentifier}'"}) 212 | } 213 | 214 | def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) { 215 | if (state.debug) log.debug "Hail received: ${cmd}" 216 | } 217 | 218 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) 219 | { 220 | if (state.debug) log.debug "doorbell value:${cmd.value}" 221 | [ 222 | createEvent([name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]), 223 | createEvent([name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]) 224 | ] 225 | } 226 | 227 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) 228 | { 229 | if (state.debug) log.debug cmd 230 | [name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 231 | } 232 | 233 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) 234 | { 235 | if (state.debug) log.debug cmd 236 | [name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 237 | } 238 | 239 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd) 240 | { 241 | if (state.debug) log.debug cmd 242 | [name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 243 | } 244 | 245 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 246 | if (state.debug) log.debug "Unhandled: $cmd sent to ${device.displayName}" 247 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 248 | } 249 | 250 | def getbatt() { 251 | if (state.debug) log.debug "Getting battery level for remote control on ${device.displayName}" 252 | def request = [ 253 | zwave.configurationV1.configurationGet(parameterNumber: 42) 254 | ] 255 | commands(request) 256 | } 257 | 258 | def btest() { 259 | if (state.debug) log.debug "Testing doorbell ring ${prefRingtone} on ${device.displayName}" 260 | on() 261 | } 262 | 263 | def atest() { 264 | if (state.debug) log.debug "Testing alarm sound ${prefAlarmtone} on ${device.displayName}" 265 | both() 266 | } 267 | 268 | def strobe() { 269 | if (state.debug) log.debug "Strobe command received" 270 | on() 271 | } 272 | 273 | def siren() { 274 | if (state.debug) log.debug "Siren command received" 275 | on() 276 | } 277 | 278 | def both() { 279 | if (state.debug) log.debug "Alarm test command received" 280 | def request = [ 281 | zwave.configurationV1.configurationSet(parameterNumber: 6, size: 1, scaledConfigurationValue: prefAlarmtone.toInteger()) 282 | ] 283 | commands(request) 284 | } 285 | 286 | def on() { 287 | if (state.debug) log.debug "Ringing ${device.displayName}" 288 | def request = [ 289 | zwave.basicV1.basicSet(value: 0xFF) 290 | ] 291 | commands(request) 292 | } 293 | 294 | def off() { 295 | if (state.debug) log.debug "turning off ${device.displayName}" 296 | def request = [ 297 | zwave.basicV1.basicSet(value: 0x00), 298 | zwave.basicV1.basicGet() 299 | ] 300 | commands(request) 301 | } 302 | 303 | def refresh() { 304 | if (state.debug) log.debug "refresh request sent to ${device.displayName}" 305 | def request = [ 306 | zwave.basicV1.basicGet(), 307 | zwave.switchBinaryV1.switchBinaryGet() 308 | ] 309 | commands(request) 310 | } 311 | 312 | def configure() { 313 | if (state.debug) { 314 | if (state.sec) { 315 | log.debug "secure configuration being sent to ${device.displayName}" 316 | } 317 | else 318 | if (state.debug) log.debug "configuration being sent to ${device.displayName}" 319 | } 320 | if (!state.prefRingtone) state.prefRingtone = 1 321 | if (!state.prefRingtone) state.prefAlarmtone = 1 322 | if (!state.prefVolume) state.prefVolume = 10 323 | if (!state.prefNumrings) state.prefNumrings = 1 324 | log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}" 325 | 326 | def request = [ 327 | //associate with group 1 and remove any group 2 association 328 | //zwave.associationV1.associationRemove(groupingIdentifier:2, nodeId:zwaveHubNodeId), 329 | //zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:zwaveHubNodeId), 330 | zwave.associationV1.associationGet(groupingIdentifier:1), 331 | zwave.associationV1.associationGet(groupingIdentifier:2), 332 | 333 | // Get Version information 334 | zwave.versionV1.versionGet(), 335 | zwave.firmwareUpdateMdV2.firmwareMdGet(), 336 | 337 | // Enable to send notifications to associated devices (Group 1) (0=nothing, 1=hail CC, 2=basic CC report) 338 | zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, scaledConfigurationValue: 2), 339 | zwave.configurationV1.configurationGet(parameterNumber: 80), 340 | 341 | // send low battery notifications 342 | zwave.configurationV1.configurationSet(parameterNumber: 81, size: 1, scaledConfigurationValue: 1), 343 | zwave.configurationV1.configurationGet(parameterNumber: 81), 344 | 345 | // Set the repetitions for playing doorbell ringtone 346 | zwave.configurationV1.configurationSet(parameterNumber: 2, size: 1, scaledConfigurationValue: prefNumrings.toInteger()), 347 | zwave.configurationV1.configurationGet(parameterNumber: 2), 348 | 349 | // Set the default doorbell ringtone 350 | zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: prefRingtone.toInteger()), 351 | zwave.configurationV1.configurationGet(parameterNumber: 5), 352 | 353 | // Set the volume of ringtone 354 | zwave.configurationV1.configurationSet(parameterNumber: 8, size: 1, scaledConfigurationValue: prefVolume.toInteger()), 355 | zwave.configurationV1.configurationGet(parameterNumber: 8), 356 | 357 | // define +- button function 358 | zwave.configurationV1.configurationSet(parameterNumber: 10, size: 1, scaledConfigurationValue: 0), 359 | zwave.configurationV1.configurationGet(parameterNumber: 10), 360 | zwave.configurationV1.configurationSet(parameterNumber: 11, size: 1, scaledConfigurationValue: 0), 361 | zwave.configurationV1.configurationGet(parameterNumber: 11), 362 | // Get last known remote battery health 363 | zwave.configurationV1.configurationGet(parameterNumber: 42) 364 | ] 365 | commands(request) 366 | } 367 | 368 | private setConfigured() { 369 | updateDataValue("configured", "true") 370 | } 371 | 372 | private isConfigured() { 373 | getDataValue("configured") == "true" 374 | } 375 | 376 | private command(physicalgraph.zwave.Command cmd) { 377 | if (state.sec) { 378 | zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() 379 | } else { 380 | cmd.format() 381 | } 382 | } 383 | 384 | private commands(commands, delay=500) { 385 | delayBetween(commands.collect{ command(it) }, delay) 386 | } -------------------------------------------------------------------------------- /Aeon Garage Door/Engineering Spec - Aeon Labs Garage Door Controller Gen5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon Garage Door/Engineering Spec - Aeon Labs Garage Door Controller Gen5.pdf -------------------------------------------------------------------------------- /Aeon LED Strip/19 LED Strip.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon LED Strip/19 LED Strip.pdf -------------------------------------------------------------------------------- /Aeon Multisensor 6/9 Multisensor 6 V1.07 - ES.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon Multisensor 6/9 Multisensor 6 V1.07 - ES.pdf -------------------------------------------------------------------------------- /Aeon Multisensor 6/Engineering Spec - Aeon Labs MultiSensor 6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon Multisensor 6/Engineering Spec - Aeon Labs MultiSensor 6.pdf -------------------------------------------------------------------------------- /Aeon Multisensor 6/archived code/Aeon Multisensor 6.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon Multisensor 6/archived code/Aeon Multisensor 6.zip -------------------------------------------------------------------------------- /Aeon Multisensor Gen 5/8 MultiSensor Gen5.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon Multisensor Gen 5/8 MultiSensor Gen5.pdf -------------------------------------------------------------------------------- /Aeon Nano Dimmer/Engineering Spec - Aeon Labs Nano Dimmer.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon Nano Dimmer/Engineering Spec - Aeon Labs Nano Dimmer.pdf -------------------------------------------------------------------------------- /Aeon Nano Dimmer/Instructions - Aeon Labs Nano Dimmer.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon Nano Dimmer/Instructions - Aeon Labs Nano Dimmer.pdf -------------------------------------------------------------------------------- /Aeon SmartDimmer 6/Engineering Spec - Aeon Labs Smart Dimmer 6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon SmartDimmer 6/Engineering Spec - Aeon Labs Smart Dimmer 6.pdf -------------------------------------------------------------------------------- /Aeon SmartSwitch 6/Engineering Spec - Aeon Labs Smart Switch 6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon SmartSwitch 6/Engineering Spec - Aeon Labs Smart Switch 6.pdf -------------------------------------------------------------------------------- /Aeon SmartSwitch 6/device_type-aeon-smartswitch6-v0.1: -------------------------------------------------------------------------------- 1 | /* 2 | * V 0.1 of Aeon Smart Switch 6 code 10/5/2015 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 4 | * in compliance with the License. You may obtain a copy of the License at: 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 9 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 10 | * for the specific language governing permissions and limitations under the License. 11 | * 12 | */ 13 | 14 | metadata { 15 | definition (name: "Aeon Smart Switch 6 - RV v0.1", namespace: "robertvandervoort", author: "Robert Vandervoort") { 16 | capability "Energy Meter" 17 | capability "Power Meter" 18 | capability "Actuator" 19 | capability "Switch" 20 | capability "Configuration" 21 | capability "Polling" 22 | capability "Refresh" 23 | capability "Sensor" 24 | 25 | command "reset" 26 | 27 | /* find homes for these 28 | 0x2C COMMAND_CLASS_SCENE_ACTUATOR_CONF 29 | 0x2B COMMAND_CLASS_SCENE_ACTIVATION 30 | 0x7A COMMAND_CLASS_FIRMWARE_UPDATE_MD 2 31 | 0xEF COMMAND_CLASS_MARK 1 32 | 0x5A ? 33 | 0x5E ? 34 | 0x25: 1 0x26: 1 0x27: 1 0x32: 3 0x33: 3 0x56: 0x59: 1 0x70: 1 0x72: 2 0x73: 1 0x82: 1 0x85: 2 0x86: 2 35 | 0x25 COMMAND_CLASS_SWITCH_BINARY 1 36 | 0x26 COMMAND_CLASS_SWITCH_MULTILEVEL 1 37 | 0x27 COMMAND_CLASS_SWITCH_ALL 1 38 | 0x32 COMMAND_CLASS_METER 3 39 | 0x33 COMMAND_CLASS_COLOR_SWITCH 3 40 | 0x56 ? 41 | 0x59 COMMAND_CLASS_ASSOCIATION_GRP_INFO 1 42 | 0x70 COMMAND_CLASS_CONFIGURATION 1 43 | 0x72 COMMAND_CLASS_MANUFACTURER_SPECIFIC 2 44 | 0x73 COMMAND_CLASS_POWERLEVEL 1 45 | 0x81 COMMAND_CLASS_CLOCK 1 46 | 0x82 COMMAND_CLASS_HAIL 1 47 | 0x85 COMMAND_CLASS_ASSOCIATION 2 48 | 0x86 COMMAND_CLASS_VERSION 2 49 | */ 50 | fingerprint deviceId: "0x1001", inClusters: "0x25,0x26,0x27,0x32,0x2C,0x2B,0x33,0x85,0x56,0x59,0x5A,0x5E,0x70,0x72,0x73,0x85,0x86", outClusters: "0x82" 51 | } 52 | // simulator metadata 53 | simulator { 54 | status "on": "command: 2003, payload: FF" 55 | status "off": "command: 2003, payload: 00" 56 | 57 | for (int i = 0; i <= 10000; i += 1000) { 58 | status "power ${i} W": 59 | new physicalgraph.zwave.Zwave().meterV3.meterReport(scaledMeterValue: i, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage() 60 | } 61 | for (int i = 0; i <= 100; i += 10) { 62 | status "energy ${i} kWh": 63 | new physicalgraph.zwave.Zwave().meterV3.meterReport(scaledMeterValue: i, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage() 64 | } 65 | 66 | // reply messages 67 | reply "2001FF,delay 100,2502": "command: 2503, payload: FF" 68 | reply "200100,delay 100,2502": "command: 2503, payload: 00" 69 | 70 | } 71 | 72 | // tile definitions 73 | tiles (scale: 2) { 74 | multiAttributeTile(name:"main", type:"generic", width:6, height:4, canChangeIcon: true) { 75 | tileAttribute("device.switch", key: "PRIMARY_CONTROL") { 76 | attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" 77 | attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" 78 | } 79 | tileAttribute("device.power", key: "SECONDARY_CONTROL") { 80 | attributeState "default",label:'${currentValue} W' 81 | } 82 | } 83 | /*standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) { 84 | state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" 85 | state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" 86 | }*/ 87 | valueTile("energy", "device.energy", decoration: "flat", width: 2, height: 2) { 88 | state "default", label:'${currentValue} kWh', action:"poll" 89 | } 90 | valueTile("current", "device.current", decoration: "flat", width: 2, height: 2) { 91 | state "default", label:'${currentValue} A', action:"poll" 92 | } 93 | valueTile("voltage", "device.voltage", decoration: "flat", width: 2, height: 2) { 94 | state "default", label:'${currentValue} V', action:"poll" 95 | } 96 | standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 97 | state "default", label:'reset kWh', action:"reset" 98 | } 99 | standardTile("configure", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 100 | state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure" 101 | } 102 | standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 103 | state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" 104 | } 105 | 106 | main "main","energy","current","voltage" 107 | details(["main","energy","current","voltage","reset","refresh","configure"]) 108 | } 109 | 110 | preferences { 111 | input "ledBehavior", "number", 112 | title: "LED Behavior", 113 | description: "0=energy tracking, 1=momentary status, 2=night light", 114 | defaultValue: 0, 115 | displayDuringSetup: true, 116 | range: "0..2" 117 | input "monitorInterval", "number", 118 | title: "Monitoring Interval", 119 | description: "The time interval in seconds for sending device reports", 120 | defaultValue: 60, 121 | range: "1..4294967295‬", 122 | required: false, 123 | displayDuringSetup: true 124 | } 125 | } 126 | 127 | def updated() 128 | { 129 | if (state.sec && !isConfigured()) { 130 | // in case we miss the SCSR 131 | response(configure()) 132 | } 133 | } 134 | 135 | def parse(String description) 136 | { 137 | def result = null 138 | if (description.startsWith("Err 106")) { 139 | state.sec = 0 140 | result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true, 141 | 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.") 142 | } else if (description != "updated") { 143 | 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]) 144 | if (cmd) { 145 | result = zwaveEvent(cmd) 146 | } 147 | } 148 | // log.debug "Parsed '${description}' to ${result.inspect()}" 149 | return result 150 | } 151 | 152 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) { 153 | 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]) 154 | state.sec = 1 155 | log.debug "encapsulated: ${encapsulatedCommand}" 156 | if (encapsulatedCommand) { 157 | zwaveEvent(encapsulatedCommand) 158 | } else { 159 | log.warn "Unable to extract encapsulated cmd from $cmd" 160 | createEvent(descriptionText: cmd.toString()) 161 | } 162 | } 163 | 164 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) { 165 | response(configure()) 166 | } 167 | 168 | def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) { 169 | log.debug "---CONFIGURATION REPORT V2--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}" 170 | } 171 | 172 | def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) { 173 | log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}" 174 | } 175 | 176 | def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd) { 177 | def meterTypes = ["Unknown", "Electric", "Gas", "Water"] 178 | def electricNames = ["energy", "energy", "power", "count", "voltage", "current", "powerFactor", "unknown"] 179 | def electricUnits = ["kWh", "kVAh", "W", "pulses", "V", "A", "Power Factor", ""] 180 | 181 | //NOTE ScaledPreviousMeterValue does not always contain a value 182 | def previousValue = cmd.scaledPreviousMeterValue ?: 0 183 | 184 | def map = [ name: electricNames[cmd.scale], unit: electricUnits[cmd.scale], displayed: state.display] 185 | switch(cmd.scale) { 186 | case 0: //kWh 187 | previousValue = device.currentValue("energy") ?: cmd.scaledPreviousMeterValue ?: 0 188 | map.value = cmd.scaledMeterValue 189 | break; 190 | case 1: //kVAh 191 | map.value = cmd.scaledMeterValue 192 | break; 193 | case 2: //Watts 194 | previousValue = device.currentValue("power") ?: cmd.scaledPreviousMeterValue ?: 0 195 | map.value = Math.round(cmd.scaledMeterValue) 196 | break; 197 | case 3: //pulses 198 | map.value = Math.round(cmd.scaledMeterValue) 199 | break; 200 | case 4: //Volts 201 | previousValue = device.currentValue("voltage") ?: cmd.scaledPreviousMeterValue ?: 0 202 | map.value = cmd.scaledMeterValue 203 | break; 204 | case 5: //Amps 205 | previousValue = device.currentValue("current") ?: cmd.scaledPreviousMeterValue ?: 0 206 | map.value = cmd.scaledMeterValue 207 | break; 208 | case 6: //Power Factor 209 | case 7: //Unknown 210 | map.value = cmd.scaledMeterValue 211 | break; 212 | default: 213 | break; 214 | } 215 | //Check if the value has changed by more than 5%, if so mark as a stateChange 216 | //map.isStateChange = ((cmd.scaledMeterValue - previousValue).abs() > (cmd.scaledMeterValue * 0.05)) 217 | 218 | createEvent(map) 219 | } 220 | 221 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) 222 | { 223 | [name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 224 | } 225 | 226 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) 227 | { 228 | [name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 229 | } 230 | 231 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) 232 | { 233 | [name: "switch", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 234 | } 235 | 236 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd) 237 | { 238 | [name: "switch", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 239 | } 240 | 241 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 242 | log.debug "Unhandled: $cmd" 243 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 244 | } 245 | 246 | def on() { 247 | delayBetween([ 248 | zwave.basicV1.basicSet(value: 0xFF).format(), 249 | zwave.basicV1.basicGet().format(), 250 | zwave.switchBinaryV1.switchBinaryGet().format() 251 | ], 2) 252 | } 253 | 254 | def off() { 255 | delayBetween([ 256 | zwave.basicV1.basicSet(value: 0x00).format(), 257 | zwave.basicV1.basicGet().format(), 258 | zwave.switchBinaryV1.switchBinaryGet().format() 259 | ], 2) 260 | } 261 | 262 | def poll() { 263 | delayBetween([ 264 | zwave.switchBinaryV1.switchBinaryGet().format(), 265 | zwave.basicV1.basicGet().format(), 266 | zwave.meterV3.meterGet(scale: 0).format(), //kWh 267 | zwave.meterV3.meterGet(scale: 1).format(), //kVAh 268 | zwave.meterV3.meterGet(scale: 2).format(), //Wattage 269 | zwave.meterV3.meterGet(scale: 4).format(), //Volts 270 | zwave.meterV3.meterGet(scale: 5).format(), //Amps 271 | zwave.meterV3.meterGet(scale: 6).format() //Power Factor 272 | ], 500) 273 | } 274 | 275 | def refresh() { 276 | delayBetween([ 277 | zwave.basicV1.basicGet().format(), 278 | zwave.switchBinaryV1.switchBinaryGet().format() 279 | ], 2) 280 | } 281 | 282 | def reset() { 283 | return [ 284 | zwave.meterV3.meterReset().format(), 285 | zwave.meterV3.meterGet(scale: 0).format(), //kWh 286 | zwave.meterV3.meterGet(scale: 2).format() //Wattage 287 | ] 288 | } 289 | 290 | def configure() { 291 | log.debug "Sending configure commands" 292 | def monitorInt = 60 293 | if (monitorInterval) { 294 | monitorInt=monitorInterval 295 | } 296 | def ledBehave = 0 297 | if (ledBehavior) { 298 | ledBehave=ledBehavior 299 | } 300 | def request = [ 301 | // set LED behavior 0 energy mode 1 momentary display 2 night light 302 | zwave.configurationV1.configurationSet(parameterNumber: 81, size: 1, scaledConfigurationValue: ledBehave), 303 | // Which reports need to send in Report group 1 304 | zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 15), 305 | // Which reports need to send in Report group 2 306 | zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 0), 307 | // Which reports need to send in Report group 3 308 | zwave.configurationV1.configurationSet(parameterNumber: 103, size: 4, scaledConfigurationValue: 0), 309 | // Interval to send Report group 1 310 | zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: monitorInt), 311 | // Interval to send Report group 2 312 | zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 600), 313 | // Interval to send Report group 3 314 | zwave.configurationV1.configurationSet(parameterNumber: 113, size: 4, scaledConfigurationValue: 600), 315 | 316 | // get LED behavior 317 | zwave.configurationV1.configurationGet(parameterNumber: 81), 318 | // get night light RGB value 319 | zwave.configurationV1.configurationGet(parameterNumber: 83), 320 | // get Energy Mode/momentary indicate LED brightness value 321 | zwave.configurationV1.configurationGet(parameterNumber: 84), 322 | // Which reports need to send in Report group 1 323 | zwave.configurationV1.configurationGet(parameterNumber: 101), 324 | // Which reports need to send in Report group 2 325 | zwave.configurationV1.configurationGet(parameterNumber: 102), 326 | // Which reports need to send in Report group 3 327 | zwave.configurationV1.configurationGet(parameterNumber: 103), 328 | // Interval to send Report group 1 329 | zwave.configurationV1.configurationGet(parameterNumber: 111), 330 | // Interval to send Report group 2 331 | zwave.configurationV1.configurationGet(parameterNumber: 112), 332 | // Interval to send Report group 3 333 | zwave.configurationV1.configurationGet(parameterNumber: 113), 334 | 335 | // Can use the zwaveHubNodeId variable to add the hub to the device's associations: 336 | zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId) 337 | ] 338 | commands(request) 339 | } 340 | 341 | private setConfigured() { 342 | updateDataValue("configured", "true") 343 | } 344 | 345 | private isConfigured() { 346 | getDataValue("configured") == "true" 347 | } 348 | 349 | private command(physicalgraph.zwave.Command cmd) { 350 | if (state.sec) { 351 | zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() 352 | } else { 353 | cmd.format() 354 | } 355 | } 356 | 357 | private commands(commands, delay=1000) { 358 | delayBetween(commands.collect{ command(it) }, delay) 359 | } 360 | -------------------------------------------------------------------------------- /Aeon SmartSwitch 6/device_type-aeon-smartswitch6-v0.2: -------------------------------------------------------------------------------- 1 | /* 2 | * V 0.2 of Aeon Smart Switch 6 code 10/5/2015 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 4 | * in compliance with the License. You may obtain a copy of the License at: 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 9 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 10 | * for the specific language governing permissions and limitations under the License. 11 | * 12 | * change log: 13 | * v 0.2 - added support for secure inclusion and command encapsulation 14 | */ 15 | 16 | metadata { 17 | definition (name: "Aeon Smart Switch 6 - RV v0.1", namespace: "robertvandervoort", author: "Robert Vandervoort") { 18 | capability "Energy Meter" 19 | capability "Power Meter" 20 | capability "Actuator" 21 | capability "Switch" 22 | capability "Configuration" 23 | capability "Polling" 24 | capability "Refresh" 25 | capability "Sensor" 26 | 27 | command "reset" 28 | 29 | /* Capability notes 30 | 37, 38, 51, 112, 39, 50, 129, 133, 89, 122, 115 31 | 32 | 0x2C COMMAND_CLASS_SCENE_ACTUATOR_CONF 33 | 0x2B COMMAND_CLASS_SCENE_ACTIVATION 34 | 0x7A COMMAND_CLASS_FIRMWARE_UPDATE_MD 2 35 | 0xEF COMMAND_CLASS_MARK 1 36 | 0x5A ? 37 | 0x5E ? 38 | 0x25: 1 0x26: 1 0x27: 1 0x32: 3 0x33: 3 0x56: 0x59: 1 0x70: 1 0x72: 2 0x73: 1 0x82: 1 0x85: 2 0x86: 2 39 | 0x25 COMMAND_CLASS_SWITCH_BINARY 1 40 | 0x26 COMMAND_CLASS_SWITCH_MULTILEVEL 1 41 | 0x27 COMMAND_CLASS_SWITCH_ALL 1 42 | 0x32 COMMAND_CLASS_METER 3 43 | 0x33 COMMAND_CLASS_COLOR_SWITCH 3 44 | 0x56 ? 45 | 0x59 COMMAND_CLASS_ASSOCIATION_GRP_INFO 1 46 | 0x70 COMMAND_CLASS_CONFIGURATION 1 47 | 0x72 COMMAND_CLASS_MANUFACTURER_SPECIFIC 2 48 | 0x73 COMMAND_CLASS_POWERLEVEL 1 49 | 0x81 COMMAND_CLASS_CLOCK 1 50 | 0x82 COMMAND_CLASS_HAIL 1 51 | 0x85 COMMAND_CLASS_ASSOCIATION 2 52 | 0x86 COMMAND_CLASS_VERSION 2 53 | */ 54 | fingerprint deviceId: "0x1001", inClusters: "0x25,0x26,0x27,0x32,0x2C,0x2B,0x33,0x85,0x56,0x59,0x5A,0x5E,0x70,0x72,0x73,0x85,0x86", outClusters: "0x82" 55 | } 56 | // simulator metadata 57 | simulator { 58 | status "on": "command: 2003, payload: FF" 59 | status "off": "command: 2003, payload: 00" 60 | 61 | for (int i = 0; i <= 10000; i += 1000) { 62 | status "power ${i} W": 63 | new physicalgraph.zwave.Zwave().meterV3.meterReport(scaledMeterValue: i, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage() 64 | } 65 | for (int i = 0; i <= 100; i += 10) { 66 | status "energy ${i} kWh": 67 | new physicalgraph.zwave.Zwave().meterV3.meterReport(scaledMeterValue: i, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage() 68 | } 69 | // reply messages 70 | reply "2001FF,delay 100,2502": "command: 2503, payload: FF" 71 | reply "200100,delay 100,2502": "command: 2503, payload: 00" 72 | 73 | } 74 | 75 | // tile definitions 76 | tiles (scale: 2) { 77 | multiAttributeTile(name:"main", type:"generic", width:6, height:4, canChangeIcon: true) { 78 | tileAttribute("device.switch", key: "PRIMARY_CONTROL") { 79 | attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" 80 | attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" 81 | } 82 | tileAttribute("device.power", key: "SECONDARY_CONTROL") { 83 | attributeState "default",label:'${currentValue} W' 84 | } 85 | } 86 | valueTile("energy", "device.energy", decoration: "flat", width: 2, height: 2) { 87 | state "default", label:'${currentValue} kWh', action:"poll" 88 | } 89 | valueTile("current", "device.current", decoration: "flat", width: 2, height: 2) { 90 | state "default", label:'${currentValue} A', action:"poll" 91 | } 92 | valueTile("voltage", "device.voltage", decoration: "flat", width: 2, height: 2) { 93 | state "default", label:'${currentValue} V', action:"poll" 94 | } 95 | standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 96 | state "default", label:'reset kWh', action:"reset" 97 | } 98 | standardTile("configure", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 99 | state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure" 100 | } 101 | standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 102 | state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" 103 | } 104 | 105 | main "main","energy","current","voltage" 106 | details(["main","energy","current","voltage","reset","refresh","configure"]) 107 | } 108 | 109 | preferences { 110 | input "ledBehavior", "integer", 111 | title: "LED Behavior", 112 | description: "0=energy tracking, 1=momentary status, 2=night light", 113 | defaultValue: 0, 114 | displayDuringSetup: true, 115 | range: "0..2" 116 | input "monitorInterval", "integer", 117 | title: "Monitoring Interval", 118 | description: "The time interval in seconds for sending device reports", 119 | defaultValue: 60, 120 | range: "1..4294967295‬", 121 | required: false, 122 | displayDuringSetup: true 123 | } 124 | } 125 | 126 | def updated() 127 | { 128 | if (state.sec && !isConfigured()) { 129 | // in case we miss the SCSR 130 | response(configure()) 131 | } 132 | } 133 | 134 | def parse(String description) 135 | { 136 | def result = null 137 | if (description.startsWith("Err 106")) { 138 | state.sec = 0 139 | result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true, 140 | 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.") 141 | } else if (description != "updated") { 142 | 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]) 143 | if (cmd) { 144 | result = zwaveEvent(cmd) 145 | } 146 | } 147 | // log.debug "Parsed '${description}' to ${result.inspect()}" 148 | return result 149 | } 150 | 151 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) { 152 | 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]) 153 | state.sec = 1 154 | // log.debug "encapsulated: ${encapsulatedCommand}" 155 | if (encapsulatedCommand) { 156 | zwaveEvent(encapsulatedCommand) 157 | } else { 158 | log.warn "Unable to extract encapsulated cmd from $cmd" 159 | createEvent(descriptionText: cmd.toString()) 160 | } 161 | } 162 | 163 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) { 164 | response(configure()) 165 | } 166 | 167 | def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) { 168 | log.debug "---CONFIGURATION REPORT V2--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}" 169 | } 170 | 171 | def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) { 172 | log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}" 173 | } 174 | 175 | def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd) { 176 | def meterTypes = ["Unknown", "Electric", "Gas", "Water"] 177 | def electricNames = ["energy", "energy", "power", "count", "voltage", "current", "powerFactor", "unknown"] 178 | def electricUnits = ["kWh", "kVAh", "W", "pulses", "V", "A", "Power Factor", ""] 179 | 180 | //NOTE ScaledPreviousMeterValue does not always contain a value 181 | def previousValue = cmd.scaledPreviousMeterValue ?: 0 182 | 183 | def map = [ name: electricNames[cmd.scale], unit: electricUnits[cmd.scale], displayed: state.display] 184 | switch(cmd.scale) { 185 | case 0: //kWh 186 | previousValue = device.currentValue("energy") ?: cmd.scaledPreviousMeterValue ?: 0 187 | map.value = cmd.scaledMeterValue 188 | break; 189 | case 1: //kVAh 190 | map.value = cmd.scaledMeterValue 191 | break; 192 | case 2: //Watts 193 | previousValue = device.currentValue("power") ?: cmd.scaledPreviousMeterValue ?: 0 194 | map.value = Math.round(cmd.scaledMeterValue) 195 | break; 196 | case 3: //pulses 197 | map.value = Math.round(cmd.scaledMeterValue) 198 | break; 199 | case 4: //Volts 200 | previousValue = device.currentValue("voltage") ?: cmd.scaledPreviousMeterValue ?: 0 201 | map.value = cmd.scaledMeterValue 202 | break; 203 | case 5: //Amps 204 | previousValue = device.currentValue("current") ?: cmd.scaledPreviousMeterValue ?: 0 205 | map.value = cmd.scaledMeterValue 206 | break; 207 | case 6: //Power Factor 208 | case 7: //Unknown 209 | map.value = cmd.scaledMeterValue 210 | break; 211 | default: 212 | break; 213 | } 214 | //Check if the value has changed by more than 5%, if so mark as a stateChange 215 | //map.isStateChange = ((cmd.scaledMeterValue - previousValue).abs() > (cmd.scaledMeterValue * 0.05)) 216 | 217 | createEvent(map) 218 | } 219 | 220 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) 221 | { 222 | [name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 223 | } 224 | 225 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) 226 | { 227 | [name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 228 | } 229 | 230 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) 231 | { 232 | [name: "switch", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 233 | } 234 | 235 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd) 236 | { 237 | [name: "switch", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 238 | } 239 | 240 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 241 | log.debug "Unhandled: $cmd" 242 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 243 | } 244 | 245 | def on() { 246 | def request = [ 247 | zwave.basicV1.basicSet(value: 0xFF), 248 | zwave.basicV1.basicGet(), 249 | zwave.switchBinaryV1.switchBinaryGet() 250 | ] 251 | commands(request) 252 | } 253 | 254 | def off() { 255 | def request = [ 256 | zwave.basicV1.basicSet(value: 0x00), 257 | zwave.basicV1.basicGet(), 258 | zwave.switchBinaryV1.switchBinaryGet() 259 | ] 260 | commands(request) 261 | } 262 | 263 | def poll() { 264 | def request = [ 265 | zwave.switchBinaryV1.switchBinaryGet(), 266 | zwave.basicV1.basicGet(), 267 | zwave.meterV3.meterGet(scale: 0), //kWh 268 | zwave.meterV3.meterGet(scale: 1), //kVAh 269 | zwave.meterV3.meterGet(scale: 2), //Wattage 270 | zwave.meterV3.meterGet(scale: 4), //Volts 271 | zwave.meterV3.meterGet(scale: 5), //Amps 272 | zwave.meterV3.meterGet(scale: 6) //Power Factor 273 | ] 274 | commands(request) 275 | } 276 | 277 | def refresh() { 278 | def request = [ 279 | zwave.basicV1.basicGet(), 280 | zwave.switchBinaryV1.switchBinaryGet() 281 | ] 282 | commands(request) 283 | } 284 | 285 | def reset() { 286 | def request = [ 287 | zwave.meterV3.meterReset(), 288 | zwave.meterV3.meterGet(scale: 0), //kWh 289 | zwave.meterV3.meterGet(scale: 1), //kVAh 290 | zwave.meterV3.meterGet(scale: 2), //Wattage 291 | zwave.meterV3.meterGet(scale: 4), //Volts 292 | zwave.meterV3.meterGet(scale: 5), //Amps 293 | zwave.meterV3.meterGet(scale: 6) //Power Factor 294 | ] 295 | commands(request) 296 | } 297 | 298 | def configure() { 299 | def monitorInt = 60 300 | if (monitorInterval) { 301 | monitorInt=monitorInterval.toInteger() 302 | } 303 | def ledBehave = 0 304 | if (ledBehavior) { 305 | ledBehave=ledBehavior.toInteger() 306 | } 307 | log.debug "Sending configure commands - monitorInterval '${monitorInt}', ledBehavior '${ledBehave}'" 308 | def request = [ 309 | // Reset switch configuration to defaults 310 | // zwave.configurationV1.configurationSet(parameterNumber: 255, size: 1, scaledConfigurationValue: 1), 311 | // set LED behavior 0 energy mode 1 momentary display 2 night light 312 | zwave.configurationV1.configurationSet(parameterNumber: 81, size: 1, scaledConfigurationValue: ledBehave), 313 | // Which reports need to send in Report group 1 314 | zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 4|2|1), 315 | // Which reports need to send in Report group 2 316 | zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 8), 317 | // Which reports need to send in Report group 3 318 | zwave.configurationV1.configurationSet(parameterNumber: 103, size: 4, scaledConfigurationValue: 0), 319 | // Interval to send Report group 1 320 | zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: monitorInt), 321 | // Interval to send Report group 2 322 | zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 60), 323 | // Interval to send Report group 3 324 | zwave.configurationV1.configurationSet(parameterNumber: 113, size: 4, scaledConfigurationValue: 0), 325 | 326 | // get LED behavior 327 | zwave.configurationV1.configurationGet(parameterNumber: 81), 328 | // get night light RGB value 329 | zwave.configurationV1.configurationGet(parameterNumber: 83), 330 | // get Energy Mode/momentary indicate LED brightness value 331 | zwave.configurationV1.configurationGet(parameterNumber: 84), 332 | // Which reports need to send in Report group 1 333 | zwave.configurationV1.configurationGet(parameterNumber: 101), 334 | // Which reports need to send in Report group 2 335 | zwave.configurationV1.configurationGet(parameterNumber: 102), 336 | // Which reports need to send in Report group 3 337 | zwave.configurationV1.configurationGet(parameterNumber: 103), 338 | // Interval to send Report group 1 339 | zwave.configurationV1.configurationGet(parameterNumber: 111), 340 | // Interval to send Report group 2 341 | zwave.configurationV1.configurationGet(parameterNumber: 112), 342 | // Interval to send Report group 3 343 | zwave.configurationV1.configurationGet(parameterNumber: 113), 344 | 345 | // Can use the zwaveHubNodeId variable to add the hub to the device's associations: 346 | zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId) 347 | ] 348 | commands(request) 349 | } 350 | 351 | private setConfigured() { 352 | updateDataValue("configured", "true") 353 | } 354 | 355 | private isConfigured() { 356 | getDataValue("configured") == "true" 357 | } 358 | 359 | private command(physicalgraph.zwave.Command cmd) { 360 | if (state.sec) { 361 | zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() 362 | } else { 363 | cmd.format() 364 | } 365 | } 366 | 367 | private commands(commands, delay=500) { 368 | delayBetween(commands.collect{ command(it) }, delay) 369 | } 370 | -------------------------------------------------------------------------------- /Aeon SmartSwitch 6/device_type-aeon-smartswitch6-v0.4: -------------------------------------------------------------------------------- 1 | /* 2 | * V 0.4 of Aeon Smart Switch 6 code 10/5/2015 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 4 | * in compliance with the License. You may obtain a copy of the License at: 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 9 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 10 | * for the specific language governing permissions and limitations under the License. 11 | * 12 | * some code used from various SmartThings device type and metering code from ElasticDev 13 | * 14 | * change log: 15 | * v 0.2 - added support for secure inclusion and command encapsulation 16 | * v 0.3 - added brightness control and zwave power level node report reporting support (6 second button press) 17 | * v 0.4 - added color control for the night light behavior 18 | */ 19 | 20 | metadata { 21 | definition (name: "Aeon Smart Switch 6 - RV v0.4", namespace: "robertvandervoort", author: "Robert Vandervoort") { 22 | capability "Energy Meter" 23 | capability "Power Meter" 24 | capability "Actuator" 25 | capability "Switch" 26 | capability "Color Control" 27 | capability "Configuration" 28 | capability "Polling" 29 | capability "Refresh" 30 | capability "Sensor" 31 | 32 | command "reset" 33 | 34 | fingerprint deviceId: "0x1001", inClusters: "0x98" 35 | fingerprint inClusters: "0x25,0x26,0x27,0x32,0x2C,0x2B,0x33,0x85,0x56,0x59,0x5A,0x5E,0x70,0x72,0x73,0x85,0x86", outClusters: "0x82" 36 | } 37 | // simulator metadata 38 | simulator { 39 | status "on": "command: 2003, payload: FF" 40 | status "off": "command: 2003, payload: 00" 41 | 42 | for (int i = 0; i <= 10000; i += 1000) { 43 | status "power ${i} W": 44 | new physicalgraph.zwave.Zwave().meterV3.meterReport(scaledMeterValue: i, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage() 45 | } 46 | for (int i = 0; i <= 100; i += 10) { 47 | status "energy ${i} kWh": 48 | new physicalgraph.zwave.Zwave().meterV3.meterReport(scaledMeterValue: i, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage() 49 | } 50 | // reply messages 51 | reply "2001FF,delay 100,2502": "command: 2503, payload: FF" 52 | reply "200100,delay 100,2502": "command: 2503, payload: 00" 53 | 54 | } 55 | 56 | // tile definitions 57 | tiles (scale: 2) { 58 | multiAttributeTile(name:"main", type:"generic", width:6, height:4, canChangeIcon: true) { 59 | tileAttribute("device.switch", key: "PRIMARY_CONTROL") { 60 | attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" 61 | attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" 62 | } 63 | tileAttribute("device.power", key: "SECONDARY_CONTROL") { 64 | attributeState "default",label:'${currentValue} W' 65 | } 66 | } 67 | valueTile("energy", "device.energy", decoration: "flat", width: 2, height: 2) { 68 | state "default", label:'${currentValue} kWh', action:"poll" 69 | } 70 | valueTile("current", "device.current", decoration: "flat", width: 2, height: 2) { 71 | state "default", label:'${currentValue} A', action:"poll" 72 | } 73 | valueTile("voltage", "device.voltage", decoration: "flat", width: 2, height: 2) { 74 | state "default", label:'${currentValue} V', action:"poll" 75 | } 76 | controlTile("rgbSelector", "device.color", "color", height: 2, width: 2, inactiveLabel: false) { 77 | state "color", action:"setColor" 78 | } 79 | standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 80 | state "default", label:'reset kWh', action:"reset" 81 | } 82 | standardTile("configure", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 83 | state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure" 84 | } 85 | standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 86 | state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" 87 | } 88 | main "main","energy","current","voltage" 89 | details(["main","energy","current","voltage","rgbSelector","reset","refresh","configure"]) 90 | } 91 | 92 | preferences { 93 | input "ledBehavior", "integer", 94 | title: "LED Behavior", 95 | description: "0=energy tracking, 1=momentary status, 2=night light", 96 | defaultValue: 0, 97 | displayDuringSetup: true, 98 | range: "0..2" 99 | input "monitorInterval", "integer", 100 | title: "Monitoring Interval", 101 | description: "The time interval in seconds for sending device reports", 102 | defaultValue: 60, 103 | range: "1..4294967295‬", 104 | required: false, 105 | displayDuringSetup: true 106 | input "ledBrightness", "integer", 107 | title: "LED Brightness", 108 | description: "Set the % brightness of indicator LEDs", 109 | defaultValue: 50, 110 | range: "0..100", 111 | required: false, 112 | displayduringSetup: true 113 | } 114 | } 115 | 116 | def updated() 117 | { 118 | if (state.sec && !isConfigured()) { 119 | // in case we miss the SCSR 120 | response(configure()) 121 | } 122 | } 123 | 124 | def parse(String description) 125 | { 126 | def result = null 127 | if (description.startsWith("Err 106")) { 128 | state.sec = 0 129 | result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true, 130 | 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.") 131 | } else if (description != "updated") { 132 | 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]) 133 | if (cmd) { 134 | result = zwaveEvent(cmd) 135 | } 136 | } 137 | // log.debug "Parsed '${description}' to ${result.inspect()}" 138 | return result 139 | } 140 | 141 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) { 142 | 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]) 143 | state.sec = 1 144 | // log.debug "encapsulated: ${encapsulatedCommand}" 145 | if (encapsulatedCommand) { 146 | zwaveEvent(encapsulatedCommand) 147 | } else { 148 | log.warn "Unable to extract encapsulated cmd from $cmd" 149 | createEvent(descriptionText: cmd.toString()) 150 | } 151 | } 152 | 153 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) { 154 | response(configure()) 155 | } 156 | 157 | def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) { 158 | log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}" 159 | def request = [ 160 | physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet() 161 | ] 162 | response(commands(request)) 163 | } 164 | 165 | def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) { 166 | log.debug "---CONFIGURATION REPORT V2--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}" 167 | } 168 | 169 | def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) { 170 | log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}" 171 | } 172 | 173 | def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd) { 174 | def meterTypes = ["Unknown", "Electric", "Gas", "Water"] 175 | def electricNames = ["energy", "energy", "power", "count", "voltage", "current", "powerFactor", "unknown"] 176 | def electricUnits = ["kWh", "kVAh", "W", "pulses", "V", "A", "Power Factor", ""] 177 | 178 | //NOTE ScaledPreviousMeterValue does not always contain a value 179 | def previousValue = cmd.scaledPreviousMeterValue ?: 0 180 | 181 | def map = [ name: electricNames[cmd.scale], unit: electricUnits[cmd.scale], displayed: state.display] 182 | switch(cmd.scale) { 183 | case 0: //kWh 184 | previousValue = device.currentValue("energy") ?: cmd.scaledPreviousMeterValue ?: 0 185 | map.value = cmd.scaledMeterValue 186 | break; 187 | case 1: //kVAh 188 | map.value = cmd.scaledMeterValue 189 | break; 190 | case 2: //Watts 191 | previousValue = device.currentValue("power") ?: cmd.scaledPreviousMeterValue ?: 0 192 | map.value = Math.round(cmd.scaledMeterValue) 193 | break; 194 | case 3: //pulses 195 | map.value = Math.round(cmd.scaledMeterValue) 196 | break; 197 | case 4: //Volts 198 | previousValue = device.currentValue("voltage") ?: cmd.scaledPreviousMeterValue ?: 0 199 | map.value = cmd.scaledMeterValue 200 | break; 201 | case 5: //Amps 202 | previousValue = device.currentValue("current") ?: cmd.scaledPreviousMeterValue ?: 0 203 | map.value = cmd.scaledMeterValue 204 | break; 205 | case 6: //Power Factor 206 | case 7: //Unknown 207 | map.value = cmd.scaledMeterValue 208 | break; 209 | default: 210 | break; 211 | } 212 | //Check if the value has changed by more than 5%, if so mark as a stateChange 213 | //map.isStateChange = ((cmd.scaledMeterValue - previousValue).abs() > (cmd.scaledMeterValue * 0.05)) 214 | 215 | createEvent(map) 216 | } 217 | 218 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) 219 | { 220 | [name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 221 | } 222 | 223 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) 224 | { 225 | [name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 226 | } 227 | 228 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) 229 | { 230 | [name: "switch", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 231 | } 232 | 233 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd) 234 | { 235 | [name: "switch", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 236 | } 237 | 238 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 239 | log.debug "Unhandled: $cmd" 240 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 241 | } 242 | 243 | def on() { 244 | def request = [ 245 | zwave.basicV1.basicSet(value: 0xFF), 246 | zwave.basicV1.basicGet(), 247 | zwave.switchBinaryV1.switchBinaryGet() 248 | ] 249 | commands(request) 250 | } 251 | 252 | def off() { 253 | def request = [ 254 | zwave.basicV1.basicSet(value: 0x00), 255 | zwave.basicV1.basicGet(), 256 | zwave.switchBinaryV1.switchBinaryGet() 257 | ] 258 | commands(request) 259 | } 260 | 261 | def setColor(value) { 262 | def result = [] 263 | log.debug "setColor: ${value}" 264 | if (value.hex) { 265 | def c = value.hex.findAll(/[0-9a-fA-F]{2}/).collect { Integer.parseInt(it, 16) } 266 | result << zwave.configurationV1.configurationSet(parameterNumber: 83, size: 3, configurationValue: [c[0], c[1], c[2]]) 267 | } 268 | if(value.hex) sendEvent(name: "color", value: value.hex) 269 | commands(result) 270 | } 271 | 272 | def poll() { 273 | def request = [ 274 | zwave.switchBinaryV1.switchBinaryGet(), 275 | zwave.basicV1.basicGet(), 276 | zwave.meterV3.meterGet(scale: 0), //kWh 277 | zwave.meterV3.meterGet(scale: 1), //kVAh 278 | zwave.meterV3.meterGet(scale: 2), //Wattage 279 | zwave.meterV3.meterGet(scale: 4), //Volts 280 | zwave.meterV3.meterGet(scale: 5), //Amps 281 | zwave.meterV3.meterGet(scale: 6) //Power Factor 282 | ] 283 | commands(request) 284 | } 285 | 286 | def refresh() { 287 | def request = [ 288 | zwave.basicV1.basicGet(), 289 | zwave.switchBinaryV1.switchBinaryGet() 290 | ] 291 | commands(request) 292 | } 293 | 294 | def reset() { 295 | def request = [ 296 | zwave.meterV3.meterReset(), 297 | zwave.meterV3.meterGet(scale: 0), //kWh 298 | zwave.meterV3.meterGet(scale: 1), //kVAh 299 | zwave.meterV3.meterGet(scale: 2), //Wattage 300 | zwave.meterV3.meterGet(scale: 4), //Volts 301 | zwave.meterV3.meterGet(scale: 5), //Amps 302 | zwave.meterV3.meterGet(scale: 6) //Power Factor 303 | ] 304 | commands(request) 305 | } 306 | 307 | def configure() { 308 | def monitorInt = 60 309 | if (monitorInterval) { 310 | monitorInt=monitorInterval.toInteger() 311 | } 312 | def ledBehave = 0 313 | if (ledBehavior) { 314 | ledBehave=ledBehavior.toInteger() 315 | } 316 | def ledBright = 50 317 | if (ledBrightness) { 318 | ledBright=ledBrightness.toInteger() 319 | } 320 | log.debug "Sending configure commands - monitorInterval '${monitorInt}', ledBehavior '${ledBehave}'" 321 | def request = [ 322 | // Reset switch configuration to defaults 323 | // zwave.configurationV1.configurationSet(parameterNumber: 255, size: 1, scaledConfigurationValue: 1), 324 | // 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) 325 | zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, configurationValue: [2]), 326 | // set LED behavior 0 energy mode 1 momentary display 2 night light 327 | zwave.configurationV1.configurationSet(parameterNumber: 81, size: 1, scaledConfigurationValue: ledBehave), 328 | // Set LED brightness 329 | zwave.configurationV1.configurationSet(parameterNumber: 84, size: 3, configurationValue: [ledBright,ledBright,ledBright]), 330 | // Which reports need to send in Report group 1 331 | zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 4|2|1), 332 | // Which reports need to send in Report group 2 333 | zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 8), 334 | // Which reports need to send in Report group 3 335 | zwave.configurationV1.configurationSet(parameterNumber: 103, size: 4, scaledConfigurationValue: 0), 336 | // Interval to send Report group 1 337 | zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: monitorInt), 338 | // Interval to send Report group 2 339 | zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 60), 340 | // Interval to send Report group 3 341 | zwave.configurationV1.configurationSet(parameterNumber: 113, size: 4, scaledConfigurationValue: 0), 342 | 343 | // get LED behavior 344 | zwave.configurationV1.configurationGet(parameterNumber: 81), 345 | // get night light RGB value 346 | zwave.configurationV1.configurationGet(parameterNumber: 83), 347 | // get Energy Mode/momentary indicate LED brightness value 348 | zwave.configurationV1.configurationGet(parameterNumber: 84), 349 | // Which reports need to send in Report group 1 350 | zwave.configurationV1.configurationGet(parameterNumber: 101), 351 | // Which reports need to send in Report group 2 352 | zwave.configurationV1.configurationGet(parameterNumber: 102), 353 | // Which reports need to send in Report group 3 354 | zwave.configurationV1.configurationGet(parameterNumber: 103), 355 | // Interval to send Report group 1 356 | zwave.configurationV1.configurationGet(parameterNumber: 111), 357 | // Interval to send Report group 2 358 | zwave.configurationV1.configurationGet(parameterNumber: 112), 359 | // Interval to send Report group 3 360 | zwave.configurationV1.configurationGet(parameterNumber: 113), 361 | 362 | // Can use the zwaveHubNodeId variable to add the hub to the device's associations: 363 | zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId) 364 | ] 365 | commands(request) 366 | } 367 | 368 | private setConfigured() { 369 | updateDataValue("configured", "true") 370 | } 371 | 372 | private isConfigured() { 373 | getDataValue("configured") == "true" 374 | } 375 | 376 | private command(physicalgraph.zwave.Command cmd) { 377 | if (state.sec) { 378 | zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() 379 | } else { 380 | cmd.format() 381 | } 382 | } 383 | 384 | private commands(commands, delay=500) { 385 | delayBetween(commands.collect{ command(it) }, delay) 386 | } -------------------------------------------------------------------------------- /Aeon SmartSwitch 6/device_type-aeon-smartswitch6-v0.4-ANDROID: -------------------------------------------------------------------------------- 1 | /* 2 | * V 0.4 of Aeon Smart Switch 6 code 10/5/2015 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 4 | * in compliance with the License. You may obtain a copy of the License at: 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 9 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 10 | * for the specific language governing permissions and limitations under the License. 11 | * 12 | * some code used from various SmartThings device type and metering code from ElasticDev 13 | * 14 | * change log: 15 | * v 0.2 - added support for secure inclusion and command encapsulation 16 | * v 0.3 - added brightness control and zwave power level node report reporting support (6 second button press) 17 | * v 0.4 - added color control for the night light behavior 18 | * ANDROID - Thanks Jeff_Pollock and RBoy for pointing out the Range values bug in Android helping to get this workign on Android OS 19 | 20 | */ 21 | 22 | metadata { 23 | definition (name: "Aeon Smart Switch 6 - RV v0.4", namespace: "robertvandervoort", author: "Robert Vandervoort") { 24 | capability "Energy Meter" 25 | capability "Power Meter" 26 | capability "Actuator" 27 | capability "Switch" 28 | capability "Color Control" 29 | capability "Configuration" 30 | capability "Polling" 31 | capability "Refresh" 32 | capability "Sensor" 33 | 34 | command "reset" 35 | 36 | fingerprint deviceId: "0x1001", inClusters: "0x98" 37 | fingerprint inClusters: "0x25,0x26,0x27,0x32,0x2C,0x2B,0x33,0x85,0x56,0x59,0x5A,0x5E,0x70,0x72,0x73,0x85,0x86", outClusters: "0x82" 38 | } 39 | // simulator metadata 40 | simulator { 41 | status "on": "command: 2003, payload: FF" 42 | status "off": "command: 2003, payload: 00" 43 | 44 | for (int i = 0; i <= 10000; i += 1000) { 45 | status "power ${i} W": 46 | new physicalgraph.zwave.Zwave().meterV3.meterReport(scaledMeterValue: i, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage() 47 | } 48 | for (int i = 0; i <= 100; i += 10) { 49 | status "energy ${i} kWh": 50 | new physicalgraph.zwave.Zwave().meterV3.meterReport(scaledMeterValue: i, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage() 51 | } 52 | // reply messages 53 | reply "2001FF,delay 100,2502": "command: 2503, payload: FF" 54 | reply "200100,delay 100,2502": "command: 2503, payload: 00" 55 | 56 | } 57 | 58 | // tile definitions 59 | tiles (scale: 2) { 60 | multiAttributeTile(name:"main", type:"generic", width:6, height:4, canChangeIcon: true) { 61 | tileAttribute("device.switch", key: "PRIMARY_CONTROL") { 62 | attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" 63 | attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" 64 | } 65 | tileAttribute("device.power", key: "SECONDARY_CONTROL") { 66 | attributeState "default",label:'${currentValue} W' 67 | } 68 | } 69 | valueTile("energy", "device.energy", decoration: "flat", width: 2, height: 2) { 70 | state "default", label:'${currentValue} kWh', action:"poll" 71 | } 72 | valueTile("current", "device.current", decoration: "flat", width: 2, height: 2) { 73 | state "default", label:'${currentValue} A', action:"poll" 74 | } 75 | valueTile("voltage", "device.voltage", decoration: "flat", width: 2, height: 2) { 76 | state "default", label:'${currentValue} V', action:"poll" 77 | } 78 | controlTile("rgbSelector", "device.color", "color", height: 2, width: 2, inactiveLabel: false) { 79 | state "color", action:"setColor" 80 | } 81 | standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 82 | state "default", label:'reset kWh', action:"reset" 83 | } 84 | standardTile("configure", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 85 | state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure" 86 | } 87 | standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 88 | state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" 89 | } 90 | main "main","energy","current","voltage" 91 | details(["main","energy","current","voltage","rgbSelector","reset","refresh","configure"]) 92 | } 93 | 94 | preferences { 95 | input "ledBehavior", "integer", 96 | title: "LED Behavior", 97 | description: "0=energy tracking, 1=momentary status, 2=night light", 98 | defaultValue: 0, 99 | displayDuringSetup: true 100 | input "monitorInterval", "integer", 101 | title: "Monitoring Interval", 102 | description: "The time interval in seconds for sending device reports", 103 | defaultValue: 60, 104 | required: false, 105 | displayDuringSetup: true 106 | input "ledBrightness", "integer", 107 | title: "LED Brightness", 108 | description: "Set the % brightness of indicator LEDs", 109 | defaultValue: 50, 110 | required: false, 111 | displayduringSetup: true 112 | } 113 | } 114 | 115 | def updated() 116 | { 117 | if (state.sec && !isConfigured()) { 118 | // in case we miss the SCSR 119 | response(configure()) 120 | } 121 | } 122 | 123 | def parse(String description) 124 | { 125 | def result = null 126 | if (description.startsWith("Err 106")) { 127 | state.sec = 0 128 | result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true, 129 | 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.") 130 | } else if (description != "updated") { 131 | 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]) 132 | if (cmd) { 133 | result = zwaveEvent(cmd) 134 | } 135 | } 136 | // log.debug "Parsed '${description}' to ${result.inspect()}" 137 | return result 138 | } 139 | 140 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) { 141 | 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]) 142 | state.sec = 1 143 | // log.debug "encapsulated: ${encapsulatedCommand}" 144 | if (encapsulatedCommand) { 145 | zwaveEvent(encapsulatedCommand) 146 | } else { 147 | log.warn "Unable to extract encapsulated cmd from $cmd" 148 | createEvent(descriptionText: cmd.toString()) 149 | } 150 | } 151 | 152 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) { 153 | response(configure()) 154 | } 155 | 156 | def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) { 157 | log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}" 158 | def request = [ 159 | physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet() 160 | ] 161 | response(commands(request)) 162 | } 163 | 164 | def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) { 165 | log.debug "---CONFIGURATION REPORT V2--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}" 166 | } 167 | 168 | def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) { 169 | log.debug "---CONFIGURATION REPORT V1--- ${device.displayName} parameter ${cmd.parameterNumber} with a byte size of ${cmd.size} is set to ${cmd.configurationValue}" 170 | } 171 | 172 | def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd) { 173 | def meterTypes = ["Unknown", "Electric", "Gas", "Water"] 174 | def electricNames = ["energy", "energy", "power", "count", "voltage", "current", "powerFactor", "unknown"] 175 | def electricUnits = ["kWh", "kVAh", "W", "pulses", "V", "A", "Power Factor", ""] 176 | 177 | //NOTE ScaledPreviousMeterValue does not always contain a value 178 | def previousValue = cmd.scaledPreviousMeterValue ?: 0 179 | 180 | def map = [ name: electricNames[cmd.scale], unit: electricUnits[cmd.scale], displayed: state.display] 181 | switch(cmd.scale) { 182 | case 0: //kWh 183 | previousValue = device.currentValue("energy") ?: cmd.scaledPreviousMeterValue ?: 0 184 | map.value = cmd.scaledMeterValue 185 | break; 186 | case 1: //kVAh 187 | map.value = cmd.scaledMeterValue 188 | break; 189 | case 2: //Watts 190 | previousValue = device.currentValue("power") ?: cmd.scaledPreviousMeterValue ?: 0 191 | map.value = Math.round(cmd.scaledMeterValue) 192 | break; 193 | case 3: //pulses 194 | map.value = Math.round(cmd.scaledMeterValue) 195 | break; 196 | case 4: //Volts 197 | previousValue = device.currentValue("voltage") ?: cmd.scaledPreviousMeterValue ?: 0 198 | map.value = cmd.scaledMeterValue 199 | break; 200 | case 5: //Amps 201 | previousValue = device.currentValue("current") ?: cmd.scaledPreviousMeterValue ?: 0 202 | map.value = cmd.scaledMeterValue 203 | break; 204 | case 6: //Power Factor 205 | case 7: //Unknown 206 | map.value = cmd.scaledMeterValue 207 | break; 208 | default: 209 | break; 210 | } 211 | //Check if the value has changed by more than 5%, if so mark as a stateChange 212 | //map.isStateChange = ((cmd.scaledMeterValue - previousValue).abs() > (cmd.scaledMeterValue * 0.05)) 213 | 214 | createEvent(map) 215 | } 216 | 217 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) 218 | { 219 | [name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 220 | } 221 | 222 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) 223 | { 224 | [name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 225 | } 226 | 227 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) 228 | { 229 | [name: "switch", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 230 | } 231 | 232 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd) 233 | { 234 | [name: "switch", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 235 | } 236 | 237 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 238 | log.debug "Unhandled: $cmd" 239 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 240 | } 241 | 242 | def on() { 243 | def request = [ 244 | zwave.basicV1.basicSet(value: 0xFF), 245 | zwave.basicV1.basicGet(), 246 | zwave.switchBinaryV1.switchBinaryGet() 247 | ] 248 | commands(request) 249 | } 250 | 251 | def off() { 252 | def request = [ 253 | zwave.basicV1.basicSet(value: 0x00), 254 | zwave.basicV1.basicGet(), 255 | zwave.switchBinaryV1.switchBinaryGet() 256 | ] 257 | commands(request) 258 | } 259 | 260 | def setColor(value) { 261 | def result = [] 262 | log.debug "setColor: ${value}" 263 | if (value.hex) { 264 | def c = value.hex.findAll(/[0-9a-fA-F]{2}/).collect { Integer.parseInt(it, 16) } 265 | result << zwave.configurationV1.configurationSet(parameterNumber: 83, size: 3, configurationValue: [c[0], c[1], c[2]]) 266 | } 267 | if(value.hex) sendEvent(name: "color", value: value.hex) 268 | commands(result) 269 | } 270 | 271 | def poll() { 272 | def request = [ 273 | zwave.switchBinaryV1.switchBinaryGet(), 274 | zwave.basicV1.basicGet(), 275 | zwave.meterV3.meterGet(scale: 0), //kWh 276 | zwave.meterV3.meterGet(scale: 1), //kVAh 277 | zwave.meterV3.meterGet(scale: 2), //Wattage 278 | zwave.meterV3.meterGet(scale: 4), //Volts 279 | zwave.meterV3.meterGet(scale: 5), //Amps 280 | zwave.meterV3.meterGet(scale: 6) //Power Factor 281 | ] 282 | commands(request) 283 | } 284 | 285 | def refresh() { 286 | def request = [ 287 | zwave.basicV1.basicGet(), 288 | zwave.switchBinaryV1.switchBinaryGet() 289 | ] 290 | commands(request) 291 | } 292 | 293 | def reset() { 294 | def request = [ 295 | zwave.meterV3.meterReset(), 296 | zwave.meterV3.meterGet(scale: 0), //kWh 297 | zwave.meterV3.meterGet(scale: 1), //kVAh 298 | zwave.meterV3.meterGet(scale: 2), //Wattage 299 | zwave.meterV3.meterGet(scale: 4), //Volts 300 | zwave.meterV3.meterGet(scale: 5), //Amps 301 | zwave.meterV3.meterGet(scale: 6) //Power Factor 302 | ] 303 | commands(request) 304 | } 305 | 306 | def configure() { 307 | def monitorInt = 60 308 | if (monitorInterval) { 309 | monitorInt=monitorInterval.toInteger() 310 | } 311 | def ledBehave = 0 312 | if (ledBehavior) { 313 | ledBehave=ledBehavior.toInteger() 314 | } 315 | def ledBright = 50 316 | if (ledBrightness) { 317 | ledBright=ledBrightness.toInteger() 318 | } 319 | log.debug "Sending configure commands - monitorInterval '${monitorInt}', ledBehavior '${ledBehave}'" 320 | def request = [ 321 | // Reset switch configuration to defaults 322 | // zwave.configurationV1.configurationSet(parameterNumber: 255, size: 1, scaledConfigurationValue: 1), 323 | // 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) 324 | zwave.configurationV1.configurationSet(parameterNumber: 80, size: 1, configurationValue: [2]), 325 | // set LED behavior 0 energy mode 1 momentary display 2 night light 326 | zwave.configurationV1.configurationSet(parameterNumber: 81, size: 1, scaledConfigurationValue: ledBehave), 327 | // Set LED brightness 328 | zwave.configurationV1.configurationSet(parameterNumber: 84, size: 3, configurationValue: [ledBright,ledBright,ledBright]), 329 | // Which reports need to send in Report group 1 330 | zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 4|2|1), 331 | // Which reports need to send in Report group 2 332 | zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 8), 333 | // Which reports need to send in Report group 3 334 | zwave.configurationV1.configurationSet(parameterNumber: 103, size: 4, scaledConfigurationValue: 0), 335 | // Interval to send Report group 1 336 | zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: monitorInt), 337 | // Interval to send Report group 2 338 | zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 60), 339 | // Interval to send Report group 3 340 | zwave.configurationV1.configurationSet(parameterNumber: 113, size: 4, scaledConfigurationValue: 0), 341 | 342 | // get LED behavior 343 | zwave.configurationV1.configurationGet(parameterNumber: 81), 344 | // get night light RGB value 345 | zwave.configurationV1.configurationGet(parameterNumber: 83), 346 | // get Energy Mode/momentary indicate LED brightness value 347 | zwave.configurationV1.configurationGet(parameterNumber: 84), 348 | // Which reports need to send in Report group 1 349 | zwave.configurationV1.configurationGet(parameterNumber: 101), 350 | // Which reports need to send in Report group 2 351 | zwave.configurationV1.configurationGet(parameterNumber: 102), 352 | // Which reports need to send in Report group 3 353 | zwave.configurationV1.configurationGet(parameterNumber: 103), 354 | // Interval to send Report group 1 355 | zwave.configurationV1.configurationGet(parameterNumber: 111), 356 | // Interval to send Report group 2 357 | zwave.configurationV1.configurationGet(parameterNumber: 112), 358 | // Interval to send Report group 3 359 | zwave.configurationV1.configurationGet(parameterNumber: 113), 360 | 361 | // Can use the zwaveHubNodeId variable to add the hub to the device's associations: 362 | zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId) 363 | ] 364 | commands(request) 365 | } 366 | 367 | private setConfigured() { 368 | updateDataValue("configured", "true") 369 | } 370 | 371 | private isConfigured() { 372 | getDataValue("configured") == "true" 373 | } 374 | 375 | private command(physicalgraph.zwave.Command cmd) { 376 | if (state.sec) { 377 | zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() 378 | } else { 379 | cmd.format() 380 | } 381 | } 382 | 383 | private commands(commands, delay=500) { 384 | delayBetween(commands.collect{ command(it) }, delay) 385 | } -------------------------------------------------------------------------------- /Aeon Wallmote Quad/Engineering Spec - Aeon Labs WallMote Quad.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon Wallmote Quad/Engineering Spec - Aeon Labs WallMote Quad.pdf -------------------------------------------------------------------------------- /Aeon Wallmote Quad/Instructions - Aeon Labs WallMote Quad.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/Aeon Wallmote Quad/Instructions - Aeon Labs WallMote Quad.pdf -------------------------------------------------------------------------------- /GE Z-Wave Switch - Improved/device_type-GE-Z-Wave-Switch-Improved: -------------------------------------------------------------------------------- 1 | /** 2 | * Created from code Copyright 2015 SmartThings 3 | * modified by Robert Vandervoort 6/12/2016 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. You may obtain a copy of the License at: 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing permissions and limitations under the License. 13 | * 14 | */ 15 | metadata { 16 | definition (name: "GE/Jasco Z-Wave Switch", namespace: "robertvandervoort", author: "Robert Vandervoort") { 17 | capability "Actuator" 18 | capability "Indicator" 19 | capability "Switch" 20 | capability "Polling" 21 | capability "Refresh" 22 | capability "Sensor" 23 | capability "Configuration" 24 | 25 | fingerprint inClusters: "0x25" 26 | } 27 | 28 | // simulator metadata 29 | simulator { 30 | status "on": "command: 2003, payload: FF" 31 | status "off": "command: 2003, payload: 00" 32 | 33 | // reply messages 34 | reply "2001FF,delay 100,2502": "command: 2503, payload: FF" 35 | reply "200100,delay 100,2502": "command: 2503, payload: 00" 36 | } 37 | 38 | // tile definitions 39 | tiles(scale: 2) { 40 | multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){ 41 | tileAttribute ("device.switch", key: "PRIMARY_CONTROL") { 42 | attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" 43 | attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" 44 | } 45 | } 46 | standardTile("indicator", "device.indicatorStatus", width: 2, height: 2, inactiveLabel: false, decoration: "flat") { 47 | state "when off", action:"indicator.indicatorWhenOn", icon:"st.indicators.lit-when-off" 48 | state "when on", action:"indicator.indicatorNever", icon:"st.indicators.lit-when-on" 49 | state "never", action:"indicator.indicatorWhenOff", icon:"st.indicators.never-lit" 50 | } 51 | standardTile("refresh", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") { 52 | state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" 53 | } 54 | main "switch" 55 | details(["switch","refresh","indicator"]) 56 | } 57 | preferences { 58 | input "debugOutput", "boolean", 59 | title: "Enable debug logging?", 60 | defaultValue: false, 61 | displayDuringSetup: true 62 | input "switchInvert", "boolean", 63 | title: "Switch inverted?", 64 | defaultValue: false, 65 | displayDuringSetup: false 66 | } 67 | } 68 | 69 | def updated() { 70 | state.debug = ("true" == debugOutput) 71 | response(configure()) 72 | } 73 | 74 | def parse(String description) { 75 | def result = null 76 | def cmd = zwave.parse(description, [0x20: 1, 0x70: 1]) 77 | if (cmd) { 78 | result = createEvent(zwaveEvent(cmd)) 79 | } 80 | if (result?.name == 'hail' && hubFirmwareLessThan("000.011.00602")) { 81 | result = [result, response(zwave.basicV1.basicGet())] 82 | log.debug "Was hailed: requesting state update" 83 | } else { 84 | log.debug "Parse returned ${result?.descriptionText}" 85 | } 86 | return result 87 | } 88 | 89 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) { 90 | [name: "switch", value: cmd.value ? "on" : "off", type: "physical"] 91 | } 92 | 93 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) { 94 | [name: "switch", value: cmd.value ? "on" : "off", type: "physical"] 95 | } 96 | 97 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) { 98 | [name: "switch", value: cmd.value ? "on" : "off", type: "digital"] 99 | } 100 | 101 | def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) { 102 | 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}" 103 | def value = "when off" 104 | if (cmd.configurationValue[0] == 1) {value = "when on"} 105 | if (cmd.configurationValue[0] == 2) {value = "never"} 106 | [name: "indicatorStatus", value: value, display: true] 107 | } 108 | 109 | def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) { 110 | [name: "hail", value: "hail", descriptionText: "Switch button was pressed", displayed: false] 111 | } 112 | 113 | def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) { 114 | if (state.debug) log.debug "manufacturerId: ${cmd.manufacturerId}" 115 | if (state.debug) log.debug "manufacturerName: ${cmd.manufacturerName}" 116 | if (state.debug) log.debug "productId: ${cmd.productId}" 117 | if (state.debug) log.debug "productTypeId: ${cmd.productTypeId}" 118 | def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId) 119 | updateDataValue("MSR", msr) 120 | updateDataValue("manufacturer", cmd.manufacturerName) 121 | createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false]) 122 | } 123 | 124 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 125 | // Handles all Z-Wave commands we aren't interested in 126 | if (state.debug) log.debug cmd 127 | } 128 | 129 | def on() { 130 | delayBetween([ 131 | zwave.basicV1.basicSet(value: 0xFF).format(), 132 | zwave.switchBinaryV1.switchBinaryGet().format() 133 | ]) 134 | } 135 | 136 | def off() { 137 | delayBetween([ 138 | zwave.basicV1.basicSet(value: 0x00).format(), 139 | zwave.switchBinaryV1.switchBinaryGet().format() 140 | ]) 141 | } 142 | 143 | def poll() { 144 | delayBetween([ 145 | zwave.switchBinaryV1.switchBinaryGet().format(), 146 | zwave.manufacturerSpecificV1.manufacturerSpecificGet().format() 147 | ]) 148 | } 149 | 150 | def refresh() { 151 | delayBetween([ 152 | zwave.switchBinaryV1.switchBinaryGet().format(), 153 | zwave.manufacturerSpecificV1.manufacturerSpecificGet().format() 154 | ]) 155 | } 156 | 157 | def indicatorWhenOn() { 158 | sendEvent(name: "indicatorStatus", value: "when on", display: false) 159 | zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format() 160 | } 161 | 162 | def indicatorWhenOff() { 163 | sendEvent(name: "indicatorStatus", value: "when off", display: false) 164 | zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format() 165 | } 166 | 167 | def indicatorNever() { 168 | sendEvent(name: "indicatorStatus", value: "never", display: false) 169 | zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 3, size: 1).format() 170 | } 171 | 172 | def configure() { 173 | if (state.debug) log.debug "sending configuration to ${device.displayName}" 174 | def invertSwitch = 0 175 | if (switchInvert == true) {invertSwitch = 1} 176 | if (switchInvert == false) {invertSwitch = 0} 177 | delayBetween([ 178 | zwave.configurationV1.configurationSet(scaledConfigurationValue: invertSwitch, parameterNumber: 4, size: 1).format(), 179 | zwave.configurationV1.configurationGet(parameterNumber: 0x00).format(), 180 | zwave.configurationV1.configurationGet(parameterNumber: 0x04).format() 181 | ]) 182 | } 183 | 184 | -------------------------------------------------------------------------------- /zooZ-4-in-1-Sensor-ZSE40/ZSE40-tech-info.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/zooZ-4-in-1-Sensor-ZSE40/ZSE40-tech-info.pdf -------------------------------------------------------------------------------- /zooZ-Indoor-Siren-ZSE01/Z-Wave command classes for Siren.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/zooZ-Indoor-Siren-ZSE01/Z-Wave command classes for Siren.pdf -------------------------------------------------------------------------------- /zooZ-Indoor-Siren-ZSE01/device_type-zooZ-indoor-siren-v1: -------------------------------------------------------------------------------- 1 | /* 2 | * V 1.0 of zooZ Indoor Siren ZSE01 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 4 | * in compliance with the License. You may obtain a copy of the License at: 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 9 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 10 | * for the specific language governing permissions and limitations under the License. 11 | * 12 | 13 | */ 14 | 15 | metadata { 16 | definition (name: "zooZ Indoor Siren ZSE01 - RV v1.0", namespace: "robertvandervoort", author: "Robert Vandervoort") { 17 | capability "Actuator" 18 | capability "Alarm" 19 | capability "Battery" 20 | capability "Switch" 21 | capability "Sensor" 22 | capability "Polling" 23 | capability "Refresh" 24 | 25 | command "reset" 26 | // RAW DESCRIPTION: 0 0 0x1005 0 0 0 9 0x5E 0x86 0x72 0x73 0x85 0x59 0x25 0x20 0x27 27 | fingerprint deviceId: "0x1005", inClusters: "0x5E 0x86 0x72 0x73 0x85 0x59 0x25 0x20 0x27", manufacturer: "zooZ", model: "ZSE01" 28 | 29 | } 30 | // simulator metadata 31 | 32 | // tile definitions 33 | tiles (scale: 2) { 34 | multiAttributeTile(name:"alarm", type:"generic", width:6, height:4, canChangeIcon: true) { 35 | tileAttribute("device.alarm", key: "PRIMARY_CONTROL") { 36 | attributeState "off", label:'OFF', action:'on', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" 37 | attributeState "on", label:'ALARM!', action:'off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" 38 | } 39 | } 40 | standardTile("off", "device.alarm", inactiveLabel: false, width: 3, height: 3) { 41 | state "default", label:'', action:"off", icon:"st.secondary.off" 42 | } 43 | valueTile("battery", "device.battery", decoration: "flat", width: 3, height: 3) { 44 | state "battery", label:'${currentValue}% battery', unit:"" 45 | } 46 | main "alarm" 47 | details(["alarm","off","battery"]) 48 | } 49 | preferences { 50 | input "debugOutput", "boolean", 51 | title: "Enable debug logging?", 52 | defaultValue: false, 53 | displayDuringSetup: false, 54 | required: false 55 | } 56 | } 57 | 58 | def updated() 59 | { 60 | updateDataValue("configured", "false") 61 | state.debug = ("true" == debugOutput) 62 | } 63 | 64 | def parse(String description) 65 | { 66 | def result = null 67 | if (description != "updated") { 68 | def cmd = zwave.parse(description, [0x25: 1]) 69 | if (cmd) { 70 | result = zwaveEvent(cmd) 71 | } 72 | } 73 | if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}" 74 | return result 75 | } 76 | 77 | def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) 78 | { 79 | def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)] 80 | if (!isConfigured()) { 81 | // we're still in the process of configuring a newly joined device 82 | if (state.debug) log.debug("late configure") 83 | result += response(configure()) 84 | } else { 85 | result += response(zwave.wakeUpV1.wakeUpNoMoreInformation()) 86 | } 87 | result 88 | } 89 | 90 | def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) { 91 | if (state.debug) log.debug "---MANUFACTURER SPECIFIC REPORT V2--- ${device.displayName} sent deviceIdDataFormat: ${cmd.deviceIdDataFormat}, deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}, deviceIdType: ${cmd.deviceIdType}, payload: ${cmd.payload}" 92 | } 93 | 94 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionCommandClassReport cmd) { 95 | if (state.debug) log.debug "---COMMAND CLASS VERSION REPORT V1--- ${device.displayName} has command class version: ${cmd.commandClassVersion} - payload: ${cmd.payload}" 96 | } 97 | 98 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) { 99 | def fw = "${cmd.applicationVersion}.${cmd.applicationSubVersion}" 100 | updateDataValue("fw", fw) 101 | if (state.debug) log.debug "---VERSION REPORT V1--- ${device.displayName} is running firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}" 102 | } 103 | 104 | def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) { 105 | 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}" 106 | } 107 | 108 | def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) { 109 | 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}" 110 | } 111 | 112 | def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLocallyNotification cmd) { 113 | if (state.debug) log.debug "---DEVICE RESET LOCALLY V1--- ${device.displayName} ${cmd}" 114 | createEvent(descriptionText: cmd.toString(), isStateChange: true, displayed: true) 115 | } 116 | 117 | def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) { 118 | log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}" 119 | def request = [ 120 | physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet() 121 | ] 122 | response(commands(request)) 123 | } 124 | 125 | def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) { 126 | def map = [ name: "battery", unit: "%" ] 127 | if (cmd.batteryLevel == 0xFF) { 128 | map.value = 1 129 | map.descriptionText = "${device.displayName} battery is low" 130 | map.isStateChange = true 131 | } else { 132 | map.value = cmd.batteryLevel 133 | } 134 | state.lastbatt = now() 135 | createEvent(map) 136 | } 137 | 138 | def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) { 139 | cmd.nodeId.each({log.debug "---ASSOCIATION REPORT--- '${cmd}', hub: '$zwaveHubNodeId' reports nodeId: '$it' is associated in group: '${cmd.groupingIdentifier}'"}) 140 | } 141 | 142 | def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) { 143 | if (state.debug) log.debug "---HAIL RECEIVED--- ${cmd}" 144 | } 145 | 146 | def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv2.SensorBinaryReport cmd) { 147 | if (state.debug) log.debug "---SENSOR BINARY REPORT V2--- ${device.displayName} sent value: ${cmd.sensorValue}" 148 | } 149 | 150 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) { 151 | if (state.debug) log.debug "---BASIC REPORT V1--- ${device.displayName} sent value: ${cmd.value}" 152 | [ 153 | createEvent([name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]), 154 | createEvent([name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]) 155 | ] 156 | } 157 | 158 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) { 159 | if (state.debug) log.debug "---BASIC SET V1--- ${device.displayName} sent value: ${cmd.value}" 160 | [name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 161 | } 162 | 163 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) { 164 | if (state.debug) log.debug "---SWITCH BINARY REPORT V1--- ${device.displayName} sent value: ${cmd.value}" 165 | [name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 166 | } 167 | 168 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd) { 169 | if (state.debug) log.debug "---SWITCH BINARY SET V1--- ${device.displayName} sent value: ${cmd.value}" 170 | [name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 171 | } 172 | 173 | def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) { 174 | if (state.debug) log.debug "---NOTIFICATION REPORT V3--- ${device.displayName} sent eventParametersLength: ${cmd.eventParametersLength} eventParameter: ${cmd.eventParameter} notificationType: ${cmd.notificationType} event: ${cmd.event}" 175 | def result = [] 176 | if (cmd.notificationType == 7) { 177 | if (cmd.event == 0x03) { 178 | result << createEvent(name: "acceleration", value: "active", descriptionText: "$device.displayName cover is open.") 179 | } 180 | else if (cmd.event == 0X00 || cmd.eventParameter == 0x03) { 181 | result << createEvent(name: "acceleration", value: "inactive", descriptionText: "$device.displayName cover has been closed.") 182 | } 183 | } 184 | else { 185 | result << createEvent(descriptionText: cmd.toString(), isStateChange: false) 186 | } 187 | result 188 | } 189 | 190 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 191 | if (state.debug) log.debug "Unhandled: $cmd sent to ${device.displayName}" 192 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 193 | } 194 | 195 | def siren() { 196 | if (state.debug) log.debug "Siren command received" 197 | on() 198 | } 199 | 200 | def both() { 201 | if (state.debug) log.debug "Siren and Strobe commands received" 202 | on() 203 | } 204 | 205 | def on() { 206 | if (state.debug) log.debug "Sounding Alarm : ${device.displayName}" 207 | def request = [ 208 | zwave.basicV1.basicSet(value: 0xFF) 209 | ] 210 | commands(request) 211 | } 212 | 213 | def off() { 214 | if (state.debug) log.debug "Cancelling Alarm : ${device.displayName}" 215 | def request = [ 216 | zwave.basicV1.basicSet(value: 0x00), 217 | zwave.basicV1.basicGet() 218 | ] 219 | commands(request) 220 | } 221 | 222 | def configure() { 223 | if (state.debug) log.debug "--Sending configuration commands to zooZ indoor siren--" 224 | if (state.debug) log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}" 225 | setConfigured() 226 | def request = [ 227 | // set wakeup interval to 20 mins 228 | zwave.wakeUpV1.wakeUpIntervalSet(seconds:1200, nodeid:zwaveHubNodeId), 229 | 230 | // Can use the zwaveHubNodeId variable to add the hub to the device's associations: 231 | // zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId), 232 | 233 | //Get association 234 | zwave.associationV1.associationGet(groupingIdentifier:1), 235 | zwave.associationV1.associationGet(groupingIdentifier:2), 236 | 237 | // Get Version information 238 | zwave.versionV1.versionGet(), 239 | zwave.firmwareUpdateMdV2.firmwareMdGet(), 240 | 241 | // get updated battery and sensor data 242 | zwave.batteryV1.batteryGet(), 243 | ] 244 | commands(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()] 245 | } 246 | 247 | private setConfigured() { 248 | updateDataValue("configured", "true") 249 | return [] 250 | } 251 | 252 | private isConfigured() { 253 | getDataValue("configured") == "true" 254 | } 255 | 256 | private command(physicalgraph.zwave.Command cmd) { 257 | cmd.format() 258 | } 259 | 260 | private commands(commands, delay=1000) { 261 | delayBetween(commands.collect{ command(it) }, delay) 262 | } -------------------------------------------------------------------------------- /zooZ-Indoor-Siren-ZSE01/device_type-zooZ-indoor-siren-v1.1: -------------------------------------------------------------------------------- 1 | /* 2 | * V 1.1 of zooZ Indoor Siren ZSE01 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 4 | * in compliance with the License. You may obtain a copy of the License at: 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 9 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 10 | * for the specific language governing permissions and limitations under the License. 11 | * 12 | 13 | */ 14 | 15 | metadata { 16 | definition (name: "zooZ Indoor Siren ZSE01 - RV v1.1", namespace: "robertvandervoort", author: "Robert Vandervoort") { 17 | capability "Actuator" 18 | capability "Alarm" 19 | capability "Battery" 20 | capability "Switch" 21 | capability "Sensor" 22 | capability "Polling" 23 | capability "Refresh" 24 | 25 | command "reset" 26 | command "getbatt" 27 | // RAW DESCRIPTION: 0 0 0x1005 0 0 0 9 0x5E 0x86 0x72 0x73 0x85 0x59 0x25 0x20 0x27 28 | fingerprint deviceId: "0x1005", inClusters: "0x5E 0x86 0x72 0x73 0x85 0x59 0x25 0x20 0x27", manufacturer: "zooZ", model: "ZSE01" 29 | 30 | } 31 | // simulator metadata 32 | 33 | // tile definitions 34 | tiles (scale: 2) { 35 | multiAttributeTile(name:"alarm", type:"generic", width:6, height:4, canChangeIcon: true) { 36 | tileAttribute("device.alarm", key: "PRIMARY_CONTROL") { 37 | attributeState "off", label:'OFF', action:'on', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" 38 | attributeState "on", label:'ALARM!', action:'off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" 39 | } 40 | } 41 | standardTile("off", "device.alarm", inactiveLabel: false, width: 3, height: 3) { 42 | state "default", label:'', action:"off", icon:"st.secondary.off" 43 | } 44 | valueTile("battery", "device.battery", decoration: "flat", width: 3, height: 3) { 45 | state "battery", label:'${currentValue}% battery', unit:"" 46 | } 47 | main "alarm" 48 | details(["alarm","off","battery"]) 49 | } 50 | preferences { 51 | input "debugOutput", "boolean", 52 | title: "Enable debug logging?", 53 | defaultValue: false, 54 | displayDuringSetup: false, 55 | required: false 56 | } 57 | } 58 | 59 | def updated() 60 | { 61 | updateDataValue("configured", "false") 62 | state.debug = ("true" == debugOutput) 63 | } 64 | 65 | def parse(String description) 66 | { 67 | def result = null 68 | if (description != "updated") { 69 | def cmd = zwave.parse(description, [0x25: 1]) 70 | if (cmd) { 71 | result = zwaveEvent(cmd) 72 | } 73 | } 74 | if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}" 75 | return result 76 | } 77 | 78 | def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) 79 | { 80 | def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)] 81 | if (!isConfigured()) { 82 | // we're still in the process of configuring a newly joined device 83 | if (state.debug) log.debug("late configure") 84 | result += response(configure()) 85 | } else { 86 | result += response(zwave.wakeUpV1.wakeUpNoMoreInformation()) 87 | } 88 | result 89 | } 90 | 91 | def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) { 92 | if (state.debug) log.debug "---MANUFACTURER SPECIFIC REPORT V2--- ${device.displayName} sent deviceIdDataFormat: ${cmd.deviceIdDataFormat}, deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}, deviceIdType: ${cmd.deviceIdType}, payload: ${cmd.payload}" 93 | } 94 | 95 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionCommandClassReport cmd) { 96 | if (state.debug) log.debug "---COMMAND CLASS VERSION REPORT V1--- ${device.displayName} has command class version: ${cmd.commandClassVersion} - payload: ${cmd.payload}" 97 | } 98 | 99 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) { 100 | def fw = "${cmd.applicationVersion}.${cmd.applicationSubVersion}" 101 | updateDataValue("fw", fw) 102 | if (state.debug) log.debug "---VERSION REPORT V1--- ${device.displayName} is running firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}" 103 | } 104 | 105 | def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) { 106 | 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}" 107 | } 108 | 109 | def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) { 110 | 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}" 111 | } 112 | 113 | def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLocallyNotification cmd) { 114 | if (state.debug) log.debug "---DEVICE RESET LOCALLY V1--- ${device.displayName} ${cmd}" 115 | createEvent(descriptionText: cmd.toString(), isStateChange: true, displayed: true) 116 | } 117 | 118 | def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) { 119 | log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}" 120 | def request = [ 121 | physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet() 122 | ] 123 | response(commands(request)) 124 | } 125 | 126 | def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) { 127 | def map = [ name: "battery", unit: "%" ] 128 | if (cmd.batteryLevel == 0xFF) { 129 | map.value = 1 130 | map.descriptionText = "${device.displayName} battery is low" 131 | map.isStateChange = true 132 | } else { 133 | map.value = cmd.batteryLevel 134 | } 135 | state.lastbatt = now() 136 | createEvent(map) 137 | } 138 | 139 | def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) { 140 | cmd.nodeId.each({log.debug "---ASSOCIATION REPORT--- '${cmd}', hub: '$zwaveHubNodeId' reports nodeId: '$it' is associated in group: '${cmd.groupingIdentifier}'"}) 141 | } 142 | 143 | def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) { 144 | if (state.debug) log.debug "---HAIL RECEIVED--- ${cmd}" 145 | } 146 | 147 | def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv2.SensorBinaryReport cmd) { 148 | if (state.debug) log.debug "---SENSOR BINARY REPORT V2--- ${device.displayName} sent value: ${cmd.sensorValue}" 149 | } 150 | 151 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) { 152 | if (state.debug) log.debug "---BASIC REPORT V1--- ${device.displayName} sent value: ${cmd.value}" 153 | [ 154 | createEvent([name: "switch", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true]), 155 | createEvent([name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true]) 156 | ] 157 | } 158 | 159 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) { 160 | if (state.debug) log.debug "---BASIC SET V1--- ${device.displayName} sent value: ${cmd.value}" 161 | [name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 162 | } 163 | 164 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) { 165 | if (state.debug) log.debug "---SWITCH BINARY REPORT V1--- ${device.displayName} sent value: ${cmd.value}" 166 | [name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 167 | } 168 | 169 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd) { 170 | if (state.debug) log.debug "---SWITCH BINARY SET V1--- ${device.displayName} sent value: ${cmd.value}" 171 | [name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 172 | } 173 | 174 | def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) { 175 | if (state.debug) log.debug "---NOTIFICATION REPORT V3--- ${device.displayName} sent eventParametersLength: ${cmd.eventParametersLength} eventParameter: ${cmd.eventParameter} notificationType: ${cmd.notificationType} event: ${cmd.event}" 176 | def result = [] 177 | if (cmd.notificationType == 7) { 178 | if (cmd.event == 0x03) { 179 | result << createEvent(name: "acceleration", value: "active", descriptionText: "$device.displayName cover is open.") 180 | } 181 | else if (cmd.event == 0X00 || cmd.eventParameter == 0x03) { 182 | result << createEvent(name: "acceleration", value: "inactive", descriptionText: "$device.displayName cover has been closed.") 183 | } 184 | } 185 | else { 186 | result << createEvent(descriptionText: cmd.toString(), isStateChange: false) 187 | } 188 | result 189 | } 190 | 191 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 192 | if (state.debug) log.debug "Unhandled: $cmd sent to ${device.displayName}" 193 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 194 | } 195 | 196 | def siren() { 197 | if (state.debug) log.debug "Siren command received" 198 | on() 199 | } 200 | 201 | def both() { 202 | if (state.debug) log.debug "Siren and Strobe commands received" 203 | on() 204 | } 205 | 206 | def on() { 207 | if (state.debug) log.debug "Sounding Alarm : ${device.displayName}" 208 | def request = [ 209 | zwave.basicV1.basicSet(value: 0xFF) 210 | ] 211 | commands(request) 212 | } 213 | 214 | def off() { 215 | if (state.debug) log.debug "Cancelling Alarm : ${device.displayName}" 216 | def request = [ 217 | zwave.basicV1.basicSet(value: 0x00), 218 | zwave.basicV1.basicGet() 219 | ] 220 | commands(request) 221 | } 222 | 223 | def configure() { 224 | if (state.debug) log.debug "--Sending configuration commands to zooZ indoor siren--" 225 | if (state.debug) log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}" 226 | setConfigured() 227 | def request = [ 228 | // set wakeup interval to 20 mins 229 | zwave.wakeUpV1.wakeUpIntervalSet(seconds:1200, nodeid:zwaveHubNodeId), 230 | 231 | // Can use the zwaveHubNodeId variable to add the hub to the device's associations: 232 | // zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId), 233 | 234 | //Get association 235 | zwave.associationV1.associationGet(groupingIdentifier:1), 236 | zwave.associationV1.associationGet(groupingIdentifier:2), 237 | 238 | // Get Version information 239 | zwave.versionV1.versionGet(), 240 | zwave.firmwareUpdateMdV2.firmwareMdGet(), 241 | 242 | // get updated battery and sensor data 243 | zwave.batteryV1.batteryGet(), 244 | ] 245 | commands(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()] 246 | } 247 | 248 | private setConfigured() { 249 | updateDataValue("configured", "true") 250 | return [] 251 | } 252 | 253 | private isConfigured() { 254 | getDataValue("configured") == "true" 255 | } 256 | 257 | private command(physicalgraph.zwave.Command cmd) { 258 | cmd.format() 259 | } 260 | 261 | private commands(commands, delay=1000) { 262 | delayBetween(commands.collect{ command(it) }, delay) 263 | } -------------------------------------------------------------------------------- /zooZ-Indoor-Siren-ZSE01/device_type-zooZ-indoor-siren-v1.2: -------------------------------------------------------------------------------- 1 | /* 2 | * V 1.2 of zooZ Indoor Siren ZSE01 3 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 4 | * in compliance with the License. You may obtain a copy of the License at: 5 | * 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 9 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 10 | * for the specific language governing permissions and limitations under the License. 11 | * 12 | --------------------------------------------------------------------------------------------------------------------------- 13 | INSTRUCTIONS: 14 | * First you will need to create a new device handler in SmartThings. Log in to the IDE and click on Device Handlers in the top menu. 15 | Then click "from code" below. You'l be presented with a blank area where you can copy this code and paste it in. 16 | * Next, scroll to the bottom and click create. Now click save, then click publish > for me. 17 | * You should now see this device type in your list of device handlers. Now we need to pair the device. 18 | * Put SmartThings into inclusion mode by going through the add new device dialog. 19 | * Tap the button on the siren a few times (turning siren on and off) and you should see it appear on the app screen. 20 | * tap the discovered device on the app screen to continue. 21 | * Now go to your devices list in the SmartThings app and open up the newly added siren. 22 | * The configuration will get sent by pressing the button to activate the siren, then tapping again to cancel. 23 | * That's it. Remember this is a USB powered device and the batteries are for BACKUP ONLY. There is no battery level indicator by design. 24 | 25 | */ 26 | 27 | metadata { 28 | definition (name: "zooZ Indoor Siren ZSE01 - RV v1.2", namespace: "robertvandervoort", author: "Robert Vandervoort") { 29 | capability "Actuator" 30 | capability "Alarm" 31 | capability "Battery" 32 | capability "Switch" 33 | capability "Sensor" 34 | capability "Polling" 35 | capability "Refresh" 36 | 37 | command "reset" 38 | // RAW DESCRIPTION: 0 0 0x1005 0 0 0 9 0x5E 0x86 0x72 0x73 0x85 0x59 0x25 0x20 0x27 39 | fingerprint deviceId: "0x1005", inClusters: "0x5E 0x86 0x72 0x73 0x85 0x59 0x25 0x20 0x27", manufacturer: "zooZ", model: "ZSE01" 40 | 41 | } 42 | // simulator metadata 43 | 44 | // tile definitions 45 | tiles (scale: 2) { 46 | multiAttributeTile(name:"alarm", type:"generic", width:6, height:4, canChangeIcon: true) { 47 | tileAttribute("device.alarm", key: "PRIMARY_CONTROL") { 48 | attributeState "off", label:'OFF', action:'on', icon:"st.alarm.alarm.alarm", backgroundColor:"#ffffff" 49 | attributeState "on", label:'ALARM!', action:'off', icon:"st.alarm.alarm.alarm", backgroundColor:"#e86d13" 50 | } 51 | } 52 | standardTile("off", "device.alarm", inactiveLabel: false, width: 6, height: 4) { 53 | state "default", label:'', action:"off", icon:"st.secondary.off" 54 | } 55 | main "alarm" 56 | details(["alarm","off"]) 57 | } 58 | preferences { 59 | input "debugOutput", "boolean", 60 | title: "Enable debug logging?", 61 | defaultValue: false, 62 | displayDuringSetup: false, 63 | required: false 64 | } 65 | } 66 | 67 | def updated() 68 | { 69 | updateDataValue("configured", "false") 70 | state.debug = ("true" == debugOutput) 71 | def result = createEvent(descriptionText: "${device.displayName} was updated", displayed: true) 72 | configure() 73 | } 74 | 75 | def parse(String description) 76 | { 77 | def result = null 78 | if (description != "updated") { 79 | def cmd = zwave.parse(description, [0x25: 1]) 80 | if (cmd) { 81 | result = zwaveEvent(cmd) 82 | } 83 | } 84 | if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}" 85 | return result 86 | } 87 | 88 | def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) { 89 | if (state.debug) log.debug "---MANUFACTURER SPECIFIC REPORT V2--- ${device.displayName} sent deviceIdDataFormat: ${cmd.deviceIdDataFormat}, deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}, deviceIdType: ${cmd.deviceIdType}, payload: ${cmd.payload}" 90 | } 91 | 92 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionCommandClassReport cmd) { 93 | if (state.debug) log.debug "---COMMAND CLASS VERSION REPORT V1--- ${device.displayName} has command class version: ${cmd.commandClassVersion} - payload: ${cmd.payload}" 94 | } 95 | 96 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) { 97 | def fw = "${cmd.applicationVersion}.${cmd.applicationSubVersion}" 98 | updateDataValue("fw", fw) 99 | if (state.debug) log.debug "---VERSION REPORT V1--- ${device.displayName} is running firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}" 100 | } 101 | 102 | def zwaveEvent(physicalgraph.zwave.commands.deviceresetlocallyv1.DeviceResetLocallyNotification cmd) { 103 | if (state.debug) log.debug "---DEVICE RESET LOCALLY V1--- ${device.displayName} ${cmd}" 104 | createEvent(descriptionText: cmd.toString(), isStateChange: true, displayed: true) 105 | } 106 | 107 | def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) { 108 | if (state.debug) log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}" 109 | def request = [ 110 | physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet() 111 | ] 112 | response(commands(request)) 113 | } 114 | 115 | def zwaveEvent(physicalgraph.zwave.commands.associationv2.AssociationReport cmd) { 116 | cmd.nodeId.each({log.debug "---ASSOCIATION REPORT--- '${cmd}', hub: '$zwaveHubNodeId' reports nodeId: '$it' is associated in group: '${cmd.groupingIdentifier}'"}) 117 | } 118 | 119 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) { 120 | if (state.debug) log.debug "---BASIC REPORT V1--- ${device.displayName} sent value: ${cmd.value}" 121 | [ 122 | createEvent([name: "switch", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]), 123 | createEvent([name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true]) 124 | ] 125 | } 126 | 127 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) { 128 | if (state.debug) log.debug "---BASIC SET V1--- ${device.displayName} sent value: ${cmd.value}" 129 | [name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 130 | } 131 | 132 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) { 133 | if (state.debug) log.debug "---SWITCH BINARY REPORT V1--- ${device.displayName} sent value: ${cmd.value}" 134 | [name: "alarm", value: cmd.value ? "on" : "off", type: "physical", displayed: true, isStateChange: true] 135 | } 136 | 137 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinarySet cmd) { 138 | if (state.debug) log.debug "---SWITCH BINARY SET V1--- ${device.displayName} sent value: ${cmd.value}" 139 | [name: "alarm", value: cmd.value ? "on" : "off", type: "digital", displayed: true, isStateChange: true] 140 | } 141 | 142 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 143 | if (state.debug) log.debug "Unhandled: $cmd sent to ${device.displayName}" 144 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 145 | } 146 | 147 | def siren() { 148 | if (state.debug) log.debug "Siren command received" 149 | on() 150 | } 151 | 152 | def both() { 153 | if (state.debug) log.debug "Siren and Strobe commands received" 154 | on() 155 | } 156 | 157 | def on() { 158 | if (state.debug) log.debug "Sounding Alarm : ${device.displayName}" 159 | def request = [ 160 | zwave.basicV1.basicSet(value: 0xFF), 161 | zwave.basicV1.basicGet() 162 | ] 163 | commands(request) 164 | } 165 | 166 | def off() { 167 | if (state.debug) log.debug "Cancelling Alarm : ${device.displayName}" 168 | def request = [ 169 | zwave.basicV1.basicSet(value: 0x00), 170 | zwave.basicV1.basicGet() 171 | ] 172 | commands(request) 173 | } 174 | 175 | def configure() { 176 | if (state.debug) log.debug "--Sending configuration commands to zooZ indoor siren--" 177 | if (state.debug) log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}" 178 | setConfigured() 179 | def request = [ 180 | //Get association 181 | zwave.associationV1.associationGet(groupingIdentifier:1), 182 | zwave.associationV1.associationGet(groupingIdentifier:2), 183 | 184 | // Get Version information 185 | zwave.versionV1.versionGet(), 186 | zwave.firmwareUpdateMdV2.firmwareMdGet(), 187 | ] 188 | commands(request) 189 | } 190 | 191 | private setConfigured() { 192 | updateDataValue("configured", "true") 193 | return [] 194 | } 195 | 196 | private isConfigured() { 197 | getDataValue("configured") == "true" 198 | } 199 | 200 | private command(physicalgraph.zwave.Command cmd) { 201 | cmd.format() 202 | } 203 | 204 | private commands(commands, delay=1000) { 205 | delayBetween(commands.collect{ command(it) }, delay) 206 | } -------------------------------------------------------------------------------- /zooZ-Indoor-Siren-ZSE01/zooz-zse01-indoor-siren-manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/zooZ-Indoor-Siren-ZSE01/zooz-zse01-indoor-siren-manual.pdf -------------------------------------------------------------------------------- /zooZ-MiniPlug-ZEN07/device_type-zooZ-MiniPlug-ZEN07-v1.1.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | zooZ MiniPlug ZEN07 device handler for SmartThings version 1.0 by Robert Vandervoort 10/10/2016 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 4 | in compliance with the License. You may obtain a copy of the License at: 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 9 | on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 10 | for the specific language governing permissions and limitations under the License. 11 | 12 | some code used from various SmartThings device type and metering code from ElasticDev 13 | 14 | */ 15 | 16 | metadata { 17 | definition (name: "zooZ MiniPlug ZEN07 - RV v1.0", namespace: "robertvandervoort", author: "Robert Vandervoort") { 18 | capability "Energy Meter" 19 | capability "Power Meter" 20 | capability "Actuator" 21 | capability "Switch" 22 | capability "Configuration" 23 | capability "Polling" 24 | capability "Refresh" 25 | capability "Sensor" 26 | 27 | command "reset" 28 | command "getPower" 29 | command "getEnergy" 30 | command "getVolts" 31 | command "getCurrent" 32 | command "checkstate" 33 | 34 | // RAW 0 0 0x1001 0 0 0 d 0x5E 0x72 0x86 0x85 0x59 0x5A 0x73 0x70 0x25 0x27 0x71 0x32 0x20 35 | // MSR 027A-0003-0087 36 | 37 | fingerprint deviceId: "0x1001", inClusters: "0x5E,0x72,0x86,0x85,0x59,0x5A,0x73,0x70,0x25,0x27,0x71,0x32,0x20" 38 | } 39 | // simulator metadata 40 | simulator { 41 | status "on": "command: 2003, payload: FF" 42 | status "off": "command: 2003, payload: 00" 43 | 44 | for (int i = 0; i <= 10000; i += 1000) { 45 | status "power ${i} W": 46 | new physicalgraph.zwave.Zwave().meterV3.meterReport(scaledMeterValue: i, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage() 47 | } 48 | for (int i = 0; i <= 100; i += 10) { 49 | status "energy ${i} kWh": 50 | new physicalgraph.zwave.Zwave().meterV3.meterReport(scaledMeterValue: i, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage() 51 | } 52 | // reply messages 53 | reply "2001FF,delay 100,2502": "command: 2503, payload: FF" 54 | reply "200100,delay 100,2502": "command: 2503, payload: 00" 55 | } 56 | 57 | // tile definitions 58 | tiles (scale: 2) { 59 | multiAttributeTile(name:"main", type:"generic", width:6, height:4, canChangeIcon: true) { 60 | tileAttribute("device.switch", key: "PRIMARY_CONTROL") { 61 | attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821" 62 | attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff" 63 | } 64 | } 65 | valueTile("power", "device.power", decoration: "flat", width: 2, height: 2) { 66 | state "default", label:'${currentValue} W', action:"getPower" 67 | } 68 | valueTile("energy", "device.energy", decoration: "flat", width: 2, height: 2) { 69 | state "default", label:'${currentValue} kWh', action:"getEnergy" 70 | } 71 | valueTile("current", "device.current", decoration: "flat", width: 2, height: 2) { 72 | state "default", label:'${currentValue} A', action:"getCurrent" 73 | } 74 | valueTile("voltage", "device.voltage", decoration: "flat", width: 2, height: 2) { 75 | state "default", label:'${currentValue} V', action:"getVoltage" 76 | } 77 | standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 78 | state "default", label:'reset kWh', action:"reset" 79 | } 80 | standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 81 | state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" 82 | } 83 | standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 84 | state "default", label:'config', action:"configure", icon:"st.secondary.refresh" 85 | } 86 | standardTile("check", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) { 87 | state "default", label:'check', action:"checkstate" 88 | } 89 | main "main" 90 | details(["main","power","energy","current","voltage","reset","refresh","configure", "check"]) 91 | } 92 | 93 | preferences { 94 | input "energyReporting", "boolean", 95 | title: "Energy usage reports", 96 | defaultValue: true, 97 | displayDuringSetup: true 98 | 99 | input "reportInterval", "integer", 100 | title: "Energy report interval", 101 | description: "The time interval in seconds for sending energy usage reports", 102 | defaultValue: 300, 103 | range: "1..4294967295‬", 104 | required: false, 105 | displayDuringSetup: false 106 | 107 | input "reportThreshold", "integer", 108 | title: "Reporting threshold", 109 | description: "The percentage of change required for sending energy usage reports", 110 | defaultValue: 5, 111 | range: "1..99", 112 | required: false, 113 | displayDuringSetup: false 114 | 115 | input "loadWarning", "integer", 116 | title: "Load warning AMPs", 117 | description: "Set to a value in AMPs to provide heavy load warning notification.", 118 | defaultValue: 12, 119 | range: "1..12", 120 | required: false, 121 | displayDuringSetup: false 122 | 123 | input "overloadProtection", "integer", 124 | title: "Overload protection AMPs", 125 | description: "Must be higher than heavy load warning value. When this value is reached, the plug shuts down and must be reset.", 126 | defaultValue: 13, 127 | range: "1..15", 128 | required: false, 129 | displayDuringSetup: false 130 | 131 | input "manualOverride", "boolean", 132 | title: "Switch manual control", 133 | description: "Enable or disable the switch on the plug. Good for tamper protection.", 134 | defaultValue: true, 135 | displayDuringSetup: false 136 | 137 | input "stateRecvovery", "boolean", 138 | title: "Return to last state after power failure?", 139 | defaultValue: true, 140 | displayDuringSetup: false 141 | 142 | input "ledNotifications", "boolean", 143 | title: "LED Notifications?", 144 | description: "Enables or disables LED color change for heavy and overload notifications.", 145 | defaultValue: true, 146 | displayDuringSetup: false 147 | 148 | input "debugOutput", "boolean", 149 | title: "Enable debug logging?", 150 | defaultValue: false, 151 | displayDuringSetup: true 152 | } 153 | } 154 | 155 | def updated() { 156 | updateDataValue("configured", "false") 157 | state.debug = ("true" == debugOutput) 158 | configure() 159 | } 160 | 161 | def parse(String description) { 162 | def result = null 163 | def cmd = zwave.parse(description) 164 | if (cmd) { 165 | result = zwaveEvent(cmd) 166 | if (state.debug) log.debug "Parsed ${cmd} to ${result.inspect()}" 167 | } else { 168 | log.debug "Non-parsed event: ${description}" 169 | } 170 | return result 171 | } 172 | 173 | def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) { 174 | log.debug("ConfigurationReportv1 ${cmd.inspect()}") 175 | } 176 | 177 | def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) { 178 | state.configParams << [(cmd.parameterNumber) : (cmd.configurationValue)] 179 | log.debug state.configParams 180 | } 181 | 182 | def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationBulkReport cmd) 183 | { 184 | log.debug "Got a bulk report, but don't know what to do with it." 185 | } 186 | 187 | def zwaveEvent(physicalgraph.zwave.commands.powerlevelv1.PowerlevelTestNodeReport cmd) { 188 | log.debug "===Power level test node report received=== ${device.displayName}: statusOfOperation: ${cmd.statusOfOperation} testFrameCount: ${cmd.testFrameCount} testNodeid: ${cmd.testNodeid}" 189 | def request = [ 190 | physicalgraph.zwave.commands.powerlevelv1.PowerlevelGet() 191 | ] 192 | response(commands(request)) 193 | } 194 | 195 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) { 196 | def fw = "${cmd.applicationVersion}.${cmd.applicationSubVersion}" 197 | updateDataValue("fw", fw) 198 | log.debug "---VERSION REPORT V1--- ${device.displayName} is running firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}" 199 | } 200 | 201 | def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) { 202 | log.debug "manufacturerId: ${cmd.manufacturerId}" 203 | log.debug "manufacturerName: ${cmd.manufacturerName}" 204 | log.debug "productId: ${cmd.productId}" 205 | log.debug "productTypeId: ${cmd.productTypeId}" 206 | def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId) 207 | updateDataValue("MSR", msr) 208 | createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false], displayed = true) 209 | } 210 | 211 | def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd) { 212 | def meterTypes = ["Unknown", "Electric", "Gas", "Water"] 213 | def electricNames = ["energy", "energy", "power", "count", "voltage", "current", "powerFactor", "unknown"] 214 | def electricUnits = ["kWh", "kVAh", "W", "pulses", "V", "A", "Power Factor", ""] 215 | 216 | //NOTE ScaledPreviousMeterValue does not always contain a value 217 | def previousValue = cmd.scaledPreviousMeterValue ?: 0 218 | 219 | def map = [ name: electricNames[cmd.scale], unit: electricUnits[cmd.scale], displayed: state.display] 220 | switch(cmd.scale) { 221 | case 0: //kWh 222 | previousValue = device.currentValue("energy") ?: cmd.scaledPreviousMeterValue ?: 0 223 | map.value = cmd.scaledMeterValue 224 | break; 225 | case 1: //kVAh 226 | map.value = cmd.scaledMeterValue 227 | break; 228 | case 2: //Watts 229 | previousValue = device.currentValue("power") ?: cmd.scaledPreviousMeterValue ?: 0 230 | map.value = cmd.scaledMeterValue 231 | break; 232 | case 4: //Volts 233 | previousValue = device.currentValue("voltage") ?: cmd.scaledPreviousMeterValue ?: 0 234 | map.value = cmd.scaledMeterValue 235 | break; 236 | case 5: //Amps 237 | previousValue = device.currentValue("current") ?: cmd.scaledPreviousMeterValue ?: 0 238 | map.value = cmd.scaledMeterValue 239 | break; 240 | } 241 | map.isStateChange = true 242 | map.displayed = true 243 | createEvent(map) 244 | } 245 | 246 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) { 247 | def value = (cmd.value ? "on" : "off") 248 | def result = [createEvent(name: "switch", value: value, type: "physical", displayed: true, isStateChange: true)] 249 | return result 250 | } 251 | 252 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) { 253 | def value = (cmd.value ? "on" : "off") 254 | def result = [createEvent(name: "switch", value: value, type: "digital", displayed: true, isStateChange: true)] 255 | return result 256 | } 257 | 258 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 259 | log.debug "Unhandled: $cmd" 260 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 261 | } 262 | 263 | def on() { 264 | def request = [ 265 | zwave.basicV1.basicSet(value: 0xFF), 266 | zwave.switchBinaryV1.switchBinaryGet() 267 | ] 268 | commands(request) 269 | } 270 | 271 | def off() { 272 | def request = [ 273 | zwave.basicV1.basicSet(value: 0x00), 274 | zwave.switchBinaryV1.switchBinaryGet() 275 | ] 276 | commands(request) 277 | } 278 | 279 | def checkstate() { 280 | // check our config state map 281 | log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}" 282 | } 283 | 284 | def getPower() { 285 | zwave.meterV3.meterGet(scale: 2).format() //Wattage 286 | } 287 | 288 | def getVoltage() { 289 | zwave.meterV3.meterGet(scale: 4).format() //Volts 290 | } 291 | 292 | def getEnergy() { 293 | zwave.meterV3.meterGet(scale: 0).format() //kWh 294 | } 295 | 296 | def getCurrent() { 297 | zwave.meterV3.meterGet(scale: 5).format() //Amps 298 | } 299 | 300 | def poll() { 301 | def request = [ 302 | zwave.switchBinaryV1.switchBinaryGet(), 303 | zwave.basicV1.basicGet(), 304 | zwave.meterV3.meterGet(scale: 0), //kWh 305 | zwave.meterV3.meterGet(scale: 1), //kVAh 306 | zwave.meterV3.meterGet(scale: 2), //Wattage 307 | zwave.meterV3.meterGet(scale: 4), //Volts 308 | zwave.meterV3.meterGet(scale: 5), //Amps 309 | zwave.meterV3.meterGet(scale: 6) //Power Factor 310 | ] 311 | commands(request) 312 | } 313 | 314 | def refresh() { 315 | def request = [ 316 | zwave.basicV1.basicGet(), 317 | zwave.switchBinaryV1.switchBinaryGet(), 318 | zwave.meterV3.meterGet(scale: 0), //kWh 319 | zwave.meterV3.meterGet(scale: 1), //kVAh 320 | zwave.meterV3.meterGet(scale: 2), //Wattage 321 | zwave.meterV3.meterGet(scale: 4), //Volts 322 | zwave.meterV3.meterGet(scale: 5), //Amps 323 | zwave.meterV3.meterGet(scale: 6) //Power Factor 324 | ] 325 | commands(request) 326 | } 327 | 328 | def reset() { 329 | def request = [ 330 | zwave.meterV3.meterReset(), 331 | zwave.meterV3.meterGet(scale: 0), //kWh 332 | zwave.meterV3.meterGet(scale: 1), //kVAh 333 | zwave.meterV3.meterGet(scale: 2), //Wattage 334 | zwave.meterV3.meterGet(scale: 4), //Volts 335 | zwave.meterV3.meterGet(scale: 5) //Amps 336 | ] 337 | commands(request) 338 | } 339 | 340 | def configure() { 341 | def request = [ 342 | // Get version and firmware info 343 | zwave.versionV1.versionGet(), 344 | zwave.firmwareUpdateMdV2.firmwareMdGet(), 345 | 346 | // get all the config values 347 | zwave.configurationV1.configurationGet(parameterNumber: 0x01), 348 | zwave.configurationV1.configurationGet(parameterNumber: 0x02), 349 | zwave.configurationV1.configurationGet(parameterNumber: 0x03), 350 | zwave.configurationV1.configurationGet(parameterNumber: 0x04), 351 | zwave.configurationV1.configurationGet(parameterNumber: 0x05), 352 | zwave.configurationV1.configurationGet(parameterNumber: 0x06), 353 | zwave.configurationV1.configurationGet(parameterNumber: 0x07), 354 | zwave.configurationV1.configurationGet(parameterNumber: 0x08), 355 | zwave.configurationV1.configurationGet(parameterNumber: 0x09), 356 | zwave.configurationV1.configurationGet(parameterNumber: 0x0A), 357 | 358 | //this doesn't seem to work in ST... 359 | //zwave.configurationV2.configurationBulkGet (parameterOffset: 0x0001, numberOfParameters: 10), 360 | 361 | // enable or disable energy metering reports 0=disabled 1=enabled 362 | zwave.configurationV1.configurationSet(parameterNumber: 0x01, size: 1, scaledConfigurationValue: 1), 363 | 364 | // Interval in seconds for sending energy metering reports 365 | zwave.configurationV1.configurationSet(parameterNumber: 0x02, size: 2, scaledConfigurationValue: 300), 366 | 367 | // Overload protection - set the number of AMPS you want to limit the plug to. 13 is what it is designed for. 368 | // when this value is hit, overload notification messages are sent and you have to press the button on the plug to reset it. 369 | zwave.configurationV1.configurationSet(parameterNumber: 0x03, size: 1, scaledConfigurationValue: 13), 370 | 371 | // Heavy load warning AMP threshold - the plug led will turn yellow when you reach this AMP value. must be less than parameter 3/ 372 | zwave.configurationV1.configurationSet(parameterNumber: 0x04, size: 1, scaledConfigurationValue: 12), 373 | 374 | // LED Notifications - 0=disabled 1=enabled 375 | zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: 1), 376 | 377 | // percentage of change in any energy metric for a report to be sent - threshold reporting 378 | zwave.configurationV1.configurationSet(parameterNumber: 0x06, size: 1, scaledConfigurationValue: 5), 379 | 380 | // power failure recovery state - 0=remain off when power restored 1=return to last state when power restored 381 | zwave.configurationV1.configurationSet(parameterNumber: 0x07, size: 1, scaledConfigurationValue: 1), 382 | 383 | // auto power off timer - 0=disabled 1=enabled 384 | zwave.configurationV1.configurationSet(parameterNumber: 0x08, size: 1, scaledConfigurationValue: 12), 385 | 386 | // auto power off timer duration - a value in minutes 1-65535 387 | zwave.configurationV1.configurationSet(parameterNumber: 0x09, size: 2, scaledConfigurationValue: 150), 388 | 389 | // manual control power on/off control - 0=disable action button 1=enable action button 390 | zwave.configurationV1.configurationSet(parameterNumber: 0x0A, size: 1, scaledConfigurationValue: 1), 391 | 392 | // Can use the zwaveHubNodeId variable to add the hub to the device's associations: 393 | zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId) 394 | ] 395 | commands(request) + setConfigured() 396 | } 397 | 398 | private setConfigured() { 399 | updateDataValue("configured", "true") 400 | } 401 | 402 | private isConfigured() { 403 | getDataValue("configured") == "true" 404 | } 405 | 406 | private command(physicalgraph.zwave.Command cmd) { 407 | cmd.format() 408 | } 409 | 410 | private commands(commands, delay=1250) { 411 | delayBetween(commands.collect{ command(it) }, delay) 412 | } -------------------------------------------------------------------------------- /zooZ-Motion-Sensor-ZSE02/Z-Wave command classes for motion sensor.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/zooZ-Motion-Sensor-ZSE02/Z-Wave command classes for motion sensor.pdf -------------------------------------------------------------------------------- /zooZ-Motion-Sensor-ZSE02/device_type-zooZ-Motion-Sensor-ZSE02_v1: -------------------------------------------------------------------------------- 1 | /* 2 | * V 1.0 of zooZ motion sensor ZSE-02 code 5/7/2016 3 | * by Robert Vandervoort 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. You may obtain a copy of the License at: 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing permissions and limitations under the License. 13 | * 14 | --------------------------------------------------------------------------------------------------------------------------- 15 | INSTRUCTIONS: 16 | * First you will need to create a new device handler in SmartThings. Log in to the IDE and click on Device Handlers in the top menu. 17 | Then click "from code" below. You'l be presented with a blank area where you can copy this code and paste it in. 18 | * Next, scroll to the bottom and click create. Now click save, then click publish > for me. 19 | * You should now see this device type in your list of device handlers. Now we need to pair the device. 20 | * Put SmartThings into inclusion mode by going through the add new device dialog. 21 | On the bottom of the zooZ 4-in-1 you will see several small holes. There is a series of four holes and a hole all by itself. 22 | You'll need a paperclip or something similar that fits into the hole. While holding the sensor a foot or so from the hub, 23 | and with SmartThings in inclusion mode, gently depress the button inside the single hole twice rapidly. The light should blink. 24 | Please wait a few moments (usually 10 seconds or so) and you should see "zooZ 4-in-1 sensor - RV 1.0" appear in the found devices area. 25 | * Touch the "zooZ 4-in-1 sensor - RV 1.0" to configure. Here we will set your temperature scale preferecne and motion preferences. 26 | After you make your choices, touch done in the app. 27 | * Now go to your devices list in the SmartThings app and open up the newly added sensor. 28 | * In order to get the configuration sent and initial sensor data, we need to wake the sensor up. Press the button on the device 29 | one time while holding it close to the hub. If you pressed the button the sensor should blink yellow once. Wait about 30 seconds, 30 | then refresh (drag the screen down) and you should see data on the screen for temp, humidity, illuminance, and battery. 31 | ** If you do not, please wait a minute or so and refresh the screen again by sliding it down. 32 | * If you still do not see anything after refreshing, touch the gear icon to enter the device preferences screen (make any adjustments or not) and then touch done. 33 | This will reset the configuration state so the device can be configured again and polled for data. Once you're back at the device screen, 34 | while holding the sensor close to the hub, press the small button we pressed earlier one time, making sure that the sensor blinks 35 | (if it doesn't, press the button again) and wait a minute or so, then refresh the device screen in the app again. 36 | You should see data on the screen now. 37 | *** IF YOU STILL ARE NOT GETTING DATA, go back to the preferences screen and enable debug logging, and touch done. You do not need 38 | to press the button on the sensor again at this point. Go into the SmartThings IDE and choose "live logging" from the top menu. 39 | While on the live logging screen and close to your hub with the sensor, press the button on the sensor, making sure it blinks, and watch the screen for results. 40 | You should see several lines of data come in slowly. This should tell you all your settings and what the configuration on the sensor is actually set to. 41 | It will then poll the sensors for data. If you do not ever see any data coming from the sensor, please post to the community or 42 | message me via github or the SmartThings community. 43 | */ 44 | 45 | metadata { 46 | definition (name: "zooZ motion sensor - RV 1.0", namespace: "robertvandervoort", author: "Robert Vandervoort") { 47 | capability "Motion Sensor" 48 | capability "Acceleration Sensor" 49 | capability "Configuration" 50 | capability "Sensor" 51 | capability "Battery" 52 | 53 | // RAW Description: 0 0 0x0701 0 0 0 a 0x5E 0x85 0x59 0x71 0x80 0x5A 0x73 0x84 0x72 0x86 54 | attribute "tamper", "enum", ["detected", "clear"] 55 | fingerprint deviceId: "0x0701", inClusters: "0x5E 0x85 0x59 0x71 0x80 0x5A 0x73 0x84 0x72 0x86" 56 | } 57 | simulator { 58 | status "no motion" : "command: 9881, payload: 00300300" 59 | status "motion" : "command: 9881, payload: 003003FF" 60 | status "clear" : " command: 9881, payload: 0071050000000007030000" 61 | status "tamper" : "command: 9881, payload: 007105000000FF07030000" 62 | 63 | for (int i in [0, 5, 10, 15, 50, 99, 100]) { 64 | status "battery ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate( 65 | new physicalgraph.zwave.Zwave().batteryV1.batteryReport( 66 | batteryLevel: i 67 | ) 68 | ).incomingMessage() 69 | } 70 | status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate( 71 | new physicalgraph.zwave.Zwave().batteryV1.batteryReport( 72 | batteryLevel: 255 73 | ) 74 | ).incomingMessage() 75 | status "wake up": "command: 8407, payload:" 76 | } 77 | tiles (scale: 2) { 78 | multiAttributeTile(name:"main", type: "generic", width: 6, height: 4){ 79 | tileAttribute ("device.motion", key: "PRIMARY_CONTROL") { 80 | attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0" 81 | attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff" 82 | } 83 | } 84 | standardTile("acceleration", "device.acceleration", width: 2, height: 2) { 85 | state("active", label:'tamper', icon:"st.motion.acceleration.active", backgroundColor:"#ff0000") 86 | state("inactive", label:'clear', icon:"st.motion.acceleration.inactive", backgroundColor:"#00ff00") 87 | } 88 | valueTile("battery", "device.battery", decoration: "flat", width: 2, height: 2) { 89 | state "battery", label:'${currentValue}% battery', unit:"" 90 | } 91 | main(["main"]) 92 | details(["main","acceleration","battery"]) 93 | } 94 | preferences { 95 | input "debugOutput", "boolean", 96 | title: "Enable debug logging?", 97 | defaultValue: false, 98 | displayDuringSetup: true 99 | input "LEDbehavior", "enum", 100 | title: "LED Behavior", 101 | options: ["LED Off", "Breathing", "Quick Blink on Temp/PIR"], 102 | defaultValue: "Quick Blink on Temp/PIR", 103 | required: false, 104 | displayDuringSetup: false 105 | input "PIRsensitivity", "number", 106 | title: "PIR motion sensitivity", 107 | description: "A value from 1-7, from high to low sensitivity (1 is highest)", 108 | range: "1..7", 109 | defaultValue: 4, 110 | required: false, 111 | displayDuringSetup: true 112 | input "MotionReset", "number", 113 | title: "PIR reset time", 114 | description: "Number of minutes to wait to report motion cleared after a motion event if there is no motion detected.", 115 | range: "1..255", 116 | defaultValue: 3, 117 | required: false, 118 | displayDuringSetup: true 119 | } 120 | } 121 | 122 | def updated() 123 | { 124 | updateDataValue("configured", "false") 125 | state.debug = ("true" == debugOutput) 126 | } 127 | 128 | def parse(String description) 129 | { 130 | def result = null 131 | if (description.startsWith("Err 106")) { 132 | state.sec = 0 133 | result = createEvent( name: "secureInclusion", value: "failed", isStateChange: true, 134 | 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.") 135 | } else if (description != "updated") { 136 | def cmd = zwave.parse(description, [0x31: 5, 0x71:3, 0x7A: 2, 0x81: 1, 0x84: 2, 0x86: 1]) 137 | if (cmd) { 138 | result = zwaveEvent(cmd) 139 | } 140 | } 141 | if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}" 142 | return result 143 | } 144 | 145 | def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) 146 | { 147 | def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)] 148 | if (!isConfigured()) { 149 | // we're still in the process of configuring a newly joined device 150 | if (state.debug) log.debug("late configure") 151 | result += response(configure()) 152 | } else { 153 | result += response(zwave.wakeUpV1.wakeUpNoMoreInformation()) 154 | } 155 | result 156 | } 157 | 158 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) { 159 | def encapsulatedCommand = cmd.encapsulatedCommand([0x31: 5, 0x71:3, 0x7A: 2, 0x81: 1, 0x84: 2, 0x86: 1]) 160 | state.sec = 1 161 | // if (state.debug) log.debug "encapsulated: ${encapsulatedCommand}" 162 | if (encapsulatedCommand) { 163 | zwaveEvent(encapsulatedCommand) 164 | } else { 165 | log.warn "Unable to extract encapsulated cmd from $cmd" 166 | createEvent(descriptionText: cmd.toString()) 167 | } 168 | } 169 | 170 | def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) { 171 | if (state.debug) log.debug "---SECURITY COMMANDS SUPPORTED REPORT V1--- ${device.displayName} sent commandClassControl: ${cmd.commandClassControl}, commandClassSupport: ${cmd.commandClassSupport}, reportsToFollow: ${cmd.reportsToFollow}" 172 | response(configure()) 173 | } 174 | 175 | def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) { 176 | if (state.debug) log.debug "---MANUFACTURER SPECIFIC REPORT V2--- ${device.displayName} sent deviceIdDataFormat: ${cmd.deviceIdDataFormat}, deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}, deviceIdType: ${cmd.deviceIdType}, payload: ${cmd.payload}" 177 | } 178 | 179 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionCommandClassReport cmd) { 180 | if (state.debug) log.debug "---COMMAND CLASS VERSION REPORT V1--- ${device.displayName} has command class version: ${cmd.commandClassVersion} - payload: ${cmd.payload}" 181 | } 182 | 183 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) { 184 | def fw = "${cmd.applicationVersion}.${cmd.applicationSubVersion}" 185 | updateDataValue("fw", fw) 186 | if (state.debug) log.debug "---VERSION REPORT V1--- ${device.displayName} is running firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}" 187 | } 188 | 189 | def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) { 190 | 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}" 191 | } 192 | 193 | def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) { 194 | 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}" 195 | } 196 | 197 | def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) { 198 | def map = [ name: "battery", unit: "%" ] 199 | if (cmd.batteryLevel == 0xFF) { 200 | map.value = 1 201 | map.descriptionText = "${device.displayName} battery is low" 202 | map.isStateChange = true 203 | } else { 204 | map.value = cmd.batteryLevel 205 | } 206 | state.lastbatt = now() 207 | createEvent(map) 208 | } 209 | 210 | def motionEvent(value) { 211 | def map = [name: "motion"] 212 | if (value != 0) { 213 | map.value = "active" 214 | map.descriptionText = "$device.displayName detected motion" 215 | } else { 216 | map.value = "inactive" 217 | map.descriptionText = "$device.displayName motion has stopped" 218 | } 219 | createEvent(map) 220 | } 221 | 222 | def zwaveEvent(physicalgraph.zwave.commands.sensorbinaryv2.SensorBinaryReport cmd) { 223 | if (state.debug) log.debug "---SENSOR BINARY REPORT V2--- ${device.displayName} sent value: ${cmd.sensorValue}" 224 | motionEvent(cmd.sensorValue) 225 | } 226 | 227 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) { 228 | if (state.debug) log.debug "---BASIC SET REPORT V1--- ${device.displayName} sent value: ${cmd.value}" 229 | motionEvent(cmd.value) 230 | } 231 | 232 | def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) { 233 | if (state.debug) log.debug "---NOTIFICATION REPORT V3--- ${device.displayName} sent eventParametersLength: ${cmd.eventParametersLength} eventParameter: ${cmd.eventParameter} notificationType: ${cmd.notificationType} event: ${cmd.event}" 234 | def result = [] 235 | if (cmd.notificationType == 7) { 236 | if (cmd.event == 0x00 && cmd.eventParameter == 0x08) { 237 | result << motionEvent(0) 238 | } 239 | else if (cmd.event == 0x03) { 240 | result << createEvent(name: "acceleration", value: "active", descriptionText: "$device.displayName cover is open.") 241 | } 242 | else if (cmd.event == 0X00 || cmd.eventParameter == 0x03) { 243 | result << createEvent(name: "acceleration", value: "inactive", descriptionText: "$device.displayName cover has been closed.") 244 | } 245 | else if (cmd.event == 0x08) { 246 | result << motionEvent(255) 247 | } 248 | } 249 | else { 250 | result << createEvent(descriptionText: cmd.toString(), isStateChange: false) 251 | } 252 | result 253 | } 254 | 255 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 256 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 257 | } 258 | 259 | def configure() { 260 | // This sensor joins as a secure device if you double-click the button to include it 261 | //if (device.device.rawDescription =~ /98/ && !state.sec) { 262 | // if (state.debug) log.debug "4-in-1 sensor not sending configure until secure" 263 | // return [] 264 | //} 265 | if (state.debug) log.debug "--Sending configuration commands to zooZ 4-in-1 sensor--" 266 | //if (state.debug) log.debug "Prefernces settings: PIRsensitivity: $PIRsensitivity, Temp offset: $tempoffset, Humidity offset: $humidityoffset, Luminance offset: $luminanceoffset" 267 | def LEDbehav = 3 268 | if (LEDbehavior == "LED Off") { 269 | LEDbehav=1 270 | } 271 | else if (LEDbehavior == "Breathing") { 272 | LEDbehav=2 273 | } 274 | else { 275 | LEDbehav=3 276 | } 277 | def PIRsens = 4 278 | if (PIRsensitivity) { 279 | PIRsens=PIRsensitivity 280 | } 281 | else { 282 | PIRsens = 4 283 | } 284 | def MotionRst = 3 285 | if (MotionReset) { 286 | MotionRst=MotionReset 287 | } 288 | else { 289 | MotionRst = 3 290 | } 291 | if (state.debug) log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}" 292 | setConfigured() 293 | def request = [ 294 | // set wakeup interval to 20 mins 295 | zwave.wakeUpV1.wakeUpIntervalSet(seconds:1200, nodeid:zwaveHubNodeId), 296 | 297 | // Get Version information 298 | zwave.versionV1.versionGet(), 299 | zwave.firmwareUpdateMdV2.firmwareMdGet(), 300 | 301 | // send no-motion report x minutes after motion stops 302 | //zwave.configurationV1.configurationSet(parameterNumber: 0x05, size: 1, scaledConfigurationValue: MotionRst), 303 | //zwave.configurationV1.configurationGet(parameterNumber: 0x05), 304 | 305 | // set motion sensor sensitivity 306 | //zwave.configurationV1.configurationSet(parameterNumber: 0x06, size: 1, scaledConfigurationValue: PIRsens), 307 | //zwave.configurationV1.configurationGet(parameterNumber: 0x06), 308 | 309 | // set LED behavior 310 | //zwave.configurationV1.configurationSet(parameterNumber: 0x07, size: 1, scaledConfigurationValue: LEDbehav), 311 | //zwave.configurationV1.configurationGet(parameterNumber: 0x07), 312 | 313 | // get updated battery data 314 | zwave.batteryV1.batteryGet(), 315 | 316 | // Can use the zwaveHubNodeId variable to add the hub to the device's associations: 317 | zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId) 318 | ] 319 | commands(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()] 320 | } 321 | 322 | private setConfigured() { 323 | updateDataValue("configured", "true") 324 | return [] 325 | } 326 | 327 | private isConfigured() { 328 | getDataValue("configured") == "true" 329 | } 330 | 331 | private command(physicalgraph.zwave.Command cmd) { 332 | if (state.sec) { 333 | zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format() 334 | } else { 335 | cmd.format() 336 | } 337 | } 338 | 339 | private commands(commands, delay=1000) { 340 | delayBetween(commands.collect{ command(it) }, delay) 341 | } -------------------------------------------------------------------------------- /zooZ-Motion-Sensor-ZSE02/device_type-zooZ-Motion-Sensor-ZSE02_v1.1: -------------------------------------------------------------------------------- 1 | /* 2 | * V 1.1 of zooZ motion sensor ZSE-02 code 5/13/16 3 | * by Robert Vandervoort 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. You may obtain a copy of the License at: 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing permissions and limitations under the License. 13 | * 14 | --------------------------------------------------------------------------------------------------------------------------- 15 | INSTRUCTIONS: 16 | * First you will need to create a new device handler in SmartThings. Log in to the IDE and click on Device Handlers in the top menu. 17 | Then click "from code" below. You'l be presented with a blank area where you can copy this code and paste it in. 18 | * Next, scroll to the bottom and click create. Now click save, then click publish > for me. 19 | * You should now see this device type in your list of device handlers. Now we need to pair the device. 20 | * Put SmartThings into inclusion mode by going through the add new device dialog. 21 | On the bottom of the zooZ 4-in-1 you will see several small holes. There is a series of four holes and a hole all by itself. 22 | You'll need a paperclip or something similar that fits into the hole. While holding the sensor a foot or so from the hub, 23 | and with SmartThings in inclusion mode, gently depress the button inside the single hole twice rapidly. The light should blink. 24 | Please wait a few moments (usually 10 seconds or so) and you should see "zooZ 4-in-1 sensor - RV 1.0" appear in the found devices area. 25 | * Touch the "zooZ 4-in-1 sensor - RV 1.0" to configure. Here we will set your temperature scale preferecne and motion preferences. 26 | After you make your choices, touch done in the app. 27 | * Now go to your devices list in the SmartThings app and open up the newly added sensor. 28 | * In order to get the configuration sent and initial sensor data, we need to wake the sensor up. Press the button on the device 29 | one time while holding it close to the hub. If you pressed the button the sensor should blink yellow once. Wait about 30 seconds, 30 | then refresh (drag the screen down) and you should see data on the screen for temp, humidity, illuminance, and battery. 31 | ** If you do not, please wait a minute or so and refresh the screen again by sliding it down. 32 | * If you still do not see anything after refreshing, touch the gear icon to enter the device preferences screen (make any adjustments or not) and then touch done. 33 | This will reset the configuration state so the device can be configured again and polled for data. Once you're back at the device screen, 34 | while holding the sensor close to the hub, press the small button we pressed earlier one time, making sure that the sensor blinks 35 | (if it doesn't, press the button again) and wait a minute or so, then refresh the device screen in the app again. 36 | You should see data on the screen now. 37 | *** IF YOU STILL ARE NOT GETTING DATA, go back to the preferences screen and enable debug logging, and touch done. You do not need 38 | to press the button on the sensor again at this point. Go into the SmartThings IDE and choose "live logging" from the top menu. 39 | While on the live logging screen and close to your hub with the sensor, press the button on the sensor, making sure it blinks, and watch the screen for results. 40 | You should see several lines of data come in slowly. This should tell you all your settings and what the configuration on the sensor is actually set to. 41 | It will then poll the sensors for data. If you do not ever see any data coming from the sensor, please post to the community or 42 | message me via github or the SmartThings community. 43 | */ 44 | 45 | metadata { 46 | definition (name: "zooZ motion sensor ZSE-02 - RV 1.1", namespace: "robertvandervoort", author: "Robert Vandervoort") { 47 | capability "Motion Sensor" 48 | capability "Acceleration Sensor" 49 | capability "Sensor" 50 | capability "Battery" 51 | 52 | // RAW Description: 0 0 0x0701 0 0 0 a 0x5E 0x85 0x59 0x71 0x80 0x5A 0x73 0x84 0x72 0x86 53 | attribute "tamper", "enum", ["detected", "clear"] 54 | fingerprint deviceId: "0x0701", inClusters: "0x5E 0x85 0x59 0x71 0x80 0x5A 0x73 0x84 0x72 0x86" 55 | } 56 | simulator { 57 | status "no motion" : "command: 9881, payload: 00300300" 58 | status "motion" : "command: 9881, payload: 003003FF" 59 | status "clear" : " command: 9881, payload: 0071050000000007030000" 60 | status "tamper" : "command: 9881, payload: 007105000000FF07030000" 61 | 62 | for (int i in [0, 5, 10, 15, 50, 99, 100]) { 63 | status "battery ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate( 64 | new physicalgraph.zwave.Zwave().batteryV1.batteryReport( 65 | batteryLevel: i 66 | ) 67 | ).incomingMessage() 68 | } 69 | status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate( 70 | new physicalgraph.zwave.Zwave().batteryV1.batteryReport( 71 | batteryLevel: 255 72 | ) 73 | ).incomingMessage() 74 | status "wake up": "command: 8407, payload:" 75 | } 76 | tiles (scale: 2) { 77 | multiAttributeTile(name:"main", type: "generic", width: 6, height: 4){ 78 | tileAttribute ("device.motion", key: "PRIMARY_CONTROL") { 79 | attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0" 80 | attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff" 81 | } 82 | } 83 | standardTile("acceleration", "device.acceleration", width: 2, height: 2) { 84 | state("active", label:'DISABLED', backgroundColor:"#ff0000") 85 | state("inactive", label:'ENABLED', backgroundColor:"#00ff00") 86 | } 87 | valueTile("battery", "device.battery", decoration: "flat", width: 2, height: 2) { 88 | state "battery", label:'${currentValue}% battery', unit:"" 89 | } 90 | main(["main"]) 91 | details(["main","acceleration","battery"]) 92 | } 93 | preferences { 94 | input "debugOutput", "boolean", 95 | title: "Enable debug logging?", 96 | defaultValue: false, 97 | displayDuringSetup: true 98 | } 99 | } 100 | 101 | def updated() 102 | { 103 | updateDataValue("configured", "false") 104 | state.debug = ("true" == debugOutput) 105 | } 106 | 107 | def parse(String description) 108 | { 109 | def result = null 110 | if (description != "updated") { 111 | def cmd = zwave.parse(description, [0x31: 5, 0x71:3, 0x7A: 2, 0x81: 1, 0x84: 2, 0x86: 1]) 112 | if (cmd) { 113 | result = zwaveEvent(cmd) 114 | } 115 | } 116 | if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}" 117 | return result 118 | } 119 | 120 | def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) 121 | { 122 | def result = [createEvent(descriptionText: "${device.displayName} woke up", isStateChange: false)] 123 | if (!isConfigured()) { 124 | // we're still in the process of configuring a newly joined device 125 | if (state.debug) log.debug("late configure") 126 | result += response(configure()) 127 | } else { 128 | result += response(zwave.wakeUpV1.wakeUpNoMoreInformation()) 129 | } 130 | result 131 | } 132 | 133 | def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) { 134 | if (state.debug) log.debug "---MANUFACTURER SPECIFIC REPORT V2--- ${device.displayName} sent deviceIdDataFormat: ${cmd.deviceIdDataFormat}, deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}, deviceIdType: ${cmd.deviceIdType}, payload: ${cmd.payload}" 135 | } 136 | 137 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionCommandClassReport cmd) { 138 | if (state.debug) log.debug "---COMMAND CLASS VERSION REPORT V1--- ${device.displayName} has command class version: ${cmd.commandClassVersion} - payload: ${cmd.payload}" 139 | } 140 | 141 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) { 142 | def fw = "${cmd.applicationVersion}.${cmd.applicationSubVersion}" 143 | updateDataValue("fw", fw) 144 | if (state.debug) log.debug "---VERSION REPORT V1--- ${device.displayName} is running firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}" 145 | } 146 | 147 | def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) { 148 | def map = [ name: "battery", unit: "%" ] 149 | if (cmd.batteryLevel == 0xFF) { 150 | map.value = 1 151 | map.descriptionText = "${device.displayName} battery is low" 152 | map.isStateChange = true 153 | } else { 154 | map.value = cmd.batteryLevel 155 | } 156 | state.lastbatt = now() 157 | createEvent(map) 158 | } 159 | 160 | def motionEvent(value) { 161 | def map = [name: "motion"] 162 | if (value != 0) { 163 | map.value = "active" 164 | map.descriptionText = "$device.displayName detected motion" 165 | } else { 166 | map.value = "inactive" 167 | map.descriptionText = "$device.displayName motion has stopped" 168 | } 169 | createEvent(map) 170 | } 171 | 172 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) { 173 | if (state.debug) log.debug "---BASIC SET REPORT V1--- ${device.displayName} sent value: ${cmd.value}" 174 | motionEvent(cmd.value) 175 | } 176 | 177 | def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) { 178 | if (state.debug) log.debug "---NOTIFICATION REPORT V3--- ${device.displayName} sent eventParametersLength: ${cmd.eventParametersLength} eventParameter: ${cmd.eventParameter} notificationType: ${cmd.notificationType} event: ${cmd.event}" 179 | def result = [] 180 | if (cmd.notificationType == 7) { 181 | if (cmd.eventParameter == [8] && cmd.event == 0x00) { 182 | result << motionEvent(0) 183 | } 184 | else if (cmd.event == 0x03) { 185 | result << createEvent(name: "acceleration", value: "active", descriptionText: "$device.displayName has been deactivated by the switch.") 186 | } 187 | else if (cmd.event == 0X00 || cmd.eventParameter == 0x03) { 188 | result << createEvent(name: "acceleration", value: "inactive", descriptionText: "$device.displayName has been reactivated by the switch.") 189 | } 190 | else if (cmd.event == 0x08) { 191 | result << motionEvent(255) 192 | } 193 | } 194 | else { 195 | result << createEvent(descriptionText: cmd.toString(), isStateChange: false) 196 | } 197 | result 198 | } 199 | 200 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 201 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 202 | } 203 | 204 | def configure() { 205 | if (state.debug) log.debug "--Sending configuration commands to zooZ motion sensor--" 206 | if (state.debug) log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}" 207 | setConfigured() 208 | def request = [ 209 | // set wakeup interval to 20 mins 210 | zwave.wakeUpV1.wakeUpIntervalSet(seconds:1200, nodeid:zwaveHubNodeId), 211 | 212 | // Can use the zwaveHubNodeId variable to add the hub to the device's associations: 213 | zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId), 214 | 215 | //Get association 216 | zwave.associationV1.associationGet(groupingIdentifier:1), 217 | zwave.associationV1.associationGet(groupingIdentifier:2), 218 | 219 | // Get Version information 220 | zwave.versionV1.versionGet(), 221 | 222 | // get updated battery and sensor data 223 | zwave.batteryV1.batteryGet(), 224 | ] 225 | commands(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()] 226 | } 227 | 228 | private setConfigured() { 229 | updateDataValue("configured", "true") 230 | return [] 231 | } 232 | 233 | private isConfigured() { 234 | getDataValue("configured") == "true" 235 | } 236 | 237 | private command(physicalgraph.zwave.Command cmd) { 238 | cmd.format() 239 | } 240 | 241 | private commands(commands, delay=1000) { 242 | delayBetween(commands.collect{ command(it) }, delay) 243 | } -------------------------------------------------------------------------------- /zooZ-Motion-Sensor-ZSE02/device_type-zooZ-Motion-Sensor-ZSE02_v1.2: -------------------------------------------------------------------------------- 1 | /* 2 | * V 1.2 of zooZ motion sensor ZSE-02 code 5/14/16 3 | * by Robert Vandervoort 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. You may obtain a copy of the License at: 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing permissions and limitations under the License. 13 | * 14 | --------------------------------------------------------------------------------------------------------------------------- 15 | INSTRUCTIONS: 16 | * First you will need to create a new device handler in SmartThings. Log in to the IDE and click on Device Handlers in the top menu. 17 | Then click "from code" below. You'l be presented with a blank area where you can copy this code and paste it in. 18 | * Next, scroll to the bottom and click create. Now click save, then click publish > for me. 19 | * You should now see this device type in your list of device handlers. Now we need to pair the device. 20 | * Put SmartThings into inclusion mode by going through the add new device dialog. 21 | * Tap zwave sensor on the app screen to configure. 22 | * Now go to your devices list in the SmartThings app and open up the newly added sensor. 23 | * The configuration and battery state will get pulled by pressing the button once, waiting a couple seconds, and pressing again. 24 | * From here on, each time the motion sensor wakes up it will query for battery level. That's it. If you see the red circle in the app 25 | that says disabled, press the switch once again so it turns green and you're now monitoring for motion. Press again to disable the sensor. 26 | 27 | */ 28 | 29 | metadata { 30 | definition (name: "zooZ motion sensor ZSE-02 - RV 1.2", namespace: "robertvandervoort", author: "Robert Vandervoort") { 31 | capability "Motion Sensor" 32 | capability "Acceleration Sensor" 33 | capability "Sensor" 34 | capability "Battery" 35 | 36 | // RAW Description: 0 0 0x0701 0 0 0 a 0x5E 0x85 0x59 0x71 0x80 0x5A 0x73 0x84 0x72 0x86 37 | attribute "tamper", "enum", ["detected", "clear"] 38 | fingerprint deviceId: "0x0701", inClusters: "0x5E 0x85 0x59 0x71 0x80 0x5A 0x73 0x84 0x72 0x86" 39 | } 40 | simulator { 41 | status "no motion" : "command: 9881, payload: 00300300" 42 | status "motion" : "command: 9881, payload: 003003FF" 43 | status "clear" : " command: 9881, payload: 0071050000000007030000" 44 | status "tamper" : "command: 9881, payload: 007105000000FF07030000" 45 | 46 | for (int i in [0, 5, 10, 15, 50, 99, 100]) { 47 | status "battery ${i}%": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate( 48 | new physicalgraph.zwave.Zwave().batteryV1.batteryReport( 49 | batteryLevel: i 50 | ) 51 | ).incomingMessage() 52 | } 53 | status "low battery alert": new physicalgraph.zwave.Zwave().securityV1.securityMessageEncapsulation().encapsulate( 54 | new physicalgraph.zwave.Zwave().batteryV1.batteryReport( 55 | batteryLevel: 255 56 | ) 57 | ).incomingMessage() 58 | status "wake up": "command: 8407, payload:" 59 | } 60 | tiles (scale: 2) { 61 | multiAttributeTile(name:"main", type: "generic", width: 6, height: 4){ 62 | tileAttribute ("device.motion", key: "PRIMARY_CONTROL") { 63 | attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0" 64 | attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff" 65 | } 66 | } 67 | standardTile("acceleration", "device.acceleration", width: 2, height: 2) { 68 | state("active", label:'DISABLED', backgroundColor:"#ff0000") 69 | state("inactive", label:'ENABLED', backgroundColor:"#00ff00") 70 | } 71 | valueTile("battery", "device.battery", decoration: "flat", width: 2, height: 2) { 72 | state "battery", label:'${currentValue}% battery', unit:"" 73 | } 74 | main(["main"]) 75 | details(["main","acceleration","battery"]) 76 | } 77 | preferences { 78 | input "debugOutput", "boolean", 79 | title: "Enable debug logging?", 80 | defaultValue: false, 81 | displayDuringSetup: true 82 | } 83 | } 84 | 85 | def updated() 86 | { 87 | updateDataValue("configured", "false") 88 | state.debug = ("true" == debugOutput) 89 | } 90 | 91 | def parse(String description) 92 | { 93 | def result = null 94 | if (description != "updated") { 95 | def cmd = zwave.parse(description, [0x31: 5, 0x71:3, 0x7A: 2, 0x81: 1, 0x84: 2, 0x86: 1]) 96 | if (cmd) { 97 | result = zwaveEvent(cmd) 98 | } 99 | } 100 | if (state.debug) log.debug "Parsed '${description}' to ${result.inspect()}" 101 | return result 102 | } 103 | 104 | def zwaveEvent(physicalgraph.zwave.commands.wakeupv2.WakeUpNotification cmd) { 105 | def result = createEvent(descriptionText: "${device.displayName} woke up", displayed: true) 106 | def cmds = [] 107 | if (!isConfigured()) { 108 | // we're still in the process of configuring a newly joined device 109 | if (state.debug) log.debug("late configure") 110 | [result, response(configure())] 111 | } else if (isConfigured()){ 112 | cmds << zwave.batteryV1.batteryGet().format() 113 | cmds << "delay 3000" 114 | cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format() 115 | [result, response(cmds)] 116 | } 117 | } 118 | 119 | def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) { 120 | if (state.debug) log.debug "---MANUFACTURER SPECIFIC REPORT V2--- ${device.displayName} sent deviceIdDataFormat: ${cmd.deviceIdDataFormat}, deviceIdDataLengthIndicator: ${cmd.deviceIdDataLengthIndicator}, deviceIdType: ${cmd.deviceIdType}, payload: ${cmd.payload}" 121 | } 122 | 123 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionCommandClassReport cmd) { 124 | if (state.debug) log.debug "---COMMAND CLASS VERSION REPORT V1--- ${device.displayName} has command class version: ${cmd.commandClassVersion} - payload: ${cmd.payload}" 125 | } 126 | 127 | def zwaveEvent(physicalgraph.zwave.commands.versionv1.VersionReport cmd) { 128 | def fw = "${cmd.applicationVersion}.${cmd.applicationSubVersion}" 129 | updateDataValue("fw", fw) 130 | if (state.debug) log.debug "---VERSION REPORT V1--- ${device.displayName} is running firmware version: $fw, Z-Wave version: ${cmd.zWaveProtocolVersion}.${cmd.zWaveProtocolSubVersion}" 131 | } 132 | 133 | def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) { 134 | if (state.debug) log.debug "---BATTERY V1 REPORT--- ${device.displayName} reports battery level of ${cmd.batteryLevel}" 135 | def result = [] 136 | def map = [ name: "battery", unit: "%" ] 137 | if (cmd.batteryLevel == 0xFF) { 138 | map.value = 1 139 | map.descriptionText = "${device.displayName} battery is low" 140 | map.isStateChange = true 141 | } else { 142 | map.value = cmd.batteryLevel 143 | map.descriptionText = "${device.displayName} battery is at ${cmd.batteryLevel}" 144 | map.isStateChange = true 145 | } 146 | state.lastbatt = now() 147 | result << createEvent(map) 148 | result 149 | } 150 | 151 | def motionEvent(value) { 152 | def map = [name: "motion"] 153 | if (value != 0) { 154 | map.value = "active" 155 | map.descriptionText = "$device.displayName detected motion" 156 | } else { 157 | map.value = "inactive" 158 | map.descriptionText = "$device.displayName motion has stopped" 159 | } 160 | createEvent(map) 161 | } 162 | 163 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) { 164 | if (state.debug) log.debug "---BASIC SET REPORT V1--- ${device.displayName} sent value: ${cmd.value}" 165 | motionEvent(cmd.value) 166 | } 167 | 168 | def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) { 169 | if (state.debug) log.debug "---NOTIFICATION REPORT V3--- ${device.displayName} sent eventParametersLength: ${cmd.eventParametersLength} eventParameter: ${cmd.eventParameter} notificationType: ${cmd.notificationType} event: ${cmd.event}" 170 | def result = [] 171 | if (cmd.notificationType == 7) { 172 | if (cmd.eventParameter == [8] && cmd.event == 0x00) { 173 | result << motionEvent(0) 174 | } 175 | else if (cmd.event == 0x03) { 176 | result << createEvent(name: "acceleration", value: "active", descriptionText: "$device.displayName has been deactivated by the switch.") 177 | } 178 | else if (cmd.eventParameter == [3] && cmd.event == 0X00) { 179 | result << createEvent(name: "acceleration", value: "inactive", descriptionText: "$device.displayName has been reactivated by the switch.") 180 | } 181 | else if (cmd.event == 0x08) { 182 | result << motionEvent(255) 183 | } 184 | } 185 | else { 186 | result << createEvent(descriptionText: cmd.toString(), isStateChange: false) 187 | } 188 | result 189 | } 190 | 191 | def zwaveEvent(physicalgraph.zwave.Command cmd) { 192 | createEvent(descriptionText: cmd.toString(), isStateChange: false) 193 | } 194 | 195 | def configure() { 196 | if (state.debug) log.debug "--Sending configuration commands to zooZ motion sensor--" 197 | if (state.debug) log.debug "settings: ${settings.inspect()}, state: ${state.inspect()}" 198 | setConfigured() 199 | def request = [ 200 | // set wakeup interval to 20 mins 201 | zwave.wakeUpV1.wakeUpIntervalSet(seconds:1200, nodeid:zwaveHubNodeId), 202 | 203 | // Can use the zwaveHubNodeId variable to add the hub to the device's associations: 204 | zwave.associationV1.associationSet(groupingIdentifier:2, nodeId:zwaveHubNodeId), 205 | 206 | //Get association 207 | zwave.associationV1.associationGet(groupingIdentifier:1), 208 | zwave.associationV1.associationGet(groupingIdentifier:2), 209 | 210 | // Get Version information 211 | zwave.versionV1.versionGet(), 212 | 213 | // get updated battery data 214 | zwave.batteryV1.batteryGet(), 215 | ] 216 | commands(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()] 217 | } 218 | 219 | private setConfigured() { 220 | updateDataValue("configured", "true") 221 | return [] 222 | } 223 | 224 | private isConfigured() { 225 | getDataValue("configured") == "true" 226 | } 227 | 228 | private command(physicalgraph.zwave.Command cmd) { 229 | cmd.format() 230 | } 231 | 232 | private commands(commands, delay=1000) { 233 | delayBetween(commands.collect{ command(it) }, delay) 234 | } 235 | -------------------------------------------------------------------------------- /zooZ-Motion-Sensor-ZSE02/zooz-zse02-motion-sensor-manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/zooZ-Motion-Sensor-ZSE02/zooz-zse02-motion-sensor-manual.pdf -------------------------------------------------------------------------------- /zooZ-Strip-ZEN20/device_type-zooZ-strip-ZEN20_v1.0: -------------------------------------------------------------------------------- 1 | /** 2 | * Derived from Aeon Smart Strip code Copyright 2015 SmartThings 3 | * reworked 6/2016 by Robert Vandervoort 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 6 | * in compliance with the License. You may obtain a copy of the License at: 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 11 | * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License 12 | * for the specific language governing permissions and limitations under the License. 13 | * 14 | */ 15 | metadata { 16 | definition (name: "zooZ ZEN20 - Z-Wave plus power strip", namespace: "robertvandervoort", author: "Robert Vandervoort") { 17 | capability "Switch" 18 | capability "Refresh" 19 | capability "Configuration" 20 | capability "Actuator" 21 | capability "Zw Multichannel" 22 | 23 | (1..5).each { n -> 24 | attribute "switch$n", "enum", ["on", "off"] 25 | command "on$n" 26 | command "off$n" 27 | } 28 | //RAW DESC 0 0 0x1004 0 0 0 b 0x5E 0x85 0x59 0x5A 0x72 0x60 0x8E 0x73 0x27 0x25 0x86 29 | // Device reset locally 0x5A, multi channel assoc 0x8E, powerlevel 0x73 30 | fingerprint deviceId: "0x1004", inClusters: "0x5E,0x85,0x59,0x5A,0x72,0x60,0x8E,0x73,0x27,0x25,0x86" 31 | } 32 | 33 | // simulator metadata 34 | simulator { 35 | status "on": "command: 2003, payload: FF" 36 | status "off": "command: 2003, payload: 00" 37 | status "switch1 on": "command: 600D, payload: 01 00 25 03 FF" 38 | status "switch1 off": "command: 600D, payload: 01 00 25 03 00" 39 | status "switch5 on": "command: 600D, payload: 05 00 25 03 FF" 40 | status "switch5 off": "command: 600D, payload: 05 00 25 03 00" 41 | // reply messages 42 | reply "2001FF,delay 100,2502": "command: 2503, payload: FF" 43 | reply "200100,delay 100,2502": "command: 2503, payload: 00" 44 | } 45 | 46 | // tile definitions 47 | tiles { 48 | (1..5).each { n -> 49 | standardTile("switch$n", "switch$n", width: 1, height: 1, canChangeIcon: true) { 50 | state "on", label: '${name}', action: "off$n", icon: "st.switches.switch.on", backgroundColor: "#79b821" 51 | state "off", label: '${name}', action: "on$n", icon: "st.switches.switch.off", backgroundColor: "#ffffff" 52 | } 53 | valueTile("label$n", "socket $n", width: 2, height: 1, decoration: "flat") { 54 | state "default", label: "$n", defaultState: true 55 | } 56 | } 57 | standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat") { 58 | state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh" 59 | } 60 | main(["switch1"]) 61 | details(["switch1", "label1", "switch2", "label2", "switch3", "label3", "switch4", "label4", "switch5", "label5"]) 62 | } 63 | } 64 | 65 | 66 | def parse(String description) { 67 | def result = null 68 | if (description.startsWith("Err")) { 69 | result = createEvent(descriptionText:description, isStateChange:true) 70 | } else if (description != "updated") { 71 | def cmd = zwave.parse(description, [0x60: 3, 0x32: 3, 0x25: 1, 0x20: 1]) 72 | if (cmd) { 73 | result = zwaveEvent(cmd, null) 74 | } 75 | } 76 | log.debug "parsed '${description}' to ${result.inspect()}" 77 | result 78 | } 79 | 80 | def endpointEvent(endpoint, map) { 81 | if (endpoint) { 82 | map.name = map.name + endpoint.toString() 83 | } 84 | createEvent(map) 85 | } 86 | 87 | def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd, endpoint) { 88 | def map = [name: "switch", type: "physical", value: (cmd.value ? "on" : "off")] 89 | def events = [endpointEvent(endpoint, map)] 90 | def cmds = [] 91 | if (endpoint) { 92 | cmds += delayBetween([2,0].collect { s -> encap(zwave.meterV3.meterGet(scale: s), endpoint) }, 1000) 93 | if(endpoint < 5) cmds += ["delay 1500", encap(zwave.basicV1.basicGet(), endpoint + 1)] 94 | } else if (events[0].isStateChange) { 95 | events += (1..5).collect { ep -> endpointEvent(ep, map.clone()) } 96 | cmds << "delay 3000" 97 | cmds += delayBetween((0..5).collect { ep -> encap(zwave.meterV3.meterGet(scale: 2), ep) }, 800) 98 | } 99 | if(cmds) events << response(cmds) 100 | events 101 | } 102 | 103 | def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd, endpoint) { 104 | def map = [name: "switch", value: (cmd.value ? "on" : "off")] 105 | def events = [endpointEvent(endpoint, map)] 106 | def cmds = [] 107 | if (!endpoint && events[0].isStateChange) { 108 | events += (1..5).collect { ep -> endpointEvent(ep, map.clone()) } 109 | } 110 | events 111 | } 112 | 113 | def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd, ep) { 114 | updateDataValue("MSR", String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)) 115 | null 116 | } 117 | 118 | def zwaveEvent(physicalgraph.zwave.Command cmd, ep) { 119 | log.debug "${device.displayName}: Unhandled ${cmd}" + (ep ? " from endpoint $ep" : "") 120 | } 121 | 122 | def onOffCmd(value, endpoint = null) { 123 | [ 124 | encap(zwave.basicV1.basicSet(value: value), endpoint), 125 | "delay 500", 126 | encap(zwave.switchBinaryV1.switchBinaryGet(), endpoint) 127 | ] 128 | } 129 | 130 | def on() { onOffCmd(0xFF) } 131 | def off() { onOffCmd(0x0) } 132 | 133 | def on1() { onOffCmd(0xFF, 1) } 134 | def on2() { onOffCmd(0xFF, 2) } 135 | def on3() { onOffCmd(0xFF, 3) } 136 | def on4() { onOffCmd(0xFF, 4) } 137 | def on5() { onOffCmd(0xFF, 5) } 138 | 139 | def off1() { onOffCmd(0, 1) } 140 | def off2() { onOffCmd(0, 2) } 141 | def off3() { onOffCmd(0, 3) } 142 | def off4() { onOffCmd(0, 4) } 143 | def off5() { onOffCmd(0, 5) } 144 | 145 | def refresh() { 146 | delayBetween([ 147 | zwave.basicV1.basicGet().format(), 148 | encap(zwave.basicV1.basicGet(), 1) // further gets are sent from the basic report handler 149 | ]) 150 | } 151 | 152 | def configure() { 153 | def cmds = [ 154 | //zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, configurationValue: [0, 0, 0, 1]).format(), 155 | //zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, configurationValue: [0, 0, 0x79, 0]).format(), 156 | //zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 90).format(), 157 | ] 158 | [5, 8, 9, 10, 11].each { p -> 159 | cmds << zwave.configurationV1.configurationSet(parameterNumber: p, size: 2, scaledConfigurationValue: 5).format() 160 | } 161 | [12, 15, 16, 17, 18].each { p -> 162 | cmds << zwave.configurationV1.configurationSet(parameterNumber: p, size: 1, scaledConfigurationValue: 50).format() 163 | } 164 | cmds += [ 165 | //zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 15*60).format(), 166 | //zwave.configurationV1.configurationSet(parameterNumber: 4, size: 1, configurationValue: [1]).format(), 167 | ] 168 | delayBetween(cmds) + "delay 5000" + refresh() 169 | } 170 | 171 | private encap(cmd, endpoint) { 172 | if (endpoint) { 173 | zwave.multiChannelV3.multiChannelCmdEncap(destinationEndPoint:endpoint).encapsulate(cmd).format() 174 | } else { 175 | cmd.format() 176 | } 177 | } -------------------------------------------------------------------------------- /zooZ-Water-Valve/Z-Wave command classes for valve.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertvandervoort/SmartThings/fd0e7fd4fa098cdf0e9ac53c785988d72f143dcf/zooZ-Water-Valve/Z-Wave command classes for valve.pdf --------------------------------------------------------------------------------