Compare commits

..

77 Commits

Author SHA1 Message Date
Daniel Segovia
401cdb4a34 MSA-2078: Door sensor 2017-07-04 19:46:46 -07:00
Vinay Rao
4547d0543b Merge pull request #2126 from SmartThingsCommunity/staging
Rolling down staging to master
2017-06-27 16:03:00 -07:00
Jack Chi
59e6f1251b Merge pull request #2097 from skt123/zigbee_button
[DHF-16] Added Health Check Implementation for Zigbee Button.
2017-06-27 10:28:47 -07:00
sushant.k1
e8939a77d7 [DHF-16]
Added Health Check Implementation for Zigbee Button.
2017-06-27 19:12:35 +05:30
Vinay Rao
5aee3a1861 Merge pull request #2114 from marstorp/icp1148dynamicModeSupport
ICP-1148 Support Thermostat Dynamic data
2017-06-23 14:15:56 -07:00
marstorp
17ae692aa0 ICP-1148 Support Thermostat Dynamic data
Adding support for dynamic thermostat and fan modes to ecobee
2017-06-23 13:24:03 -07:00
Vinay Rao
f02428b99f Merge pull request #2113 from larsfinander/DVCSMP-2702_smartpower-outlet_remove_light_staging
DVCSMP-2702 smartpower-outlet DTH incorrectly has capability.light
2017-06-22 12:25:26 -07:00
Lars Finander
34174b730c DVCSMP-2702 smartpower-outlet DTH incorrectly has capability.light 2017-06-22 13:13:08 -06:00
Vinay Rao
12f874408a Merge pull request #2110 from SmartThingsCommunity/master
Rolling up master to staging
2017-06-20 11:46:47 -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
535fc112de Merge pull request #2055 from jmagnuson/DVCSMP-2537
DVCSMP-2537 Add CRC16 un-encapsulation to Z-Wave switches
2017-06-02 16:36:50 -05:00
Jon Magnuson
a844e85c47 Remove extra comment slash 2017-06-02 16:25:04 -05: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
60f6e9c02c Merge pull request #2064 from SmartThingsCommunity/staging
Rolling down staging to master
2017-05-31 13:56:22 -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
Vinay Rao
d3731b49fe Merge pull request #2062 from SmartThingsCommunity/production
Rolling down production to staging
2017-05-31 11:44:22 -07:00
Vinay Rao
da139056e1 Merge pull request #2047 from dkirker/ICP-1076
ICP-1076 Fix Aeon Door/Window Sensor 6 initial value of null
2017-05-31 11:24:20 -07:00
Donald Kirker
d864c5e3b3 ICP-1076 Fix Aeon Door/Window Sensor 6 initial value of null 2017-05-31 11:00:43 -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
Vinay Rao
7064ce972a Merge pull request #2048 from dkirker/ICP-1016
ICP-1016 Fix default value for states for Aeon Siren Gen5
2017-05-30 11:53:51 -07:00
Vinay Rao
936ee59242 Merge pull request #2056 from jackchi/zwave-lock-1hr-ping
[DHF-7] [ICP-1084] Adds scheduled 1 hr ping for offline devices
2017-05-30 00:27:24 -07:00
jackchi
79a6a6472e [DHF-7] [ICP-1084] Adds scheduled 1 hr ping for offline devices; updates checkInterval to 1 hour 2017-05-29 11:02:48 -07:00
bflorian
919111ed22 Merge pull request #2051 from bflorian/MSA-1951-1-staging
MSA-1951 Added Inovelli 2-Channel Smart Plug
2017-05-26 13:55:20 -04:00
Bob Florian
fc1f1508ad MSA-1951 Added Inovelli 2-Channel Smart Plug 2017-05-26 13:38:45 -04:00
Donald Kirker
7f3cd0cdaa ICP-1016 Fix default value for states for Aeon Siren Gen5 2017-05-26 01:39:05 -07:00
Vinay Rao
423c25df53 Merge pull request #2045 from workingmonk/hotfix/siren
ICP-1056 Updating the icon and ocf device type for fortrezz siren
2017-05-25 17:17:48 -07:00
Vinay Rao
df8e435fcc ICP-1056 Updating the icon and ocf device type for fortrezz siren 2017-05-25 17:09:54 -07:00
Jon Magnuson
8aceef9be4 Add CRC16 un-encapsulation to Z-Wave switches
Fixes DVCSMP-2663 and DVCSMP-2537.
2017-05-25 17:07:12 -05:00
Vinay Rao
144314d9ae Merge pull request #2042 from twack/ocf-update-fortrezz-siren
ICP-1056 ocf-update-fortrezz-siren
2017-05-25 11:04:17 -07:00
Vinay Rao
a1f39849ed Merge pull request #2043 from SmartThingsCommunity/staging
Rolling down staging to master
2017-05-25 10:58:53 -07:00
Vinay Rao
8eed22ca0c Merge pull request #2041 from parijatdas/aeon-multisensor
[CHF-616] Health check Aeon Multi sensor motion detector
2017-05-25 10:58:25 -07:00
twack
d626c5f2a1 ocf-update-fortrezz-siren 2017-05-25 07:57:19 -07:00
Parijat Das
1dae5d3936 Added health check implementation for Aeon MultiSensor 2017-05-25 18:56:38 +05:30
Vinay Rao
807ff53c6d Merge pull request #2036 from SmartThingsCommunity/master
Rolling up master to staging
2017-05-23 13:52:46 -07:00
Vinay Rao
453dbbdde3 Merge pull request #2034 from SmartThingsCommunity/staging
Rolling up staging to production
2017-05-23 13:49:56 -07:00
49 changed files with 861 additions and 200 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

@@ -0,0 +1,268 @@
/**
*
* Inovelli 2-Channel Smart Plug
*
* github: Eric Maycock (erocm123)
* Date: 2017-04-27
* Copyright Eric Maycock
*
* Includes all configuration parameters and ease of advanced configuration.
*
* 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: "Inovelli 2-Channel Smart Plug", namespace: "erocm123", author: "Eric Maycock") {
capability "Actuator"
capability "Sensor"
capability "Switch"
capability "Polling"
capability "Refresh"
capability "Health Check"
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 {}
tiles {
multiAttributeTile(name: "switch", type: "lighting", width: 6, height: 4, canChangeIcon: true) {
tileAttribute("device.switch", key: "PRIMARY_CONTROL") {
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00a0dc", nextState: "turningOff"
attributeState "turningOff", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
attributeState "turningOn", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00a0dc", nextState: "turningOff"
}
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label: "", action: "refresh.refresh", icon: "st.secondary.refresh"
}
main(["switch"])
details(["switch",
childDeviceTiles("all"), "refresh"
])
}
}
def parse(String description) {
def result = []
def cmd = zwave.parse(description)
if (cmd) {
result += zwaveEvent(cmd)
logging("Parsed ${cmd} to ${result.inspect()}", 1)
} else {
logging("Non-parsed event: ${description}", 2)
}
return result
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd, ep = null) {
logging("BasicReport ${cmd} - ep ${ep}", 2)
if (ep) {
def event
childDevices.each {
childDevice ->
if (childDevice.deviceNetworkId == "$device.deviceNetworkId-ep$ep") {
childDevice.sendEvent(name: "switch", value: cmd.value ? "on" : "off")
}
}
if (cmd.value) {
event = [createEvent([name: "switch", value: "on"])]
} else {
def allOff = true
childDevices.each {
n ->
if (n.currentState("switch").value != "off") allOff = false
}
if (allOff) {
event = [createEvent([name: "switch", value: "off"])]
} else {
event = [createEvent([name: "switch", value: "on"])]
}
}
return event
}
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
logging("BasicSet ${cmd}", 2)
def result = createEvent(name: "switch", value: cmd.value ? "on" : "off", type: "digital")
def cmds = []
cmds << encap(zwave.switchBinaryV1.switchBinaryGet(), 1)
cmds << encap(zwave.switchBinaryV1.switchBinaryGet(), 2)
return [result, response(commands(cmds))] // returns the result of reponse()
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd, ep = null) {
logging("SwitchBinaryReport ${cmd} - ep ${ep}", 2)
if (ep) {
def event
def childDevice = childDevices.find {
it.deviceNetworkId == "$device.deviceNetworkId-ep$ep"
}
if (childDevice) childDevice.sendEvent(name: "switch", value: cmd.value ? "on" : "off")
if (cmd.value) {
event = [createEvent([name: "switch", value: "on"])]
} else {
def allOff = true
childDevices.each {
n->
if (n.currentState("switch").value != "off") allOff = false
}
if (allOff) {
event = [createEvent([name: "switch", value: "off"])]
} else {
event = [createEvent([name: "switch", value: "on"])]
}
}
return event
} else {
def result = createEvent(name: "switch", value: cmd.value ? "on" : "off", type: "digital")
def cmds = []
cmds << encap(zwave.switchBinaryV1.switchBinaryGet(), 1)
cmds << encap(zwave.switchBinaryV1.switchBinaryGet(), 2)
return [result, response(commands(cmds))] // returns the result of reponse()
}
}
def zwaveEvent(physicalgraph.zwave.commands.multichannelv3.MultiChannelCmdEncap cmd) {
logging("MultiChannelCmdEncap ${cmd}", 2)
def encapsulatedCommand = cmd.encapsulatedCommand([0x32: 3, 0x25: 1, 0x20: 1])
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand, cmd.sourceEndPoint as Integer)
}
}
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
logging("ManufacturerSpecificReport ${cmd}", 2)
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
logging("msr: $msr", 2)
updateDataValue("MSR", msr)
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// This will capture any commands not handled by other instances of zwaveEvent
// and is recommended for development so you can see every command the device sends
logging("Unhandled Event: ${cmd}", 2)
}
def on() {
logging("on()", 1)
commands([
zwave.switchAllV1.switchAllOn(),
encap(zwave.switchBinaryV1.switchBinaryGet(), 1),
encap(zwave.switchBinaryV1.switchBinaryGet(), 2)
])
}
def off() {
logging("off()", 1)
commands([
zwave.switchAllV1.switchAllOff(),
encap(zwave.switchBinaryV1.switchBinaryGet(), 1),
encap(zwave.switchBinaryV1.switchBinaryGet(), 2)
])
}
void childOn(String dni) {
logging("childOn($dni)", 1)
def cmds = []
cmds << new physicalgraph.device.HubAction(command(encap(zwave.basicV1.basicSet(value: 0xFF), channelNumber(dni))))
cmds << new physicalgraph.device.HubAction(command(encap(zwave.switchBinaryV1.switchBinaryGet(), channelNumber(dni))))
sendHubCommand(cmds, 1000)
}
void childOff(String dni) {
logging("childOff($dni)", 1)
def cmds = []
cmds << new physicalgraph.device.HubAction(command(encap(zwave.basicV1.basicSet(value: 0x00), channelNumber(dni))))
cmds << new physicalgraph.device.HubAction(command(encap(zwave.switchBinaryV1.switchBinaryGet(), channelNumber(dni))))
sendHubCommand(cmds, 1000)
}
void childRefresh(String dni) {
logging("childRefresh($dni)", 1)
def cmds = []
cmds << new physicalgraph.device.HubAction(command(encap(zwave.switchBinaryV1.switchBinaryGet(), channelNumber(dni))))
sendHubCommand(cmds, 1000)
}
def poll() {
logging("poll()", 1)
commands([
encap(zwave.switchBinaryV1.switchBinaryGet(), 1),
encap(zwave.switchBinaryV1.switchBinaryGet(), 2),
])
}
def refresh() {
logging("refresh()", 1)
commands([
encap(zwave.switchBinaryV1.switchBinaryGet(), 1),
encap(zwave.switchBinaryV1.switchBinaryGet(), 2),
])
}
def ping() {
logging("ping()", 1)
refresh()
}
def installed() {
logging("installed()", 1)
command(zwave.manufacturerSpecificV1.manufacturerSpecificGet())
createChildDevices()
}
def updated() {
logging("updated()", 1)
if (!childDevices) {
createChildDevices()
} else if (device.label != state.oldLabel) {
childDevices.each {
if (it.label == "${state.oldLabel} (CH${channelNumber(it.deviceNetworkId)})") {
def newLabel = "${device.displayName} (CH${channelNumber(it.deviceNetworkId)})"
it.setLabel(newLabel)
}
}
state.oldLabel = device.label
}
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
sendEvent(name: "needUpdate", value: device.currentValue("needUpdate"), displayed: false, isStateChange: true)
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd) {
logging("${device.displayName} parameter '${cmd.parameterNumber}' with a byte size of '${cmd.size}' is set to '${cmd2Integer(cmd.configurationValue)}'", 2)
}
private encap(cmd, endpoint) {
if (endpoint) {
zwave.multiChannelV3.multiChannelCmdEncap(destinationEndPoint: endpoint).encapsulate(cmd)
} else {
cmd
}
}
private command(physicalgraph.zwave.Command cmd) {
if (state.sec) {
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
} else {
cmd.format()
}
}
private commands(commands, delay = 1000) {
delayBetween(commands.collect {
command(it)
}, delay)
}
private channelNumber(String dni) {
dni.split("-ep")[-1] as Integer
}
private void createChildDevices() {
state.oldLabel = device.label
for (i in 1..2) {
addChildDevice("Switch Child Device", "${device.deviceNetworkId}-ep${i}", null, [completedSetup: true, label: "${device.displayName} (CH${i})",
isComponent: true, componentName: "ep$i", componentLabel: "Channel $i"
])
}
}
private def logging(message, level) {
if (logLevel != "0") {
switch (logLevel) {
case "1":
if (level > 1) log.debug "$message"
break
case "99":
log.debug "$message"
break
}
}
}

View File

@@ -0,0 +1,49 @@
/**
* Switch Child Device
*
* Copyright 2017 Eric Maycock
*
* 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: "Switch Child Device", namespace: "erocm123", author: "Eric Maycock") {
capability "Switch"
capability "Actuator"
capability "Sensor"
capability "Refresh"
}
tiles {
multiAttributeTile(name:"switch", type: "lighting", width: 3, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState:"turningOn"
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC", nextState:"turningOff"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
}
}
void on() {
parent.childOn(device.deviceNetworkId)
}
void off() {
parent.childOff(device.deviceNetworkId)
}
void refresh() {
parent.childRefresh(device.deviceNetworkId)
}

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

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

View File

@@ -0,0 +1,48 @@
# Aeon Multisensor
Cloud Execution
Works with:
* [Aeotec MultiSensor (DSB05-ZWUS)](https://www.smartthings.com/products/aeotec-multisensor-5)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Battery](#battery-specification)
* [Troubleshooting](#troubleshooting)
## Capabilities
* **Motion Sensor** - can detect motion
* **Temperature Measurement** - defines device measures current temperature
* **Relative Humidity Measurement** - allow reading the relative humidity from devices that support it
* **Illuminance Measurement** - gives the illuminance reading from devices that support it
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Sensor** - detects sensor events
* **Battery** - defines device uses a battery
* **Health Check** - indicates ability to get device health notifications
## Device Health
Aeon Labs MultiSensor is polled by the hub.
As of hubCore version 0.14.38 the hub sends up reports every 15 minutes regardless of whether the state changed.
Device-Watch allows 2 check-in misses from device plus some lag time. So Check-in interval = (2*15 + 2)mins = 32 mins.
Not to mention after going OFFLINE when the device is plugged back in, it might take a considerable amount of time for
the device to appear as ONLINE again. This is because if this listening device does not respond to two poll requests in a row,
it is not polled for 5 minutes by the hub. This can delay up the process of being marked ONLINE by quite some time.
* __32min__ checkInterval
## Battery Specification
Four AAA batteries are required.
## Troubleshooting
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range.
Pairing needs to be tried again by placing the device closer to the hub.
Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link:
* [Aeon MultiSensor Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/206157226-How-to-connect-Aeon-Labs-MultiSensors)

View File

@@ -20,6 +20,7 @@ metadata {
capability "Illuminance Measurement"
capability "Sensor"
capability "Battery"
capability "Health Check"
fingerprint deviceId: "0x2001", inClusters: "0x30,0x31,0x80,0x84,0x70,0x85,0x72,0x86"
}
@@ -93,6 +94,16 @@ metadata {
}
}
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])
}
def updated(){
// 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])
}
// Parse incoming device messages to generate events
def parse(String description)
{
@@ -179,6 +190,13 @@ def zwaveEvent(physicalgraph.zwave.Command cmd) {
[:]
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
secure(zwave.batteryV1.batteryGet())
}
def configure() {
delayBetween([
// send binary sensor report instead of basic set for motion

View File

@@ -61,6 +61,8 @@ metadata {
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(secure(zwave.basicV1.basicGet()))
}
def updated() {
@@ -163,4 +165,4 @@ private secure(physicalgraph.zwave.Command cmd) {
* */
def ping() {
secure(zwave.basicV1.basicGet())
}
}

View File

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

View File

@@ -108,11 +108,20 @@ def updated(){
}
}
def getCommandClassVersions() {
[
0x20: 1, // Basic
0x26: 1, // SwitchMultilevel
0x56: 1, // Crc16Encap
0x70: 1, // Configuration
]
}
def parse(String description) {
def result = null
if (description != "updated") {
log.debug "parse() >> zwave.parse($description)"
def cmd = zwave.parse(description, [0x20: 1, 0x26: 1, 0x70: 1])
def cmd = zwave.parse(description, commandClassVersions)
if (cmd) {
result = zwaveEvent(cmd)
}
@@ -179,6 +188,16 @@ def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelS
[createEvent(name:"switch", value:"on"), response(zwave.switchMultilevelV1.switchMultilevelGet().format())]
}
def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd) {
def versions = commandClassVersions
def version = versions[cmd.commandClass as Integer]
def ccObj = version ? zwave.commandClass(cmd.commandClass, version) : zwave.commandClass(cmd.commandClass)
def encapsulatedCommand = ccObj?.command(cmd.command)?.parse(cmd.data)
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren't interested in
[:]

View File

@@ -70,7 +70,7 @@ metadata {
state "heat", action:"switchMode", nextState: "updating", icon: "st.thermostat.heat"
state "cool", action:"switchMode", nextState: "updating", icon: "st.thermostat.cool"
state "auto", action:"switchMode", nextState: "updating", icon: "st.thermostat.auto"
state "emergency heat", action:"switchMode", icon: "st.thermostat.emergency-heat" // emergency heat = auxHeatOnly
state "auxheatonly", action:"switchMode", icon: "st.thermostat.emergency-heat"
state "updating", label:"Working", icon: "st.secondary.secondary"
}
standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false, decoration: "flat") {
@@ -156,47 +156,49 @@ void poll() {
def generateEvent(Map results) {
log.debug "parsing data $results"
if(results) {
results.each { name, value ->
def linkText = getLinkText(device)
def isChange = false
def isDisplayed = true
def supportedThermostatModes = []
def thermostatMode = null
results.each { name, value ->
def event = [name: name, linkText: linkText, descriptionText: getThermostatDescriptionText(name, value, linkText),
handlerName: name]
if (name=="temperature" || name=="heatingSetpoint" || name=="coolingSetpoint" ) {
def sendValue = location.temperatureScale == "C"? roundC(convertFtoC(value.toDouble())) : value.toInteger()
isChange = isTemperatureStateChange(device, name, value.toString())
isDisplayed = isChange
event << [value: sendValue, unit: temperatureScale, isStateChange: isChange, displayed: isDisplayed]
event << [value: sendValue, unit: temperatureScale]
} else if (name=="maxCoolingSetpoint" || name=="minCoolingSetpoint" || name=="maxHeatingSetpoint" || name=="minHeatingSetpoint") {
def sendValue = location.temperatureScale == "C"? roundC(convertFtoC(value.toDouble())) : value.toInteger()
event << [value: sendValue, unit: temperatureScale, displayed: false]
} else if (name=="heatMode" || name=="coolMode" || name=="autoMode" || name=="auxHeatMode"){
isChange = isStateChange(device, name, value.toString())
event << [value: value.toString(), isStateChange: isChange, displayed: false]
if (value == true) {
supportedThermostatModes << ((name == "auxHeatMode") ? "auxheatonly" : name - "Mode")
}
return // as we don't want to send this event here, proceed to next name/value pair
} else if (name=="thermostatFanMode"){
isChange = isStateChange(device, name, value.toString())
event << [value: value.toString(), isStateChange: isChange, displayed: false]
sendEvent(name: "supportedThermostatFanModes", value: fanModes(), displayed: false)
event << [value: value.toString(), data:[supportedThermostatFanModes: fanModes()]]
} else if (name=="humidity") {
isChange = isStateChange(device, name, value.toString())
event << [value: value.toString(), isStateChange: isChange, displayed: false, unit: "%"]
event << [value: value.toString(), displayed: false, unit: "%"]
} else if (name == "deviceAlive") {
isChange = isStateChange(device, name, value.toString())
event['isStateChange'] = isChange
event['displayed'] = false
} else if (name == "thermostatMode") {
def mode = value.toString()
mode = (mode == "auxHeatOnly") ? "emergency heat" : mode
isChange = isStateChange(device, name, mode)
event << [value: mode, isStateChange: isChange, displayed: isDisplayed]
thermostatMode = value.toLowerCase()
return // as we don't want to send this event here, proceed to next name/value pair
} else {
isChange = isStateChange(device, name, value.toString())
isDisplayed = isChange
event << [value: value.toString(), isStateChange: isChange, displayed: isDisplayed]
event << [value: value.toString()]
}
sendEvent(event)
}
if (state.supportedThermostatModes != supportedThermostatModes) {
state.supportedThermostatModes = supportedThermostatModes
sendEvent(name: "supportedThermostatModes", value: supportedThermostatModes, displayed: false)
}
if (thermostatMode) {
sendEvent(name: "thermostatMode", value: thermostatMode, data:[supportedThermostatModes:state.supportedThermostatModes], linkText: linkText,
descriptionText: getThermostatDescriptionText("thermostatMode", thermostatMode, linkText), handlerName: "thermostatMode")
}
generateSetpointEvent ()
generateStatusEvent ()
}
@@ -322,15 +324,7 @@ void resumeProgram() {
}
def modes() {
if (state.modes) {
log.debug "Modes = ${state.modes}"
return state.modes
}
else {
state.modes = parent.availableModes(this)
log.debug "Modes = ${state.modes}"
return state.modes
}
return state.supportedThermostatModes
}
def fanModes() {
@@ -413,11 +407,13 @@ def setThermostatFanMode(String mode) {
}
def generateModeEvent(mode) {
sendEvent(name: "thermostatMode", value: mode, descriptionText: "$device.displayName is in ${mode} mode", displayed: true)
sendEvent(name: "thermostatMode", value: mode, data:[supportedThermostatModes: state.supportedThermostatModes],
descriptionText: "$device.displayName is in ${mode} mode")
}
def generateFanModeEvent(fanMode) {
sendEvent(name: "thermostatFanMode", value: fanMode, descriptionText: "$device.displayName fan is in ${fanMode} mode", displayed: true)
sendEvent(name: "thermostatFanMode", value: fanMode, data:[supportedThermostatFanModes: fanModes()],
descriptionText: "$device.displayName fan is in ${fanMode} mode")
}
def generateOperatingStateEvent(operatingState) {
@@ -453,14 +449,14 @@ def heat() {
}
def emergencyHeat() {
auxHeatOnly()
auxheatonly()
}
def auxHeatOnly() {
log.debug "auxHeatOnly = emergency heat"
def auxheatonly() {
log.debug "auxheatonly()"
def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.setMode ("auxHeatOnly", deviceId))
generateModeEvent("emergency heat") // emergency heat = auxHeatOnly
generateModeEvent("auxheatonly")
else {
log.debug "Error setting new mode."
def currentMode = device.currentState("thermostatMode")?.value
@@ -593,7 +589,7 @@ def generateSetpointEvent() {
} else if (mode == "off") {
sendEvent("name":"thermostatSetpoint", "value":averageSetpoint, "unit":location.temperatureScale)
sendEvent("name":"displayThermostatSetpoint", "value":"Off", displayed: false)
} else if (mode == "emergency heat") { // emergency heat = auxHeatOnly
} else if (mode == "auxheatonly") {
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
sendEvent("name":"displayThermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale, displayed: false)
}
@@ -632,7 +628,7 @@ void raiseSetpoint() {
targetvalue = thermostatSetpoint ? thermostatSetpoint : 0
targetvalue = location.temperatureScale == "F"? targetvalue + 1 : targetvalue + 0.5
if ((mode == "heat" || mode == "emergency heat") && targetvalue > maxHeatingSetpoint) { // emergency heat = auxHeatOnly
if ((mode == "heat" || mode == "auxheatonly") && targetvalue > maxHeatingSetpoint) {
targetvalue = maxHeatingSetpoint
} else if (mode == "cool" && targetvalue > maxCoolingSetpoint) {
targetvalue = maxCoolingSetpoint
@@ -678,7 +674,7 @@ void lowerSetpoint() {
targetvalue = thermostatSetpoint ? thermostatSetpoint : 0
targetvalue = location.temperatureScale == "F"? targetvalue - 1 : targetvalue - 0.5
if ((mode == "heat" || mode == "emergency heat") && targetvalue < minHeatingSetpoint) { // emergency heat = auxHeatOnly
if ((mode == "heat" || mode == "auxheatonly") && targetvalue < minHeatingSetpoint) {
targetvalue = minHeatingSetpoint
} else if (mode == "cool" && targetvalue < minCoolingSetpoint) {
targetvalue = minCoolingSetpoint
@@ -719,7 +715,7 @@ void alterSetpoint(temp) {
}
//step1: check thermostatMode, enforce limits before sending request to cloud
if (mode == "heat" || mode == "emergency heat"){ // emergency heat = auxHeatOnly
if (mode == "heat" || mode == "auxheatonly"){
if (temp.value > coolingSetpoint){
targetHeatingSetpoint = temp.value
targetCoolingSetpoint = temp.value
@@ -754,7 +750,7 @@ void alterSetpoint(temp) {
log.debug "alterSetpoint in mode $mode succeed change setpoint to= ${temp.value}"
} else {
log.error "Error alterSetpoint()"
if (mode == "heat" || mode == "emergency heat"){ // emergency heat = auxHeatOnly
if (mode == "heat" || mode == "auxheatonly"){
sendEvent("name": "thermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false)
sendEvent("name": "displayThermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false)
} else if (mode == "cool") {
@@ -783,7 +779,7 @@ def generateStatusEvent() {
log.debug "Cooling set point = ${coolingSetpoint}"
log.debug "HVAC Mode = ${mode}"
if (mode == "heat") {
if (mode == "heat" || mode == "auxheatonly") {
if (temperature >= heatingSetpoint) {
statusText = "Right Now: Idle"
} else {
@@ -806,8 +802,6 @@ def generateStatusEvent() {
}
} else if (mode == "off") {
statusText = "Right Now: Off"
} else if (mode == "emergency heat") { // emergency heat = auxHeatOnly
statusText = "Emergency Heat"
} else {
statusText = "?"
}

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

@@ -16,7 +16,7 @@
* Date: 2013-03-05
*/
metadata {
definition (name: "SmartAlert Siren", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.smokedetector") {
definition (name: "SmartAlert Siren", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.smoke") {
capability "Actuator"
capability "Switch"
capability "Sensor"

View File

@@ -23,7 +23,6 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Light"
capability "Outlet"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3200", deviceJoinName: "Outlet"

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

@@ -293,4 +293,4 @@ private byte[] reverseArray(byte[] array) {
i++;
}
return array
}
}

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

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

View File

@@ -0,0 +1,43 @@
# ZigBee Button
Cloud Execution
Works with:
* [OSRAM LIGHTIFY Dimming Switch](https://support.smartthings.com/hc/en-us/articles/115000236823-SYLVANIA-Dimming-Switch)
* [Iris Smart Button](https://support.smartthings.com/hc/en-us/articles/115000190186-Iris-Smart-Button)
* [Iris KeyFob](https://support.smartthings.com/hc/en-us/articles/217409686-Iris-Smart-Fob)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Troubleshooting](#troubleshooting)
## Capabilities
* **Actuator** - It represents that a device has commands.
* **Battery** - It defines that the device has a battery
* **Button** - It defines that a device has one or more buttons
* **Holdable Button** - It defines that a device has one or more holdable buttons
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Refresh** - _refresh()_ command for status updates
* **Sensor** - it represents that a Device has attributes.
* **Health Check** - indicates ability to get device health notifications
## Device Health
SmartThings platform will ping the device after `checkInterval` seconds of inactivity in last attempt to reach the device before marking it `OFFLINE`
* __722min__ checkInterval
## Troubleshooting
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that the device is out of range.
Pairing needs to be tried again by placing the device closer to the hub.
It may also happen that you need to reset the device.
Instructions related to pairing, resetting and removing the device from SmartThings can be found in the following link:
* [OSRAM LIGHTIFY Dimming Switch Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/115000236823-SYLVANIA-Dimming-Switch)
* [Iris Smart Button Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/115000190186-Iris-Smart-Button)
* [Iris KeyFob Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/217409686-Iris-Smart-Fob)

View File

@@ -24,6 +24,7 @@ metadata {
capability "Configuration"
capability "Refresh"
capability "Sensor"
capability "Health Check"
command "enrollResponse"
@@ -182,6 +183,13 @@ private Map parseNonIasButtonMessage(Map descMap){
}
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
refresh()
}
def refresh() {
log.debug "Refreshing Battery"
@@ -190,6 +198,8 @@ def refresh() {
}
def configure() {
// Device-Watch allows 2 check-in misses from device (plus 2 mins lag time)
sendEvent(name: "checkInterval", value: 2 * 6 * 60 * 60 + 2 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def cmds = []
if (device.getDataValue("model") == "3450-L") {

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

@@ -88,11 +88,20 @@ def updated(){
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
}
def getCommandClassVersions() {
[
0x20: 1, // Basic
0x26: 1, // SwitchMultilevel
0x56: 1, // Crc16Encap
0x70: 1, // Configuration
]
}
def parse(String description) {
def result = null
if (description != "updated") {
log.debug "parse() >> zwave.parse($description)"
def cmd = zwave.parse(description, [0x20: 1, 0x26: 1, 0x70: 1])
def cmd = zwave.parse(description, commandClassVersions)
if (cmd) {
result = zwaveEvent(cmd)
}
@@ -159,6 +168,16 @@ def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelS
[createEvent(name:"switch", value:"on"), response(zwave.switchMultilevelV1.switchMultilevelGet().format())]
}
def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd) {
def versions = commandClassVersions
def version = versions[cmd.commandClass as Integer]
def ccObj = version ? zwave.commandClass(cmd.commandClass, version) : zwave.commandClass(cmd.commandClass)
def encapsulatedCommand = ccObj?.command(cmd.command)?.parse(cmd.data)
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren't interested in
[:]

View File

@@ -113,9 +113,9 @@ def updated() {
def configure() {
commands([
zwave.manufacturerSpecificV2.manufacturerSpecificGet(),
zwave.batteryV1.batteryGet()
], 6000)
zwave.sensorBinaryV2.sensorBinaryGet(sensorType: zwave.sensorBinaryV2.SENSOR_TYPE_DOOR_WINDOW),
zwave.manufacturerSpecificV2.manufacturerSpecificGet()
], 1000)
}
def sensorValueEvent(value) {
@@ -190,11 +190,17 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
cmds << command(zwave.manufacturerSpecificV2.manufacturerSpecificGet())
cmds << "delay 1200"
}
if (device.currentValue("contact") == null) { // Incase our initial request didn't make it
cmds << command(zwave.sensorBinaryV2.sensorBinaryGet(sensorType: zwave.sensorBinaryV2.SENSOR_TYPE_DOOR_WINDOW))
}
if (!state.lastbat || now() - state.lastbat > 53*60*60*1000) {
cmds << command(zwave.batteryV1.batteryGet())
} else {
} else { // If we check the battery state we will send NoMoreInfo in the handler for BatteryReport so that we definitely get the report
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
}
[event, response(cmds)]
}

View File

@@ -86,13 +86,13 @@ import physicalgraph.zwave.commands.doorlockv1.*
import physicalgraph.zwave.commands.usercodev1.*
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])
// Device-Watch pings if no device events received for 1 hour (checkInterval)
sendEvent(name: "checkInterval", value: 1 * 60 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
}
def updated() {
// 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])
// Device-Watch pings if no device events received for 1 hour (checkInterval)
sendEvent(name: "checkInterval", value: 1 * 60 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
try {
if (!state.init) {
state.init = true
@@ -152,6 +152,10 @@ def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityCommandsSupported
def zwaveEvent(DoorLockOperationReport cmd) {
def result = []
unschedule("followupStateCheck")
unschedule("stateCheck")
def map = [ name: "lock" ]
if (cmd.doorLockMode == 0xFF) {
map.value = "locked"
@@ -365,7 +369,7 @@ def zwaveEvent(UserCodeReport cmd) {
code = state["set$name"] ?: decrypt(state[name]) ?: "****"
state.remove("set$name".toString())
} else {
map = [ name: "codeReport", value: cmd.userIdentifier, data: [ code: code ] ]
map = [ name: "codeReport", value: cmd.userIdentifier, data: [ code: code ], isStateChange: true ]
map.descriptionText = "$device.displayName code $cmd.userIdentifier is set"
map.displayed = (cmd.userIdentifier != state.requestCode && cmd.userIdentifier != state.pollCode)
map.isStateChange = true
@@ -456,11 +460,12 @@ def zwaveEvent(physicalgraph.zwave.commands.timev1.TimeGet cmd) {
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
// The old Schlage locks use group 1 for basic control - we don't want that, so unsubscribe from group 1
def result = [ createEvent(name: "lock", value: cmd.value ? "unlocked" : "locked") ]
result << response(zwave.associationV1.associationRemove(groupingIdentifier:1, nodeId:zwaveHubNodeId))
if (state.assoc != zwaveHubNodeId) {
result << response(zwave.associationV1.associationGet(groupingIdentifier:2))
}
result
def cmds = [
zwave.associationV1.associationRemove(groupingIdentifier:1, nodeId:zwaveHubNodeId).format(),
"delay 1200",
zwave.associationV1.associationGet(groupingIdentifier:2).format()
]
[result, response(cmds)]
}
def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
@@ -530,11 +535,18 @@ def unlockwtimeout() {
lockAndCheck(DoorLockOperationSet.DOOR_LOCK_MODE_DOOR_UNSECURED_WITH_TIMEOUT)
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
refresh()
runIn(30, followupStateCheck)
secure(zwave.doorLockV1.doorLockOperationGet())
}
def followupStateCheck() {
runEvery1Hour(stateCheck)
stateCheck()
}
def stateCheck() {
sendHubCommand(new physicalgraph.device.HubAction(secure(zwave.doorLockV1.doorLockOperationGet())))
}
def refresh() {

View File

@@ -85,11 +85,21 @@ metadata {
details(["switch", "power", "energy", "levelSliderControl", "refresh", "reset"])
}
def getCommandClassVersions() {
[
0x20: 1, // Basic
0x26: 3, // SwitchMultilevel
0x56: 1, // Crc16Encap
0x70: 1, // Configuration
0x32: 3, // Meter
]
}
// parse events into attributes
def parse(String description) {
def result = null
if (description != "updated") {
def cmd = zwave.parse(description, [0x20: 1, 0x26: 3, 0x70: 1, 0x32:3])
def cmd = zwave.parse(description, commandClassVersions)
if (cmd) {
result = zwaveEvent(cmd)
log.debug("'$description' parsed to $result")
@@ -124,6 +134,21 @@ def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelR
dimmerEvents(cmd)
}
def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd) {
def versions = commandClassVersions
def version = versions[cmd.commandClass as Integer]
def ccObj = version ? zwave.commandClass(cmd.commandClass, version) : zwave.commandClass(cmd.commandClass)
def encapsulatedCommand = ccObj?.command(cmd.command)?.parse(cmd.data)
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren't interested in
[:]
}
def dimmerEvents(physicalgraph.zwave.Command cmd) {
def result = []
def value = (cmd.value ? "on" : "off")

View File

@@ -89,10 +89,19 @@ def updated() {
} catch (e) { log.debug e }
}
def getCommandClassVersions() {
[
0x20: 1, // Basic
0x32: 1, // SwitchMultilevel
0x56: 1, // Crc16Encap
0x72: 2, // ManufacturerSpecific
]
}
def parse(String description) {
def result = null
if(description == "updated") return
def cmd = zwave.parse(description, [0x20: 1, 0x32: 1, 0x72: 2])
def cmd = zwave.parse(description, commandClassVersions)
if (cmd) {
result = zwaveEvent(cmd)
}
@@ -157,6 +166,16 @@ def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerS
result
}
def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd) {
def versions = commandClassVersions
def version = versions[cmd.commandClass as Integer]
def ccObj = version ? zwave.commandClass(cmd.commandClass, version) : zwave.commandClass(cmd.commandClass)
def encapsulatedCommand = ccObj?.command(cmd.command)?.parse(cmd.data)
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
log.debug "$device.displayName: Unhandled: $cmd"
[:]

View File

@@ -16,7 +16,7 @@
* Date: 2014-07-15
*/
metadata {
definition (name: "Z-Wave Siren", namespace: "smartthings", author: "SmartThings") {
definition (name: "Z-Wave Siren", namespace: "smartthings", author: "SmartThings", ocfDeviceType: "x.com.st.d.sensor.smoke") {
capability "Actuator"
capability "Alarm"
capability "Battery"

View File

@@ -71,9 +71,17 @@ def updated(){
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
}
def getCommandClassVersions() {
[
0x20: 1, // Basic
0x56: 1, // Crc16Encap
0x70: 1, // Configuration
]
}
def parse(String description) {
def result = null
def cmd = zwave.parse(description, [0x20: 1, 0x70: 1])
def cmd = zwave.parse(description, commandClassVersions)
if (cmd) {
result = createEvent(zwaveEvent(cmd))
}
@@ -120,6 +128,15 @@ def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerS
createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false])
}
def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd) {
def versions = commandClassVersions
def version = versions[cmd.commandClass as Integer]
def ccObj = version ? zwave.commandClass(cmd.commandClass, version) : zwave.commandClass(cmd.commandClass)
def encapsulatedCommand = ccObj?.command(cmd.command)?.parse(cmd.data)
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren't interested in

View File

@@ -89,9 +89,17 @@ def updated(){
}
}
def getCommandClassVersions() {
[
0x20: 1, // Basic
0x56: 1, // Crc16Encap
0x70: 1, // Configuration
]
}
def parse(String description) {
def result = null
def cmd = zwave.parse(description, [0x20: 1, 0x70: 1])
def cmd = zwave.parse(description, commandClassVersions)
if (cmd) {
result = createEvent(zwaveEvent(cmd))
}
@@ -138,6 +146,16 @@ def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerS
createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false])
}
def zwaveEvent(physicalgraph.zwave.commands.crc16encapv1.Crc16Encap cmd) {
def versions = commandClassVersions
def version = versions[cmd.commandClass as Integer]
def ccObj = version ? zwave.commandClass(cmd.commandClass, version) : zwave.commandClass(cmd.commandClass)
def encapsulatedCommand = ccObj?.command(cmd.command)?.parse(cmd.data)
if (encapsulatedCommand) {
zwaveEvent(encapsulatedCommand)
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren't interested in

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
*