Yes. It is being worked on but not getting anywhere with it.
Thanks
Yes. It is being worked on but not getting anywhere with it.
Thanks
Not seeing the (Ring Keypad Sync) with your bundle manager. Am I missing something?
Doh! Found it. Thanks! I was looking in another place.
@bptworld do you know if the announcement volume and siren volumes are correctly implemented? It seems no matter what volume I choose for announcements & siren, they are the same. Keypad tones work fine, but at volume "4" the keypad tones are significantly louder than announcements or sirens.
Any tips? Just getting around to setting up HSM and love that this driver works with HSM natively. Thanks again for all the amazing work on this driver.
Scratch that!! I had to disable the proximity sensor now it works fine. I guess pulling the air gaps couldn't hurt but as soon as I turned the proximity sensor back on poof.
NM the problem was on my end. I fixed it by disconnecting power to all repeating devices. Started working right away. Man ZWAVE Hurts! Air gaps are awesome BTW
I just bought 3 of these a few days ago. They get one way zwave communication. I can get them working temporarily if I mess around a lot. Maybe it's because they shipped with a new firmware not sure. Same problem if you use this driver or built in driver. They work perfect with Home Assistant so yeah I don't know. I've seen other closed posts on the forum with the same issue with no solution. No it's not a ghost thing or non s2. Might want to take it off the compatibility list. Video of the issues, I get it working around 4:00 set it to 4k so you can see
Few questions.
Are those the hubs right next to it. May want to seperate them by a little distance? Could you try seperating them by about 1m. It is my understanding to close can cause a issue.
Have you upgraded the Zwave radio to the latest firmware?
By chance do you have any zwave devices that do power reporting?.
The fact you can get it working on and off to me seems like either the device itself is locking for sone reason or there is a radio problem with communication. My keypad does lock occasionally, but they are few and far between.
They normally sit in the server rack just threw them on the desk for the video. The've never been a meter apart lol everything else works really well. One runs my Zwave one runs zigbee.
I have plenty of wave devices that can power report but the reporting is turned off.
I agree but my zwave actually works really well. I could make a video of that but that be even more boring then this video. Trust me things happen instantly, well um instantly as zwave can be. The keypad is direct not using any repeaters and as you can see in the zwave log there's no weird traffic going on.
The zwave log reports some stuff. But may not show all wonkyness.
The Zooz zen25 is a great example of a device that is know for causing strange Zwave issues and not showing anything strange in the Zwave logs. Folks can turn off power reporting, pair it without security and it will cause issues.
I Fixed the problem by disabling the proximity sensor. I guess it ended up being a driver problem after all with the latest firmware Didn't hurt anything to go over my zwave network though.
You were right. You got me thinking it more than likely has to be my network. I just forgot the advice I use to give out myself and go around the house and either pull the air gaps or unplug any repeating device. Seems to have fixed the issues . Thank you
That actually kind of makes sense. The proximity sensor has had a few changes to it made over time. Early on it was not controllable at all, and did not send any data back to HE. Then at some point it started reporting and that is when @bptworld enabled it to be used as a motion sensor. Perhaps there is some compatibility issue with it with the latest firmware version.
So you just flipped the switch in the preferences to "Disable the Proximity Sensor"?
Yep Just flipped the switch to disable the Proximity sensor. Keypads been working right since, you just have to make sure to turn the proximity sensor off when motion is inactive or else there problems. Kinda sucks because now you have to actual push a button to see system status. I'll keep one of them on HE and put the other two on HA since there's no problems using them with HA You can actually see it break in the first few seconds of my video. Drove me crazy figuring this out.
Merged, thank you!
I see the problem now.
Arm away (etc) events from the keypad are received by parseEntryControl -> armAway -> armAwayEnd
However, the Arm Away/Arm Home/Disarm buttons on the device page (provided by capability SecurityKeypad) call armAway/disarm directly.
The sendEvent armingIn that HSM subscribes to is only inside parseEntryControl.
So, the device page goes direct (never touches parseEntryControl) -- which never get the opportunity to send the armingIn event.
I moved the armingIn event inside armHomeEnd/armAwayEnd/armNightEnd/disarmEnd and all seems to work.
w00t.
Can you test this before merging ?
Seems to work.
Can you test this before merging ?
Nope, sorry. I've moved all my keypads over to a Ring hub. Feel free to branch off this driver and continue to offer it up to the community.
Nope, sorry. I've moved all my keypads over to a Ring hub.
doh! I'd appreciate if someones reading this can give it a test.
code is temporarily here
EDIT: code was merged, fingers crossed.
I’ll give it a shot. I have just one keypad but I’ll order another if this works. Thanks for working on it.
During Black Friday I almost bought more into the ring ecosystem, but I held off for another year.
I’ll reply back with an update soon.
I'm not an expert on GitHub stuff (yet, anyway) and I would hate to bust something too badly...
But, I was looking at the driver and made some changes (on my hub):
input name: "partialFunctionValue", type: "enum", title: "Home Button Action", options: [
["armHome":"Arm Home (default)"],
["armNight":"Arm Night"],
], defaultValue: "armHome", description: "After setting this, press \"Save Preferences\" below then press the \"Set Partial Function\" button above"
if (!mode) {
mode = partialFunctionValue
if (logEnable) log.debug "In setPartialFunction (${version()}) - set mode from preferences: ${mode}"
}
using this line of code:
sendEvent(name:"validCode", value: "false", isStateChange: true)
int kpstatus = status
if (kpstatus == 0x00) kpstatus = 0x0A
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:kpstatus, propertyId:2, value:0xFF]]).format())
/*
Ring Keypad Gen 2 - Community Driver
Copyright 2020 -> 2021 Hubitat Inc. All Rights Reserved
Special Thanks to Bryan Copeland (@bcopeland) for writing and releasing this code to the community!
1.2.9 - 12/04/22 - Force "validCode" false for Police, Fire, Medical buttons and when "Check Mark" codes aren't validated, add preference to allow Partial Function to be set, set the keypad status in armNightEnd
1.2.8 - 12/01/22 - Fix device page buttons by sending armingIn event in the arm/disarm subs
1.2.7 - 12/01/22 - Fix Arm Night on device page
1.2.6 - 08/05/22 - Adjusted for use with HSM. To sync keypads without using HPM, a separate app will be available in Bundle Manager (Ring Keypad Sync).
1.2.4 - 07/01/22 - Rollback to working version
1.2.2 - 06/09/22 - @dkilgore90 add "validCode" attribute and "validateCheck" preference
1.2.1 - 04/14/22 - Bug hunting
1.2.0 - 04/04/22 - Fixed Tones
---
1.0.0 - 11/11/21 - Initial Community Release
*/
import groovy.transform.Field
import groovy.json.JsonOutput
def version() {
return "1.2.8.1"
}
metadata {
definition (name: "Ring Alarm Keypad G2 Community", namespace: "hubitat", author: "Community") {
capability "Actuator"
capability "Sensor"
capability "Configuration"
capability "SecurityKeypad"
capability "Battery"
capability "Alarm"
capability "PowerSource"
capability "LockCodes"
capability "Motion Sensor"
capability "PushableButton"
capability "HoldableButton"
command "entry"
command "keypadUpdateStatus", ["string"]
command "setArmNightDelay", ["number"]
command "setArmAwayDelay", ["number"]
command "setArmHomeDelay", ["number"]
command "setArmNightDelay", ["number"]
command "setPartialFunction"
command "resetKeypad"
command "playTone", [[name: "Play Tone", type: "STRING", description: "Tone_1, Tone_2, etc."]]
command "volAnnouncement", [[name:"Announcement Volume", type:"NUMBER", description: "Volume level (1-10)"]]
command "volKeytone", [[name:"Keytone Volume", type:"NUMBER", description: "Volume level (1-10)"]]
command "volSiren", [[name:"Chime Tone Volume", type:"NUMBER", description: "Volume level (1-10)"]]
attribute "alarmStatusChangeTime", "STRING"
attribute "alarmStatusChangeEpochms", "NUMBER"
attribute "armingIn", "NUMBER"
attribute "armAwayDelay", "NUMBER"
attribute "armHomeDelay", "NUMBER"
attribute "armNightDelay", "NUMBER"
attribute "lastCodeName", "STRING"
attribute "lastCodeTime", "STRING"
attribute "lastCodeEpochms", "NUMBER"
attribute "motion", "STRING"
attribute "validCode", "ENUM", ["true", "false"]
attribute "volAnnouncement", "NUMBER"
attribute "volKeytone", "NUMBER"
attribute "volSiren", "NUMBER"
fingerprint mfr:"0346", prod:"0101", deviceId:"0301", inClusters:"0x5E,0x98,0x9F,0x6C,0x55", deviceJoinName: "Ring Alarm Keypad G2"
}
preferences {
input name: "about", type: "paragraph", element: "paragraph", title: "Ring Alarm Keypad G2 Community Driver", description: "${version()}<br>Note:<br>The first 3 Tones are alarm sounds that also flash the Red Indicator Bar on the keypads. The rest are more pleasant sounds that could be used for a variety of things."
configParams.each { input it.value.input }
input name: "theTone", type: "enum", title: "Chime tone", options: [
["Tone_1":"(Tone_1) Siren (default)"],
["Tone_2":"(Tone_2) 3 Beeps"],
["Tone_3":"(Tone_3) 4 Beeps"],
["Tone_4":"(Tone_4) Navi"],
["Tone_5":"(Tone_5) Guitar"],
["Tone_6":"(Tone_6) Windchimes"],
["Tone_7":"(Tone_7) DoorBell 1"],
["Tone_8":"(Tone_8) DoorBell 2"],
["Tone_9":"(Tone_9) Invalid Code Sound"],
], defaultValue: "Tone_1", description: ""
input name: "instantArming", type: "bool", title: "Enable set alarm without code", defaultValue: false, description: ""
input name: "validateCheck", type: "bool", title: "Validate codes submitted with checkmark", defaultValue: false, description: ""
input name: "partialFunctionValue", type: "enum", title: "Home Button Action", options: [
["armHome":"Arm Home (default)"],
["armNight":"Arm Night"],
], defaultValue: "armHome", description: "After setting this, press \"Save Preferences\" below then press the \"Set Partial Function\" button above"
input name: "proximitySensor", type: "bool", title: "Disable the Proximity Sensor", defaultValue: false, description: ""
input name: "optEncrypt", type: "bool", title: "Enable lockCode encryption", defaultValue: false, description: ""
input name: "logEnable", type: "bool", title: "Enable debug logging", defaultValue: true
input name: "txtEnable", type: "bool", title: "Enable descriptionText logging", defaultValue: true
}
}
@Field static Map configParams = [
//4: [input: [name: "configParam4", type: "enum", title: "Announcement Volume", description:"", defaultValue:7, options:[0:"0",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10"]],parameterSize:1],
//5: [input: [name: "configParam5", type: "enum", title: "Keytone Volume", description:"", defaultValue:6, options:[0:"0",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10"]],parameterSize:1],
//6: [input: [name: "configParam6", type: "enum", title: "Siren Volume", description:"", defaultValue:10, options:[0:"0",1:"1",2:"2",3:"3",4:"4",5:"5",6:"6",7:"7",8:"8",9:"9",10:"10"]],parameterSize:1],
7: [input: [name: "configParam7", type: "number", title: "Long press Emergency Duration", description:"", defaultValue: 3, range:"2..5"],parameterSize:1],
8: [input: [name: "configParam8", type: "number", title: "Long press Number pad Duration", description:"", defaultValue: 3, range:"2..5"],parameterSize:1],
12: [input: [name: "configParam12", type: "number", title: "Security Mode Brightness", description:"", defaultValue: 100, range:"0..100"],parameterSize:1],
13: [input: [name: "configParam13", type: "number", title: "Key Backlight Brightness", description:"", defaultValue: 100, range:"0..100"],parameterSize:1],
]
@Field static Map armingStates = [
0x00: [securityKeypadState: "armed night", hsmCmd: "armNight"],
0x02: [securityKeypadState: "disarmed", hsmCmd: "disarm"],
0x0A: [securityKeypadState: "armed home", hsmCmd: "armHome"],
0x0B: [securityKeypadState: "armed away", hsmCmd: "armAway"]
]
@Field static Map CMD_CLASS_VERS=[0x86:2, 0x70:1, 0x20:1, 0x86:3]
void logsOff(){
log.warn "debug logging disabled..."
device.updateSetting("logEnable", [value:"false", type:"bool"])
}
void updated() {
log.info "updated..."
log.warn "debug logging is: ${logEnable == true}"
log.warn "description logging is: ${txtEnable == true}"
log.warn "encryption is: ${optEncrypt == true}"
unschedule()
if (logEnable) runIn(1800,logsOff)
sendToDevice(runConfigs())
updateEncryption()
proximitySensorHandler()
volAnnouncement()
volKeytone()
volSiren()
}
void installed() {
initializeVars()
}
void uninstalled() {
}
void initializeVars() {
// first run only
sendEvent(name:"codeLength", value: 4)
sendEvent(name:"maxCodes", value: 100)
sendEvent(name:"lockCodes", value: "")
sendEvent(name:"armHomeDelay", value: 5)
sendEvent(name:"armAwayDelay", value: 5)
sendEvent(name:"armNightDelay", value: 5)
sendEvent(name:"volAnnouncement", value: 7)
sendEvent(name:"volKeytone", value: 5)
sendEvent(name:"volSiren", value: 75)
sendEvent(name:"securityKeypad", value:"disarmed")
state.keypadConfig=[entryDelay:5, exitDelay: 5, armNightDelay:5, armAwayDelay:5, armHomeDelay: 5, codeLength: 4, partialFunction: "armHome"]
state.keypadStatus=2
state.initialized=true
}
void resetKeypad() {
state.initialized=false
configure()
getCodes()
}
void configure() {
if (logEnable) log.debug "configure()"
if (!state.initialized) initializeVars()
if (!state.keypadConfig) initializeVars()
keypadUpdateStatus(state.keypadStatus, state.type, state.code)
runIn(5,pollDeviceData)
}
void pollDeviceData() {
List<String> cmds = []
cmds.add(zwave.versionV3.versionGet().format())
cmds.add(zwave.manufacturerSpecificV2.deviceSpecificGet(deviceIdType: 1).format())
cmds.add(zwave.batteryV1.batteryGet().format())
cmds.add(zwave.notificationV8.notificationGet(notificationType: 8, event: 0).format())
cmds.add(zwave.notificationV8.notificationGet(notificationType: 7, event: 0).format())
cmds.addAll(processAssociations())
sendToDevice(cmds)
}
void keypadUpdateStatus(Integer status,String type="digital", String code) {
int kpstatus = status
if (kpstatus == 0x00) kpstatus = 0x0A
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:kpstatus, propertyId:2, value:0xFF]]).format())
state.keypadStatus = status
if (state.code != "") { type = "physical" }
eventProcess(name: "securityKeypad", value: armingStates[status].securityKeypadState, type: type, data: state.code)
state.code = ""
state.type = "digital"
}
void armNight(delay) {
if (logEnable) log.debug "In armNight (${version()}) - delay: ${delay}"
def sk = device.currentValue("securityKeypad")
if(sk != "armed night") {
if (delay > 0 ) {
exitDelay(delay)
runIn(delay, armNightEnd)
} else {
armNightEnd()
}
} else {
if (logEnable) log.debug "In armNight - securityKeypad already set to 'armed night', so skipping."
}
}
void armNightEnd() {
if (!state.code) { state.code = "" }
if (!state.type) { state.type = "physical" }
def sk = device.currentValue("securityKeypad")
if(sk != "armed night") {
keypadUpdateStatus(0x00, state.type, state.code)
Date now = new Date()
long ems = now.getTime()
sendEvent(name:"armingIn", value: state.keypadConfig.armNightDelay, data:[armMode: armingStates[0x0B].securityKeypadState, armCmd: armingStates[0x0B].hsmCmd], isStateChange:true)
sendEvent(name:"alarmStatusChangeTime", value: "${now}", isStateChange:true)
sendEvent(name:"alarmStatusChangeEpochms", value: "${ems}", isStateChange:true)
}
}
void armAway(delay) {
if (logEnable) log.debug "In armAway (${version()}) - delay: ${delay}"
def sk = device.currentValue("securityKeypad")
if(sk != "armed away") {
if (delay > 0 ) {
exitDelay(delay)
runIn(delay, armAwayEnd)
} else {
armAwayEnd()
}
} else {
if (logEnable) log.debug "In armAway - securityKeypad already set to 'armed away', so skipping."
}
}
void armAwayEnd() {
if (!state.code) { state.code = "" }
if (!state.type) { state.type = "physical" }
def sk = device.currentValue("securityKeypad")
if(sk != "armed away") {
keypadUpdateStatus(0x0B, state.type, state.code)
Date now = new Date()
long ems = now.getTime()
sendEvent(name:"armingIn", value: state.keypadConfig.armAwayDelay, data:[armMode: armingStates[0x0B].securityKeypadState, armCmd: armingStates[0x0B].hsmCmd], isStateChange:true)
sendEvent(name:"alarmStatusChangeTime", value: "${now}", isStateChange:true)
sendEvent(name:"alarmStatusChangeEpochms", value: "${ems}", isStateChange:true)
changeStatus("set")
}
}
void armHome(delay) {
if (logEnable) log.debug "In armHome (${version()}) - delay: ${delay}"
def sk = device.currentValue("securityKeypad")
if(sk != "armed home") {
if (delay > 0) {
exitDelay(delay)
runIn(delay, armHomeEnd)
} else {
armHomeEnd()
}
} else {
if (logEnable) log.debug "In armHome - securityKeypad already set to 'armed home', so skipping."
}
}
void armHomeEnd() {
if (!state.code) { state.code = "" }
if (!state.type) { state.type = "physical" }
def sk = device.currentValue("securityKeypad")
if(sk != "armed home") {
keypadUpdateStatus(0x0A, state.type, state.code)
Date now = new Date()
long ems = now.getTime()
sendEvent(name:"armingIn", value: state.keypadConfig.armHomeDelay, data:[armMode: armingStates[0x0A].securityKeypadState, armCmd: armingStates[0x0A].hsmCmd], isStateChange:true)
sendEvent(name:"alarmStatusChangeTime", value: "${now}", isStateChange:true)
sendEvent(name:"alarmStatusChangeEpochms", value: "${ems}", isStateChange:true)
changeStatus("set")
}
}
void disarm(delay) {
if (logEnable) log.debug "In disarm (${version()}) - delay: ${delay}"
def sk = device.currentValue("securityKeypad")
if(sk != "disarmed") {
if (delay > 0 ) {
exitDelay(delay)
runIn(delay, disarmEnd)
} else {
disarmEnd()
}
} else {
if (logEnable) log.debug "In disarm - securityKeypad already set to 'disarmed', so skipping."
}
}
void disarmEnd() {
if (!state.code) { state.code = "" }
if (!state.type) { state.type = "physical" }
def sk = device.currentValue("securityKeypad")
if(sk != "disarmed") {
keypadUpdateStatus(0x02, state.type, state.code)
Date now = new Date()
long ems = now.getTime()
sendEvent(name:"armingIn", value: 0, data:[armMode: armingStates[0x02].securityKeypadState, armCmd: armingStates[0x02].hsmCmd], isStateChange:true)
sendEvent(name:"alarmStatusChangeTime", value: "${now}", isStateChange:true)
sendEvent(name:"alarmStatusChangeEpochms", value: "${ems}", isStateChange:true)
changeStatus("off")
unschedule(armHomeEnd)
unschedule(armAwayEnd)
unschedule(armNightEnd)
unschedule(changeStatus)
}
}
void exitDelay(delay){
if (logEnable) log.debug "In exitDelay (${version()}) - delay: ${delay}"
if (delay) {
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x12, propertyId:7, value:delay.toInteger()]]).format())
// update state so that a disarm command during the exit delay resets the indicator lights
state.keypadStatus = "18"
type = state.code != "" ? "physical" : "digital"
eventProcess(name: "securityKeypad", value: "exit delay", type: type, data: state.code)
}
}
def changeStatus(data) {
if (logEnable) log.debug "In changeStatus (${version()}) - data: ${data}"
sendEvent(name: "alarm", value: data, isStateChange: true)
}
void setEntryDelay(delay){
if (logEnable) log.debug "In setEntryDelay (${version()}) - delay: ${delay}"
state.keypadConfig.entryDelay = delay != null ? delay.toInteger() : 0
}
void setExitDelay(Map delays){
if (logEnable) log.debug "In setExitDelay (${version()}) - delay: ${delays}"
state.keypadConfig.exitDelay = (delays?.awayDelay ?: 0).toInteger()
state.keypadConfig.armNightDelay = (delays?.nightDelay ?: 0).toInteger()
state.keypadConfig.armHomeDelay = (delays?.homeDelay ?: 0).toInteger()
state.keypadConfig.armAwayDelay = (delays?.awayDelay ?: 0).toInteger()
}
void setExitDelay(delay){
if (logEnable) log.debug "In setExitDelay (${version()}) - delay: ${delay}"
state.keypadConfig.exitDelay = delay != null ? delay.toInteger() : 0
}
void setArmNightDelay(delay){
if (logEnable) log.debug "In setArmNightDelay (${version()}) - delay: ${delay}"
sendEvent(name:"armNightDelay", value: delay)
state.keypadConfig.armNightDelay = delay != null ? delay.toInteger() : 0
}
void setArmAwayDelay(delay){
if (logEnable) log.debug "In setArmAwayDelay (${version()}) - delay: ${delay}"
sendEvent(name:"armAwayDelay", value: delay)
state.keypadConfig.armAwayDelay = delay != null ? delay.toInteger() : 0
}
void setArmHomeDelay(delay){
if (logEnable) log.debug "In setArmHomeDelay (${version()}) - delay: ${delay}"
sendEvent(name:"armHomeDelay", value: delay)
state.keypadConfig.armHomeDelay = delay != null ? delay.toInteger() : 0
}
void setCodeLength(pincodelength) {
if (logEnable) log.debug "In setCodeLength (${version()}) - pincodelength: ${pincodelength}"
eventProcess(name:"codeLength", value: pincodelength, descriptionText: "${device.displayName} codeLength set to ${pincodelength}")
state.keypadConfig.codeLength = pincodelength
// set zwave entry code key buffer
// 6F06XX10
sendToDevice("6F06" + hubitat.helper.HexUtils.integerToHexString(pincodelength.toInteger()+1,1).padLeft(2,'0') + "0F")
}
void setPartialFunction(mode = null) {
if (logEnable) log.debug "In setPartialFunction (${version()}) - mode: ${mode}"
if (!mode) {
mode = partialFunctionValue
if (logEnable) log.debug "In setPartialFunction (${version()}) - set mode from preferences: ${mode}"
}
if ( !(mode in ["armHome","armNight"]) ) {
if (txtEnable) log.warn "custom command used by HSM"
} else if (mode in ["armHome","armNight"]) {
state.keypadConfig.partialFunction = mode == "armHome" ? "armHome" : "armNight"
}
}
// alarm capability commands
void off() {
if (logEnable) log.debug "In off (${version()})"
eventProcess(name:"alarm", value:"off")
changeStatus("off")
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:state.keypadStatus, propertyId:2, value:0xFF]]).format())
}
void both() {
if (logEnable) log.debug "In both (${version()})"
siren()
}
void siren() {
if (logEnable) log.debug "In Siren (${version()})"
eventProcess(name:"alarm", value:"siren")
changeStatus("siren")
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x0C, propertyId:2, value:0xFF]]).format())
}
void strobe() {
if (logEnable) log.debug "In strobe (${version()})"
eventProcess(name:"alarm", value:"strobe")
changeStatus("strobe")
List<String> cmds=[]
cmds.add(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x0C, propertyId:2, value:0xFF]]).format())
cmds.add(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x0C, propertyId:2, value:0x00]]).format())
sendToDevice(cmds)
}
void zwaveEvent(hubitat.zwave.commands.basicv1.BasicReport cmd) {
// this is redundant/ambiguous and I don't care what happens here
}
void parseEntryControl(Short command, List<Short> commandBytes) {
if (logEnable) log.debug "In parseEntryControl (${version()})"
//log.debug "parse: ${command}, ${commandBytes}"
if (command == 0x01) {
Map ecn = [:]
ecn.sequenceNumber = commandBytes[0]
ecn.dataType = commandBytes[1]
ecn.eventType = commandBytes[2]
ecn.eventDataLength = commandBytes[3]
def currentStatus = device.currentValue('securityKeypad')
def alarmStatus = device.currentValue('alarm')
String code=""
if (ecn.eventDataLength>0) {
for (int i in 4..(ecn.eventDataLength+3)) {
if (logEnable) log.debug "character ${i}, value ${commandBytes[i]}"
code += (char) commandBytes[i]
}
}
if (logEnable) log.debug "Entry control: ${ecn} keycache: ${code}"
switch (ecn.eventType) {
case 5: // Away Mode Button
if (logEnable) log.debug "In case 5 - Away Mode Button"
if (validatePin(code) || instantArming) {
if(currentStatus == "disarmed") {
if (logEnable) log.debug "In case 5 - Passed - currentStatus: ${currentStatus}"
state.type="physical"
if (!state.keypadConfig.armAwayDelay) { state.keypadConfig.armAwayDelay = 0 }
armAway(state.keypadConfig.armAwayDelay)
} else {
if (logEnable) log.debug "In case 5 - Failed - Please Disarm Alarm before changing alarm type - currentStatus: ${currentStatus}"
}
} else {
if (logEnable) log.debug "In case 5 - Failed - Invalid PIN - currentStatus: ${currentStatus}"
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x09, propertyId:2, value:0xFF]]).format())
}
break
case 6: // Home Mode Button
if (logEnable) log.debug "In case 6 - Home Mode Button"
if (validatePin(code) || instantArming) {
if(currentStatus == "disarmed") {
if (logEnable) log.debug "In case 6 - Passed"
state.type="physical"
if(!state.keypadConfig.partialFunction) state.keypadConfig.partialFunction="armHome"
if (state.keypadConfig.partialFunction == "armHome") {
if (logEnable) log.debug "In case 6 - Partial Passed"
if (!state.keypadConfig.armHomeDelay) { state.keypadConfig.armHomeDelay = 0 }
armHome(state.keypadConfig.armHomeDelay)
}
} else {
if(alarmStatus == "active") {
if (logEnable) log.debug "In case 6 - Silenced - Alarm will sound again in 10 seconds - currentStatus: ${currentStatus}"
changeStatus("silent")
runIn(10, changeStatus, [data:"active"])
} else {
if (logEnable) log.debug "In case 6 - Failed - Please Disarm Alarm before changing alarm type - currentStatus: ${currentStatus}"
}
}
} else {
if (logEnable) log.debug "In case 6 - Home Mode Failed - Invalid PIN - currentStatus: ${currentStatus}"
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x09, propertyId:2, value:0xFF]]).format())
}
break
case 3: // Disarm Mode Button
if (logEnable) log.debug "In case 3 - Disarm Mode Button"
if (validatePin(code)) {
if (logEnable) log.debug "In case 3 - Code Passed"
state.type="physical"
disarm()
} else {
if (logEnable) log.debug "In case 3 - Disarm Failed - Invalid PIN - currentStatus: ${currentStatus}"
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x09, propertyId:2, value:0xFF]]).format())
}
break
// Added all buttons
case 2: // Code sent after hitting the Check Mark
state.type="physical"
Date now = new Date()
long ems = now.getTime()
if(!code) code = "check mark"
if (validateCheck) {
if (validatePin(code)) {
if (logEnable) log.debug "In case 2 (check mark) - Code Passed"
} else {
if (logEnable) log.debug "In case 2 (check mark) - Code Failed - Invalid PIN - currentStatus: ${currentStatus}"
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x09, propertyId:2, value:0xFF]]).format())
}
} else {
sendEvent(name:"validCode", value: "false", isStateChange: true)
sendEvent(name:"lastCodeName", value: "${code}", isStateChange:true)
sendEvent(name:"lastCodeTime", value: "${now}", isStateChange:true)
sendEvent(name:"lastCodeEpochms", value: "${ems}", isStateChange:true)
}
break
case 17: // Police Button
state.type="physical"
Date now = new Date()
long ems = now.getTime()
sendEvent(name:"validCode", value: "false", isStateChange: true)
sendEvent(name:"lastCodeName", value: "police", isStateChange:true)
sendEvent(name:"lastCodeTime", value: "${now}", isStateChange:true)
sendEvent(name:"lastCodeEpochms", value: "${ems}", isStateChange:true)
sendEvent(name: "held", value: 11, isStateChange: true)
break
case 16: // Fire Button
state.type="physical"
Date now = new Date()
long ems = now.getTime()
sendEvent(name:"validCode", value: "false", isStateChange: true)
sendEvent(name:"lastCodeName", value: "fire", isStateChange:true)
sendEvent(name:"lastCodeTime", value: "${now}", isStateChange:true)
sendEvent(name:"lastCodeEpochms", value: "${ems}", isStateChange:true)
sendEvent(name: "held", value: 12, isStateChange: true)
break
case 19: // Medical Button
state.type="physical"
Date now = new Date()
long ems = now.getTime()
sendEvent(name:"validCode", value: "false", isStateChange: true)
sendEvent(name:"lastCodeName", value: "medical", isStateChange:true)
sendEvent(name:"lastCodeTime", value: "${now}", isStateChange:true)
sendEvent(name:"lastCodeEpochms", value: "${ems}", isStateChange:true)
sendEvent(name: "held", value: 13, isStateChange: true)
break
case 1: // Button pressed or held, idle timeout reached without explicit submission
state.type="physical"
handleButtons(code)
break
}
}
}
void handleButtons(String code) {
List<String> buttons = code.split('')
for (String btn : buttons) {
try {
int val = Integer.parseInt(btn)
sendEvent(name: "pushed", value: val, isStateChange: true)
} catch (NumberFormatException e) {
// Handle button holds here
char ch = btn
char a = 'A'
int pos = ch - a + 1
sendEvent(name: "held", value: pos, isStateChange: true)
}
}
}
void push(btn) {
state.type = "digital"
sendEvent(name: "pushed", value: btn, isStateChange: true)
}
void hold(btn) {
state.type = "digital"
sendEvent(name: "held", value: btn, isStateChange:true)
switch (btn) {
case 11:
Date now = new Date()
long ems = now.getTime()
sendEvent(name:"lastCodeName", value: "police", isStateChange:true)
sendEvent(name:"lastCodeTime", value: "${now}", isStateChange:true)
sendEvent(name:"lastCodeEpochms", value: "${ems}", isStateChange:true)
break
case 12:
Date now = new Date()
long ems = now.getTime()
sendEvent(name:"lastCodeName", value: "fire", isStateChange:true)
sendEvent(name:"lastCodeTime", value: "${now}", isStateChange:true)
sendEvent(name:"lastCodeEpochms", value: "${ems}", isStateChange:true)
break
case 13:
Date now = new Date()
long ems = now.getTime()
sendEvent(name:"lastCodeName", value: "medical", isStateChange:true)
sendEvent(name:"lastCodeTime", value: "${now}", isStateChange:true)
sendEvent(name:"lastCodeEpochms", value: "${ems}", isStateChange:true)
break
}
}
void zwaveEvent(hubitat.zwave.commands.notificationv8.NotificationReport cmd) {
Map evt = [:]
if (cmd.notificationType == 8) {
// power management
switch (cmd.event) {
case 1:
// Power has been applied
if (txtEnable) log.info "${device.displayName} Power has been applied"
break
case 2:
// AC mains disconnected
evt.name = "powerSource"
evt.value = "battery"
evt.descriptionText = "${device.displayName} AC mains disconnected"
eventProcess(evt)
break
case 3:
// AC mains re-connected
evt.name = "powerSource"
evt.value = "mains"
evt.descriptionText = "${device.displayName} AC mains re-connected"
eventProcess(evt)
break
case 12:
// battery is charging
if (txtEnable) log.info "${device.displayName} Battery is charging"
break
}
}
}
void entry(){
int intDelay = state.keypadConfig.entryDelay ? state.keypadConfig.entryDelay.toInteger() : 0
if (intDelay) entry(intDelay)
}
void entry(entranceDelay){
if (logEnable) log.debug "In entry (${version()}) - delay: ${entranceDelay}"
if (entranceDelay) {
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x11, propertyId:7, value:entranceDelay.toInteger()]]).format())
}
}
void getCodes(){
if (logEnable) log.debug "getCodes()"
updateEncryption()
}
private updateEncryption(){
String lockCodes = device.currentValue("lockCodes") //encrypted or decrypted
if (lockCodes){
if (optEncrypt && lockCodes[0] == "{") { //resend encrypted
sendEvent(name:"lockCodes",value: encrypt(lockCodes), isStateChange:true)
} else if (!optEncrypt && lockCodes[0] != "{") { //resend decrypted
sendEvent(name:"lockCodes", value: decrypt(lockCodes), isStateChange:true)
} else {
sendEvent(name:"lockCodes", value: lockCodes, isStateChange:true)
}
}
}
private Boolean validatePin(String pincode) {
boolean retVal = false
Map lockcodes = [:]
if (optEncrypt) {
try {
lockcodes = parseJson(decrypt(device.currentValue("lockCodes")))
} catch(e) {
log.warn "Ring Alarm Keypad G2 Community - No lock codes found."
}
} else {
try {
lockcodes = parseJson(device.currentValue("lockCodes"))
} catch(e) {
log.warn "Ring Alarm Keypad G2 Community - No lock codes found."
}
}
//log.debug "Lock codes: ${lockcodes}"
if(lockcodes) {
lockcodes.each {
if(it.value["code"] == pincode) {
Date now = new Date()
long ems = now.getTime()
//log.debug "found code: ${pincode} user: ${it.value['name']}"
sendEvent(name:"validCode", value: "true", isStateChange: true)
sendEvent(name:"lastCodeName", value: "${it.value['name']}", isStateChange:true)
sendEvent(name:"lastCodeTime", value: "${now}", isStateChange:true)
sendEvent(name:"lastCodeEpochms", value: "${ems}", isStateChange:true)
retVal=true
String code = JsonOutput.toJson(["${it.key}":["name": "${it.value.name}", "code": "${it.value.code}", "isInitiator": true]])
if (optEncrypt) {
state.code=encrypt(code)
} else {
state.code=code
}
}
}
}
if (!retVal) {
sendEvent(name:"validCode", value: "false", isStateChange: true)
}
return retVal
}
void setCode(codeposition, pincode, name) {
if (logEnable) log.debug "setCode(${codeposition}, ${pincode}, ${name})"
boolean newCode = true
Map lockcodes = [:]
if (device.currentValue("lockCodes") != null) {
if (optEncrypt) {
lockcodes = parseJson(decrypt(device.currentValue("lockCodes")))
} else {
lockcodes = parseJson(device.currentValue("lockCodes"))
}
}
if (lockcodes["${codeposition}"]) { newCode = false }
lockcodes["${codeposition}"] = ["code": "${pincode}", "name": "${name}"]
if (optEncrypt) {
sendEvent(name: "lockCodes", value: encrypt(JsonOutput.toJson(lockcodes)))
} else {
sendEvent(name: "lockCodes", value: JsonOutput.toJson(lockcodes), isStateChange: true)
}
if (newCode) {
sendEvent(name: "codeChanged", value:"added")
} else {
sendEvent(name: "codeChanged", value: "changed")
}
//log.debug "Lock codes: ${lockcodes}"
}
void deleteCode(codeposition) {
if (logEnable) log.debug "deleteCode(${codeposition})"
Map lockcodes=[:]
if (device.currentValue("lockCodes") != null) {
if (optEncrypt) {
lockcodes = parseJson(decrypt(device.currentValue("lockCodes")))
} else {
lockcodes = parseJson(device.currentValue("lockCodes"))
}
}
lockcodes["${codeposition}"] = [:]
lockcodes.remove("${codeposition}")
if (optEncrypt) {
sendEvent(name: "lockCodes", value: encrypt(JsonOutput.toJson(lockcodes)))
} else {
sendEvent(name: "lockCodes", value: JsonOutput.toJson(lockcodes), isStateChange: true)
}
sendEvent(name: "codeChanged", value: "deleted")
//log.debug "remove ${codeposition} Lock codes: ${lockcodes}"
}
void zwaveEvent(hubitat.zwave.commands.indicatorv3.IndicatorReport cmd) {
// Don't need to handle reports
}
// standard config
List<String> runConfigs() {
List<String> cmds = []
configParams.each { param, data ->
if (settings[data.input.name]) {
cmds.addAll(configCmd(param, data.parameterSize, settings[data.input.name]))
}
}
return cmds
}
List<String> pollConfigs() {
List<String> cmds = []
configParams.each { param, data ->
if (settings[data.input.name]) {
cmds.add(zwave.configurationV1.configurationGet(parameterNumber: param.toInteger()).format())
}
}
return cmds
}
List<String> configCmd(parameterNumber, size, scaledConfigurationValue) {
List<String> cmds = []
cmds.add(zwave.configurationV1.configurationSet(parameterNumber: parameterNumber.toInteger(), size: size.toInteger(), scaledConfigurationValue: scaledConfigurationValue.toInteger()).format())
cmds.add(zwave.configurationV1.configurationGet(parameterNumber: parameterNumber.toInteger()).format())
return cmds
}
void zwaveEvent(hubitat.zwave.commands.configurationv1.ConfigurationReport cmd) {
if(configParams[cmd.parameterNumber.toInteger()]) {
Map configParam = configParams[cmd.parameterNumber.toInteger()]
int scaledValue
cmd.configurationValue.reverse().eachWithIndex { v, index ->
scaledValue = scaledValue | v << (8 * index)
}
device.updateSetting(configParam.input.name, [value: "${scaledValue}", type: configParam.input.type])
}
}
// Battery v1
void zwaveEvent(hubitat.zwave.commands.batteryv1.BatteryReport cmd) {
Map evt = [name: "battery", unit: "%"]
if (cmd.batteryLevel == 0xFF) {
evt.descriptionText = "${device.displayName} has a low battery"
evt.value = 1
} else {
evt.value = cmd.batteryLevel
evt.descriptionText = "${device.displayName} battery is ${evt.value}${evt.unit}"
}
evt.isStateChange = true
if (txtEnable && evt.descriptionText) log.info evt.descriptionText
sendEvent(evt)
}
// MSP V2
void zwaveEvent(hubitat.zwave.commands.manufacturerspecificv2.DeviceSpecificReport cmd) {
if (logEnable) log.debug "Device Specific Report - DeviceIdType: ${cmd.deviceIdType}, DeviceIdFormat: ${cmd.deviceIdDataFormat}, Data: ${cmd.deviceIdData}"
if (cmd.deviceIdType == 1) {
String serialNumber = ""
if (cmd.deviceIdDataFormat == 1) {
cmd.deviceIdData.each { serialNumber += hubitat.helper.HexUtils.integerToHexString(it & 0xff,1).padLeft(2, '0')}
} else {
cmd.deviceIdData.each { serialNumber += (char) it }
}
device.updateDataValue("serialNumber", serialNumber)
}
}
// Version V2
void zwaveEvent(hubitat.zwave.commands.versionv3.VersionReport cmd) {
Double firmware0Version = cmd.firmware0Version + (cmd.firmware0SubVersion / 100)
Double protocolVersion = cmd.zWaveProtocolVersion + (cmd.zWaveProtocolSubVersion / 100)
if (logEnable) log.debug "Version Report - FirmwareVersion: ${firmware0Version}, ProtocolVersion: ${protocolVersion}, HardwareVersion: ${cmd.hardwareVersion}"
device.updateDataValue("firmwareVersion", "${firmware0Version}")
device.updateDataValue("protocolVersion", "${protocolVersion}")
device.updateDataValue("hardwareVersion", "${cmd.hardwareVersion}")
if (cmd.firmwareTargets > 0) {
cmd.targetVersions.each { target ->
Double targetVersion = target.version + (target.subVersion / 100)
device.updateDataValue("firmware${target.target}Version", "${targetVersion}")
}
}
}
// Association V2
List<String> setDefaultAssociation() {
List<String> cmds = []
cmds.add(zwave.associationV2.associationSet(groupingIdentifier: 1, nodeId: zwaveHubNodeId).format())
cmds.add(zwave.associationV2.associationGet(groupingIdentifier: 1).format())
return cmds
}
List<String> processAssociations(){
List<String> cmds = []
cmds.addAll(setDefaultAssociation())
return cmds
}
void zwaveEvent(hubitat.zwave.commands.associationv2.AssociationReport cmd) {
List<String> temp = []
if (cmd.nodeId != []) {
cmd.nodeId.each {
temp.add(it.toString().format( '%02x', it.toInteger() ).toUpperCase())
}
}
if (logEnable) log.debug "Association Report - Group: ${cmd.groupingIdentifier}, Nodes: $temp"
}
// event filter
void eventProcess(Map evt) {
if (txtEnable && evt.descriptionText) log.info evt.descriptionText
if (device.currentValue(evt.name).toString() != evt.value.toString()) {
sendEvent(evt)
}
}
// universal
void zwaveEvent(hubitat.zwave.Command cmd) {
if (logEnable) log.debug "skip:${cmd}"
}
void zwaveEvent(hubitat.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
hubitat.zwave.Command encapsulatedCommand = cmd.encapsulatedCommand(CMD_CLASS_VERS)
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
}
}
void zwaveEvent(hubitat.zwave.commands.supervisionv1.SupervisionGet cmd) {
if (logEnable) log.debug "Supervision Get - SessionID: ${cmd.sessionID}, CC: ${cmd.commandClassIdentifier}, Command: ${cmd.commandIdentifier}"
if (cmd.commandClassIdentifier == 0x6F) {
parseEntryControl(cmd.commandIdentifier, cmd.commandByte)
} else {
hubitat.zwave.Command encapsulatedCommand = cmd.encapsulatedCommand(CMD_CLASS_VERS)
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
}
}
// device quirk requires this to be unsecure reply
sendToDevice(zwave.supervisionV1.supervisionReport(sessionID: cmd.sessionID, reserved: 0, moreStatusUpdates: false, status: 0xFF, duration: 0).format())
}
void parse(String description) {
if (logEnable) log.debug "parse - ${description}"
ver = getDataValue("firmwareVersion")
if(ver >= "1.18") {
if(description.contains("6C01") && description.contains("FF 07 08 00")) {
sendEvent(name:"motion", value: "active", isStateChange:true)
} else if(description.contains("6C01") && description.contains("FF 07 00 01 08")) {
sendEvent(name:"motion", value: "inactive", isStateChange:true)
}
}
hubitat.zwave.Command cmd = zwave.parse(description, CMD_CLASS_VERS)
if (cmd) {
zwaveEvent(cmd)
}
}
void sendToDevice(List<String> cmds, Long delay=300) {
sendHubCommand(new hubitat.device.HubMultiAction(commands(cmds, delay), hubitat.device.Protocol.ZWAVE))
}
void sendToDevice(String cmd, Long delay=300) {
sendHubCommand(new hubitat.device.HubAction(zwaveSecureEncap(cmd), hubitat.device.Protocol.ZWAVE))
}
List<String> commands(List<String> cmds, Long delay=300) {
return delayBetween(cmds.collect{ zwaveSecureEncap(it) }, delay)
}
void proximitySensorHandler() {
if(proximitySensor) {
if (logEnable) log.debug "Turning the Proximity Sensor OFF"
sendToDevice(new hubitat.zwave.commands.configurationv1.ConfigurationSet(parameterNumber: 15, size: 1, scaledConfigurationValue: 0).format())
} else {
if (logEnable) log.debug "Turning the Proximity Sensor ON"
sendToDevice(new hubitat.zwave.commands.configurationv1.ConfigurationSet(parameterNumber: 15, size: 1, scaledConfigurationValue: 1).format())
}
}
def volAnnouncement(newVol=null) {
if (logEnable) log.debug "In volAnnouncement (${version()}) - newVol: ${newVol}"
if(newVol) {
def currentVol = device.currentValue('volAnnouncement')
if(newVol.toString() == currentVol.toString()) {
if (logEnable) log.debug "Announcement Volume hasn't changed, so skipping"
} else {
if (logEnable) log.debug "Setting the Announcement Volume to $newVol"
nVol = newVol.toInteger()
sendToDevice(new hubitat.zwave.commands.configurationv1.ConfigurationSet(parameterNumber: 4, size: 1, scaledConfigurationValue: nVol).format())
sendEvent(name:"volAnnouncement", value: newVol, isStateChange:true)
}
} else {
if (logEnable) log.debug "Announcement value not specified, so skipping"
}
}
def volKeytone(newVol=null) {
if (logEnable) log.debug "In volKeytone (${version()}) - newVol: ${newVol}"
if(newVol) {
def currentVol = device.currentValue('volKeytone')
if(newVol.toString() == currentVol.toString()) {
if (logEnable) log.debug "Keytone Volume hasn't changed, so skipping"
} else {
if (logEnable) log.debug "Setting the Keytone Volume to $newVol"
nVol = newVol.toInteger()
sendToDevice(new hubitat.zwave.commands.configurationv1.ConfigurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: nVol).format())
sendEvent(name:"volKeytone", value: newVol, isStateChange:true)
}
} else {
if (logEnable) log.debug "Keytone value not specified, so skipping"
}
}
def volSiren(newVol=null) {
if (logEnable) log.debug "In volSiren (${version()}) - newVol: ${newVol}"
if(newVol) {
def currentVol = device.currentValue('volSiren')
if(newVol.toString() == currentVol.toString()) {
if (logEnable) log.debug "Siren Volume hasn't changed, so skipping"
def sVol = currentVol.toInteger() * 10
} else {
if (logEnable) log.debug "Setting the Siren Volume to $newVol"
sVol = newVol.toInteger() * 10
sendToDevice(new hubitat.zwave.commands.configurationv1.ConfigurationSet(parameterNumber: 6, size: 1, scaledConfigurationValue: sVol).format())
sendEvent(name:"volSiren", value: newVol, isStateChange:true)
}
} else {
def currentVol = device.currentValue('volSiren')
if(currentVol) {
sVol = currentVol.toInteger() * 10
} else {
sVol = 90
}
}
return sVol
}
def playTone(tone=null) {
volSiren()
if (logEnable) log.debug "In playTone (${version()}) - tone: ${tone} at Volume: ${sVol}"
if(!tone) {
tone = theTone
if (logEnable) log.debug "In playTone - Tone is NULL, so setting tone to theTone: ${tone}"
}
if(tone == "Tone_1") {
if (logEnable) log.debug "In playTone - Tone 1" // Siren
changeStatus("active")
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x0C, propertyId:2, value:sVol]]).format())
} else if(tone == "Tone_2") {
if (logEnable) log.debug "In playTone - Tone 2" // 3 chirps
changeStatus("active")
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x0E, propertyId:2, value:sVol]]).format())
} else if(tone == "Tone_3") {
if (logEnable) log.debug "In playTone - Tone 3" // 4 chirps
changeStatus("active")
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x0F, propertyId:2, value:sVol]]).format())
} else if(tone == "Tone_4") {
if (logEnable) log.debug "In playTone - Tone 4" // Navi
changeStatus("active")
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x60, propertyId:0x09, value:sVol]]).format())
} else if(tone == "Tone_5") {
if (logEnable) log.debug "In playTone - Tone 5" // Guitar
changeStatus("active")
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x61, propertyId:0x09, value:sVol]]).format())
} else if(tone == "Tone_6") {
if (logEnable) log.debug "In playTone - Tone 6" // Windchimes
changeStatus("active")
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x62, propertyId:0x09, value:sVol]]).format())
} else if(tone == "Tone_7") {
if (logEnable) log.debug "In playTone - Tone 7" // Doorbell 1
changeStatus("active")
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x63, propertyId:0x09, value:sVol]]).format())
} else if(tone == "Tone_8") {
if (logEnable) log.debug "In playTone - Tone 8" // Doorbell 2
changeStatus("active")
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x64, propertyId:0x09, value:sVol]]).format())
} else if(tone == "Tone_9") {
if (logEnable) log.debug "In playTone - Tone 9" // Invalid Code Sound
changeStatus("active")
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x09, propertyId:0x01, value:sVol]]).format())
} else if(tone == "test") {
if (logEnable) log.debug "In playTone - test" // test
changeStatus("active")
//sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x61, propertyId:0x09, value:0xFF]]).format())
//pauseExecution(5000)
sendToDevice(zwave.indicatorV3.indicatorSet(indicatorCount:1, value: 0, indicatorValues:[[indicatorId:0x61, propertyId:0x09, value:sVol]]).format())
}
}
I have a few questions about that driver...
I can't tell what the "Keypad Update Status" function does. It accepts a string from the device page and appears to call the "keypadUpdateStatus" function in the driver--but that function expects 3 parameters (an integer and 2 strings). Not sure it could possibly work as-is??
I don't understand why the "armNightEnd" function isn't calling the "keypadUpdateStatus" function (like all the other arm/disarm functions). In my code above, I tried something, guessing that the "0x00" code that HSM likes wasn't valid for the Ring Keypad--so I sent the "0x0A" code to the keypad and retained the "0x00" code for the "event" that HSM should handle.
Thoughts?