Compare commits

...

11 Commits

Author SHA1 Message Date
Vincent Romo
0c6cc43347 MSA-2048: chime 2017-06-21 20:23:03 -07:00
Vinay Rao
513e44912c Merge pull request #2109 from SmartThingsCommunity/staging
Rolling down staging to master
2017-06-20 11:38:53 -07:00
Vinay Rao
6e1701f955 Merge pull request #2106 from larsfinander/DVCSMP-2703_OpenT2T_Update_6_20_submission_staging
DVCSMP-2703 OpenT2T: Update to 6/20 submission
2017-06-20 09:09:52 -07:00
Lars Finander
9f5378c2b6 DVCSMP-2703 OpenT2T: Update to 6/20 submission 2017-06-20 10:06:23 -06:00
Vinay Rao
39e828b16d Merge pull request #2105 from SmartThingsCommunity/staging
Rolling down staging to master
2017-06-19 18:32:03 -07:00
Jack Chi
91a77afb2d Merge pull request #2099 from pchomal/aeon_keyfob_hc
[DHF-14] Health Check Aeon Key Fob
2017-06-19 11:19:17 -07:00
Jack Chi
006ffa8a0b Merge pull request #2098 from pchomal/aeon_minimote_hc
[DHF-15] Health Check Aeon Minimote
2017-06-19 11:19:01 -07:00
piyush.c
17465c87c0 [DHF-14] Health Check Aeon Key Fob 2017-06-19 18:12:28 +05:30
piyush.c
370b435874 [DHF-15] Health Check Aeon Minimote 2017-06-19 18:02:29 +05:30
David Hastings
be9bdae4cc Merge pull request #2094 from unixbeast/iotevent_786
IOTEVENT-786 check for null/empty values before sending events
2017-06-16 14:49:19 -05:00
Dave Hastings
c278e035f6 IOTEVENT-786 check for null/empty values before sending events 2017-06-15 14:44:14 -05:00
8 changed files with 908 additions and 9 deletions

View File

@@ -0,0 +1,813 @@
/**
* Zooz Smart Chime v1.2.1
* (Model: ZSE33)
*
* Author:
* Kevin LaFramboise (krlaframboise)
*
* URL to documentation: https://community.smartthings.com/t/release-zooz-smart-chime/77152?u=krlaframboise
*
*
* Changelog:
*
* 1.2.1 (04/23/2017)
* - SmartThings broke parse method response handling so switched to sendhubaction.
* - Bug fix for location timezone issue.
*
* 1.2 (04/14/2017)
* - Added Switch Level capability
*
* 1.1 (02/19/2017)
* - Added Health Check and self polling.
*
* 1.0 (01/16/2017)
* - Initial Release
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
metadata {
definition (
name: "Zooz Smart Chime",
namespace: "krlaframboise",
author: "Kevin LaFramboise"
) {
capability "Actuator"
capability "Alarm"
capability "Battery"
capability "Configuration"
capability "Refresh"
capability "Switch"
capability "Tone"
capability "Health Check"
capability "Polling"
capability "Switch Level"
attribute "lastCheckin", "string"
attribute "status", "enum", ["alarm", "beep", "off", "on", "custom"]
command "customChime"
fingerprint deviceId: "0x1005", inClusters: "0x25, 0x59, 0x5A, 0x5E, 0x70, 0x71, 0x72, 0x73, 0x80, 0x85, 0x86, 0x87"
fingerprint mfr:"027A", prod:"0003", model:"0088"
}
simulator { }
preferences {
input "sirenSound", "number",
title: "Siren Sound [1-10]:",
range: "1..10",
displayDuringSetup: true,
defaultValue: sirenSoundSetting
input "sirenVolume", "number",
title: "Siren Volume [1-3]:${getNameValueSettingDesc(volumeOptions)}",
range: "1..3",
required: false,
defaultValue: sirenVolumeSetting,
displayDuringSetup: true
input "sirenLength", "number",
title: "Siren Length [0-4]:${getNameValueSettingDesc(sirenLengthOptions)}",
range: "0..4",
defaultValue: sirenLengthSetting,
required: false,
displayDuringSetup: true
input "sirenLED", "number",
title: "Siren LED [0-1]:${getNameValueSettingDesc(ledOptions)}",
range: "0..1",
defaultValue: sirenLEDSetting,
required: false,
displayDuringSetup: true
input "onChimeSound", "number",
title: "Switch On Chime Sound [1-10]:",
range: "1..10",
required: false,
displayDuringSetup: true,
defaultValue: onChimeSoundSetting
input "beepChimeSound", "number",
title: "Beep Chime Sound [1-10]:",
range: "1..10",
required: false,
displayDuringSetup: true,
defaultValue: beepChimeSoundSetting
input "chimeVolume", "number",
title: "Chime Volume [1-3]:${getNameValueSettingDesc(volumeOptions)}",
range: "1..3",
required: false,
defaultValue: chimeVolumeSetting,
displayDuringSetup: true
input "chimeRepeat", "number",
title: "Chime Repeat [1-255]:\n(1-254 = # of Cycles)\n(255 = ${noLengthMsg})",
range: "1..255",
required: false,
displayDuringSetup: true,
defaultValue: chimeRepeatSetting
input "chimeLED", "number",
title: "Chime LED [0-1]:${getNameValueSettingDesc(ledOptions)}",
range: "0..1",
defaultValue: chimeLEDSetting,
required: false,
displayDuringSetup: true
input "checkinInterval", "enum",
title: "Checkin Interval:",
defaultValue: checkinIntervalSetting,
required: false,
displayDuringSetup: true,
options: checkinIntervalOptions.collect { it.name }
input "debugOutput", "bool",
title: "Enable debug logging?",
defaultValue: true,
required: false
}
tiles(scale: 2) {
multiAttributeTile(name:"status", type: "generic", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.status", key: "PRIMARY_CONTROL") {
attributeState "off",
label:'Off',
action: "off",
icon: "st.Entertainment.entertainment2",
backgroundColor:"#ffffff"
attributeState "on",
label:'Chime (On)!',
action: "off",
icon:"st.Entertainment.entertainment2",
backgroundColor: "#99c2ff"
attributeState "alarm",
label:'Siren!',
action: "off",
icon:"st.alarm.alarm.alarm",
backgroundColor:"#ff9999"
attributeState "beep",
label:'Chime (Beep)!',
action: "off",
icon:"st.Entertainment.entertainment2",
backgroundColor:"#99ff99"
attributeState "custom",
label:'Chime (Custom)!',
action: "off",
icon:"st.Entertainment.entertainment2",
backgroundColor:"#cc99cc"
}
}
standardTile("playAlarm", "device.alarm", width: 2, height: 2) {
state "default",
label:'Alarm',
action:"alarm.both",
icon:"st.security.alarm.clear",
backgroundColor:"#ff9999"
state "both",
label:'Turn Off',
action:"alarm.off",
icon:"st.alarm.alarm.alarm",
background: "#ffffff"
}
standardTile("playOn", "device.switch", width: 2, height: 2) {
state "default",
label:'Turn On',
action:"switch.on",
icon:"st.Entertainment.entertainment2",
backgroundColor:"#99c2ff"
state "on",
label:'Turn Off',
action:"switch.off",
icon:"st.Entertainment.entertainment2",
background: "#ffffff"
}
standardTile("playBeep", "device.status", width: 2, height: 2) {
state "default",
label:'Beep',
action:"tone.beep",
icon:"st.Entertainment.entertainment2",
backgroundColor: "#99FF99"
state "beep",
label:'Stop',
action:"off",
icon:"st.Entertainment.entertainment2",
background: "#ffffff"
}
standardTile("turnOff", "device.off", width: 2, height: 2) {
state "default",
label:'Off',
action:"switch.off",
backgroundColor: "#ffffff"
}
standardTile("refresh", "device.refresh", width: 2, height: 2) {
state "refresh", label:'Refresh', action: "refresh", icon:"st.secondary.refresh-icon"
}
valueTile("battery", "device.battery", decoration: "flat", width: 2, height: 2){
state "battery", label:'${currentValue}% battery', unit:""
}
main "status"
details(["status", "playOn", "playBeep", "playAlarm", "turnOff", "refresh", "battery"])
}
}
def updated() {
// This method always gets called twice when preferences are saved.
if (!isDuplicateCommand(state.lastUpdated, 3000)) {
state.lastUpdated = new Date().time
state.activeEvents = []
logTrace "updated()"
initializeCheckin()
if (state.firstUpdate == false) {
def result = []
result += configure()
if (result) {
return sendResponse(result)
}
}
else {
// Skip first time updating because it calls the configure method while it's already running.
state.firstUpdate = false
}
}
}
private sendResponse(cmds) {
def actions = []
cmds?.each { cmd ->
actions << new physicalgraph.device.HubAction(cmd)
}
sendHubCommand(actions)
return []
}
private initializeCheckin() {
// Set the Health Check interval so that it pings the device if it's 1 minute past the scheduled checkin.
def checkInterval = ((checkinIntervalSettingMinutes * 60) + 60)
sendEvent(name: "checkInterval", value: checkInterval, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
unschedule(healthPoll)
switch (checkinIntervalSettingMinutes) {
case 5:
runEvery5Minutes(healthPoll)
break
case 10:
runEvery10Minutes(healthPoll)
break
case 15:
runEvery15Minutes(healthPoll)
break
case 30:
runEvery30Minutes(healthPoll)
break
case [60, 120]:
runEvery1Hour(healthPoll)
break
default:
runEvery3Hours(healthPoll)
}
}
def healthPoll() {
logTrace "healthPoll()"
sendHubCommand([new physicalgraph.device.HubAction(batteryGetCmd())], 100)
}
def ping() {
logTrace "ping()"
if (canCheckin()) {
logDebug "Attempting to ping device."
// Restart the polling schedule in case that's the reason why it's gone too long without checking in.
initializeCheckin()
return poll()
}
}
def poll() {
if (canCheckin()) {
logTrace "Polling Device"
return batteryGetCmd()
}
else {
logTrace "Skipped Poll"
}
}
def configure() {
logTrace "configure()"
def cmds = []
def refreshAll = (!state.isConfigured || state.pendingRefresh || !settings?.sirenSound)
if (!state.isConfigured) {
logTrace "Waiting 1 second because this is the first time being configured"
cmds << "delay 1000"
}
configData.each {
cmds += updateConfigVal(it.paramNum, it.value, refreshAll)
}
if (refreshAll) {
cmds << switchBinaryGetCmd()
cmds << batteryGetCmd()
}
if (cmds) {
logDebug "Sending configuration to device."
return delayBetween(cmds, 250)
}
else {
return cmds
}
}
private updateConfigVal(paramNum, val, refreshAll) {
def result = []
def configVal = state["configVal${paramNum}"]
if (refreshAll || (configVal != val)) {
result << configSetCmd(paramNum, val)
result << configGetCmd(paramNum)
}
return result
}
def off() {
logDebug "Turning Off()"
return sirenToggleCmds(0x00)
}
def on() {
logDebug "Playing On Chime (#${onChimeSoundSetting})"
addPendingSound("switch", "on")
return chimePlayCmds(onChimeSoundSetting)
}
def setLevel(level, rate=null) {
logTrace "Executing setLevel($level)"
if (!device.currentValue("level")) {
sendEvent(name:"level", value:0, displayed:false)
}
return customChime(extractSoundFromLevel(level))
}
private extractSoundFromLevel(level) {
def sound = safeToInt(level, 1)
if (sound <= 10) {
return 1
}
else {
if ((sound % 10) != 0) {
sound = (sound - (sound % 10))
}
return (sound / 10)
}
}
def beep() {
logDebug "Playing Beep Chime (#${beepChimeSoundSetting})"
addPendingSound("status", "beep")
return chimePlayCmds(beepChimeSoundSetting)
}
def customChime(sound) {
def val = validateSound(sound, beepChimeSoundSetting)
if ("${sound}" != "${val}") {
logDebug "Playing Custom Chime (#${val}) - (${sound} is not a valid sound number)"
}
else {
logDebug "Playing Custom Chime (#${val})"
}
addPendingSound("status", "custom")
return chimePlayCmds(val)
}
def siren() { return both() }
def strobe() { return both() }
def both() {
logDebug "Playing Siren (#${sirenSoundSetting})"
addPendingSound("alarm", "both")
if (sirenLengthSetting == 0) {
// Siren Length is set to chime.
return chimePlayCmds(sirenSoundSetting)
}
else {
def result = []
result += sirenToggleCmds(0xFF)
return result
}
}
private addPendingSound(name, value) {
state.pendingSound = [name: "$name", value: "$value", time: new Date().time]
}
def refresh() {
logTrace "refresh()"
state.pendingRefresh = true
return configure()
}
def parse(String description) {
def result = []
if (description.startsWith("Err")) {
log.warn "Parse Error: $description"
result << createEvent(descriptionText: "$device.displayName $description", isStateChange: true)
}
else {
def cmd = zwave.parse(description, getCommandClassVersions())
if (cmd) {
result += zwaveEvent(cmd)
}
else {
logDebug "Unable to parse description: $description"
}
}
if (canCheckin()) {
result << createLastCheckinEvent()
}
return result
}
private getCommandClassVersions() {
[
0x59: 1, // AssociationGrpInfo
0x5A: 1, // DeviceResetLocally
0x5E: 2, // ZwaveplusInfo
0x70: 1, // Configuration
0x71: 3, // Notification v4
0x72: 2, // ManufacturerSpecific
0x73: 1, // Powerlevel
0x80: 1, // Battery
0x85: 2, // Association
0x86: 1, // Version (2)
0x87: 1, // Indicator
0x25: 1, // Switch Binary
]
}
private canCheckin() {
def minimumCheckinInterval = ((checkinIntervalSettingMinutes * 60 * 1000) - 5000)
return (!state.lastCheckinTime || ((new Date().time - state.lastCheckinTime) >= minimumCheckinInterval))
}
private createLastCheckinEvent() {
logDebug "Device Checked In"
state.lastCheckinTime = new Date().time
return createEvent(name: "lastCheckin", value: convertToLocalTimeString(new Date()), displayed: false)
}
private convertToLocalTimeString(dt) {
def timeZoneId = location?.timeZone?.ID
if (timeZoneId) {
return dt.format("MM/dd/yyyy hh:mm:ss a", TimeZone.getTimeZone(timeZoneId))
}
else {
return "$dt"
}
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
logTrace "BatteryReport: $cmd"
def isNew = (device.currentValue("battery") != cmd.batteryLevel)
def val = (cmd.batteryLevel == 0xFF ? 1 : cmd.batteryLevel)
def result = []
result << createEvent(name: "battery", value: val, unit: "%", displayed: isNew, isStateChange: true)
return result
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
def name = configData.find { it.paramNum == cmd.parameterNumber }?.name
if (name) {
def val = cmd.configurationValue[0]
logDebug "${name} = ${val}"
state."configVal${cmd.parameterNumber}" = val
}
else {
logDebug "Parameter ${cmd.parameterNumber}: ${cmd.configurationValue}"
}
state.isConfigured = true
state.pendingRefresh = false
return []
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
def result = []
logTrace "BasicReport: ${cmd}"
if (cmd.value == 0x00) {
result += handleDeviceOff()
}
else {
result += sendResponse(["delay 3000", basicGetCmd()])
}
return result
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
def result = []
logTrace "SwitchBinaryReport: ${cmd}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.notificationv3.NotificationReport cmd) {
def result = []
logTrace "NotificationReport: ${cmd}"
if (cmd.notificationType == 14) {
if (cmd.event == 0) {
result += handleDeviceOff()
}
else if (cmd.event == 1) {
result += handleDeviceOn(state.activeSound, state.pendingSound)
}
}
return result
}
private handleDeviceOn(activeSound, pendingSound) {
def result = []
def activeSoundName = activeSound?.name
state.activeSound = pendingSound
if (pendingSound) {
result << createEvent(getEventMap(pendingSound, true))
def statusVal = ""
if (pendingSound.name == "alarm") {
statusVal = "alarm"
}
else if (pendingSound.name == "switch") {
statusVal = "on"
}
if (statusVal) {
result << createEvent(getStatusEventMap(statusVal))
}
}
else {
logTrace "Unable to create event on because the pending sound has not been set."
}
return result
}
private handleDeviceOff() {
def result = []
["alarm", "switch", "status"].each { n ->
def displayed = false
if ("${n}" == "${state.activeSound?.name}") {
// Only the active event was initially displayed so it's the only off event that gets displayed.
displayed = true
state.activeSound = null
}
result << createEvent(getEventMap([name: "$n", value: "off"], displayed))
}
return result
}
private getStatusEventMap(val) {
return getEventMap([name: "status", value: val], false)
}
private getEventMap(event, displayed=false) {
def isStateChange = (device.currentValue(event.name) != event.value)
def eventMap = [
name: event.name,
value: event.value,
displayed: displayed,
isStateChange: true
]
logTrace "Creating Event: ${eventMap}"
return eventMap
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
logDebug "Unhandled Command: $cmd"
return []
}
private chimePlayCmds(sound) {
def cmds = []
cmds << indicatorSetCmd(sound)
if ((sound in [1, 9, 10]) && chimeRepeatSetting == 1) {
// Fixes problem where these sounds stop playing before the start events are created causing the off events to never get created.
cmds << basicGetCmd()
cmds << "delay 3000"
}
return cmds
}
private indicatorSetCmd(val) {
return zwave.indicatorV1.indicatorSet(value: val).format()
}
private sirenToggleCmds(val) {
return [
switchBinarySetCmd(val),
switchBinaryGetCmd()
]
}
private switchBinaryGetCmd() {
return zwave.switchBinaryV1.switchBinaryGet().format()
}
private switchBinarySetCmd(val) {
return zwave.switchBinaryV1.switchBinarySet(switchValue: val).format()
}
private basicGetCmd() {
return zwave.basicV1.basicGet().format()
}
private batteryGetCmd() {
return zwave.batteryV1.batteryGet().format()
}
private configGetCmd(paramNum) {
return zwave.configurationV1.configurationGet(parameterNumber: paramNum).format()
}
private configSetCmd(paramNum, val) {
return zwave.configurationV1.configurationSet(parameterNumber: paramNum, size: 1, scaledConfigurationValue: val).format()
}
// Configuration Parameters
private getConfigData() {
// [paramNum: 6, name: "Chime Sound"]
return [
[paramNum: 5, name: "Siren Sound", value: sirenSoundSetting],
[paramNum: 1, name: "Siren Volume", value: sirenVolumeSetting],
[paramNum: 2, name: "Siren Length", value: (sirenLengthSetting == 4 ? 255 : sirenLengthSetting)],
[paramNum: 8, name: "Siren LED", value: sirenLEDSetting],
[paramNum: 4, name: "Chime Volume", value: chimeVolumeSetting],
[paramNum: 3, name: "Chime Repeat", value: chimeRepeatSetting],
[paramNum: 9, name: "Chime LED", value: chimeLEDSetting],
[paramNum: 7, name: "Chime Mode", value: chimeModeSetting]
]
}
// Settings
private getDebugOutputSetting() {
return (settings?.debugOutput != false)
}
private getSirenSoundSetting() {
return validateSound(settings?.sirenSound, 9)
}
private getSirenVolumeSetting() {
return safeToInt(settings?.sirenVolume, 3)
}
private getSirenLengthSetting() {
return safeToInt(settings?.sirenLength, 0)
}
private getSirenLEDSetting() {
return safeToInt(settings?.sirenLED, 1)
}
private getOnChimeSoundSetting() {
return validateSound(settings?.onChimeSound, 1)
}
private getBeepChimeSoundSetting() {
return validateSound(settings?.beepChimeSound, 3)
}
private getChimeVolumeSetting() {
return safeToInt(settings?.chimeVolume, 3)
}
private getChimeRepeatSetting() {
return safeToInt(settings?.chimeRepeat, 1)
}
private getChimeLEDSetting() {
return safeToInt(settings?.chimeLED, 0)
}
private getChimeModeSetting() {
return 1 // Chime Mode should always be disabled.
}
private getCheckinIntervalSettingMinutes() {
return convertOptionSettingToInt(checkinIntervalOptions, checkinIntervalSetting)
}
private getCheckinIntervalSetting() {
return settings?.checkinInterval ?: findDefaultOptionName(checkinIntervalOptions)
}
private validateSound(sound, defaultVal) {
def val = safeToInt(sound, defaultVal)
if (val > 10) {
val = 10
}
else if (val < 1) {
val = 1
}
return val
}
private getVolumeOptions() {
[
[name: "Low", value: 1],
[name: "Medium", value: 2],
[name: "High", value: 3]
]
}
private getLedOptions() {
[
[name: "Off", value: 0],
[name: "On", value: 1]
]
}
private getSirenLengthOptions() {
[
[name: "Chime", value: 0],
[name: "30 Seconds", value: 1],
[name: "1 Minute", value: 2],
[name: "5 Minutes", value: 3],
[name: "${noLengthMsg}", value: 4] // config value is 255
]
}
private getNoLengthMsg() {
return "Play until battery is depleted"
}
private getNameValueSettingDesc(nameValueMap) {
def desc = ""
nameValueMap?.sort { it.value }.each {
desc = "${desc}\n(${it.value} - ${it.name})"
}
return desc
}
private getCheckinIntervalOptions() {
[
[name: "5 Minutes", value: 5],
[name: "10 Minutes", value: 10],
[name: "15 Minutes", value: 15],
[name: "30 Minutes", value: 30],
[name: "1 Hour", value: 60],
[name: "2 Hours", value: 120],
[name: "3 Hours", value: 180],
[name: "6 Hours", value: 360],
[name: "9 Hours", value: 540],
[name: formatDefaultOptionName("12 Hours"), value: 720],
[name: "18 Hours", value: 1080],
[name: "24 Hours", value: 1440]
]
}
private convertOptionSettingToInt(options, settingVal) {
return safeToInt(options?.find { "${settingVal}" == it.name }?.value, 0)
}
private formatDefaultOptionName(val) {
return "${val}${defaultOptionSuffix}"
}
private findDefaultOptionName(options) {
def option = options?.find { it.name?.contains("${defaultOptionSuffix}") }
return option?.name ?: ""
}
private getDefaultOptionSuffix() {
return " (Default)"
}
private safeToInt(val, defaultVal=-1) {
return "${val}"?.isInteger() ? "${val}".toInteger() : defaultVal
}
private isDuplicateCommand(lastExecuted, allowedMil) {
!lastExecuted ? false : (lastExecuted + allowedMil > new Date().time)
}
private logDebug(msg) {
if (debugOutputSetting) {
log.debug "$msg"
}
}
private logTrace(msg) {
// log.trace "$msg"
}

View File

@@ -0,0 +1,2 @@
.st-ignore
README.md

View File

@@ -0,0 +1,34 @@
# Aeon Labs Key Fob
Cloud Execution
Works with:
* [Aeon Labs Key Fob](http://aeotec.com/z-wave-key-fob-remote-control)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Troubleshooting](#troubleshooting)
## Capabilities
* **Actuator** - represents device has commands
* **Button** - represents a device with one or more buttons
* **Holdable Button** - represents a device with one or more holdable buttons
* **Configuration** - allows for configuration of devices
* **Sensor** - detects sensor events
* **Battery** - defines device uses a battery
* **Health Check** - indicates ability to get device health notifications
## Device Health
Aeon Key Fob is a ZWave totally sleepy device and is marked offline only in the case when Hub is offline.
## Troubleshooting
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the sensor is out of range.
Pairing needs to be tried again by placing the sensor closer to the hub.
Instructions related to pairing, resetting and removing the Aeon Labs Key Fob from SmartThings can be found in the following link:
* [Aeotec Key Fob Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202294120-Aeon-Labs-Key-Fob)

View File

@@ -1,3 +1,4 @@
import groovy.json.JsonOutput
/**
* Copyright 2015 SmartThings
*
@@ -19,6 +20,7 @@ metadata {
capability "Configuration"
capability "Sensor"
capability "Battery"
capability "Health Check"
fingerprint deviceId: "0x0101", inClusters: "0x86,0x72,0x70,0x80,0x84,0x85"
fingerprint mfr: "0086", prod: "0001", model: "0026", deviceJoinName: "Aeon Panic Button"
@@ -131,6 +133,9 @@ def updated() {
}
def initialize() {
// Arrival sensors only goes OFFLINE when Hub is off
sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "zigbee", scheme:"untracked"]), displayed: false)
def zwMap = getZwaveInfo()
def buttons = 4 // Default for Key Fob

View File

@@ -0,0 +1,2 @@
.st-ignore
README.md

View File

@@ -0,0 +1,33 @@
# Aeon Minimote
Cloud Execution
Works with:
* [Aeotec Minimote](http://aeotec.com/small-z-wave-remote-control)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Troubleshooting](#troubleshooting)
## Capabilities
* **Actuator** - represents device has commands
* **Button** - represents a device with one or more buttons
* **Holdable Button** - represents a device with one or more holdable buttons
* **Configuration** - allows for configuration of devices
* **Sensor** - detects sensor events
* **Health Check** - indicates ability to get device health notifications
## Device Health
Aeon Minimote is a ZWave totally sleepy device and is marked offline only in the case when Hub is offline.
## Troubleshooting
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the sensor is out of range.
Pairing needs to be tried again by placing the sensor closer to the hub.
Instructions related to pairing, resetting and removing the Aeotec Minimote from SmartThings can be found in the following link:
* [Aeotec Minimote Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202087904-Aeotec-Minimote)

View File

@@ -1,3 +1,4 @@
import groovy.json.JsonOutput
/**
* Copyright 2015 SmartThings
*
@@ -18,6 +19,7 @@ metadata {
capability "Holdable Button"
capability "Configuration"
capability "Sensor"
capability "Health Check"
fingerprint deviceId: "0x0101", inClusters: "0x86,0x72,0x70,0x9B", outClusters: "0x26,0x2B"
fingerprint deviceId: "0x0101", inClusters: "0x86,0x72,0x70,0x9B,0x85,0x84", outClusters: "0x26" // old style with numbered buttons
@@ -119,5 +121,7 @@ def updated() {
}
def initialize() {
// Arrival sensors only goes OFFLINE when Hub is off
sendEvent(name: "DeviceWatch-Enroll", value: JsonOutput.toJson([protocol: "zigbee", scheme:"untracked"]), displayed: false)
sendEvent(name: "numberOfButtons", value: 4)
}

View File

@@ -300,15 +300,21 @@ def setColor(value) {
value.hex = "#${hex(value.red)}${hex(value.green)}${hex(value.blue)}"
}
sendEvent(name: "hue", value: value.hue, displayed: false)
sendEvent(name: "saturation", value: value.saturation, displayed: false)
sendEvent(name: "color", value: value.hex, displayed: false)
if (value.level) {
sendEvent(name: "level", value: value.level)
}
if (value.switch) {
sendEvent(name: "switch", value: value.switch)
}
if(value.hue) {
sendEvent(name: "hue", value: value.hue, displayed: false)
}
if(value.saturation) {
sendEvent(name: "saturation", value: value.saturation, displayed: false)
}
if(value.hex?.trim()) {
sendEvent(name: "color", value: value.hex, displayed: false)
}
if (value.level) {
sendEvent(name: "level", value: value.level)
}
if (value.switch?.trim()) {
sendEvent(name: "switch", value: value.switch)
}
sendRGB(value.rh, value.gh, value.bh)
}