Compare commits

...

47 Commits

Author SHA1 Message Date
Vincent Romo
4cc578ee64 MSA-2049: chime 2017-06-21 20:23:07 -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
505ec4ff0f Merge pull request #2107 from larsfinander/DVCSMP-2703_OpenT2T_Update_6_20_submission_2_staging
DVCSMP-2703 OpenT2T: Update to 6/20 submission
2017-06-20 09:19:50 -07:00
Lars Finander
fe0f555f10 DVCSMP-2703 OpenT2T: Update to 6/20 submission 2017-06-20 10:17:49 -06: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
Vinay Rao
42353044e6 Merge pull request #2104 from SmartThingsCommunity/production
Rolling down production to staging
2017-06-19 18:31:41 -07:00
Vinay Rao
78f06a0b9d Merge pull request #2103 from workingmonk/bug/appengine_version
Fix circle ci issues with new artifactory server
2017-06-19 16:25:32 -07:00
Vinay Rao
7f13dd356d Fix circle ci issues with new artifactory server 2017-06-19 16:24:58 -07:00
Vinay Rao
4042bbbf98 Merge pull request #2102 from SmartThingsCommunity/bug/deploy_script2
DVCSMP-2701 Update Deployment Jobs to new Artifactory.
2017-06-19 14:24:34 -07:00
Vinay Rao
20407441d9 DVCSMP-2701 Update Deployment Jobs to new Artifactory. set build gradle to new artifactory server 2017-06-19 14:23:44 -07:00
Vinay Rao
52925d6d99 Merge pull request #2093 from dkirker/DVCSMP-2698
DVCSMP-2698 Temporary bandage to properly show valve states in the device tile of local running devices
2017-06-19 12:15:01 -07:00
Vinay Rao
e6c17131af Merge pull request #2101 from SmartThingsCommunity/bug/deploy_script
DVCSMP-2701 Update Deployment Jobs to new Artifactory
2017-06-19 11:27:21 -07:00
Vinay Rao
cc70865fbf DVCSMP-2701 Update Deployment Jobs to new Artifactory 2017-06-19 11:21:05 -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
Donald Kirker
e53d9c910c DVCSMP-2698 Temporary bandage to properly show valve states in the device tile of local running devices 2017-06-14 17:35:11 -07:00
Vinay Rao
c13014936b Merge pull request #2090 from SmartThingsCommunity/master
Rolling up master to staging
2017-06-13 15:25:30 -07:00
Vinay Rao
d6b0f6a8ed Merge pull request #2089 from SmartThingsCommunity/staging
Rolling down staging to master
2017-06-13 15:24:44 -07:00
Vinay Rao
62c810ba90 Merge pull request #2078 from dkirker/ICP-1110
ICP-1110 Read valve state during pairing
2017-06-13 15:23:07 -07:00
Vinay Rao
ea3abb26c0 Merge pull request #2088 from SmartThingsCommunity/staging
Rolling up staging to production
2017-06-13 14:10:07 -07:00
Vinay Rao
0b81793b0f Merge pull request #2081 from SmartThingsCommunity/staging
Rolling down staging to master
2017-06-09 13:03:54 -07:00
Vinay Rao
16f41bddae Merge pull request #2080 from workingmonk/bug/mark_files_deprecated
SLC-82 Marking old connect apps and device types as deprecated
2017-06-09 13:01:45 -07:00
Vinay Rao
117adea586 SLC-82 Marking old connect apps and device types as deprecated 2017-06-09 11:44:06 -07:00
Vinay Rao
783538e36d Merge pull request #2070 from dkirker/ICP-1097
ICP-1097 Fix Sengled Classic default level on pairing
2017-06-08 16:28:50 -07:00
Donald Kirker
fb8e4a2416 ICP-1110 Read valve state during pairing 2017-06-07 23:47:13 -07:00
Vinay Rao
320c8918f8 Merge pull request #2075 from lymanepp/master
MSA-2076: Fix debug message
2017-06-07 15:32:43 -07:00
Lyman Epp
0f3656cd12 Fix debug message 2017-06-07 12:22:33 -05:00
Vinay Rao
6110aaa0fa Merge pull request #2074 from SmartThingsCommunity/master
Rolling up master to staging
2017-06-06 12:01:26 -07:00
Vinay Rao
c391ce4b43 Merge pull request #2073 from SmartThingsCommunity/staging
Rolling down staging to master
2017-06-06 11:55:16 -07:00
Vinay Rao
073bac8dac Merge pull request #2069 from larsfinander/DVCSMP-2688_Remove_sending_turningOn_Off_events_staging
DVCSMP-2688 Remove sending turningOn/Off events
2017-06-06 11:50:59 -07:00
Vinay Rao
c4c2a3ffd7 Merge pull request #2072 from SmartThingsCommunity/staging
Rolling up staging to production
2017-06-06 11:35:06 -07:00
Vinay Rao
3c83bfb53b Merge pull request #2071 from SmartThingsCommunity/production
Rolling down production to staging
2017-06-06 11:34:24 -07:00
Donald Kirker
6325101f52 ICP-1097 Fix Sengled Classic default level on pairing
Code brought oever from @varzac commit 8bcbe7b924
Original commit message:

> Fix sengled use of FF for max level
> This works around the fact that sengled element touches can get back
> into a state of reporting an invalid value (of FF) if the physical
> button on the bulb is used to cycle back to the 100% state.  Here we
> interpret FF as FE for sengled and then issue a move to level command to
> put it in a state where it will report FE until the level is changed
> again.
>
> This resolves: https://smartthings.atlassian.net/browse/DVCSMP-2597

While the Classic does not have a physical button, since it does represent 100% as FF we want to always catch this.
2017-06-06 03:29:41 -07:00
Lars Finander
945a972082 DVCSMP-2688 Remove sending turningOn/Off events
-Removed createSwitchEvent()
2017-06-05 16:50:03 -06:00
Tom Manley
b65acdb91f Merge pull request #2060 from varzac/aeon-multisensor-gen5
[DVCSMP-2680] Correctly configure Aeon Multisensor Gen5
2017-06-02 12:02:59 -05:00
Vinay Rao
4067e6e7e2 Merge pull request #2058 from juano2310/jumping_fix
ICP-1124 - Sylvania SMART BR30 RGBW ' s color ticker moving randomly
2017-06-01 17:40:42 -07:00
Zach Varberg
4c6d1eddb2 Correctly configure Aeon Multisensor Gen5
Previously this device had been changed to use configureAfterSecure to
work around the secure inclusion for Z-Wave.  However, support was added
hub side for handling this so it needed to be changed back to using the
normal configure process.

This resolves: https://smartthings.atlassian.net/browse/DVCSMP-2680
2017-06-01 08:28:12 -05:00
Vinay Rao
10d2097ebe Merge pull request #2065 from bflorian/MSA-1951-1-production-fingerprint
MSA-1951 added second Inovelli fingerprint
2017-05-31 17:35:00 -07:00
Bob Florian
d3728d95b2 MSA-1951 added second Inovelli fingerprint 2017-05-31 16:45:55 -07:00
Vinay Rao
b645872d8f Merge pull request #2063 from SmartThingsCommunity/staging
Rolling up staging to production
2017-05-31 13:42:12 -07:00
juano2310
74a35eeddb ICP-1124 - Sylvania SMART BR30 RGBW ' s color ticker moving randomly
state

overwrite: true
2017-05-30 18:18:22 -04:00
29 changed files with 1033 additions and 127 deletions

View File

@@ -9,7 +9,7 @@ apply plugin: 'smartthings-slack'
buildscript {
dependencies {
classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.11"
classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.12"
}
repositories {
mavenLocal()
@@ -19,7 +19,7 @@ buildscript {
username smartThingsArtifactoryUserName
password smartThingsArtifactoryPassword
}
url "https://artifactory.smartthings.com/libs-release-local"
url "https://smartthings.jfrog.io/smartthings/libs-release-local"
}
}
}
@@ -32,7 +32,7 @@ repositories {
username smartThingsArtifactoryUserName
password smartThingsArtifactoryPassword
}
url "https://artifactory.smartthings.com/libs-release-local"
url "https://smartthings.jfrog.io/smartthings/libs-release-local"
}
}
@@ -51,10 +51,10 @@ sourceSets {
dependencies {
devicetypesCompile 'org.codehaus.groovy:groovy-all:2.4.7'
devicetypesCompile 'smartthings:appengine-z-wave:0.1.2'
devicetypesCompile 'smartthings:appengine-zigbee:0.1.11'
devicetypesCompile 'smartthings:appengine-z-wave:0.1.3'
devicetypesCompile 'smartthings:appengine-zigbee:0.1.12'
smartappsCompile 'org.codehaus.groovy:groovy-all:2.4.7'
smartappsCompile 'smartthings:appengine-common:0.1.8'
smartappsCompile 'smartthings:appengine-common:0.1.9'
smartappsCompile 'org.codehaus.groovy.modules.http-builder:http-builder:0.7.1'
smartappsCompile 'org.grails:grails-web:2.3.11'
smartappsCompile 'org.json:json:20140107'
@@ -74,19 +74,19 @@ slackSendMessage {
String username
switch (branch) {
case 'master':
username = 'Hickory'
username = 'DEV'
iconUrl = wolverine
color = '#35D0F2'
messageText = 'Began deployment of _SmartThingsPublic[master]_ branch to the _Dev_ environments.'
break
case 'staging':
username = 'Dickory'
username = 'STG'
iconUrl = beach
color = '#FFDE20'
messageText = 'Began deployment of _SmartThingsPublic[staging]_ branch to the _Staging_ environments.'
break
case 'production':
username = 'Dock'
username = 'PRD'
iconUrl = drinks
color = '#FF1D23'
messageText = 'Began deployment of _SmartThingsPublic[production]_ branch to the _Prod_ environments.'

View File

@@ -26,7 +26,9 @@ metadata {
capability "Polling"
capability "Refresh"
capability "Health Check"
fingerprint manufacturer: "015D", prod: "0221", model: "251C"
fingerprint manufacturer: "015D", prod: "0221", model: "251C", deviceJoinName: "Show Home 2-Channel Smart Plug"
fingerprint manufacturer: "0312", prod: "B221", model: "251C", deviceJoinName: "Inovelli 2-Channel Smart Plug"
}
simulator {}
preferences {}

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

@@ -22,8 +22,6 @@ metadata {
capability "Battery"
capability "Health Check"
command "configureAfterSecure"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x98,0x7A", outClusters:"0x5A"
fingerprint mfr:"0086", prod:"0102", model:"004A", deviceJoinName: "Aeon Labs MultiSensor (Gen 5)"
}
@@ -91,12 +89,12 @@ metadata {
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "battery", label:'${currentValue}% battery', unit:""
}
standardTile("configureAfterSecure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "configure", label:'', action:"configureAfterSecure", icon:"st.secondary.configure"
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "configure", label:'', action:"configure", icon:"st.secondary.configure"
}
main(["motion", "temperature", "humidity", "illuminance"])
details(["motion", "temperature", "humidity", "illuminance", "battery", "configureAfterSecure"])
details(["motion", "temperature", "humidity", "illuminance", "battery", "configure"])
}
}
@@ -131,8 +129,8 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
if (!isConfigured()) {
// we're still in the process of configuring a newly joined device
log.debug("not sending wakeUpNoMoreInformation yet")
result += response(configureAfterSecure())
log.debug("not sending wakeUpNoMoreInformation yet: late configure")
result += response(configure())
} else {
result += response(zwave.wakeUpV1.wakeUpNoMoreInformation())
}
@@ -150,11 +148,6 @@ def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulat
}
}
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupportedReport cmd) {
// log.debug "Received SecurityCommandsSupportedReport"
response(configureAfterSecure())
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def map = [ name: "battery", unit: "%" ]
if (cmd.batteryLevel == 0xFF) {
@@ -226,36 +219,6 @@ def zwaveEvent(physicalgraph.zwave.Command cmd) {
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
def configureAfterSecure() {
// log.debug "configureAfterSecure()"
def request = [
// send temperature, humidity, and illuminance every 8 minutes
zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 128|64|32),
zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 8*60),
// send battery every 20 hours
zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 1),
zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 20*60*60),
// send no-motion report 60 seconds after motion stops
zwave.configurationV1.configurationSet(parameterNumber: 3, size: 2, scaledConfigurationValue: 60),
// send binary sensor report instead of basic set for motion
zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: 2),
// disable notification-style motion events
zwave.notificationV3.notificationSet(notificationType: 7, notificationStatus: 0),
zwave.batteryV1.batteryGet(),
zwave.sensorBinaryV2.sensorBinaryGet(sensorType:0x0C)
]
setConfigured()
secureSequence(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
@@ -265,7 +228,36 @@ def ping() {
def configure() {
// log.debug "configure()"
//["delay 30000"] + secure(zwave.securityV1.securityCommandsSupportedGet())
def request = []
// send temperature, humidity, and illuminance every 8 minutes
request << zwave.configurationV1.configurationSet(parameterNumber: 101, size: 4, scaledConfigurationValue: 128|64|32)
request << zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: 8*60)
// send battery every 20 hours
request << zwave.configurationV1.configurationSet(parameterNumber: 102, size: 4, scaledConfigurationValue: 1)
request << zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 20*60*60)
// send no-motion report 60 seconds after motion stops
request << zwave.configurationV1.configurationSet(parameterNumber: 3, size: 2, scaledConfigurationValue: 60)
// send binary sensor report instead of basic set for motion
request << zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: 2)
// Turn on the Multisensor Gen5 PIR sensor
request << zwave.configurationV1.configurationSet(parameterNumber: 4, size: 1, scaledConfigurationValue: 1)
// disable notification-style motion events
request << zwave.notificationV3.notificationSet(notificationType: 7, notificationStatus: 0)
request << zwave.batteryV1.batteryGet()
request << zwave.sensorBinaryV2.sensorBinaryGet(sensorType: 0x0C) //motion
request << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x01) //temperature
request << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x03) //illuminance
request << zwave.sensorMultilevelV5.sensorMultilevelGet(sensorType: 0x05) //humidity
setConfigured()
secureSequence(request) + ["delay 20000", zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
}
private setConfigured() {

View File

@@ -1,3 +1,5 @@
//DEPRECATED. INTEGRATION MOVED TO SUPER LAN CONNECT
/**
* Bose SoundTouch
*

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)
}

View File

@@ -35,8 +35,8 @@ metadata {
// tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"valve", type: "generic", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.valve", key: "PRIMARY_CONTROL") {
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
attributeState "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing"
attributeState "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff", nextState:"opening"
attributeState "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
@@ -48,14 +48,16 @@ metadata {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
main "valve"
details(["valve","refresh"])
main "contact"
details(["contact","refresh"])
}
}
def installed(){
// Device-Watch simply pings if no device events received for 32min(checkInterval)
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
response(refresh())
}
def updated(){
@@ -85,11 +87,17 @@ def zwaveEvent(physicalgraph.zwave.Command cmd) {
}
def open() {
zwave.switchBinaryV1.switchBinarySet(switchValue: 0x00).format()
delayBetween([
zwave.switchBinaryV1.switchBinarySet(switchValue: 0x00).format(),
zwave.switchBinaryV1.switchBinaryGet().format()
], 500)
}
def close() {
zwave.switchBinaryV1.switchBinarySet(switchValue: 0xFF).format()
delayBetween([
zwave.switchBinaryV1.switchBinarySet(switchValue: 0xFF).format(),
zwave.switchBinaryV1.switchBinaryGet().format()
], 500)
}
/**
@@ -105,6 +113,6 @@ def refresh() {
def createEventWithDebug(eventMap) {
def event = createEvent(eventMap)
log.debug "Event created with ${event?.descriptionText}"
log.debug "Event created with ${event?.name}:${event?.value} - ${event?.descriptionText}"
return event
}

View File

@@ -1,3 +1,5 @@
//DEPRECATED. INTEGRATION MOVED TO SUPER LAN CONNECT
/**
* Hue Bloom
*

View File

@@ -1,3 +1,5 @@
//DEPRECATED. INTEGRATION MOVED TO SUPER LAN CONNECT
/**
* Hue Bridge
*

View File

@@ -1,3 +1,5 @@
//DEPRECATED. INTEGRATION MOVED TO SUPER LAN CONNECT
/**
* Hue Bulb
*

View File

@@ -1,3 +1,5 @@
//DEPRECATED. INTEGRATION MOVED TO SUPER LAN CONNECT
/**
* Hue Lux Bulb
*

View File

@@ -1,3 +1,5 @@
//DEPRECATED. INTEGRATION MOVED TO SUPER LAN CONNECT
/**
* Hue White Ambiance Bulb
*

View File

@@ -49,6 +49,6 @@ def arrived() {
def departed() {
log.trace "Executing 'arrived'"
log.trace "Executing 'departed'"
sendEvent(name: "presence", value: "not present")
}

View File

@@ -1,3 +1,5 @@
//DEPRECATED. INTEGRATION MOVED TO SUPER LAN CONNECT
/**
* Copyright 2015 SmartThings
*

View File

@@ -1,3 +1,5 @@
//DEPRECATED. INTEGRATION MOVED TO SUPER LAN CONNECT
/**
* Copyright 2015 SmartThings
*

View File

@@ -1,3 +1,5 @@
//DEPRECATED. INTEGRATION MOVED TO SUPER LAN CONNECT
/**
* Copyright 2015 SmartThings
*

View File

@@ -66,22 +66,29 @@ def parse(String description) {
else {
sendEvent(event)
}
}
else {
def cluster = zigbee.parse(description)
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
if (cluster.data[0] == 0x00) {
} else {
def descMap = zigbee.parseDescriptionAsMap(description)
if (descMap && descMap.clusterInt == 0x0006 && descMap.commandInt == 0x07) {
if (descMap.data[0] == "00") {
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
} else {
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
}
}
else {
} else if (device.getDataValue("manufacturer") == "sengled" && descMap && descMap.clusterInt == 0x0008 && descMap.attrInt == 0x0000) {
// This is being done because the sengled element touch/classic incorrectly uses the value 0xFF for the max level.
// Per the ZCL spec for the UINT8 data type 0xFF is an invalid value, and 0xFE should be the max. Here we
// manually handle the invalid attribute value since it will be ignored by getEvent as an invalid value.
// We also set the level of the bulb to 0xFE so future level reports will be 0xFE until it is changed by
// something else.
if (descMap.value.toUpperCase() == "FF") {
descMap.value = "FE"
}
sendHubCommand(zigbee.command(zigbee.LEVEL_CONTROL_CLUSTER, 0x00, "FE0000").collect { new physicalgraph.device.HubAction(it) }, 0)
sendEvent(zigbee.getEventFromAttrData(descMap.clusterInt, descMap.attrInt, descMap.encoding, descMap.value))
} else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug "${cluster}"
log.debug "${descMap}"
}
}
}

View File

@@ -103,12 +103,12 @@ def parse(String description) {
if (zigbeeMap?.clusterInt == COLOR_CONTROL_CLUSTER) {
if(zigbeeMap.attrInt == ATTRIBUTE_HUE){ //Hue Attribute
def hueValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 0xfe * 100)
sendEvent(name: "hue", value: hueValue, descriptionText: "Color has changed")
state.hueValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 0xfe * 100)
runIn(5, updateColor, [overwrite: true])
}
else if(zigbeeMap.attrInt == ATTRIBUTE_SATURATION){ //Saturation Attribute
def saturationValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 0xfe * 100)
sendEvent(name: "saturation", value: saturationValue, descriptionText: "Color has changed", displayed: false)
state.saturationValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 0xfe * 100)
runIn(5, updateColor, [overwrite: true])
}
}
else if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
@@ -127,6 +127,11 @@ def parse(String description) {
}
}
def updateColor() {
sendEvent(name: "hue", value: state.hueValue, descriptionText: "Color has changed")
sendEvent(name: "saturation", value: state.saturationValue, descriptionText: "Color has changed", displayed: false)
}
def on() {
zigbee.on()
}
@@ -204,9 +209,9 @@ def setColor(value){
log.trace "setColor($value)"
zigbee.on() +
zigbee.command(COLOR_CONTROL_CLUSTER, MOVE_TO_HUE_AND_SATURATION_COMMAND,
getScaledHue(value.hue), getScaledSaturation(value.saturation), "0000") +
zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) +
zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION)
getScaledHue(value.hue), getScaledSaturation(value.saturation), "0000") +
zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) +
zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE)
}
def setHue(value) {

View File

@@ -38,8 +38,8 @@ metadata {
}
tiles(scale: 2) {
multiAttributeTile(name:"valve", type: "generic", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.valve", key: "PRIMARY_CONTROL") {
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
attributeState "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing"
attributeState "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff", nextState:"opening"
attributeState "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing"
@@ -58,8 +58,8 @@ metadata {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
main(["valve"])
details(["valve", "battery", "refresh"])
main(["contact"])
details(["contact", "battery", "refresh"])
}
}

View File

@@ -195,7 +195,10 @@ def registerDeviceChange() {
state.deviceSubscriptionMap.put(deviceId, [subscriptionEndpt])
log.info "Added subscription URL: ${subscriptionEndpt} for ${myDevice.displayName}"
} else if (!state.deviceSubscriptionMap[deviceId].contains(subscriptionEndpt)) {
state.deviceSubscriptionMap[deviceId] << subscriptionEndpt
// state.deviceSubscriptionMap[deviceId] << subscriptionEndpt
// For now, we will only have one subscription endpoint per device
state.deviceSubscriptionMap.remove(deviceId)
state.deviceSubscriptionMap.put(deviceId, [subscriptionEndpt])
log.info "Added subscription URL: ${subscriptionEndpt} for ${myDevice.displayName}"
}

View File

@@ -1,3 +1,5 @@
//DEPRECATED. INTEGRATION MOVED TO SUPER LAN CONNECT
/**
* Bose SoundTouch (Connect)
*

View File

@@ -1,3 +1,5 @@
//DEPRECATED. INTEGRATION MOVED TO SUPER LAN CONNECT
/**
* Hue Service Manager
*
@@ -1083,7 +1085,6 @@ def on(childDevice) {
log.debug "Executing 'on'"
def id = getId(childDevice)
updateInProgress()
createSwitchEvent(childDevice, "on")
put("lights/$id/state", [on: true])
return "Bulb is turning On"
}
@@ -1092,7 +1093,6 @@ def off(childDevice) {
log.debug "Executing 'off'"
def id = getId(childDevice)
updateInProgress()
createSwitchEvent(childDevice, "off")
put("lights/$id/state", [on: false])
return "Bulb is turning Off"
}
@@ -1108,8 +1108,6 @@ def setLevel(childDevice, percent) {
else
level = Math.min(Math.round(percent * 254 / 100), 254)
createSwitchEvent(childDevice, level > 0, percent)
// For Zigbee lights, if level is set to 0 ST just turns them off without changing level
// that means that the light will still be on when on is called next time
// Lets emulate that here
@@ -1128,7 +1126,6 @@ def setSaturation(childDevice, percent) {
// 0 - 254
def level = Math.min(Math.round(percent * 254 / 100), 254)
// TODO should this be done by app only or should we default to on?
createSwitchEvent(childDevice, "on")
put("lights/$id/state", [sat: level, on: true])
return "Setting saturation to $percent"
}
@@ -1140,7 +1137,6 @@ def setHue(childDevice, percent) {
// 0 - 65535
def level = Math.min(Math.round(percent * 65535 / 100), 65535)
// TODO should this be done by app only or should we default to on?
createSwitchEvent(childDevice, "on")
put("lights/$id/state", [hue: level, on: true])
return "Setting hue to $percent"
}
@@ -1151,7 +1147,6 @@ def setColorTemperature(childDevice, huesettings) {
updateInProgress()
// 153 (6500K) to 500 (2000K)
def ct = hueSettings == 6500 ? 153 : Math.round(1000000 / huesettings)
createSwitchEvent(childDevice, "on")
put("lights/$id/state", [ct: ct, on: true])
return "Setting color temperature to $ct"
}
@@ -1210,7 +1205,6 @@ def setColor(childDevice, huesettings) {
if (huesettings.switch == "off")
value.on = false
createSwitchEvent(childDevice, value.on ? "on" : "off")
put("lights/$id/state", value)
return "Setting color to $value"
}
@@ -1322,32 +1316,6 @@ private List getRealHubFirmwareVersions() {
return location.hubs*.firmwareVersionString.findAll { it }
}
/**
* Sends appropriate turningOn/turningOff state events depending on switch or level changes.
*
* @param childDevice device to send event for
* @param setSwitch The new switch state, "on" or "off"
* @param setLevel Optional, switchLevel between 0-100, used if you set level to 0 for example since
* that should generate "off" instead of level change
*/
private void createSwitchEvent(childDevice, setSwitch, setLevel = null) {
if (setLevel == null) {
setLevel = childDevice.device?.currentValue("level")
}
// Create on, off, turningOn or turningOff event as necessary
def currentState = childDevice.device?.currentValue("switch")
if ((currentState == "off" || currentState == "turningOff")) {
if (setSwitch == "on" || setLevel > 0) {
childDevice.sendEvent(name: "switch", value: "turningOn", displayed: false)
}
} else if ((currentState == "on" || currentState == "turningOn")) {
if (setSwitch == "off" || setLevel == 0) {
childDevice.sendEvent(name: "switch", value: "turningOff", displayed: false)
}
}
}
/**
* Return the supported color range for different Hue lights. If model is not specified
* it defaults to the smallest Gamut (B) to ensure that colors set on a mix of devices

View File

@@ -1,3 +1,5 @@
//DEPRECATED. INTEGRATION MOVED TO SUPER LAN CONNECT
/**
* Copyright 2015 SmartThings
*