Compare commits

..

347 Commits

Author SHA1 Message Date
Kevin Shuk
a9aee8fd96 Merge pull request #1367 from surfous/DVCSMP-2134-2135-ZLL-bulb-hchk2
Add health check for:
* DVCSMP-2134 ZLL white color temperature bulb
* DVCSMP-2135 ZLL dimmer bulb
2016-10-19 22:48:28 -07:00
Kevin Shuk
5c015cf678 DVCSMP-2135 health check ZLL dimmable bulb
* checkInterval set to 12 min (2 misses + leeway)
* configure a healthPoll every 5 min
 * refreshes on/off state, switch level, and white color temperature
 * schedule and set interval from either configure() or updated()
  * but only once per execution
* ping refreshes level setting
2016-10-19 22:40:23 -07:00
Kevin Shuk
cf1a46e309 DVCSMP-2134 health check ZLL white color temp bulb
* checkInterval set to 12 min (2 misses + leeway)
* configure a healthPoll every 5 min
 * refreshes on/off state, switch level, and white color temperature
 * schedule and set interval from either configure() or updated()
  * but only once per execution
* ping refreshes level setting
2016-10-19 22:38:57 -07:00
Jack Chi
1ff77dc608 Merge pull request #1355 from skt123/zwave_switch
[CHF-425] Health Check Implementation for Z-wave switch
2016-10-18 22:53:40 -07:00
Jack Chi
afbec02217 Merge pull request #1281 from parijatdas/leviton
[CHF-404] [CHF-422] Health check for Leviton DZPA1 Plug-in Appliance Module and GE Plug-In Outdoor Smart Switch (GE 12720) (Z-Wave)
2016-10-18 22:51:44 -07:00
Jack Chi
434a72bd13 Merge pull request #1292 from pchomal/zwave_dimmer
CHF-406
2016-10-18 22:50:14 -07:00
sushant.k1
3fba7c9422 Added Health Check Implementation for following Z-wave switches:
1. Plug-In Smart Switch (GE 12719)
2. In-Wall Smart Outlet (GE 12721)
3. In-Wall Smart Switch (GE 12722)
4. In-Wall Smart Toggle Switch (GE 12727)

Added Health Check Implementation for following Z-wave switches:
1. Plug-In Smart Switch (GE 12719)
2. In-Wall Smart Outlet (GE 12721)
3. In-Wall Smart Switch (GE 12722)
4. In-Wall Smart Toggle Switch (GE 12727)
2016-10-19 10:18:38 +05:30
piyush.c
b63d4a9156 CHF-406
Updated HealthCheck Implementation for Z-wave Dimmer (GE 12718, GE 12724, GE 12729) with checkInterval of 32min
2016-10-19 10:06:38 +05:30
Parijat Das
6eb29ad019 Added health check for Leviton DZPA1 Plug-in Appliance Module and GE Plug-In Outdoor Smart Switch (GE 12720) (Z-Wave) along with the README.md 2016-10-19 08:45:53 +05:30
Vinay Rao
711cdc3ebf Merge pull request #1370 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-10-18 18:48:17 -07:00
Vinay Rao
f58a1ef589 Merge pull request #1369 from workingmonk/bug/osram_name
DVCSMP-1447 adding missing deviceJoinName in the generic dth
2016-10-18 18:47:35 -07:00
Vinay Rao
db5237ca33 adding missing deviceJoinName in the generic dth 2016-10-18 18:45:27 -07:00
Vinay Rao
7791c68a8a Merge pull request #1364 from SmartThingsCommunity/master
Rolling up master to staging
2016-10-18 14:40:53 -07:00
Vinay Rao
db4140ffd6 Merge pull request #1363 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-10-18 14:39:44 -07:00
Vinay Rao
ac422076c8 Merge pull request #1361 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2016-10-18 14:02:37 -07:00
Lars Finander
c11c146690 Merge pull request #1349 from larsfinander/DVCSMP-2131_Philips_Hue_Handle_invalid_username_staging
DVCSMP-2131 Philips Hue: Handle case if bridge username becomes invalid
2016-10-18 10:39:02 -06:00
Lars Finander
9a5d506668 DVCSMP-2131 Philips Hue: Handle case if bridge username becomes invalid 2016-10-14 16:18:51 -06:00
Zach Varberg
723ef7e7e6 Merge pull request #1343 from varzac/fix-button-zone-status
[DPROT-180] Correctly parse zone status in zigbee-button
2016-10-14 09:28:17 -05:00
Zach Varberg
84c72de640 Merge pull request #1345 from varzac/handle-both-mfg-temp-humidity
[DPROT-183] Handle both mfgIDs for temp-humidity sensors
2016-10-14 09:26:01 -05:00
Zach Varberg
570454e6c3 Merge pull request #1341 from varzac/swap-refresh-configure-order
[DPROT-177] Call refresh before configure
2016-10-14 09:25:44 -05:00
Zach Varberg
a5d95fb025 Correctly parse zone status in zigbee-button
Previously the DTH didn't handle the extended status from zone status
reporting.  This moves to use the library for parsing zone status
which will handle the extended status properly.

This resolves: https://smartthings.atlassian.net/browse/DPROT-180
2016-10-14 09:09:04 -05:00
Zach Varberg
50696902cf Handle both mfgIDs for temp-humidity sensors
With upcoming OTA support for ZigBee end devices centralite devices
change manufacturer IDs between versions.  As a result when reading a
manufacturer specific value, we have to handle the possibility of either
mfgID being correct.  The simplest solution (and the one employed here)
was to simply read the attribute using both mfgIDs and ignoring null
responses.

This resolves: https://smartthings.atlassian.net/browse/DPROT-183
2016-10-13 13:28:50 -05:00
Zach Varberg
409658e899 Call refresh before configure
With the changes in https://smartthings.atlassian.net/browse/DPROT-168
it can take a little longer for the configuration process for a device
to complete.  As a result sensor values may not be available immediately
by calling the refresh commands before the configure commands we can
populate those values sooner.

This resolves: https://smartthings.atlassian.net/browse/DPROT-177
2016-10-13 09:51:22 -05:00
Vinay Rao
1068a553f5 Merge pull request #1339 from workingmonk/feature/rgb_dth
DVCSMP-1447 Support for RGB ZigBee DTH
2016-10-12 12:40:20 -07:00
Vinay Rao
bbdf9ff02a DVCSMP-1447 Support for RGB ZigBee DTH 2016-10-12 12:39:54 -07:00
Vinay Rao
9dac541473 Merge pull request #1338 from jackchi/health-checkInterval-value-fix
[CHF-417] Fix for onOffConfig older periodic values
2016-10-11 16:22:12 -07:00
jackchi
a6cc506803 [CHF-417] Fix for onOffConfig older periodic values 2016-10-11 16:18:06 -07:00
Vinay Rao
aba8a7ad4b Merge pull request #1337 from SmartThingsCommunity/master
Rolling up master to staging
2016-10-11 14:18:00 -07:00
Vinay Rao
b4c912ab80 Merge pull request #1336 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
2016-10-11 13:23:51 -07:00
Vinay Rao
f5b7dfd4eb Merge branch 'staging'
# Conflicts:
#	devicetypes/smartthings/cree-bulb.src/cree-bulb.groovy
#	smartapps/smartthings/logitech-harmony-connect.src/logitech-harmony-connect.groovy
2016-10-11 12:12:31 -07:00
Jack Chi
3e0306e912 Merge pull request #1330 from jackchi/healthcheck-chf417
[DVCSMP-2117] Fix NPE for unknown descriptions in parse
2016-10-10 10:15:57 -07:00
jackchi
2c2d75ae37 [DVCSMP-2117] Fix NPE for unknown descriptions in parse 2016-10-10 09:02:59 -07:00
Lars Finander
61ef40831c Merge pull request #1327 from larsfinander/DVCSMP-2043_OSRAM_Saturation_fix_staging
DVCSMP-2043 OSRAM: Saturation values are not updated in older firmwares
2016-10-10 09:56:19 -06:00
Lars Finander
19169748df DVCSMP-2043 OSRAM: Saturation values are not updated in older firmwares 2016-10-10 09:55:04 -06:00
Jack Chi
0f5a2c5e21 Merge pull request #1320 from jackchi/healthcheck-chf417
[CHF-417] [CHF-416] Health Check devices enroll with right checkInterval
2016-10-07 15:49:06 -07:00
jackchi
6dbb61536b [CHF-417] [CHF-416] Health Check devices enroll with appropriate checkInterval 2016-10-07 15:18:28 -07:00
dsainteclaire
84323afa04 Merge pull request #1324 from james-smartthings/DVCSMP-2097-add-alterSetpoint-check
alterSetpoint - check for auto or off mode
2016-10-07 10:03:08 -07:00
Juan Pablo Risso
04a7627c21 DVCSMP-2104 - Harmony - Fix Exceptions, improve logging (#1322) 2016-10-07 11:34:44 -04:00
James Chen
12b09acfa8 alterSetpoint - check for auto or off mode
changed debug message
2016-10-06 16:02:09 -07:00
bflorian
9e8ad0dfdf Merge pull request #1323 from bflorian/PROB-1359-fibaro-motion-temperature
PROB-1359 set Fibaro motion ZW5 temperature scale properly
2016-10-06 11:29:48 -07:00
bflorian
80eb1e43b9 PROB-1359 set Fibaro motion ZW5 temperature scale properly 2016-10-06 10:22:51 -07:00
Lars Finander
af383de368 Merge pull request #1315 from larsfinander/DVCSMP-2101_Philips_Hue_Exception_lights_removed__staging
DVCSMP-2101 Philips Hue: Exception if lights removed outside of ST
2016-10-05 13:34:50 -06:00
Juan Pablo Risso
427fa88ed8 Harmony - Fix Exceptions (#1321)
response.status
2016-10-05 14:33:38 -04:00
Jack Chi
57514944d5 Merge pull request #1139 from parijatdas/CHF-156_NYCE_sensor
[CHF-156] Health Check NYCE Door/Window Sensor NCZ-3011
2016-10-05 09:34:01 -07:00
Parijat Das
823efed562 Added health checks for NYCE open/closed sensor
checkInterval value determined and added
Implemented ping functionality
Fixed indentation in the metadata section
2016-10-05 08:24:08 +05:30
Jack Chi
540db429f3 Merge pull request #1270 from jackchi/cree-schedule-fix
[CHF-374] Better healthPoll scheduling for Cree Bulb
2016-10-04 16:13:10 -07:00
Jack Chi
0c3a5de661 Merge pull request #1314 from parijatdas/category_removal
[CHF-402] Removing categorization from DTHs
2016-10-04 15:48:52 -07:00
Vinay Rao
989f08708b Merge pull request #1319 from SmartThingsCommunity/master
Rolling up master to staging for next week deploy
2016-10-04 15:05:01 -07:00
Vinay Rao
60e09c56b7 Merge pull request #1318 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-10-04 15:04:25 -07:00
Vinay Rao
9f5eb7b85a Merge pull request #1316 from SmartThingsCommunity/staging
Rolling up staging to prod for deployment
2016-10-04 14:41:53 -07:00
Lars Finander
62b37f5c3d DVCSMP-2101 Philips Hue: Exception if lights removed outside of ST 2016-10-04 14:08:57 -06:00
Lars Finander
64e4ccc517 Merge pull request #1311 from larsfinander/CHF-413_hue_unavailable_16minutes_staging
CHF-413 Philips Hue bulb shows unavailable after 16minutes and
2016-10-04 10:33:00 -06:00
Parijat Das
c17830ab56 Removed categorization in DTHs for the following devices:
1. SmartSense Moisture Sensor
2. SmartSense Temp/Humidity Sensor
3. SmartSense Multi Sensor
4. SmartSense Open/closed Sensor
5. SmartPower Outlet
6. SmartSense Motion Sensor
7. OSRAM Lightify LED On/Off/Dim
8. OSRAM Lightify LED RGBW
9. OSRAM Lightify Tunable 60 White
10. Tyco Door/Window Sensor
2016-10-04 18:19:41 +05:30
Lars Finander
aa890ae3d5 CHF-413 Philips Hue bulb shows unavailable after 16minutes and
CHF-412 Hue Bridge shows OFFLINE instead of "Unavailable"
2016-10-03 14:36:15 -06:00
Lars Finander
8d701b9fea Merge pull request #1298 from dsainteclaire/DVCSMP-2087-device-temperature-unit-wrong-type
DVCSMP-2087 changed deviceTemperatureUnit attribute to be type string
2016-10-03 09:39:50 -06:00
Jack Chi
c7f78a69e4 Merge pull request #1307 from pchomal/tycosensor
CHF-273
2016-09-30 14:25:16 -07:00
Jack Chi
80500207a8 Merge pull request #1285 from jackchi/health-hardwareid
[CHF-392] Add Hub Hardware ID to Device-Watch
2016-09-29 14:54:40 -07:00
piyush.c
29db335e1c CHF-273
Updated Tyco Door/Window Sensor
2016-09-29 16:48:46 +05:30
Jack Chi
55b5b7d03d Merge pull request #1269 from pchomal/tyco_new
CHF-273
2016-09-28 16:51:14 -07:00
piyush.c
730ccccd45 CHF-273
Updated Health Check capability implementation for "Tyco-Door-Window-Sensor".
2016-09-28 12:35:02 +05:30
Vinay Rao
719b24ecd6 Merge pull request #1304 from SmartThingsCommunity/master
Rolling up master to staging
2016-09-27 14:39:24 -07:00
Vinay Rao
9d5ab3bfc8 Merge pull request #1303 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-09-27 14:38:13 -07:00
Vinay Rao
aae7f23a22 Merge pull request #1302 from SmartThingsCommunity/staging
Rolling up staging for production deployment
2016-09-27 14:14:57 -07:00
Juan Pablo Risso
218cc43520 DVCSMP-2089 - Harmony - Make HTTP Requests Async (#1299) 2016-09-27 15:43:37 -04:00
David Sainte-Claire
5b0ca4b815 changed deviceTemperatureUnit attribute to be type string 2016-09-27 07:48:54 -07:00
Zach Varberg
9ddc020f04 Merge pull request #1248 from varzac/add-send-to-raw-messages
Add explicit send commands for zigbee raw
2016-09-27 09:07:55 -05:00
Vinay Rao
aab3b8d7f8 Merge pull request #1297 from workingmonk/feature/temp_rounding
SSVD-2897 to round celsius and fix rounding on fahrenheit
2016-09-26 14:40:42 -07:00
Vinay Rao
a0ccf35eaa SSVD-2897 to round celsius and fix rounding on fahrenheit 2016-09-26 14:39:07 -07:00
Steve Vlaminck
9fbbaec8f6 Merge pull request #1296 from vlaminck/GWU-completion-percentage-fix
Fix: Cleanup event feed when dimming cycle ends
2016-09-26 14:21:31 -05:00
vlaminck
e4c1824afd Fix: reorder events so the feed makes more sense 2016-09-26 14:18:31 -05:00
vlaminck
797a58cb68 Fix: hide reset events 2016-09-26 14:14:55 -05:00
vlaminck
c428267d63 Fix: stop sending 100 percent from completion 2016-09-26 14:05:03 -05:00
Vinay Rao
02f30cf425 Merge pull request #1295 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2016-09-26 11:50:24 -07:00
Lars Finander
fea802ffce Merge pull request #1294 from larsfinander/DVCSMP-2070_Philips_Hue_unreachable_devices_staging
DVCSMP-2070 Philips Hue: No commands sent if light is unreachable
2016-09-26 12:06:57 -06:00
Lars Finander
6400d26f4a DVCSMP-2070 Philips Hue: No commands sent if light is unreachable
-PROB-1384
2016-09-26 11:59:48 -06:00
Lars Finander
5e3aaa3270 Merge pull request #1293 from larsfinander/DVCSMP-2081_Philips_Hue_650k_exceptions_staging
DVCSMP-2081 Philips Hue: Bridge is throwing 650k exceptions a day
2016-09-26 11:52:12 -06:00
Lars Finander
f5c3997679 DVCSMP-2081 Philips Hue: Bridge is throwing 650k exceptions a day 2016-09-26 10:21:03 -06:00
Jason Botello
81cf1179ef Merge pull request #985 from SmartThingsCommunity/MSA-1351-2
MSA-1351: Gideon AI implementation
2016-09-23 13:38:52 -07:00
jackchi
7113d7470e [CHF-392] Add Hub Hardware ID to Device-Watch 2016-09-22 16:03:25 -07:00
Juan Pablo Risso
79d20b0edb SSVD-2740 - Remove zipcode input (#1267)
Limit to samsungtv channel
2016-09-22 18:59:07 -04:00
twack
b6d862fdd4 Merge pull request #1283 from twack/update_generic_zigbee_for_yale
(PROD-736) Update generic zigbee lock for Yale Key-Free Deadbolt. Requested changes incorporated.
2016-09-22 14:40:30 -07:00
twack
d58084c438 Update zigbee-lock.groovy 2016-09-22 12:06:29 -07:00
Juan Pablo Risso
dbfaef3e69 DVCSMP-2076 - Async Update (#1279) 2016-09-22 14:55:25 -04:00
twack
40ed88e7fd Changed name to be consistent
Changed name to be consistent with "Yale Touch Screen Deadbolt Lock"
2016-09-22 11:34:33 -07:00
twack
1d6e22dc16 removed tabs 2016-09-22 11:23:29 -07:00
Lars Finander
30993aa218 Merge pull request #1284 from larsfinander/SSVD-2798_philips_hue_discovery_bridge_staging
SSVD-2798 Philips Hue: Bridge keeps getting unchecked during discovery
2016-09-22 12:11:15 -06:00
Lars Finander
2f8ed277ff SSVD-2798 Philips Hue: Bridge keeps getting unchecked during discovery 2016-09-22 12:07:09 -06:00
twack
1d180ac487 update generic zigbee lock for Yale Key-Free Deadbolt (PROD-736) 2016-09-22 10:19:23 -07:00
Zach Varberg
230541a145 Add explicit send commands for zigbee raw
Previously a few places depended on the dev-conn behavior of
automatically appending a send command after a raw zigbee command.  We
intend to deprecate that behavior and so we are adding explicit sends
where they were missing.
2016-09-22 11:08:30 -05:00
Lars Finander
8c4f7edc83 Merge pull request #1276 from larsfinander/DVCSMP-2057_Philips_Hue_Correct_incorrect_bridge_mac_production
INC-6888 Philips Hue: Correct incorrect bridge mac
2016-09-21 13:11:12 -06:00
Lars Finander
4f188581df INC-6888 Philips Hue: Correct incorrect bridge mac 2016-09-21 11:14:11 -06:00
Jack Chi
71880e2644 Merge pull request #1246 from skt123/osram
CHF-356 : Modifying Readme for Core Devices
2016-09-20 14:24:27 -07:00
Vinay Rao
0b7bb40474 Merge pull request #1274 from SmartThingsCommunity/master
Rolling up master for next week deploy
2016-09-20 12:05:49 -07:00
Vinay Rao
8d920ea072 Merge pull request #1273 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-09-20 12:05:10 -07:00
Vinay Rao
e373b6f92e Merge pull request #1272 from SmartThingsCommunity/staging
Rolling up staging to production for deployment
2016-09-20 11:53:36 -07:00
Vinay Rao
43a1ae6371 Merge pull request #1271 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2016-09-20 11:52:40 -07:00
jackchi
60a98e3074 [CHF-374] Better healthPoll scheduling for Cree Bulb 2016-09-20 11:10:31 -07:00
Vinay Rao
a441b94a33 Merge pull request #1264 from posborne/bugfix/fix-hue-connect-http-headers
PROB-1373: hue: fix HTTP request headers
2016-09-20 08:43:01 -07:00
sushant.k1
ced03d746d Added Readme files for the following devices:
1. OSRAM Lightify LED On/Off/Dim
2. OSRAM Lightify LED RGBW
3. OSRAM Lightify Tunable 60 White

Modified Readme files for the following devices:
1. SmartSense Moisture Sensor
2. SmartSense Temp/Humidity Sensor
3. SmartSense Multi Sensor
4. SmartSense Open/closed Sensor
5. SmartPower Outlet
6. Connected Cree Bulb
7. SmartSense Motion Sensor

Added Readme files for the following devices:
1. OSRAM Lightify LED On/Off/Dim
2. OSRAM Lightify LED RGBW
3. OSRAM Lightify Tunable 60 White

Modified Readme files for the following devices:
1. SmartSense Moisture Sensor
2. SmartSense Temp/Humidity Sensor
3. SmartSense Multi Sensor
4. SmartSense Open/closed Sensor
5. SmartPower Outlet
6. Connected Cree Bulb
7. SmartSense Motion Sensor

Added Readme files for the following devices:
1. OSRAM Lightify LED On/Off/Dim
2. OSRAM Lightify LED RGBW
3. OSRAM Lightify Tunable 60 White

Modified Readme files for the following devices:
1. SmartSense Moisture Sensor
2. SmartSense Temp/Humidity Sensor
3. SmartSense Multi Sensor
4. SmartSense Open/closed Sensor
5. SmartPower Outlet
6. Connected Cree Bulb
7. SmartSense Motion Sensor

Added Readme files for the following devices:
1. OSRAM Lightify LED On/Off/Dim
2. OSRAM Lightify LED RGBW
3. OSRAM Lightify Tunable 60 White

Modified Readme files for the following devices:
1. SmartSense Moisture Sensor
2. SmartSense Temp/Humidity Sensor
3. SmartSense Multi Sensor
4. SmartSense Open/closed Sensor
5. SmartPower Outlet
6. Connected Cree Bulb
7. SmartSense Motion Sensor
2016-09-20 17:20:50 +05:30
Vinay Rao
5341d0d06f Merge pull request #1268 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-09-19 17:22:19 -07:00
Vinay Rao
2a58d7ff62 Merge pull request #1266 from jimmyjames/revert-async-ecobee
Revert "[DVCSMP-1979] Use async http for polling and refresh tokens."
2016-09-19 15:22:20 -07:00
Juan Pablo Risso
260917d515 MKTP-829 - Moving disclaimer to first page (#1261) 2016-09-19 14:01:33 -04:00
Paul Osborne
c1478d3e96 hue: fix HTTP request headers
Previously, the whitespace characters from the file were used for
newlines in HTTP headers.  In order for the HTTP headers sent to
the hue to be valid, line separators must always be \r\n.  Oddly, the
hue seemed to accept and respond to requests with the invalid header
that was being sent but it would cause increased latency for all
other API clients.

In addition to the missing carriage returns, the GET request was also
missing the required blank line which marks the end of the request
headers.

https://smartthings.atlassian.net/browse/PROB-1366
http://status.smartthings.com/incidents/13j8g8g2w7ly
https://community.smartthings.com/t/new-hue-delay/57569
2016-09-19 11:01:52 -05:00
Jim Anderson
8b9bff15dc Revert "[DVCSMP-1979] Use async http for polling and refresh tokens."
This reverts commit 826993cc45.
2016-09-19 09:38:33 -05:00
Lars Finander
75c1ede16c Merge pull request #1260 from larsfinander/SSVD-2737_philips_hue_color_handling_staging
SSVD-2736 Philips Hue: Color Coordinator does not work
2016-09-16 11:33:14 -06:00
Lars Finander
a7acc384a2 SSVD-2736 Philips Hue: Color Coordinator does not work
-SSVD-2631 Double color events
-SSVD-2601 Color picker control does not show the current color
-Changed color model for Philips Hue to use hue/sat instead of x/y
-Added color events in hex
-Added HSV color conversion algorithms
2016-09-16 11:16:31 -06:00
Vinay Rao
c6998e5f1d Merge pull request #1249 from jackchi/healthcheck-12min-checkin
[CHF-363] Set HealthCheck interval to 12 min
2016-09-14 14:37:02 -07:00
jackchi
f95e906d6e [CHF-363] Set HealthCheck interval to 12 min 2016-09-14 13:46:54 -07:00
Juan Pablo Risso
a6c7ab49b6 SSVD-2737 - Temperature Unit (#1247) 2016-09-14 09:43:26 -04:00
Jack Chi
4891e3b947 Merge pull request #1245 from jackchi/healthcheck-5min-reporting
[CHF-353] Cree Bulb polling fix; reads status every 5 minutes
2016-09-13 17:03:19 -07:00
jackchi
ae91f9bff5 [CHF-353] Cree Bulb polling fix; reads status every 5 minutes 2016-09-13 17:01:19 -07:00
Vinay Rao
bb87ad2cf0 Merge pull request #1196 from juano2310/disclaimer
MKTP-829 - Adding disclaimer
2016-09-13 15:13:43 -07:00
Vinay Rao
5dff03fb69 Merge pull request #1244 from SmartThingsCommunity/master
Rolling up master to staging for next week's deploy
2016-09-13 13:46:05 -07:00
Vinay Rao
629d768575 Merge pull request #1243 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-09-13 13:44:38 -07:00
Vinay Rao
dd7c6b90d5 Merge pull request #1241 from SmartThingsCommunity/staging
Rolling up staging to prod for deploy
2016-09-13 12:28:13 -07:00
Andrew Bresee
4523498dab Add parens to unsubscribe method (#1231) 2016-09-13 13:23:55 -04:00
Jason Terhune
e89e45e000 Another circle fix: dependencies task needs artifactory creds too. 2016-09-13 08:47:22 -05:00
Jason Terhune
78ec280e83 Fix circle build. 2016-09-13 08:37:20 -05:00
Jason Terhune-Wold
1f144d36e4 Merge pull request #1221 from jterhune/gradle-compile
Configure gradle to compile devicetypes and smartapps.
2016-09-13 08:30:57 -05:00
Vinay Rao
f5bd580c9e Merge pull request #1240 from juano2310/staging
SSVD-2733 -  Typo fix
2016-09-12 18:00:11 -07:00
juano2310
d5329dbde3 SSVD-2733 - Typo fix 2016-09-12 20:58:36 -04:00
Vinay Rao
48818cfb06 Merge pull request #1239 from larsfinander/CHF-348_philips_hue_staging
CHF-348 Philips Hue: Change offline time to 16 min
2016-09-12 16:23:41 -07:00
Lars Finander
079919260b CHF-348 Philips Hue: Change offline time to 16 min 2016-09-12 17:19:14 -06:00
Vinay Rao
570922e2ac Merge pull request #1238 from jackchi/healthcheck-5min-reporting
[CHF-348] Set 10 VD required devices to report in at 5 minutes
2016-09-12 15:52:29 -07:00
Lars Finander
53ed9b4d2b Merge pull request #1237 from larsfinander/add_hue_offline_events_staging
Add offline events to Philips Hue
2016-09-12 16:49:57 -06:00
jackchi
7149a81c85 [CHF-348] Set 10 VD required devices to report in at 5 minutes 2016-09-12 14:51:57 -07:00
Vinay Rao
30274f0cd7 Merge pull request #914 from jazzslider/motion-labels
Newer Fibaro motion sensor handler needs motion state labels
2016-09-12 13:26:28 -07:00
Jack Chi
8869cd3af0 Merge pull request #1232 from jackchi/healthcheck-all
[CHF-201] Removing DTH workaround now that all events go to Kafka
2016-09-12 10:46:12 -07:00
Jack Chi
fb0caa6446 Merge pull request #1233 from jackchi/healthcheck-removehack
[CHF-201] Removing DTH workaround now that all events go to Kafka
2016-09-12 08:24:10 -07:00
Lars Finander
3d05d42cb8 Add offline events to Philips Hue
-Handles case when bridge goes offline
-Handles case when indiviudual lights go offline
2016-09-11 22:56:24 -06:00
Vinay Rao
3184615e87 Merge pull request #1235 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-09-09 16:50:50 -07:00
Vinay Rao
0f70362e0a Merge pull request #1234 from larsfinander/DVCSMP-2024_OSRAM_Hue_incorrect_staging
DVCSMP-2024 OSRAM: Hue is incorrectly set to be 0-360
2016-09-09 16:49:31 -07:00
Lars Finander
bc817f8530 DVCSMP-2024 OSRAM: Hue is incorrectly set to be 0-360
-Hue changed to handle 0-100 according to SmartThings API
2016-09-09 17:41:46 -06:00
jackchi
01b8399893 [CHF-201] Removing DTH workaround now that all events go to Kafka 2016-09-09 14:58:03 -07:00
jackchi
81318bafac [CHF-201] Removing DTH workaround now that all events go to Kafka 2016-09-09 14:48:19 -07:00
Lars Finander
60c2006bfc Merge pull request #1230 from larsfinander/SSVD-2798_Philips_Hue_discovery_issue
SSVD-2798 Philips Hue: Light discovery UI issue
2016-09-09 11:01:40 -06:00
Lars Finander
1e4f1223e7 SSVD-2798 Philips Hue: Light discovery UI issue
-Keep checked lights in "lights to add list" when page refreshes
2016-09-09 10:50:23 -06:00
Jason Terhune
b78bce55b2 Configure gradle to compile devicetypes and smartapps. 2016-09-09 09:41:11 -05:00
Vinay Rao
01593c3973 Merge pull request #1229 from SmartThingsCommunity/staging
Rolling down hotfix to master
2016-09-08 19:34:52 -07:00
Vinay Rao
6862785d6c Merge pull request #1228 from SmartThingsCommunity/production
Rolling down hotfix to staging
2016-09-08 19:33:26 -07:00
Amol Mundayoor
763d7411e2 Merge pull request #1227 from munds/netatmo
Removing debug logs for netatmo
2016-09-08 11:22:42 -07:00
Amol Mundayoor
c703543f36 Commenting out log.debug instead of removing them 2016-09-08 11:20:27 -07:00
dsainteclaire
5db6ecda3e Merge pull request #1226 from dsainteclaire/DVCSMP-1959-remove-logging-of-phone-numbers
DVCSMP-1959 removed logging of device and phone information due to security concerns
2016-09-08 11:10:22 -07:00
Amol Mundayoor
43b836f413 Removing debug logs for netatmo 2016-09-08 11:07:31 -07:00
David Sainte-Claire
006b5e7bea removed logging of device and phone information due to security concerns 2016-09-08 10:54:04 -07:00
Rohan Desai
62c8c19805 Merge pull request #1225 from rohandesai/dynamic-execution-fix
DVCSMP-1959: fixes for dynamic execution (Curb-control)
2016-09-08 10:47:55 -07:00
Rohan Desai
48e9a4bd6a removed semi colons 2016-09-08 10:46:40 -07:00
dsainteclaire
07a4c0decc Merge pull request #1223 from dsainteclaire/DVCSMP-1959-remove-sensitive-information-withings
DVCSMP-1959 removed logging of sensitive access tokens from smartapp
2016-09-08 10:41:56 -07:00
Andrew Bresee
6aa09bb052 Change log statement to not log personal phone number (#1224) 2016-09-08 13:40:35 -04:00
Rohan Desai
2f889de11a fixes for dynamic execution 2016-09-08 10:36:28 -07:00
David Sainte-Claire
5584020e96 removed logging of sensitive access tokens from smartapp 2016-09-08 10:31:24 -07:00
Jim Anderson
4ef2e694c2 Merge pull request #1180 from jimmyjames/ecobee-async-http-polling
[DVCSMP-1979] Use async http for polling and refresh tokens.
2016-09-08 12:13:53 -05:00
Jim Anderson
826993cc45 [DVCSMP-1979] Use async http for polling and refresh tokens. 2016-09-08 12:11:21 -05:00
Luke Bredeson
ae3306928b Merge pull request #1220 from lbredeso/fix-smart-security
DVCSMP-2020: smart-security app contains invalid code
2016-09-08 10:14:01 -05:00
Luke Bredeson
8777ec5f6d DVCSMP-2020: smart-security app contains invalid code 2016-09-08 10:06:38 -05:00
Andrew Bresee
91eb59a10d DVCSMP-1959: Replace log logging personal phone number (#1217)
* Replace log logging personal phone number

* Removed commented out log
2016-09-08 07:45:30 -04:00
Andrew Bresee
324ac13afb DVCSMP-1959: Unsubscribe from a pointless method (#1215)
* Unsubscribe from a pointless method

* Remove subscription to pointless method
2016-09-07 18:07:01 -04:00
Andrew Bresee
878eb66b8b Remove log logging personal information about a device (#1214) 2016-09-07 16:30:35 -04:00
Rohan Desai
8dfc270c2d Merge pull request #1213 from rohandesai/log-security-fixes
DVCSMP-1959 security fixes for SAs
2016-09-07 12:58:25 -07:00
Rohan Desai
614573a15c security fixes for SAs 2016-09-07 11:28:08 -07:00
dsainteclaire
9c7b0875ba Merge pull request #1211 from dsainteclaire/DVCSMP-1959-remove-sensitive-information-bon-voyage
DVCSMP-1959 removed log messages from smartapp that may print sensitive information
2016-09-07 11:24:22 -07:00
Andrew Bresee
7568cbf781 DVCSMP-1959: Security review - removing potentially confidential log statements (#1210)
* Commented out log statement logging users access token

* Commented out log.info logging potentially confidential device information

* Remove log logging potentially confidential information on the app
2016-09-07 14:11:20 -04:00
Vinay Rao
1858c280a5 Merge pull request #1212 from workingmonk/bug/negative_battery_1
SSVD-2771 fix to avoid negative values
2016-09-07 11:09:02 -07:00
Vinay Rao
6b7d0968f6 chaning min battery percentage to 1 2016-09-07 11:07:30 -07:00
David Sainte-Claire
159d3acf4f removed log messages from smartapp that may print sensitive information 2016-09-07 10:56:25 -07:00
Vinay Rao
e8101630a3 Merge pull request #1209 from workingmonk/bug/negative_battery
SSVD-2771 fix to avoid negative values
2016-09-07 10:49:40 -07:00
Vinay Rao
f5ba78b221 fix to avoid negative values 2016-09-07 10:46:12 -07:00
tslagle13
19b8a7eeb9 Merge pull request #1167 from CosmicPuppy/CosmicPuppy-Netatmo-CapabilitySensor
MSA-1468 - To Netatmo DTHs, added Capability "Sensor"
2016-09-07 10:15:42 -07:00
twack
1b37d649a5 Merge pull request #1207 from twack/20160907_update_its_too_hot
(DVCSMP-1959) 20160907_update_its_to_hot_for_security
2016-09-07 09:22:09 -07:00
twack
dedb0f8465 Update its-too-hot.groovy 2016-09-07 09:20:13 -07:00
Juan Pablo Risso
06acc13575 DVCSMP-1959 - Remove sensitive information from logs (#1206) 2016-09-07 12:14:58 -04:00
twack
c051d719cc 20160907_update_its_to_hot_for_security 2016-09-07 09:14:19 -07:00
Vinay Rao
1e54b93b0c Merge pull request #1203 from SmartThingsCommunity/master
Rolling up master to staging
2016-09-06 17:15:57 -07:00
Vinay Rao
bac37f9ca2 Merge pull request #1202 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-09-06 17:08:39 -07:00
Vinay Rao
f0ecb65c09 Merge pull request #1201 from SmartThingsCommunity/revert-1197-revert_WWST-40_staging
Revert "Revert "WWST-40 Philips Hue: Implement device watch""
2016-09-06 17:07:33 -07:00
Vinay Rao
1c0ddd2571 Revert "Revert "WWST-40 Philips Hue: Implement device watch"" 2016-09-06 17:07:14 -07:00
Vinay Rao
b7e0cbda09 Merge pull request #1200 from SmartThingsCommunity/revert-1194-revert-latest-ecobee-changes
Revert "revert changes for DVCSMP-1980 and SSVD-2534 on staging"
2016-09-06 17:07:06 -07:00
Vinay Rao
f80e094bd9 Revert "revert changes for DVCSMP-1980 and SSVD-2534 on staging" 2016-09-06 17:06:38 -07:00
Vinay Rao
ce9ac624d0 Merge pull request #1199 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
2016-09-06 16:41:19 -07:00
Juan Pablo Risso
f3f5cc42c9 CREX-5826 - Missing braces (#1198) 2016-09-06 17:38:45 -04:00
Vinay Rao
313fe8b734 Merge pull request #1197 from larsfinander/revert_WWST-40_staging
Revert "WWST-40 Philips Hue: Implement device watch"
2016-09-06 12:33:51 -07:00
Vinay Rao
0d693386d1 Merge pull request #1194 from jimmyjames/revert-latest-ecobee-changes
revert changes for DVCSMP-1980 and SSVD-2534 on staging
2016-09-06 12:01:30 -07:00
Lars Finander
d1aee1e874 Revert "WWST-40 Philips Hue: Implement device watch"
This reverts commit bacd335991.
2016-09-06 12:42:11 -06:00
Lars Finander
3528e7da51 Merge pull request #1195 from larsfinander/DVCSMP-2004_Philips_Hue_Nullpointer_in_bridge_staging
DVCSMP-2004 Philips Hue: Nullpointer in bridge
2016-09-06 12:40:02 -06:00
juano2310
fe2fbc3b97 MKTP-829 - Adding disclaimer 2016-09-06 14:01:20 -04:00
Lars Finander
5c2e06c98d DVCSMP-2004 Philips Hue: Nullpointer in bridge 2016-09-06 10:43:03 -06:00
Jim Anderson
26df619b4f revert changes for DVCSMP-1980 and SSVD-2534 on staging 2016-09-06 11:22:06 -05:00
Juan Pablo Risso
af2ea04442 CREX-5826 - 2 SMS bug fix (#1193)
options.method = 'none' & variable name update

Revert variable name
2016-09-06 12:04:26 -04:00
Juan Pablo Risso
383f72580a SSVD-2738 - SSVD-2734 - SSVD-2733 (#1187)
* SSVD-2738 - Count Down Bug

* SSVD-2734 - Copy text

* SSVD-2733 - Add Unit
2016-09-06 11:39:18 -04:00
Vinay Rao
090a306939 Merge pull request #1184 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-08-31 16:05:08 -07:00
Vinay Rao
d0a16c10b2 Merge pull request #1183 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2016-08-31 16:04:45 -07:00
Lars Finander
faa65f204d Merge pull request #1181 from larsfinander/WWST-40_Philips_Hue_device_watch_staging
WWST-40 Philips Hue: Implement device watch
2016-08-31 16:39:26 -06:00
Lars Finander
bacd335991 WWST-40 Philips Hue: Implement device watch 2016-08-31 15:00:34 -06:00
Vinay Rao
740e5e096c Merge pull request #1179 from varzac/smartsense-motion-temp-alarm2
DVCSMP-1999 Use proper IAS Zone alarm for triggering motion
2016-08-31 13:00:49 -07:00
Vinay Rao
aac2f9b177 Merge pull request #1174 from workingmonk/bug/osram_hue_name
SSVD-2632 The Device Details Recently tab does not log any
2016-08-31 13:00:24 -07:00
Vinay Rao
048eb77e64 fixes SSVD-2632 The Device Details Recently tab does not log any activity regarding OSRAM Lightify RGWB bulb color change 2016-08-31 12:47:09 -07:00
Zach Varberg
dadec937fa Use proper IAS Zone alarm for triggering motion
Previously we were incorrectly looking at the alarm1 bit when we should
be looking at the alarm2 bit.

This resolves: https://smartthings.atlassian.net/browse/DVCSMP-1999
2016-08-31 13:09:18 -05:00
Vinay Rao
78aa6691c4 Merge pull request #1173 from SmartThingsCommunity/master
Rolling up changes for next week deploy
2016-08-30 13:32:36 -07:00
Vinay Rao
315918dc6f Merge pull request #1172 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-08-30 13:19:16 -07:00
Vinay Rao
a22f71bc29 Merge pull request #1171 from SmartThingsCommunity/staging
Rolling up staging to prod for deploy
2016-08-30 12:57:12 -07:00
Vinay Rao
8eeb29a8a7 Merge pull request #1170 from SmartThingsCommunity/production
Rolling down prod hotfix to staging
2016-08-30 12:56:16 -07:00
Lars Finander
3d84bca3d7 Merge pull request #1168 from larsfinander/SSVD-2603_removing_hue_bridge_issue_staging
SSVD-2603 Prevent removing of Hue bridge
2016-08-30 12:54:17 -06:00
Lars Finander
46f47128bd Merge pull request #1169 from larsfinander/SSVD-2613_stop_removing_hue_lights_staging
SSVD-2613 UX for Hue when adding lights is confusing
2016-08-30 12:54:08 -06:00
Lars Finander
9c8398b7a0 SSVD-2613 UX for Hue when adding lights is confusing
-Split lights list in SmartApp into already added lights and new lights
-Also fixed WWST-39 Sort list of bulbs by name during discovery
2016-08-29 16:18:07 -06:00
Lars Finander
cdf5d21e8f SSVD-2603 Prevent removing of Hue bridge
-Moved warning messages to top of bridge DTH screen
-User is now presented with a warning message when removing
2016-08-29 15:35:58 -06:00
CosmicPuppy
5e6b4f74e0 To Netatmo DTHs, added Capability "Sensor" per http://docs.smartthings.com/en/latest/device-type-developers-guide/overview.html?highlight=sensor%20actuator#actuator-and-sensor.
There are some SmartApps out there using the "Actuator" and "Sensor" Capabilities and this Device doesn't show up for them (e.g., SmartTiles V6).
2016-08-29 13:55:19 -07:00
Mike Robinet
276f7d3b43 Merge pull request #1158 from mrobinet/ssvd-2534
SSVD-2534 Set temperature unit/scale when sending temperature events
2016-08-29 13:36:28 -05:00
Vinay Rao
ce12ad5013 Merge pull request #1164 from marstorp/bose-routine-fix
DVCSMP-1954 Routines turning Bose speaker on/off, toggles the power
2016-08-29 11:07:08 -07:00
Mike Robinet
beed783d19 SSVD-2534 Set temperature unit/scale when sending temperature events 2016-08-29 12:40:11 -05:00
Jim Anderson
7f347638d5 Merge pull request #1148 from jimmyjames/ecobee-cleanup
[DVCSMP-1980] some cleanup of Ecobee Connect SmartApp
2016-08-29 12:26:03 -05:00
marstorp
1f8ce734e7 DVCSMP-1954 Routines turning Bose speaker on/off, toggles the power state to off/on 2016-08-29 10:20:04 -07:00
Vinay Rao
17bf040c7e Merge pull request #1161 from SmartThingsCommunity/staging
Rolling down staging health hotfix to master
2016-08-27 01:07:59 -07:00
Vinay Rao
d5b8db99a2 Merge pull request #1160 from workingmonk/bug/battery_health_timeout
CHF-201 changing timeout for health check to 4 hours
2016-08-27 01:07:04 -07:00
Vinay Rao
6ad4f0990c CHF-201 changing timeout for health check to 4 hours for battery powered devices 2016-08-27 01:05:10 -07:00
Vinay Rao
f1c3f5942b Merge pull request #1159 from workingmonk/feature/osram_new_aug26
DEVC-479 adding support for osram tw b40
2016-08-26 15:21:21 -07:00
Vinay Rao
212c9c4179 adding support for osram tw b40 2016-08-26 15:17:02 -07:00
Vinay Rao
4898006e4e Merge pull request #1157 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-08-26 14:02:48 -07:00
Vinay Rao
b1c318ef36 Merge pull request #1156 from workingmonk/feature/osram_cct_health
CHF-239 health extension for osram cct bulbs
2016-08-26 13:39:15 -07:00
Vinay Rao
8eb6001f9f CHF-239 extension for osram cct bulbs 2016-08-26 13:20:51 -07:00
Rohan Desai
d3eb7f756f Merge pull request #1155 from rohandesai/life-360-security-fix
Removed log debugs of sensitive info
2016-08-26 11:39:06 -07:00
Rohan Desai
b95ba37364 removed log debugs of sensitive info 2016-08-26 11:12:41 -07:00
Jack Chi
87f8755faf Merge pull request #1154 from parijatdas/troubleshooting
[CHF-240] Added Troubleshooting Tips for the 7 devices in their README.md
2016-08-26 07:59:34 -07:00
Parijat Das
555a9f5ab4 Added troubleshooting component in README for the following devices:
1. SmartPower Outlet
2. SmartSense Moisture Sensor
3. SmartSense Motion Sensor
4. SmartSense Multi Sensor
5. SmartSense Open/Closed Sensor
6. SmartSense Temp-Humidity Sensor
7. Connected Cree LED Bulb
2016-08-26 19:10:19 +05:30
Jim Anderson
0744384dbf remove logging of token information 2016-08-25 20:36:41 -05:00
Juan Pablo Risso
97e0e9d0f8 CREX-5826 - Replace text (#1153) 2016-08-25 20:03:44 -04:00
Juan Pablo Risso
655e756b1b DVCSMP-1959 - Remove logs with sensitive information (#1152) 2016-08-25 20:03:20 -04:00
Jim Anderson
7ce7ad86bd [DVCSMP-1980] fix some missed parent call method signature changes 2016-08-25 12:48:36 -05:00
Vinay Rao
d90e15ee31 Merge pull request #1151 from larsfinander/PROB-1352_Hue_colors_rendering_incorrectly_production
PROB-1352 Hue colors rendering incorrectly
2016-08-24 13:13:45 -07:00
Lars Finander
cfe25607ac PROB-1352 Hue colors rendering incorrectly
-Disable color conversion algorithm for hue/sat
2016-08-24 13:56:06 -06:00
Vinay Rao
f251042954 Merge pull request #1149 from varzac/dprot-153-null-pointer
Fix event map name in NYCE Motion sensor
2016-08-24 12:10:40 -07:00
Zach Varberg
33df9b1ff1 Fix event map name in NYCE Motion sensor
There was a null pointer as a result of using the wrong map name

This resolves: https://smartthings.atlassian.net/browse/DPROT-153
2016-08-24 14:04:19 -05:00
Jack Chi
24c64608a9 Merge pull request #1140 from ShunmugaSundar/Adding_Readme
CHF-240 : Adding readme.md files for below devices
2016-08-24 10:28:28 -07:00
Jim Anderson
dbc2a1e45c a few more whitespace fixes 2016-08-24 07:29:04 -05:00
ShunmugaSundar
92cc8afdf7 CHF-240 : Adding readme.md files for below devices
1. SmartSense Moisture Sensor
 2. SmartSense Temp/Humidity Sensor
 3. SmartSense Multi Sensor
 4. SmartSense Open/closed Sensor
 5. SmartPower Outlet
 6. Connected Cree Bulb
 7. Aeon Multisensor
 8. Aeon Multisensor Gen5
 9. Aeon Multisensor 6
 10. SmartSense Motion Sensor

CHF-240 : Added readme.md files for below devices

1. SmartSense Moisture Sensor
2. SmartSense Temp/Humidity Sensor
3. SmartSense Multi Sensor
4. SmartSense Open/closed Sensor
5. SmartPower Outlet
6. Connected Cree Bulb
7. SmartSense Motion Sensor
2016-08-24 15:05:14 +05:30
Jim Anderson
e545842f7c [DVCSMP-1980] some cleanup of Ecobee Connect SmartApp 2016-08-23 23:27:30 -05:00
Vinay Rao
c8bda222cb Merge pull request #1146 from SmartThingsCommunity/master
Rolling up master for next week's deploy
2016-08-23 15:12:15 -07:00
Vinay Rao
17014dd248 Merge branch 'staging'
# Conflicts:
#	devicetypes/smartthings/smartpower-outlet.src/smartpower-outlet.groovy
#	devicetypes/smartthings/zigbee-dimmer.src/zigbee-dimmer.groovy
#	devicetypes/smartthings/zigbee-rgbw-bulb.src/zigbee-rgbw-bulb.groovy
2016-08-23 14:50:39 -07:00
Vinay Rao
555edf623a Merge pull request #1144 from SmartThingsCommunity/revert-1141-revert-dprot-2
DPROT-2 Reverting again to put the change back " Revert "Update DTHs to use ZigBee library ZoneStatus""
2016-08-23 14:05:48 -07:00
Vinay Rao
feb6ba0e24 Revert " Revert DPROT-2: "Update DTHs to use ZigBee library ZoneStatus"" 2016-08-23 14:04:47 -07:00
Vinay Rao
9d65150bf7 Merge pull request #1143 from SmartThingsCommunity/staging
Rolling up changes to production for deploy
2016-08-23 14:04:20 -07:00
Vinay Rao
99d6e9f668 Merge pull request #1142 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2016-08-23 12:23:38 -07:00
Vinay Rao
a35f271a8e Merge pull request #1138 from workingmonk/bug/SSVD-2532
SSVD-2532 setting up the generic name at install
2016-08-23 11:34:46 -07:00
Vinay Rao
fd4969981f Merge pull request #1141 from varzac/revert-dprot-2
Revert DPROT-2: "Update DTHs to use ZigBee library ZoneStatus"
2016-08-23 11:27:23 -07:00
Jack Chi
1ec110155d Merge pull request #1137 from jackchi/healthcheck-osram
[CHF-239] Health Check Osram RGB / Dimmer Devices
2016-08-23 10:03:04 -07:00
Zach Varberg
79b90d741f Revert "Update DTHs to use ZigBee library ZoneStatus"
This reverts commit 7bfa0304af.
2016-08-23 08:45:47 -05:00
Vinay Rao
6009bc52ab SSVD-2532 setting up the generic name at install 2016-08-23 02:59:06 -07:00
Lars Finander
33a8fe108e Merge pull request #1133 from larsfinander/DVCSMP-1727_Philips_Hue_Update_status_response_staging
DVCSMP-1727 Philips Hue: Update status on response
2016-08-22 16:09:37 -06:00
jackchi
fadc496e1f [CHF-239] Health Check Osram RGB / Dimmer Devices 2016-08-22 15:06:57 -07:00
Vinay Rao
910694f1d1 Merge pull request #1136 from jackchi/revert-pr1424
Revert PR-1424
2016-08-22 14:08:58 -07:00
jackchi
fa9ebed998 Revert PR-1424 2016-08-22 13:58:11 -07:00
Jack Chi
0a2f2bffc2 Merge pull request #1131 from jackchi/healthcheck-core
[CHF-201] [CHF-206] Health Check Core Devices
2016-08-22 11:14:12 -07:00
jackchi
8dc36eb8f6 [CHF-201] [CHF-206] Health Check Core Devices 2016-08-22 11:05:24 -07:00
Jason Botello
d0929ab89e Merge pull request #1017 from SmartThingsCommunity/MSA-1375-1
MSA-1375: Reminders using notifications and light
2016-08-19 17:08:29 -07:00
Lars Finander
df6646103a DVCSMP-1727 Philips Hue: Update status on response
-Only send events when feedback is recevied from bridge
-Cleaned up color conversions
-DVCSMP-1728 Philips Hue: Handle new LAN polling
-DVCSMP-1763 Philips Hue: Bad rounding can cause level to be 0, light on
-DVCSMP-1678 Philips Hue: Bridge detail page should display the status.
-DVCSMP-1669 Phillips Hue: The on/off button flickering between states
-DEVC-450 Hue Connect app is throwing errors in the IDE
-Changed manual refresh to check bridge and run poll()
-Updated some strings
2016-08-19 14:58:44 -06:00
Vinay Rao
014affe1ea Merge pull request #1130 from workingmonk/cccTile
SSVD-2465 changing the kelvin tile to name tiles for OSRAM
2016-08-18 16:17:48 -07:00
Vinay Rao
53fc948b00 SSVD-2465 changing the kelvin tile to name tiles 2016-08-18 15:04:48 -07:00
Vinay Rao
f389e925d2 Merge pull request #1129 from workingmonk/vdfixosram
SSVD-2463 hotfix for level jumping issues
2016-08-17 21:59:52 -07:00
Vinay Rao
ef47ec9393 hotfix for level jumping issues 2016-08-17 18:21:54 -07:00
Vinay Rao
62d800e99a Merge pull request #1128 from larsfinander/SSVD-2465_production
SSVD-2465 Philips Hue No description for slider
2016-08-17 15:08:18 -07:00
Lars Finander
a79c9c1ade SVD-2465 Philips Hue No description for slider
-Changed Kelvin tile to Whites (same as Philips Hue app)
2016-08-17 15:56:31 -06:00
Vinay Rao
4505ca85b2 Merge pull request #1126 from SmartThingsCommunity/master
Rolling up master to staging
2016-08-16 16:11:09 -07:00
Vinay Rao
3c0c050b3a Merge pull request #1125 from SmartThingsCommunity/staging
Rolling up staging to production for deployment
2016-08-16 14:45:48 -07:00
Rohan Desai
2cd915ba77 Merge pull request #1124 from moorage/master
DVCSMP-1959: remove logging of phone number in barkley been fed
2016-08-16 13:58:24 -07:00
Matthew Moore
4866ecd204 DVCSMP-1959: remove logging of phone number in barkley been fed 2016-08-16 13:52:53 -07:00
dsainteclaire
f0071aad6d Merge pull request #1123 from dsainteclaire/DVCSMP-1959-fix-smartapps-logging-personal-information
DVCSMP-1959 fixed issue with logging personal information and unused subscription from SmartApps
2016-08-16 12:35:50 -07:00
David Sainte-Claire
0d4a00ae2b fixed wrong subscription based on code review comment 2016-08-16 11:46:47 -07:00
David Sainte-Claire
90384d0852 DVCSMP-1959 fixed issue with logging personal information and unused subscription from SmartApps 2016-08-16 11:35:04 -07:00
Jack Chi
47183ebbff Merge pull request #1116 from jackchi/healthcheck-outlet
[CHF-204] Implementation of PING in SmartPower Outlet
2016-08-15 14:32:13 -07:00
jackchi
d68f70b3dd [CHF-204] Implementation of PING in SmartPower Outlet 2016-08-12 14:33:42 -07:00
Vinay Rao
e1b1479cfc Merge pull request #1101 from CosmicPuppy/CosmicPuppy-SensorActuator-Patches
Added Capability "Sensor" and/or "Actuator" per DTH standards.
2016-08-11 12:12:34 -07:00
Zach Varberg
16e4954f10 Merge pull request #1087 from varzac/update-zonestatus
Update DTHs to use ZigBee library ZoneStatus
2016-08-10 10:04:59 -05:00
Vinay Rao
a1b375c929 Merge pull request #1111 from SmartThingsCommunity/master
Rolling up master to staging
2016-08-09 14:55:52 -07:00
Vinay Rao
929f8e1a44 Merge pull request #1110 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-08-09 14:54:50 -07:00
Vinay Rao
4f97d1a3ef Merge pull request #1109 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
2016-08-09 14:30:15 -07:00
Vinay Rao
255185ee8c Merge pull request #1108 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2016-08-09 14:29:35 -07:00
SmartThings, Inc
ad50582e92 Merge pull request #1013 from SmartThingsCommunity/MSA-1372-2
Merged publication request 'Gidjit - Smart Launcher OAuth Permission Capability'
2016-08-09 14:02:26 -05:00
Vinay Rao
6de6704502 Merge pull request #694 from workingmonk/feature/zigbee_valve
[DEVC-21] zigbee valve DTH for HA 1.2 Waxman Valve
2016-08-08 20:05:45 -07:00
Vinay Rao
a5bc475cc1 zigbee valve DTH for HA 1.2 Waxman Valve 2016-08-08 20:04:23 -07:00
Vinay Rao
4fd5cc5d70 Merge pull request #1106 from workingmonk/leviton_switch
DEVC-365 adding leviton switch to zigbee switch post certification
2016-08-08 12:38:39 -07:00
Vinay Rao
236c37290e adding leviton switch to zigbee switch post certification 2016-08-08 12:36:22 -07:00
CosmicPuppy
7beb2e3905 Added Capability "Sensor" and/or "Actuator" per http://docs.smartthings.com/en/latest/device-type-developers-guide/overview.html?highlight=sensor%20actuator#actuator-and-sensor.
There are some integrations out there using the "Actuator" and "Sensor" Capabilities and this doesn't show up for them (e.g., SmartTiles V6).
2016-08-05 01:09:32 -07:00
Vinay Rao
d17bc1869f Merge pull request #1098 from marstorp/bose-power-8-4
SSVD-1605 and SSVD-1897 Fix for update of switch tile
2016-08-04 16:57:31 -07:00
marstorp
534118a47a Fix for SSVD-1605 and SSVD-1897, update of switch tile when speaker is turned on/off 2016-08-04 16:47:13 -07:00
Vinay Rao
c7396349f1 Merge pull request #851 from workingmonk/feature/new_button_dth
DVCSMP-1742 DVCSMP-1513 Adding support for osram and iris ZigBee buttons
2016-08-04 15:55:47 -07:00
Vinay Rao
089cc1a5dd adding support for osram and iris buttons
commenting out iris fingerprints until cert is complete
2016-08-04 15:43:22 -07:00
Zach Varberg
7bfa0304af Update DTHs to use ZigBee library ZoneStatus
This makes use of a new class exposed from the ZigBee library to
automatically parse the ZoneStatus attribute bit map and expose
the individual values in a simple way.  This fixes a lot of
unhandled cases in the previous copy-pasted switch statements,
as well as allowing for a simpler interface with less copy/pasted
code.
2016-08-03 15:53:30 -05:00
Vinay Rao
842f39e9ff Merge pull request #1091 from juano2310/staging
SSVD-1823 - Name change to correct filename and filepath for new zwave device
2016-08-03 13:53:25 -07:00
juano2310
dd308f6d8f SSVD-1823 - Name change 2016-08-02 18:53:28 -04:00
Vinay Rao
1a72158a9a Merge pull request #1089 from SmartThingsCommunity/master
Rolling up master to staging for next week's deploy
2016-08-02 14:38:46 -07:00
Vinay Rao
94ab309335 Merge pull request #1088 from SmartThingsCommunity/staging
Rolling up staging to production
2016-08-02 13:54:57 -07:00
Luke Ness
f4571289a5 Merge pull request #1086 from gausnes/PRP-205
[PRP-205] Fixing dimmer name to reflect other Z-Wave devices
2016-08-02 11:32:14 -07:00
Luke Ness
b9b0cc6b37 [PRP-205] Changed name of ZWave Dimmer to reflect other DTH naming conventions 2016-08-02 12:48:18 -05:00
Juan Pablo Risso
34ad221f5d No parenthesis (#1085)
* SSVD-1823 - Z-wave Switch Generic

Remove Indicator

Update Name

deviceJoinName

* SSVD-1823 - Drop parenthesis
2016-08-02 12:04:34 -04:00
Juan Pablo Risso
7d8acd5dd6 SSVD-1823 - Z-wave Dimmer Switch (Generic) (#1084)
- deviceJoinName
- Wall
- sendHubCommand and preferences
- remove 014F
2016-07-30 17:42:01 -04:00
Juan Pablo Risso
dba8ea7b99 SSVD-1823 - Z-wave Switch Generic (#1083)
Remove Indicator

Update Name

deviceJoinName
2016-07-30 17:14:02 -04:00
Juan Pablo Risso
49eec58de2 SSVD-1823 - Indicator Light Preference page (#1080)
required = false

indentation

Bob's update
2016-07-30 14:08:39 -04:00
Vinay Rao
f2d635ab44 Merge pull request #1079 from SmartThingsCommunity/master
Rolling up master to staging
2016-07-26 14:09:07 -07:00
Vinay Rao
a7cd9e072b Merge pull request #1078 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
2016-07-26 13:45:49 -07:00
Donald C. Kirker
b70706f150 Merge pull request #1077 from SmartThingsCommunity/aeon-multi-6
Aeon multi 6
2016-07-26 09:31:58 -07:00
Donald C. Kirker
0d0a3f5ebb Protect ternary operations in configure
Protect ternary operations against order of operations, resulting in incorrect math and math against null values.
2016-07-26 06:32:23 -07:00
Donald C. Kirker
be7fad76fc Add updated Aeon Multisensor 6 fingerprint 2016-07-26 05:30:31 -07:00
Steve Vlaminck
f0e87fa5e9 Merge pull request #1070 from vlaminck/DVCSMP-1904
Fix: Gentle Wake Up requires contact input for Contact Book users [DVCSMP-1904]
2016-07-22 08:23:51 -05:00
vlaminck
1b385afa5b Fix: Gentle Wake Up requires contact input for Contact Book users 2016-07-22 08:16:42 -05:00
Vinay Rao
b5843acc38 Merge pull request #1067 from SmartThingsCommunity/master
Rolling up master to staging
2016-07-19 16:00:31 -07:00
Vinay Rao
863c49ffd4 Merge pull request #1066 from SmartThingsCommunity/staging
Rolling down staging hotfix to production
2016-07-19 15:55:53 -07:00
Vinay Rao
4e5d1f6ad0 Merge pull request #1065 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
2016-07-19 15:09:07 -07:00
Vinay Rao
2f0d8d814b Merge pull request #1064 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2016-07-19 15:06:43 -07:00
Vinay Rao
a86eba494f Merge pull request #1063 from tslagle13/add-capability-SS-open/closed
Add capability sensor to SS Open/Closed
2016-07-18 15:46:21 -07:00
tslagle13
2549372bb7 Add capability sensor to SS Open/Closed
There are some integrations out there using the "Actuator" and "Sensor" Capabilities and this doesn't show up for them.
2016-07-18 15:20:06 -07:00
Vinay Rao
38cdde7479 Merge pull request #1057 from SmartThingsCommunity/DVCSMP-1892
DVCSMP-1892 Fix error in Z-Wave Door/Window Sensor wake up handler
2016-07-14 10:54:36 -07:00
Duncan McKee
853f616cc8 DVCSMP-1892 Fix error in Z-Wave Door/Window Sensor wake up handler 2016-07-14 13:51:36 -04:00
Vinay Rao
2b3a4e1278 Merge pull request #1055 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-07-13 19:45:29 -07:00
Vinay Rao
825e693efd Merge pull request #1054 from SmartThingsCommunity/production
Rolling down prod hotfix to staging
2016-07-13 19:44:57 -07:00
Vinay Rao
686c8f7337 Merge pull request #1053 from rappleg/FixFalseBatteryNotificationOnNewerGroovyVersion
PRP-192 Fix false low battery notifications on Groovy 2.4.4
2016-07-13 19:40:55 -07:00
rappleg
11f4e42fe9 PRP-192 Fix false low battery notifications on Groovy 2.4.4 2016-07-13 21:22:57 -05:00
Steve Vlaminck
bc459ae178 Merge pull request #1051 from vlaminck/GWU-exception-fix
fix divide by zero exception [DVCSMP-1891]
2016-07-13 10:01:10 -05:00
vlaminck
1392b6e1a5 fix divide by zero exception 2016-07-13 09:27:23 -05:00
Vinay Rao
3db96faa00 Merge pull request #1049 from SmartThingsCommunity/master
Rolling up master to staging
2016-07-12 15:04:26 -07:00
Vinay Rao
399fbcb676 Merge pull request #1048 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-07-12 15:03:28 -07:00
Vinay Rao
eed1ced71b Merge pull request #1047 from SmartThingsCommunity/staging
Rolling up staging for production deploy
2016-07-12 14:33:19 -07:00
Vinay Rao
d080833d5c Merge pull request #1046 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2016-07-12 14:26:10 -07:00
Vinay Rao
e998528e8e Merge pull request #1041 from rappleg/ProductionFixJsonSlurperHashMap
PRP-172 Fix Hue Connect parse errors on newer versions of Groovy
2016-07-11 23:49:10 -07:00
Jack Chi
3472ee329d Merge pull request #1036 from jackchi/healthcheck-zwave-aeon
[CHF-138] Adds HealthCheck to Z-Wave Sensors
2016-07-11 11:21:30 -07:00
Juan Pablo Risso
577b127287 PRP-151 Harmony cloud fix + PENG-161 - Allow setLevel (#1035)
* PRP-151 - Harmony Cloud

Added is IP

Try around Integer.parseInt

declare int p outside try

* Remove unsubscribe & unschedule

* PENG-161 - Allow setLevel for switch capability

Last version
2016-07-11 10:04:32 -04:00
rappleg
d85566bb98 PRP-172 Fix Hue Connect parse errors on newer versions of Groovy 2016-07-10 15:35:12 -05:00
jackchi
5f41af35e2 [CHF-138] Adds HealthCheck to Z-Wave Sensors 2016-07-08 15:36:58 -07:00
Duncan McKee
e1a5b4dd27 Merge pull request #1034 from SmartThingsCommunity/DVCSMP-1879
DVCSMP-1879 Fix error in Z-Wave Door/Window Sensor throwing exceptions on update
2016-07-06 17:43:42 -04:00
Duncan McKee
a2baa37901 DVCSMP-1879 Fix error in Z-Wave Door/Window Sensor throwing exceptions on update 2016-07-06 17:08:15 -04:00
Vinay Rao
922ab45343 Merge pull request #1033 from SmartThingsCommunity/master
Rolling up master to staging for deploy
2016-07-06 13:59:03 -07:00
Vinay Rao
962774996e Merge pull request #1032 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-07-06 13:57:35 -07:00
Vinay Rao
d79594cbcb Merge pull request #1031 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2016-07-06 13:56:39 -07:00
Vinay Rao
bf8fe4cad7 Merge pull request #1030 from rappleg/RevertLazyMapNewerGroovyVersion
Revert "PRP-172 Fix Hue Connect parse errors on newer versions of Groovy"
2016-07-06 13:53:32 -07:00
rappleg
65752ce378 Revert "PRP-172 Fix Hue Connect parse errors on newer versions of Groovy"
This reverts commit be7f6a76a9.
2016-07-06 14:44:58 -05:00
spurohit1
95f08aeb3d Update logitech-harmony-connect.groovy (#1009)
If port is present in the callbackUrl then send command to hub else post the request through http.
Removed isIP function since it is no longer required.
2016-07-06 09:40:29 -04:00
Vinay Rao
cd7bc1b262 Merge pull request #1023 from rappleg/FixHueConnectParseErrorsGrailsUpgradeProduction
PRP-172 Fix Hue Connect parse errors on newer versions of Groovy
2016-06-30 00:46:24 -07:00
rappleg
be7f6a76a9 PRP-172 Fix Hue Connect parse errors on newer versions of Groovy 2016-06-30 02:42:24 -05:00
Jim Mangione
1ddd0632c9 Modifying 'Reminders using notifications and light' 2016-06-29 20:44:59 -05:00
Jim Mangione
53d0957383 Modifying 'Reminders using notifications and light' 2016-06-29 20:03:27 -05:00
Vinay Rao
10e5b7e9d7 Merge pull request #1021 from SmartThingsCommunity/master
Rolling up master to staging
2016-06-28 22:57:32 -07:00
Vinay Rao
fc38c534f9 Merge pull request #1020 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-06-28 21:04:33 -07:00
Jim Mangione
b4a4d83ce7 MSA-1375: These apps use different sensors to detect if a draw or container has been opened or moved. If no activity is detected without 60 minutes of a set reminder time, then an in-app reminder is generated. If no activity after 10 additional minutes, an LED light is turned on and set to RED until activity is recorded.
Additionally, the Temp-Motion app sends an in-app notification if the temperature of the container exceeds a particular threshold.
2016-06-27 20:31:56 -05:00
Matthew Page
ef29820fa1 MSA-1372: This is an updated version of the previous, however a user can now set the preferences and permissions from an OAuth page. 2016-06-24 10:31:30 -05:00
Steve Vlaminck
fd47bcb8a8 Merge pull request #1011 from vlaminck/gwu-exception-handling
Gwu exception handling
2016-06-23 12:26:42 -05:00
vlaminck
972599b1b5 Provide a way to remove unsupported devices from settings 2016-06-23 12:19:54 -05:00
vlaminck
f5d3cca6a0 Guard against devices that don't support necessary commands 2016-06-23 09:27:54 -05:00
Nicola Russo
4ad0a6fd9d MSA-1351: The Gideon AI smart app allows you to connect and control all of your smartThings devices with the Gideon AI app. Gideon AI smart app makes your smartThings device even smarter adding features like energy monitoring, vdeo surveillance history etc.. 2016-06-12 08:35:14 -05:00
Adam Jensen
22185c5440 Added labels to the motion attribute in the main multiattributetile 2016-05-24 08:18:51 -05:00
140 changed files with 5260 additions and 2212 deletions

View File

@@ -19,7 +19,7 @@ buildscript {
username smartThingsArtifactoryUserName
password smartThingsArtifactoryPassword
}
url "http://artifactory.smartthings.com/libs-release-local"
url "https://artifactory.smartthings.com/libs-release-local"
}
}
}
@@ -27,9 +27,37 @@ buildscript {
repositories {
mavenLocal()
jcenter()
maven {
credentials {
username smartThingsArtifactoryUserName
password smartThingsArtifactoryPassword
}
url "https://artifactory.smartthings.com/libs-release-local"
}
}
sourceSets {
devicetypes {
groovy {
srcDirs = ['devicetypes']
}
}
smartapps {
groovy {
srcDirs = ['smartapps']
}
}
}
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'
smartappsCompile 'org.codehaus.groovy:groovy-all:2.4.7'
smartappsCompile 'smartthings:appengine-common:0.1.8'
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'
}
slackSendMessage {

View File

@@ -5,7 +5,9 @@ machine:
dependencies:
override:
- echo "Nothing to do."
- ./gradlew dependencies -PsmartThingsArtifactoryUserName="$ARTIFACTORY_USERNAME" -PsmartThingsArtifactoryPassword="$ARTIFACTORY_PASSWORD"
post:
- ./gradlew compileSmartappsGroovy compileDevicetypesGroovy -PsmartThingsArtifactoryUserName="$ARTIFACTORY_USERNAME" -PsmartThingsArtifactoryPassword="$ARTIFACTORY_PASSWORD"
test:
override:

View File

@@ -15,6 +15,7 @@
*/
metadata {
definition (name: "Netatmo Additional Module", namespace: "dianoga", author: "Brian Steere") {
capability "Sensor"
capability "Relative Humidity Measurement"
capability "Temperature Measurement"

View File

@@ -15,6 +15,7 @@
*/
metadata {
definition (name: "Netatmo Basestation", namespace: "dianoga", author: "Brian Steere") {
capability "Sensor"
capability "Relative Humidity Measurement"
capability "Temperature Measurement"

View File

@@ -15,6 +15,7 @@
*/
metadata {
definition (name: "Netatmo Outdoor Module", namespace: "dianoga", author: "Brian Steere") {
capability "Sensor"
capability "Relative Humidity Measurement"
capability "Temperature Measurement"
}

View File

@@ -15,6 +15,8 @@
*/
metadata {
definition (name: "Netatmo Rain", namespace: "dianoga", author: "Brian Steere") {
capability "Sensor"
attribute "rain", "number"
attribute "rainSumHour", "number"
attribute "rainSumDay", "number"

View File

@@ -33,8 +33,8 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"FGMS", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app
tileAttribute("device.motion", key:"PRIMARY_CONTROL") {
attributeState("inactive", icon:"st.motion.motion.inactive", backgroundColor:"#79b821")
attributeState("active", icon:"st.motion.motion.active", backgroundColor:"#ffa81e")
attributeState("inactive", label:"no motion", icon:"st.motion.motion.inactive", backgroundColor:"#79b821")
attributeState("active", label:"motion", icon:"st.motion.motion.active", backgroundColor:"#ffa81e")
}
tileAttribute("device.tamper", key:"SECONDARY_CONTROL") {
@@ -127,9 +127,10 @@ def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv5.SensorMultilevelR
def map = [ displayed: true ]
switch (cmd.sensorType) {
case 1:
map.name = "temperature"
map.unit = cmd.scale == 1 ? "F" : "C"
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, map.unit, cmd.precision)
def cmdScale = cmd.scale == 1 ? "F" : "C"
map.name = "temperature"
map.unit = getTemperatureScale()
map.value = convertTemperatureIfNeeded(cmd.scaledSensorValue, cmdScale, cmd.precision)
break
case 3:
map.name = "illuminance"
@@ -278,4 +279,4 @@ private encap(physicalgraph.zwave.Command cmd) {
} else {
crc16(cmd)
}
}
}

View File

@@ -274,6 +274,7 @@ private Map makeTemperatureResult(value) {
name: 'temperature',
value: "" + value,
descriptionText: "${linkText} is ${value}°${temperatureScale}",
unit: temperatureScale
]
}

View File

@@ -254,7 +254,8 @@ private Map getTemperatureResult(value) {
return [
name: 'temperature',
value: value,
descriptionText: descriptionText
descriptionText: descriptionText,
unit: temperatureScale
]
}

View File

@@ -28,6 +28,7 @@ metadata {
attribute "powerSupply", "enum", ["USB Cable", "Battery"]
fingerprint deviceId: "0x2101", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x7A", outClusters: "0x5A"
fingerprint deviceId: "0x2101", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x7A,0x5A"
}
simulator {
@@ -352,7 +353,7 @@ def configure() {
motionSensitivity == "minimum" ? 0 : 64)
//5. report every x minutes (threshold reports don't work on battery power, default 8 mins)
request << zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: timeOptionValueMap[reportInterval] ?: 8*60) //association group 1
request << zwave.configurationV1.configurationSet(parameterNumber: 111, size: 4, scaledConfigurationValue: timeOptionValueMap[reportInterval] ?: (8*60)) //association group 1
request << zwave.configurationV1.configurationSet(parameterNumber: 112, size: 4, scaledConfigurationValue: 6*60*60) //association group 2

View File

@@ -21,6 +21,8 @@ metadata {
capability "Sensor"
capability "Battery"
command "configureAfterSecure"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x59,0x85,0x73,0x71,0x84,0x80,0x30,0x31,0x70,0x98,0x7A", outClusters:"0x5A"
}

View File

@@ -87,16 +87,27 @@ def beep() {
up to this long from the time you send the message to the time you hear a sound.
*/
// Used source endpoint of 0x02 because we are using smartthings manufacturer specific cluster.
[
"raw 0xFC05 {15 0A 11 00 00 15 01}",
"delay 200",
"send 0x$zigbee.deviceNetworkId 0x02 0x$zigbee.endpointId",
"delay 7000",
"raw 0xFC05 {15 0A 11 00 00 15 01}",
"delay 200",
"send 0x$zigbee.deviceNetworkId 0x02 0x$zigbee.endpointId",
"delay 7000",
"raw 0xFC05 {15 0A 11 00 00 15 01}",
"delay 200",
"send 0x$zigbee.deviceNetworkId 0x02 0x$zigbee.endpointId",
"delay 7000",
"raw 0xFC05 {15 0A 11 00 00 15 01}",
"delay 200",
"send 0x$zigbee.deviceNetworkId 0x02 0x$zigbee.endpointId",
"delay 7000",
"raw 0xFC05 {15 0A 11 00 00 15 01}"
"raw 0xFC05 {15 0A 11 00 00 15 01}",
"delay 200",
"send 0x$zigbee.deviceNetworkId 0x02 0x$zigbee.endpointId",
]
}

View File

@@ -47,6 +47,9 @@ metadata {
command "everywhereJoin"
command "everywhereLeave"
command "forceOff"
command "forceOn"
}
/**
@@ -64,8 +67,10 @@ metadata {
}
standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) {
state "off", label: '${name}', action: "switch.on", icon: "st.Electronics.electronics16", backgroundColor: "#ffffff"
state "on", label: '${name}', action: "switch.off", icon: "st.Electronics.electronics16", backgroundColor: "#79b821"
state "on", label: '${name}', action: "forceOff", icon: "st.Electronics.electronics16", backgroundColor: "#79b821", nextState:"turningOff"
state "turningOff", label:'TURNING OFF', icon:"st.Electronics.electronics16", backgroundColor:"#ffffff"
state "off", label: '${name}', action: "forceOn", icon: "st.Electronics.electronics16", backgroundColor: "#ffffff", nextState:"turningOn"
state "turningOn", label:'TURNING ON', icon:"st.Electronics.electronics16", backgroundColor:"#79b821"
}
valueTile("1", "device.station1", decoration: "flat", canChangeIcon: false) {
state "station1", label:'${currentValue}', action:"preset1"
@@ -138,8 +143,22 @@ metadata {
* one place.
*
*/
def off() { onAction("off") }
def on() { onAction("on") }
def off() {
if (device.currentState("switch")?.value == "on") {
onAction("off")
}
}
def forceOff() {
onAction("off")
}
def on() {
if (device.currentState("switch")?.value == "off") {
onAction("on")
}
}
def forceOn() {
onAction("on")
}
def volup() { onAction("volup") }
def voldown() { onAction("voldown") }
def preset1() { onAction("1") }
@@ -238,11 +257,11 @@ def onAction(String user, data=null) {
def actions = null
switch (user) {
case "on":
actions = boseSetPowerState(true)
boseSetPowerState(true)
break
case "off":
boseSetNowPlaying(null, "STANDBY")
actions = boseSetPowerState(false)
boseSetPowerState(false)
break
case "volume":
actions = boseSetVolume(data)
@@ -747,8 +766,16 @@ def cb_boseSetInput(xml, input) {
*/
def boseSetPowerState(boolean enable) {
log.info "boseSetPowerState(${enable})"
queueCallback('nowPlaying', "cb_boseSetPowerState", enable ? "POWERON" : "POWEROFF")
return boseRefreshNowPlaying()
// Fix to get faster update of power status back from speaker after sending on/off
// Instead of queuing the command to be sent after the refresh send it directly via sendHubCommand
// Note: This is a temporary hack that should be replaced by a re-design of the
// DTH to use sendHubCommand for all commands
sendHubCommand(bosePOST("/key", "<key state=\"press\" sender=\"Gabbo\">POWER</key>"))
sendHubCommand(bosePOST("/key", "<key state=\"release\" sender=\"Gabbo\">POWER</key>"))
sendHubCommand(boseGET("/now_playing"))
if (enable) {
queueCallback('nowPlaying', "cb_boseConfirmPowerOn", 5)
}
}
/**
@@ -787,10 +814,11 @@ def cb_boseSetPowerState(xml, state) {
*/
def cb_boseConfirmPowerOn(xml, tries) {
def result = []
log.warn "boseConfirmPowerOn() attempt #" + tries
if (xml.attributes()['source'] == "STANDBY" && tries > 0) {
def attempt = tries as Integer
log.warn "boseConfirmPowerOn() attempt #$attempt"
if (xml.attributes()['source'] == "STANDBY" && attempt > 0) {
result << boseRefreshNowPlaying()
queueCallback('nowPlaying', "cb_boseConfirmPowerOn", tries-1)
queueCallback('nowPlaying', "cb_boseConfirmPowerOn", attempt-1)
}
return result
}

View File

@@ -105,11 +105,21 @@ def parseDescriptionAsMap(description) {
// Commands to device
def on() {
'zcl on-off on'
[
'zcl on-off on',
'delay 200',
"send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}",
'delay 500'
]
}
def off() {
'zcl on-off off'
[
'zcl on-off off',
'delay 200',
"send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}",
'delay 500'
]
}
def setLevel(value) {

View File

@@ -89,14 +89,17 @@ def parse(String description) {
log.debug "TEMP"
map.name = "temperature"
map.value = getTemperature(descMap.value)
map.unit = temperatureScale
} else if (descMap.cluster == "0201" && descMap.attrId == "0011") {
log.debug "COOLING SETPOINT"
map.name = "coolingSetpoint"
map.value = getTemperature(descMap.value)
map.unit = temperatureScale
} else if (descMap.cluster == "0201" && descMap.attrId == "0012") {
log.debug "HEATING SETPOINT"
map.name = "heatingSetpoint"
map.value = getTemperature(descMap.value)
map.unit = temperatureScale
} else if (descMap.cluster == "0201" && descMap.attrId == "001c") {
log.debug "MODE"
map.name = "thermostatMode"
@@ -169,7 +172,7 @@ def setHeatingSetpoint(degrees) {
def degreesInteger = Math.round(degrees)
log.debug "setHeatingSetpoint({$degreesInteger} ${temperatureScale})"
sendEvent("name": "heatingSetpoint", "value": degreesInteger)
sendEvent("name": "heatingSetpoint", "value": degreesInteger, "unit": temperatureScale)
def celsius = (getTemperatureScale() == "C") ? degreesInteger : (fahrenheitToCelsius(degreesInteger) as Double).round(2)
"st wattr 0x${device.deviceNetworkId} 1 0x201 0x12 0x29 {" + hex(celsius * 100) + "}"
@@ -180,7 +183,7 @@ def setCoolingSetpoint(degrees) {
if (degrees != null) {
def degreesInteger = Math.round(degrees)
log.debug "setCoolingSetpoint({$degreesInteger} ${temperatureScale})"
sendEvent("name": "coolingSetpoint", "value": degreesInteger)
sendEvent("name": "coolingSetpoint", "value": degreesInteger, "unit": temperatureScale)
def celsius = (getTemperatureScale() == "C") ? degreesInteger : (fahrenheitToCelsius(degreesInteger) as Double).round(2)
"st wattr 0x${device.deviceNetworkId} 1 0x201 0x11 0x29 {" + hex(celsius * 100) + "}"
}

View File

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

View File

@@ -0,0 +1,34 @@
# Connected Cree LED Bulb
Works with:
* [Connected Cree LED Bulb](https://support.smartthings.com/hc/en-us/articles/204258280-Cree-Connected-LED-Bulb)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
## Capabilities
* **Actuator** - represents that a Device has commands
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Polling** - represents that poll() can be implemented for the device
* **Refresh** - _refresh()_ command for status updates
* **Switch** - can detect state (possible values: on/off)
* **Switch Level** - represents current light level, usually 0-100 in percent
* **Health Check** - indicates ability to get device health notifications
## Device Health
A Category C6 Connected Cree LED Bulb with maxReportTime of 5 mins.
Check-in interval = 12 mins
## 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:
* [Cree Connected LED Bulb Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/204258280-Cree-Connected-LED-Bulb)

View File

@@ -19,10 +19,10 @@ metadata {
capability "Actuator"
capability "Configuration"
capability "Polling"
capability "Refresh"
capability "Switch"
capability "Switch Level"
capability "Health Check"
fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,1000", outClusters: "0000,0019"
}
@@ -85,15 +85,27 @@ def setLevel(value) {
zigbee.setLevel(value) + ["delay 500"] + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report
}
def refresh() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig() + zigbee.levelConfig()
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.levelRefresh()
}
def poll() {
def refresh() {
zigbee.onOffRefresh() + zigbee.levelRefresh()
}
def configure() {
log.debug "Configuring Reporting and Bindings."
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()
def healthPoll() {
log.debug "healthPoll()"
def cmds = zigbee.onOffRefresh() + zigbee.levelRefresh()
cmds.each{ sendHubCommand(new physicalgraph.device.HubAction(it))}
}
def configure() {
unschedule()
runEvery5Minutes("healthPoll")
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
zigbee.onOffRefresh() + zigbee.levelRefresh()
}

View File

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

View File

@@ -0,0 +1,45 @@
# Z-wave Dimmer Switch
Works with:
* [GE Z-Wave In-Wall Smart Dimmer (GE 12724)](http://products.z-wavealliance.org/products/1197)
* [GE Z-Wave In-Wall Smart Dimmer (Toggle) (GE 12729)](http://products.z-wavealliance.org/products/1201)
* [GE Z-Wave Plug-in Smart Dimmer (GE 12718)](http://products.z-wavealliance.org/products/1191)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Troubleshooting](#Troubleshooting)
## Capabilities
* **Switch Level** - it's defined to accept two parameters, the level and the rate of dimming
* **Actuator** - represents that a Device has commands
* **Indicator** - gives you the ability to set the indicator LED light on a Z-Wave switch
* **Switch** - can detect state (possible values: on/off)
* **Polling** - represents that poll() can be implemented for the device
* **Refresh** - _refresh()_ command for status updates
* **Sensor** - detects sensor events
* **Health Check** - indicates ability to get device health notifications
## Device Health
Z-Wave Smart Dimmers (In-Wall, In-Wall(Toggle), Plug-In) are 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.
Check-in interval = 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.
## 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:
* [General Z-Wave Dimmer/Switch Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200955890-Troubleshooting-GE-in-wall-switch-or-dimmer-won-t-respond-to-commands-or-automations-Z-Wave-)
* [GE Z-Wave In-Wall Smart Dimmer (GE 12724) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200902600-GE-In-Wall-Paddle-Dimmer-Switch-GE-12724-Z-Wave-)
* [GE Z-Wave In-Wall Smart Dimmer (Toggle) (GE 12729) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/207568463-GE-In-Wall-Smart-Toggle-Dimmer-GE-12729-Z-Wave-)
* [GE Z-Wave Plug-in Smart Dimmer (GE 12718) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202088474-GE-Plug-In-Smart-Dimmer-GE-12718-Z-Wave-)

View File

@@ -20,8 +20,11 @@ metadata {
capability "Polling"
capability "Refresh"
capability "Sensor"
capability "Health Check"
fingerprint inClusters: "0x26"
fingerprint mfr:"0063", prod:"4457", deviceJoinName: "Z-Wave Wall Dimmer"
fingerprint mfr:"0063", prod:"4944", deviceJoinName: "Z-Wave Wall Dimmer"
fingerprint mfr:"0063", prod:"5044", deviceJoinName: "Z-Wave Plug-In Dimmer"
}
simulator {
@@ -42,6 +45,10 @@ metadata {
reply "200163,delay 5000,2602": "command: 2603, payload: 63"
}
preferences {
input "ledIndicator", "enum", title: "LED Indicator", description: "Turn LED indicator... ", required: false, options:["on": "When On", "off": "When Off", "never": "Never"], defaultValue: "off"
}
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
@@ -70,11 +77,30 @@ metadata {
}
main(["switch"])
details(["switch", "level", "indicator", "refresh"])
details(["switch", "level", "refresh"])
}
}
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])
switch (ledIndicator) {
case "on":
indicatorWhenOn()
break
case "off":
indicatorWhenOff()
break
case "never":
indicatorNever()
break
default:
indicatorWhenOn()
break
}
}
def parse(String description) {
def result = null
if (description != "updated") {
@@ -192,6 +218,13 @@ def poll() {
zwave.switchMultilevelV1.switchMultilevelGet().format()
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
refresh()
}
def refresh() {
log.debug "refresh() is called"
def commands = []
@@ -202,19 +235,19 @@ def refresh() {
delayBetween(commands,100)
}
def indicatorWhenOn() {
sendEvent(name: "indicatorStatus", value: "when on")
zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format()
void indicatorWhenOn() {
sendEvent(name: "indicatorStatus", value: "when on", display: false)
sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format()))
}
def indicatorWhenOff() {
sendEvent(name: "indicatorStatus", value: "when off")
zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format()
void indicatorWhenOff() {
sendEvent(name: "indicatorStatus", value: "when off", display: false)
sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format()))
}
def indicatorNever() {
sendEvent(name: "indicatorStatus", value: "never")
zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 3, size: 1).format()
void indicatorNever() {
sendEvent(name: "indicatorStatus", value: "never", display: false)
sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 3, size: 1).format()))
}
def invertSwitch(invert=true) {
@@ -224,4 +257,4 @@ def invertSwitch(invert=true) {
else {
zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 4, size: 1).format()
}
}
}

View File

@@ -31,13 +31,13 @@ metadata {
command "switchMode"
command "switchFanMode"
attribute "thermostatSetpoint","number"
attribute "thermostatStatus","string"
attribute "thermostatSetpoint", "number"
attribute "thermostatStatus", "string"
attribute "maxHeatingSetpoint", "number"
attribute "minHeatingSetpoint", "number"
attribute "maxCoolingSetpoint", "number"
attribute "minCoolingSetpoint", "number"
attribute "deviceTemperatureUnit", "number"
attribute "deviceTemperatureUnit", "string"
}
tiles {
@@ -152,11 +152,11 @@ def generateEvent(Map results) {
sendValue = location.temperatureScale == "C"? roundC(sendValue) : sendValue
isChange = isTemperatureStateChange(device, name, value.toString())
isDisplayed = isChange
event << [value: sendValue, isStateChange: isChange, displayed: isDisplayed]
event << [value: sendValue, unit: temperatureScale, isStateChange: isChange, displayed: isDisplayed]
} else if (name=="maxCoolingSetpoint" || name=="minCoolingSetpoint" || name=="maxHeatingSetpoint" || name=="minHeatingSetpoint") {
def sendValue = convertTemperatureIfNeeded(value.toDouble(), "F", 1) //API return temperature value in F
sendValue = location.temperatureScale == "C"? roundC(sendValue) : sendValue
event << [value: sendValue, displayed: false]
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]
@@ -234,9 +234,9 @@ void setHeatingSetpoint(setpoint) {
def heatingValue = location.temperatureScale == "C"? convertCtoF(heatingSetpoint) : heatingSetpoint
def sendHoldType = holdType ? (holdType=="Temporary")? "nextTransition" : (holdType=="Permanent")? "indefinite" : "indefinite" : "indefinite"
if (parent.setHold(this, heatingValue, coolingValue, deviceId, sendHoldType)) {
sendEvent("name":"heatingSetpoint", "value":heatingSetpoint)
sendEvent("name":"coolingSetpoint", "value":coolingSetpoint)
if (parent.setHold(heatingValue, coolingValue, deviceId, sendHoldType)) {
sendEvent("name":"heatingSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
sendEvent("name":"coolingSetpoint", "value":coolingSetpoint, "unit":location.temperatureScale)
log.debug "Done setHeatingSetpoint> coolingSetpoint: ${coolingSetpoint}, heatingSetpoint: ${heatingSetpoint}"
generateSetpointEvent()
generateStatusEvent()
@@ -271,9 +271,9 @@ void setCoolingSetpoint(setpoint) {
def heatingValue = location.temperatureScale == "C"? convertCtoF(heatingSetpoint) : heatingSetpoint
def sendHoldType = holdType ? (holdType=="Temporary")? "nextTransition" : (holdType=="Permanent")? "indefinite" : "indefinite" : "indefinite"
if (parent.setHold(this, heatingValue, coolingValue, deviceId, sendHoldType)) {
sendEvent("name":"heatingSetpoint", "value":heatingSetpoint)
sendEvent("name":"coolingSetpoint", "value":coolingSetpoint)
if (parent.setHold(heatingValue, coolingValue, deviceId, sendHoldType)) {
sendEvent("name":"heatingSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
sendEvent("name":"coolingSetpoint", "value":coolingSetpoint, "unit":location.temperatureScale)
log.debug "Done setCoolingSetpoint>> coolingSetpoint = ${coolingSetpoint}, heatingSetpoint = ${heatingSetpoint}"
generateSetpointEvent()
generateStatusEvent()
@@ -287,14 +287,14 @@ void resumeProgram() {
log.debug "resumeProgram() is called"
sendEvent("name":"thermostatStatus", "value":"resuming schedule", "description":statusText, displayed: false)
def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.resumeProgram(this, deviceId)) {
if (parent.resumeProgram(deviceId)) {
sendEvent("name":"thermostatStatus", "value":"setpoint is updating", "description":statusText, displayed: false)
runIn(5, "poll")
log.debug "resumeProgram() is done"
sendEvent("name":"resumeProgram", "value":"resume", descriptionText: "resumeProgram is done", displayed: false, isStateChange: true)
} else {
sendEvent("name":"thermostatStatus", "value":"failed resume click refresh", "description":statusText, displayed: false)
log.error "Error resumeProgram() check parent.resumeProgram(this, deviceId)"
log.error "Error resumeProgram() check parent.resumeProgram(deviceId)"
}
}
@@ -406,7 +406,7 @@ def generateOperatingStateEvent(operatingState) {
def off() {
log.debug "off"
def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.setMode (this,"off", deviceId))
if (parent.setMode ("off", deviceId))
generateModeEvent("off")
else {
log.debug "Error setting new mode."
@@ -420,7 +420,7 @@ def off() {
def heat() {
log.debug "heat"
def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.setMode (this,"heat", deviceId))
if (parent.setMode ("heat", deviceId))
generateModeEvent("heat")
else {
log.debug "Error setting new mode."
@@ -438,7 +438,7 @@ def emergencyHeat() {
def auxHeatOnly() {
log.debug "auxHeatOnly"
def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.setMode (this,"auxHeatOnly", deviceId))
if (parent.setMode ("auxHeatOnly", deviceId))
generateModeEvent("auxHeatOnly")
else {
log.debug "Error setting new mode."
@@ -452,7 +452,7 @@ def auxHeatOnly() {
def cool() {
log.debug "cool"
def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.setMode (this,"cool", deviceId))
if (parent.setMode ("cool", deviceId))
generateModeEvent("cool")
else {
log.debug "Error setting new mode."
@@ -466,7 +466,7 @@ def cool() {
def auto() {
log.debug "auto"
def deviceId = device.deviceNetworkId.split(/\./).last()
if (parent.setMode (this,"auto", deviceId))
if (parent.setMode ("auto", deviceId))
generateModeEvent("auto")
else {
log.debug "Error setting new mode."
@@ -489,7 +489,7 @@ def fanOn() {
def coolingValue = location.temperatureScale == "C"? convertCtoF(coolingSetpoint) : coolingSetpoint
def heatingValue = location.temperatureScale == "C"? convertCtoF(heatingSetpoint) : heatingSetpoint
if (parent.setFanMode(this, heatingValue, coolingValue, deviceId, sendHoldType, fanMode)) {
if (parent.setFanMode(heatingValue, coolingValue, deviceId, sendHoldType, fanMode)) {
generateFanModeEvent(fanMode)
} else {
log.debug "Error setting new mode."
@@ -510,7 +510,7 @@ def fanAuto() {
def coolingValue = location.temperatureScale == "C"? convertCtoF(coolingSetpoint) : coolingSetpoint
def heatingValue = location.temperatureScale == "C"? convertCtoF(heatingSetpoint) : heatingSetpoint
if (parent.setFanMode(this, heatingValue, coolingValue, deviceId, sendHoldType, fanMode)) {
if (parent.setFanMode(heatingValue, coolingValue, deviceId, sendHoldType, fanMode)) {
generateFanModeEvent(fanMode)
} else {
log.debug "Error setting new mode."
@@ -556,12 +556,12 @@ def generateSetpointEvent() {
if (mode == "heat") {
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint )
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
}
else if (mode == "cool") {
sendEvent("name":"thermostatSetpoint", "value":coolingSetpoint)
sendEvent("name":"thermostatSetpoint", "value":coolingSetpoint, "unit":location.temperatureScale)
} else if (mode == "auto") {
@@ -573,7 +573,7 @@ def generateSetpointEvent() {
} else if (mode == "auxHeatOnly") {
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint)
sendEvent("name":"thermostatSetpoint", "value":heatingSetpoint, "unit":location.temperatureScale)
}
@@ -608,7 +608,7 @@ void raiseSetpoint() {
targetvalue = maxCoolingSetpoint
}
sendEvent("name":"thermostatSetpoint", "value":targetvalue, displayed: false)
sendEvent("name":"thermostatSetpoint", "value":targetvalue, "unit":location.temperatureScale, displayed: false)
log.info "In mode $mode raiseSetpoint() to $targetvalue"
runIn(3, "alterSetpoint", [data: [value:targetvalue], overwrite: true]) //when user click button this runIn will be overwrite
@@ -644,7 +644,7 @@ void lowerSetpoint() {
targetvalue = minCoolingSetpoint
}
sendEvent("name":"thermostatSetpoint", "value":targetvalue, displayed: false)
sendEvent("name":"thermostatSetpoint", "value":targetvalue, "unit":location.temperatureScale, displayed: false)
log.info "In mode $mode lowerSetpoint() to $targetvalue"
runIn(3, "alterSetpoint", [data: [value:targetvalue], overwrite: true]) //when user click button this runIn will be overwrite
@@ -655,55 +655,60 @@ void lowerSetpoint() {
void alterSetpoint(temp) {
def mode = device.currentValue("thermostatMode")
def heatingSetpoint = device.currentValue("heatingSetpoint")
def coolingSetpoint = device.currentValue("coolingSetpoint")
def deviceId = device.deviceNetworkId.split(/\./).last()
def targetHeatingSetpoint
def targetCoolingSetpoint
//step1: check thermostatMode, enforce limits before sending request to cloud
if (mode == "heat" || mode == "auxHeatOnly"){
if (temp.value > coolingSetpoint){
targetHeatingSetpoint = temp.value
targetCoolingSetpoint = temp.value
} else {
targetHeatingSetpoint = temp.value
targetCoolingSetpoint = coolingSetpoint
}
} else if (mode == "cool") {
//enforce limits before sending request to cloud
if (temp.value < heatingSetpoint){
targetHeatingSetpoint = temp.value
targetCoolingSetpoint = temp.value
} else {
targetHeatingSetpoint = heatingSetpoint
targetCoolingSetpoint = temp.value
}
}
log.debug "alterSetpoint >> in mode ${mode} trying to change heatingSetpoint to $targetHeatingSetpoint " +
"coolingSetpoint to $targetCoolingSetpoint with holdType : ${holdType}"
def sendHoldType = holdType ? (holdType=="Temporary")? "nextTransition" : (holdType=="Permanent")? "indefinite" : "indefinite" : "indefinite"
def coolingValue = location.temperatureScale == "C"? convertCtoF(targetCoolingSetpoint) : targetCoolingSetpoint
def heatingValue = location.temperatureScale == "C"? convertCtoF(targetHeatingSetpoint) : targetHeatingSetpoint
if (parent.setHold(this, heatingValue, coolingValue, deviceId, sendHoldType)) {
sendEvent("name": "thermostatSetpoint", "value": temp.value, displayed: false)
sendEvent("name": "heatingSetpoint", "value": targetHeatingSetpoint)
sendEvent("name": "coolingSetpoint", "value": targetCoolingSetpoint)
log.debug "alterSetpoint in mode $mode succeed change setpoint to= ${temp.value}"
if (mode == "off" || mode == "auto") {
log.warn "this mode: $mode does not allow alterSetpoint"
} else {
log.error "Error alterSetpoint()"
def heatingSetpoint = device.currentValue("heatingSetpoint")
def coolingSetpoint = device.currentValue("coolingSetpoint")
def deviceId = device.deviceNetworkId.split(/\./).last()
def targetHeatingSetpoint
def targetCoolingSetpoint
//step1: check thermostatMode, enforce limits before sending request to cloud
if (mode == "heat" || mode == "auxHeatOnly"){
sendEvent("name": "thermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false)
if (temp.value > coolingSetpoint){
targetHeatingSetpoint = temp.value
targetCoolingSetpoint = temp.value
} else {
targetHeatingSetpoint = temp.value
targetCoolingSetpoint = coolingSetpoint
}
} else if (mode == "cool") {
sendEvent("name": "thermostatSetpoint", "value": coolingSetpoint.toString(), displayed: false)
//enforce limits before sending request to cloud
if (temp.value < heatingSetpoint){
targetHeatingSetpoint = temp.value
targetCoolingSetpoint = temp.value
} else {
targetHeatingSetpoint = heatingSetpoint
targetCoolingSetpoint = temp.value
}
}
log.debug "alterSetpoint >> in mode ${mode} trying to change heatingSetpoint to $targetHeatingSetpoint " +
"coolingSetpoint to $targetCoolingSetpoint with holdType : ${holdType}"
def sendHoldType = holdType ? (holdType=="Temporary")? "nextTransition" : (holdType=="Permanent")? "indefinite" : "indefinite" : "indefinite"
def coolingValue = location.temperatureScale == "C"? convertCtoF(targetCoolingSetpoint) : targetCoolingSetpoint
def heatingValue = location.temperatureScale == "C"? convertCtoF(targetHeatingSetpoint) : targetHeatingSetpoint
if (parent.setHold(heatingValue, coolingValue, deviceId, sendHoldType)) {
sendEvent("name": "thermostatSetpoint", "value": temp.value, displayed: false)
sendEvent("name": "heatingSetpoint", "value": targetHeatingSetpoint, "unit": location.temperatureScale)
sendEvent("name": "coolingSetpoint", "value": targetCoolingSetpoint, "unit": location.temperatureScale)
log.debug "alterSetpoint in mode $mode succeed change setpoint to= ${temp.value}"
} else {
log.error "Error alterSetpoint()"
if (mode == "heat" || mode == "auxHeatOnly"){
sendEvent("name": "thermostatSetpoint", "value": heatingSetpoint.toString(), displayed: false)
} else if (mode == "cool") {
sendEvent("name": "thermostatSetpoint", "value": coolingSetpoint.toString(), displayed: false)
}
}
generateStatusEvent()
}
generateStatusEvent()
}
def generateStatusEvent() {

View File

@@ -682,7 +682,7 @@ def setHeatingSetpoint(degrees) {
def temperatureScale = getTemperatureScale()
def degreesInteger = degrees as Integer
sendEvent("name":"heatingSetpoint", "value":degreesInteger)
sendEvent("name":"heatingSetpoint", "value":degreesInteger, "unit":temperatureScale)
def celsius = (getTemperatureScale() == "C") ? degreesInteger : (fahrenheitToCelsius(degreesInteger) as Double).round(2)
"st wattr 0x${device.deviceNetworkId} 1 0x201 0x12 0x29 {" + hex(celsius*100) + "}"
@@ -691,7 +691,7 @@ def setHeatingSetpoint(degrees) {
def setCoolingSetpoint(degrees) {
def degreesInteger = degrees as Integer
sendEvent("name":"coolingSetpoint", "value":degreesInteger)
sendEvent("name":"coolingSetpoint", "value":degreesInteger, "unit":temperatureScale)
def celsius = (getTemperatureScale() == "C") ? degreesInteger : (fahrenheitToCelsius(degreesInteger) as Double).round(2)
"st wattr 0x${device.deviceNetworkId} 1 0x201 0x11 0x29 {" + hex(celsius*100) + "}"

View File

@@ -16,6 +16,7 @@ metadata {
capability "Switch"
capability "Refresh"
capability "Sensor"
capability "Health Check"
command "setAdjustedColor"
command "reset"
@@ -43,7 +44,7 @@ metadata {
}
standardTile("reset", "device.reset", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
state "default", label:"Reset Color", action:"reset", icon:"st.lights.philips.hue-single"
state "default", label:"Reset To White", action:"reset", icon:"st.lights.philips.hue-single"
}
standardTile("refresh", "device.refresh", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
@@ -51,10 +52,14 @@ metadata {
}
main(["rich-control"])
details(["rich-control", "colorTempSliderControl", "colorTemp", "reset", "refresh"])
details(["rich-control", "reset", "refresh"])
}
}
void installed() {
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan", hubHardwareId: device.hub.hardwareID], displayed: false)
}
// parse events into attributes
def parse(description) {
log.debug "parse() - $description"
@@ -75,118 +80,78 @@ def parse(description) {
// handle commands
void on() {
log.trace parent.on(this)
sendEvent(name: "switch", value: "on")
}
void off() {
log.trace parent.off(this)
sendEvent(name: "switch", value: "off")
}
void nextLevel() {
def level = device.latestValue("level") as Integer ?: 0
if (level <= 100) {
level = Math.min(25 * (Math.round(level / 25) + 1), 100) as Integer
}
else {
level = 25
}
setLevel(level)
}
void setLevel(percent) {
log.debug "Executing 'setLevel'"
if (verifyPercent(percent)) {
parent.setLevel(this, percent)
sendEvent(name: "level", value: percent, descriptionText: "Level has changed to ${percent}%")
sendEvent(name: "switch", value: "on")
log.trace parent.setLevel(this, percent)
}
}
void setSaturation(percent) {
log.debug "Executing 'setSaturation'"
if (verifyPercent(percent)) {
parent.setSaturation(this, percent)
sendEvent(name: "saturation", value: percent, displayed: false)
log.trace parent.setSaturation(this, percent)
}
}
void setHue(percent) {
log.debug "Executing 'setHue'"
if (verifyPercent(percent)) {
parent.setHue(this, percent)
sendEvent(name: "hue", value: percent, displayed: false)
log.trace parent.setHue(this, percent)
}
}
void setColor(value) {
log.debug "setColor: ${value}, $this"
def events = []
def validValues = [:]
if (verifyPercent(value.hue)) {
events << createEvent(name: "hue", value: value.hue, displayed: false)
validValues.hue = value.hue
}
if (verifyPercent(value.saturation)) {
events << createEvent(name: "saturation", value: value.saturation, displayed: false)
validValues.saturation = value.saturation
}
if (value.hex != null) {
if (value.hex ==~ /^\#([A-Fa-f0-9]){6}$/) {
events << createEvent(name: "color", value: value.hex)
validValues.hex = value.hex
} else {
log.warn "$value.hex is not a valid color"
}
}
if (verifyPercent(value.level)) {
events << createEvent(name: "level", value: value.level, descriptionText: "Level has changed to ${value.level}%")
validValues.level = value.level
}
if (value.switch == "off" || (value.level != null && value.level <= 0)) {
events << createEvent(name: "switch", value: "off")
validValues.switch = "off"
} else {
events << createEvent(name: "switch", value: "on")
validValues.switch = "on"
}
if (!events.isEmpty()) {
parent.setColor(this, validValues)
}
events.each {
sendEvent(it)
if (!validValues.isEmpty()) {
log.trace parent.setColor(this, validValues)
}
}
void reset() {
log.debug "Executing 'reset'"
def value = [level:100, saturation:56, hue:23]
setAdjustedColor(value)
parent.poll()
def value = [hue:20, saturation:2]
setAdjustedColor(value)
}
void setAdjustedColor(value) {
if (value) {
log.trace "setAdjustedColor: ${value}"
def adjusted = value + [:]
adjusted.hue = adjustOutgoingHue(value.hue)
// Needed because color picker always sends 100
adjusted.level = null
setColor(adjusted)
setColor(adjusted)
} else {
log.warn "Invalid color input"
}
}
void setColorTemperature(value) {
if (value) {
log.trace "setColorTemperature: ${value}k"
parent.setColorTemperature(this, value)
sendEvent(name: "colorTemperature", value: value)
sendEvent(name: "switch", value: "on")
} else {
log.warn "Invalid color temperature"
log.warn "Invalid color input $value"
}
}
@@ -195,22 +160,6 @@ void refresh() {
parent.manualRefresh()
}
def adjustOutgoingHue(percent) {
def adjusted = percent
if (percent > 31) {
if (percent < 63.0) {
adjusted = percent + (7 * (percent -30 ) / 32)
}
else if (percent < 73.0) {
adjusted = 69 + (5 * (percent - 62) / 10)
}
else {
adjusted = percent + (2 * (100 - percent) / 28)
}
}
log.info "percent: $percent, adjusted: $adjusted"
adjusted
}
def verifyPercent(percent) {
if (percent == null)
@@ -222,3 +171,7 @@ def verifyPercent(percent) {
return false
}
}
def ping() {
log.debug "${parent.ping(this)}"
}

View File

@@ -7,8 +7,15 @@
metadata {
// Automatically generated. Make future change here.
definition (name: "Hue Bridge", namespace: "smartthings", author: "SmartThings") {
attribute "serialNumber", "string"
capability "Health Check"
attribute "networkAddress", "string"
// Used to indicate if bridge is reachable or not, i.e. is the bridge connected to the network
// Possible values "Online" or "Offline"
attribute "status", "string"
// Id is the number on the back of the hub, Hue uses last six digits of Mac address
// This is also used in the Hue application as ID
attribute "idNumber", "string"
}
simulator {
@@ -17,25 +24,30 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"rich-control"){
tileAttribute ("", key: "PRIMARY_CONTROL") {
attributeState "default", label: "Hue Bridge", action: "", icon: "st.Lighting.light99-hue", backgroundColor: "#F3C200"
tileAttribute ("device.status", key: "PRIMARY_CONTROL") {
attributeState "Offline", label: '${currentValue}', action: "", icon: "st.Lighting.light99-hue", backgroundColor: "#ffffff"
attributeState "Online", label: '${currentValue}', action: "", icon: "st.Lighting.light99-hue", backgroundColor: "#79b821"
}
tileAttribute ("serialNumber", key: "SECONDARY_CONTROL") {
attributeState "default", label:'SN: ${currentValue}'
}
}
valueTile("serialNumber", "device.serialNumber", decoration: "flat", height: 1, width: 2, inactiveLabel: false) {
state "default", label:'SN: ${currentValue}'
valueTile("doNotRemove", "v", decoration: "flat", height: 2, width: 6, inactiveLabel: false) {
state "default", label:'If removed, Hue lights will not work properly'
}
valueTile("networkAddress", "device.networkAddress", decoration: "flat", height: 2, width: 4, inactiveLabel: false) {
state "default", label:'${currentValue}', height: 1, width: 2, inactiveLabel: false
valueTile("idNumber", "device.idNumber", decoration: "flat", height: 2, width: 6, inactiveLabel: false) {
state "default", label:'ID: ${currentValue}'
}
valueTile("networkAddress", "device.networkAddress", decoration: "flat", height: 2, width: 6, inactiveLabel: false) {
state "default", label:'IP: ${currentValue}'
}
main (["rich-control"])
details(["rich-control", "networkAddress"])
details(["rich-control", "doNotRemove", "idNumber", "networkAddress"])
}
}
void installed() {
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan"], displayed: false)
}
// parse events into attributes
def parse(description) {
log.debug "Parsing '${description}'"
@@ -56,7 +68,7 @@ def parse(description) {
log.trace "HUE BRIDGE, GENERATING EVENT: $map.name: $map.value"
results << createEvent(name: "${map.name}", value: "${map.value}")
} else {
log.trace "Parsing description"
log.trace "Parsing description"
def msg = parseLanMessage(description)
if (msg.body) {
def contentType = msg.headers["Content-Type"]
@@ -64,18 +76,17 @@ def parse(description) {
def bulbs = new groovy.json.JsonSlurper().parseText(msg.body)
if (bulbs.state) {
log.info "Bridge response: $msg.body"
} else {
// Sending Bulbs List to parent"
if (parent.state.inBulbDiscovery)
log.info parent.bulbListHandler(device.hub.id, msg.body)
}
}
else if (contentType?.contains("xml")) {
} else if (contentType?.contains("xml")) {
log.debug "HUE BRIDGE ALREADY PRESENT"
parent.hubVerification(device.hub.id, msg.body)
parent.hubVerification(device.hub.id, msg.body)
}
}
}
}
results
}
def ping() {
log.debug "${parent.ping(this)}"
}

View File

@@ -17,6 +17,7 @@ metadata {
capability "Switch"
capability "Refresh"
capability "Sensor"
capability "Health Check"
command "setAdjustedColor"
command "reset"
@@ -43,16 +44,16 @@ metadata {
}
}
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2000..6500)") {
state "colorTemperature", action:"color temperature.setColorTemperature"
}
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2000..6500)") {
state "colorTemperature", action:"color temperature.setColorTemperature"
}
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "colorTemperature", label: '${currentValue} K'
}
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "colorTemperature", label: 'WHITES'
}
standardTile("reset", "device.reset", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
state "default", label:"Reset Color", action:"reset", icon:"st.lights.philips.hue-single"
state "default", label:"Reset To White", action:"reset", icon:"st.lights.philips.hue-single"
}
standardTile("refresh", "device.refresh", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
@@ -64,6 +65,10 @@ metadata {
}
}
void installed() {
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan", hubHardwareId: device.hub.hardwareID], displayed: false)
}
// parse events into attributes
def parse(description) {
log.debug "parse() - $description"
@@ -84,141 +89,92 @@ def parse(description) {
// handle commands
void on() {
log.trace parent.on(this)
sendEvent(name: "switch", value: "on")
}
void off() {
log.trace parent.off(this)
sendEvent(name: "switch", value: "off")
}
void nextLevel() {
def level = device.latestValue("level") as Integer ?: 0
if (level <= 100) {
level = Math.min(25 * (Math.round(level / 25) + 1), 100) as Integer
}
else {
level = 25
}
setLevel(level)
}
void setLevel(percent) {
log.debug "Executing 'setLevel'"
if (verifyPercent(percent)) {
parent.setLevel(this, percent)
sendEvent(name: "level", value: percent, descriptionText: "Level has changed to ${percent}%")
sendEvent(name: "switch", value: "on")
log.trace parent.setLevel(this, percent)
}
}
void setSaturation(percent) {
log.debug "Executing 'setSaturation'"
if (verifyPercent(percent)) {
parent.setSaturation(this, percent)
sendEvent(name: "saturation", value: percent, displayed: false)
log.trace parent.setSaturation(this, percent)
}
}
void setHue(percent) {
log.debug "Executing 'setHue'"
if (verifyPercent(percent)) {
parent.setHue(this, percent)
sendEvent(name: "hue", value: percent, displayed: false)
log.trace parent.setHue(this, percent)
}
}
void setColor(value) {
log.debug "setColor: ${value}, $this"
def events = []
def validValues = [:]
if (verifyPercent(value.hue)) {
events << createEvent(name: "hue", value: value.hue, displayed: false)
validValues.hue = value.hue
}
if (verifyPercent(value.saturation)) {
events << createEvent(name: "saturation", value: value.saturation, displayed: false)
validValues.saturation = value.saturation
}
if (value.hex != null) {
if (value.hex ==~ /^\#([A-Fa-f0-9]){6}$/) {
events << createEvent(name: "color", value: value.hex)
validValues.hex = value.hex
} else {
log.warn "$value.hex is not a valid color"
}
}
if (verifyPercent(value.level)) {
events << createEvent(name: "level", value: value.level, descriptionText: "Level has changed to ${value.level}%")
validValues.level = value.level
}
if (value.switch == "off" || (value.level != null && value.level <= 0)) {
events << createEvent(name: "switch", value: "off")
validValues.switch = "off"
} else {
events << createEvent(name: "switch", value: "on")
validValues.switch = "on"
}
if (!events.isEmpty()) {
parent.setColor(this, validValues)
}
events.each {
sendEvent(it)
if (!validValues.isEmpty()) {
log.trace parent.setColor(this, validValues)
}
}
void reset() {
log.debug "Executing 'reset'"
def value = [level:100, saturation:56, hue:23]
setAdjustedColor(value)
parent.poll()
setColorTemperature(4000)
}
void setAdjustedColor(value) {
if (value) {
log.trace "setAdjustedColor: ${value}"
def adjusted = value + [:]
adjusted.hue = adjustOutgoingHue(value.hue)
// Needed because color picker always sends 100
adjusted.level = null
setColor(adjusted)
setColor(adjusted)
} else {
log.warn "Invalid color input"
log.warn "Invalid color input $value"
}
}
void setColorTemperature(value) {
if (value) {
log.trace "setColorTemperature: ${value}k"
parent.setColorTemperature(this, value)
sendEvent(name: "colorTemperature", value: value)
sendEvent(name: "switch", value: "on")
log.trace parent.setColorTemperature(this, value)
} else {
log.warn "Invalid color temperature"
log.warn "Invalid color temperature $value"
}
}
void refresh() {
log.debug "Executing 'refresh'"
parent.manualRefresh()
}
def adjustOutgoingHue(percent) {
def adjusted = percent
if (percent > 31) {
if (percent < 63.0) {
adjusted = percent + (7 * (percent -30 ) / 32)
}
else if (percent < 73.0) {
adjusted = 69 + (5 * (percent - 62) / 10)
}
else {
adjusted = percent + (2 * (100 - percent) / 28)
}
}
log.info "percent: $percent, adjusted: $adjusted"
adjusted
parent?.manualRefresh()
}
def verifyPercent(percent) {
@@ -231,3 +187,7 @@ def verifyPercent(percent) {
return false
}
}
def ping() {
log.trace "${parent.ping(this)}"
}

View File

@@ -14,6 +14,7 @@ metadata {
capability "Switch"
capability "Refresh"
capability "Sensor"
capability "Health Check"
command "refresh"
}
@@ -48,6 +49,10 @@ metadata {
}
}
void installed() {
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan", hubHardwareId: device.hub.hardwareID], displayed: false)
}
// parse events into attributes
def parse(description) {
log.debug "parse() - $description"
@@ -68,20 +73,16 @@ def parse(description) {
// handle commands
void on() {
log.trace parent.on(this)
sendEvent(name: "switch", value: "on")
}
void off() {
log.trace parent.off(this)
sendEvent(name: "switch", value: "off")
}
void setLevel(percent) {
log.debug "Executing 'setLevel'"
if (percent != null && percent >= 0 && percent <= 100) {
parent.setLevel(this, percent)
sendEvent(name: "level", value: percent)
sendEvent(name: "switch", value: "on")
} else {
log.warn "$percent is not 0-100"
}
@@ -91,3 +92,7 @@ void refresh() {
log.debug "Executing 'refresh'"
parent.manualRefresh()
}
def ping() {
log.debug "${parent.ping(this)}"
}

View File

@@ -15,6 +15,7 @@ metadata {
capability "Color Temperature"
capability "Switch"
capability "Refresh"
capability "Health Check"
command "refresh"
}
@@ -36,12 +37,12 @@ metadata {
}
}
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2000..6500)") {
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2200..6500)") {
state "colorTemperature", action:"color temperature.setColorTemperature"
}
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "colorTemperature", label: '${currentValue} K'
state "colorTemperature", label: 'WHITES'
}
standardTile("refresh", "device.refresh", height: 2, width: 2, inactiveLabel: false, decoration: "flat") {
@@ -53,6 +54,10 @@ metadata {
}
}
void installed() {
sendEvent(name: "checkInterval", value: 60 * 12, data: [protocol: "lan", hubHardwareId: device.hub.hardwareID], displayed: false)
}
// parse events into attributes
def parse(description) {
log.debug "parse() - $description"
@@ -73,20 +78,16 @@ def parse(description) {
// handle commands
void on() {
log.trace parent.on(this)
sendEvent(name: "switch", value: "on")
}
void off() {
log.trace parent.off(this)
sendEvent(name: "switch", value: "off")
}
void setLevel(percent) {
log.debug "Executing 'setLevel'"
if (percent != null && percent >= 0 && percent <= 100) {
parent.setLevel(this, percent)
sendEvent(name: "level", value: percent)
sendEvent(name: "switch", value: "on")
log.trace parent.setLevel(this, percent)
} else {
log.warn "$percent is not 0-100"
}
@@ -95,9 +96,7 @@ void setLevel(percent) {
void setColorTemperature(value) {
if (value) {
log.trace "setColorTemperature: ${value}k"
parent.setColorTemperature(this, value)
sendEvent(name: "colorTemperature", value: value)
sendEvent(name: "switch", value: "on")
log.trace parent.setColorTemperature(this, value)
} else {
log.warn "Invalid color temperature"
}
@@ -108,3 +107,6 @@ void refresh() {
parent.manualRefresh()
}
def ping() {
log.debug "${parent.ping(this)}"
}

View File

@@ -13,6 +13,7 @@
* for the specific language governing permissions and limitations under the License.
*
*/
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
metadata {
definition (name: "NYCE Motion Sensor", namespace: "smartthings", author: "SmartThings") {
@@ -143,51 +144,14 @@ private Map parseReportAttributeMessage(String description) {
private Map parseIasMessage(String description) {
List parsedMsg = description.split(' ')
String msgCode = parsedMsg[2]
Map resultMap = [:]
switch(msgCode) {
case '0x0030': // Closed/No Motion/Dry
log.debug 'no motion'
resultMap.name = 'motion'
resultMap.value = 'inactive'
break
ZoneStatus zs = zigbee.parseZoneStatus(description)
Map resultMap = [:]
case '0x0032': // Open/Motion/Wet
log.debug 'motion'
resultMap.name = 'motion'
resultMap.value = 'active'
break
resultMap.name = 'motion'
resultMap.value = zs.isAlarm2Set() ? 'active' : 'inactive'
log.debug(zs.isAlarm2Set() ? 'motion' : 'no motion')
case '0x0032': // Tamper Alarm
log.debug 'motion with tamper alarm'
resultMap.name = 'motion'
resultMap.value = 'active'
break
case '0x0033': // Battery Alarm
break
case '0x0034': // Supervision Report
log.debug 'no motion with tamper alarm'
resultMap.name = 'motion'
resultMap.value = 'inactive'
break
case '0x0035': // Restore Report
break
case '0x0036': // Trouble/Failure
log.debug 'motion with failure alarm'
resultMap.name = 'motion'
resultMap.value = 'active'
break
case '0x0038': // Test Mode
break
}
return resultMap
return resultMap
}
def refresh()

View File

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

View File

@@ -0,0 +1,37 @@
# Nyce Door/Window Sensor (Open/Close Sensor)
Works with:
* [NYCE Door/Window Sensor NCZ-3011](https://support.smartthings.com/hc/en-us/articles/204576764-NYCE-Door-Window-Sensor)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Battery](#battery-specification)
* [Troubleshooting](#troubleshooting)
## Capabilities
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Contact Sensor** - can detect contact (with possible values - open/closed)
* **Battery** - defines device uses a battery
* **Refresh** - _refresh()_ command for status updates
* **Health Check** - indicates ability to get device health notifications
## Device Health
A Category C2 Nyce Door/Window sensor that has 12min check-in interval
## Battery Specification
One 3V CR2032 battery required.
## 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 sensor from SmartThings can be found in the following link:
* [Nyce Door/Window Sensor](https://support.smartthings.com/hc/en-us/articles/204576764-NYCE-Door-Window-Sensor)

View File

@@ -13,28 +13,32 @@
* for the specific language governing permissions and limitations under the License.
*
*/
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
metadata {
definition (name: "NYCE Open/Closed Sensor", namespace: "smartthings", author: "NYCE") {
capability "Battery"
capability "Battery"
capability "Configuration"
capability "Contact Sensor"
capability "Contact Sensor"
capability "Refresh"
command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0500,0020", manufacturer: "NYCE", model: "3010", deviceJoinName: "NYCE Door Hinge Sensor"
capability "Health Check"
command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0500,0020", manufacturer: "NYCE", model: "3010", deviceJoinName: "NYCE Door Hinge Sensor"
fingerprint inClusters: "0000,0001,0003,0406,0500,0020", manufacturer: "NYCE", model: "3011", deviceJoinName: "NYCE Door/Window Sensor"
fingerprint inClusters: "0000,0001,0003,0500,0020", manufacturer: "NYCE", model: "3011", deviceJoinName: "NYCE Door/Window Sensor"
fingerprint inClusters: "0000,0001,0003,0406,0500,0020", manufacturer: "NYCE", model: "3014", deviceJoinName: "NYCE Tilt Sensor"
fingerprint inClusters: "0000,0001,0003,0500,0020", manufacturer: "NYCE", model: "3014", deviceJoinName: "NYCE Tilt Sensor"
fingerprint inClusters: "0000,0001,0003,0500,0020", manufacturer: "NYCE", model: "3011", deviceJoinName: "NYCE Door/Window Sensor"
fingerprint inClusters: "0000,0001,0003,0406,0500,0020", manufacturer: "NYCE", model: "3014", deviceJoinName: "NYCE Tilt Sensor"
fingerprint inClusters: "0000,0001,0003,0500,0020", manufacturer: "NYCE", model: "3014", deviceJoinName: "NYCE Tilt Sensor"
}
simulator {
}
tiles {
standardTile("contact", "device.contact", width: 2, height: 2) {
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
@@ -219,40 +223,33 @@ private Map parseReportAttributeMessage(String description) {
}
private List parseIasMessage(String description) {
List parsedMsg = description.split(" ")
String msgCode = parsedMsg[2]
ZoneStatus zs = zigbee.parseZoneStatus(description)
log.debug "parseIasMessage: $description"
List resultListMap = []
Map resultMap_battery = [:]
Map resultMap_battery_state = [:]
Map resultMap_sensor = [:]
// Relevant bit field definitions from ZigBee spec
def BATTERY_BIT = ( 1 << 3 )
def TROUBLE_BIT = ( 1 << 6 )
def SENSOR_BIT = ( 1 << 0 ) // it's ALARM1 bit from the ZCL spec
// Convert hex string to integer
def zoneStatus = Integer.parseInt(msgCode[-4..-1],16)
log.debug "parseIasMessage: zoneStatus: ${zoneStatus}"
resultMap_sensor.name = "contact"
resultMap_sensor.value = zs.isAlarm1Set() ? "open" : "closed"
// Check each relevant bit, create map for it, and add to list
log.debug "parseIasMessage: Battery Status ${zoneStatus & BATTERY_BIT}"
log.debug "parseIasMessage: Trouble Status ${zoneStatus & TROUBLE_BIT}"
log.debug "parseIasMessage: Sensor Status ${zoneStatus & SENSOR_BIT}"
log.debug "parseIasMessage: Battery Status ${zs.battery}"
log.debug "parseIasMessage: Trouble Status ${zs.trouble}"
log.debug "parseIasMessage: Sensor Status ${zs.alarm1}"
/* Comment out this path to check the battery state to avoid overwriting the
battery value (Change log #2), but keep these conditions for later use
resultMap_battery_state.name = "battery_state"
if (zoneStatus & TROUBLE_BIT) {
if (zs.isTroubleSet()) {
resultMap_battery_state.value = "failed"
resultMap_battery.name = "battery"
resultMap_battery.value = 0
}
else {
if (zoneStatus & BATTERY_BIT) {
if (zs.isBatterySet()) {
resultMap_battery_state.value = "low"
// to generate low battery notification by the platform
@@ -270,9 +267,6 @@ private List parseIasMessage(String description) {
}
*/
resultMap_sensor.name = "contact"
resultMap_sensor.value = (zoneStatus & SENSOR_BIT) ? "open" : "closed"
resultListMap << resultMap_battery_state
resultListMap << resultMap_battery
resultListMap << resultMap_sensor
@@ -280,23 +274,28 @@ private List parseIasMessage(String description) {
return resultListMap
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
}
def configure() {
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
def configCmds = [
//battery reporting and heartbeat
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 1 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 1 0x20 0x20 600 3600 {01}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 1500",
def enrollCmds = [
// Writes CIE attribute on end device to direct reports to the hub's EUID
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
]
log.debug "configure: Write IAS CIE"
return configCmds
// battery minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
return enrollCmds + zigbee.batteryConfig(30, 300) + refresh() // send refresh cmds as part of config
}
def enrollResponse() {
@@ -341,7 +340,8 @@ Integer convertHexToInt(hex) {
def refresh() {
log.debug "Refreshing Battery"
[
def refreshCmds = [
"st rattr 0x${device.deviceNetworkId} ${endpointId} 1 0x20", "delay 200"
]
return refreshCmds + enrollResponse()
}

View File

@@ -21,9 +21,6 @@ metadata {
attribute "colorName", "string"
command "setAdjustedColor"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Gardenspot RGB"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY Gardenspot RGB"
}
// simulator metadata
@@ -91,7 +88,7 @@ def parse(String description) {
if (descMap.cluster == "0300") {
if(descMap.attrId == "0000"){ //Hue Attribute
def hueValue = Math.round(convertHexToInt(descMap.value) / 255 * 360)
def hueValue = Math.round(convertHexToInt(descMap.value) / 255 * 100)
log.debug "Hue value returned is $hueValue"
sendEvent(name: "hue", value: hueValue, displayed:false)
}
@@ -203,7 +200,7 @@ def setLevel(value) {
//input Hue Integer values; returns color name for saturation 100%
private getColorName(hueValue){
if(hueValue>360 || hueValue<0)
if(hueValue>100 || hueValue<0)
return
hueValue = Math.round(hueValue / 100 * 360)

View File

@@ -1,4 +1,4 @@
/*
/*
Osram Flex RGBW Light Strip
Osram bulbs have a firmware issue causing it to forget its dimming level when turned off (via commands). Handling
@@ -8,7 +8,7 @@
metadata {
definition (name: "OSRAM LIGHTIFY LED Flexible Strip RGBW", namespace: "smartthings", author: "SmartThings") {
capability "Color Temperature"
capability "Actuator"
capability "Switch"
@@ -18,7 +18,7 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Color Control"
attribute "colorName", "string"
command "setAdjustedColor"
@@ -49,7 +49,7 @@ metadata {
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", height: 1, width: 2, inactiveLabel: false, range:"(2700..6500)") {
state "colorTemperature", action:"color temperature.setColorTemperature"
}
@@ -118,7 +118,7 @@ def parse(String description) {
}
}
else if(descMap.attrId == "0000"){ //Hue Attribute
def hueValue = Math.round(convertHexToInt(descMap.value) / 255 * 360)
def hueValue = Math.round(convertHexToInt(descMap.value) / 255 * 100)
log.debug "Hue value returned is $hueValue"
sendEvent(name: "hue", value: hueValue, displayed:false)
}
@@ -274,7 +274,7 @@ private getGenericName(value){
//input Hue Integer values; returns color name for saturation 100%
private getColorName(hueValue){
if(hueValue>360 || hueValue<0)
if(hueValue>100 || hueValue<0)
return
hueValue = Math.round(hueValue / 100 * 360)
@@ -449,7 +449,7 @@ def setColor(value){
def level = hex(value.level * 255 / 100)
cmd << zigbeeSetLevel(level)
}
if (value.switch == "off") {
cmd << "delay 150"
cmd << off()

View File

@@ -133,7 +133,7 @@ def refresh() {
}
def configure() {
onOffConfig() + levelConfig() + powerConfig() + refresh()
refresh() + onOffConfig() + levelConfig() + powerConfig()
}

View File

@@ -47,9 +47,21 @@ def parse(String description) {
// Commands to device
def on() {
'zcl on-off on'
[
'zcl on-off on',
'delay 200',
"send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}",
'delay 500'
]
}
def off() {
'zcl on-off off'
[
'zcl on-off off',
'delay 200',
"send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}",
'delay 500'
]
}

View File

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

View File

@@ -0,0 +1,38 @@
# SmartPower Outlet
Works with:
* [Samsung SmartPower Outlet](https://shop.smartthings.com/#!/products/smartpower-outlet)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
## Capabilities
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Actuator** - represents that a Device has commands
* **Switch** - can detect state (possible values: on/off)
* **Refresh** - _refresh()_ command for status updates
* **Power Meter** - detects power meter for device in either w or kw.
* **Health Check** - indicates ability to get device health notifications
* **Sensor** - detects sensor events
## Device Health
A Category C1 smart power outlet with maxReportTime of 5 mins.
Check-in interval is double the value of maxReportTime.
This gives the device twice the amount of time to respond before it is marked as offline.
Check-in interval = 12 mins
## 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 links
for the different models:
* [SmartPower Outlet Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/201084854-SmartPower-Outlet)
* [Samsung SmartThings Outlet Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/205957620)

View File

@@ -16,7 +16,7 @@
metadata {
// Automatically generated. Make future change here.
definition (name: "SmartPower Outlet", namespace: "smartthings", author: "SmartThings", category: "C1") {
definition (name: "SmartPower Outlet", namespace: "smartthings", author: "SmartThings") {
capability "Actuator"
capability "Switch"
capability "Power Meter"
@@ -104,8 +104,21 @@ def parse(String description) {
}
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug zigbee.parseDescriptionAsMap(description)
def cluster = zigbee.parse(description)
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07){
if (cluster.data[0] == 0x00) {
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
}
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug "${cluster}"
}
}
}
@@ -116,14 +129,24 @@ def off() {
def on() {
zigbee.on()
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.onOffRefresh()
}
def refresh() {
zigbee.onOffRefresh() + zigbee.refreshData("0x0B04", "0x050B")
zigbee.onOffRefresh() + zigbee.electricMeasurementPowerRefresh()
}
def configure() {
sendEvent(name: "checkInterval", value: 1200, displayed: false)
zigbee.onOffConfig() + powerConfig() + refresh()
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
refresh() + zigbee.onOffConfig(0, 300) + powerConfig()
}
//power config for devices with min reporting interval as 1 seconds and reporting interval if no activity as 10min (600s)

View File

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

View File

@@ -0,0 +1,44 @@
# Smartsense Moisture Sensor
Works with:
* [Samsung SmartThings Moisture Sensor](https://shop.smartthings.com/#!/products/samsung-smartthings-water-leak-sensor)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Battery](#battery-specification)
## Capabilities
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Battery** - defines device uses a battery
* **Refresh** - _refresh()_ command for status updates
* **Temperature Measurement** - defines device measures current temperature
* **Water Sensor** - can detect presence of water (dry or wet)
* **Health Check** - indicates ability to get device health notifications
## Device Health
A Category C2 moisture sensor with maxReportTime of 5 mins.
Check-in interval is double the value of maxReportTime.
This gives the device twice the amount of time to respond before it is marked as offline.
Check-in interval = 12 mins
## Battery Specification
One CR2 3V battery required.
## Troubleshooting
If the sensor 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 different sensors from SmartThings can be found in the following links
for the different models:
* [SmartSense Moisture Sensor Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202847044-SmartSense-Moisture-Sensor)
* [Samsung SmartThings Water Leak Sensor Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/205957630)
Other troubleshooting tips are listed as follows:
* [Troubleshooting: Samsung SmartThings Water Leak Sensor wont pair after removing pull-tab](https://support.smartthings.com/hc/en-us/articles/204966616-Troubleshooting-Samsung-SmartThings-device-won-t-pair-after-removing-pull-tab)

View File

@@ -13,15 +13,18 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
metadata {
definition (name: "SmartSense Moisture Sensor",namespace: "smartthings", author: "SmartThings", category: "C2") {
definition (name: "SmartSense Moisture Sensor",namespace: "smartthings", author: "SmartThings") {
capability "Configuration"
capability "Battery"
capability "Refresh"
capability "Temperature Measurement"
capability "Water Sensor"
capability "Health Check"
capability "Sensor"
command "enrollResponse"
@@ -115,14 +118,28 @@ private Map parseCatchAllMessage(String description) {
if (shouldProcessMessage(cluster)) {
switch(cluster.clusterId) {
case 0x0001:
resultMap = getBatteryResult(cluster.data.last())
// 0x07 - configure reporting
if (cluster.command != 0x07) {
resultMap = getBatteryResult(cluster.data.last())
}
break
case 0x0402:
// temp is last 2 data values. reverse to swap endian
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
def value = getTemperature(temp)
resultMap = getTemperatureResult(value)
if (cluster.command == 0x07) {
if (cluster.data[0] == 0x00){
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
}
}
else {
// temp is last 2 data values. reverse to swap endian
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
def value = getTemperature(temp)
resultMap = getTemperatureResult(value)
}
break
}
}
@@ -132,10 +149,8 @@ private Map parseCatchAllMessage(String description) {
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
// 0x07 is bind message
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
cluster.command == 0x07 ||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
return !ignoredMessage
}
@@ -169,50 +184,17 @@ private Map parseCustomMessage(String description) {
}
private Map parseIasMessage(String description) {
List parsedMsg = description.split(' ')
String msgCode = parsedMsg[2]
ZoneStatus zs = zigbee.parseZoneStatus(description)
Map resultMap = [:]
switch(msgCode) {
case '0x0020': // Closed/No Motion/Dry
resultMap = getMoistureResult('dry')
break
case '0x0021': // Open/Motion/Wet
resultMap = getMoistureResult('wet')
break
case '0x0022': // Tamper Alarm
break
case '0x0023': // Battery Alarm
break
case '0x0024': // Supervision Report
log.debug 'dry with tamper alarm'
resultMap = getMoistureResult('dry')
break
case '0x0025': // Restore Report
log.debug 'water with tamper alarm'
resultMap = getMoistureResult('wet')
break
case '0x0026': // Trouble/Failure
break
case '0x0028': // Test Mode
break
}
return resultMap
return zs.isAlarm1Set() ? getMoistureResult('wet') : getMoistureResult('dry')
}
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16).shortValue() / 100
if(getTemperatureScale() == "C"){
return celsius
return Math.round(celsius)
} else {
return celsiusToFahrenheit(celsius) as Integer
return Math.round(celsiusToFahrenheit(celsius))
}
}
@@ -255,7 +237,10 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
}
}
@@ -281,7 +266,8 @@ private Map getTemperatureResult(value) {
name: 'temperature',
value: value,
descriptionText: descriptionText,
translatable: true
translatable: true,
unit: temperatureScale
]
}
@@ -300,6 +286,13 @@ private Map getMoistureResult(value) {
]
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
}
def refresh() {
log.debug "Refreshing Temperature and Battery"
def refreshCmds = [
@@ -311,23 +304,13 @@ def refresh() {
}
def configure() {
sendEvent(name: "checkInterval", value: 7200, displayed: false)
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 1 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 1 0x20 0x20 30 21600 {01}", //checkin time 6 hrs
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 0x402 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 0x402 0 0x29 30 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500"
]
return configCmds + refresh() // send refresh cmds as part of config
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
// battery minReport 30 seconds, maxReportTime 6 hrs by default
return refresh() + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config
}
def enrollResponse() {

View File

@@ -9,7 +9,8 @@ Works with:
## Table of contents
* [Capabilities](#capabilities)
* [Health]($health)
* [Health](#device-health)
* [Battery](#battery-specification)
## Capabilities
@@ -21,10 +22,24 @@ Works with:
## Device Health
A Category C2 motion sensor that has 120min check-in interval
A Category C2 motion sensor with maxReportTime of 5 mins.
Check-in interval is double the value of maxReportTime.
This gives the device twice the amount of time to respond before it is marked as offline.
Check-in interval = 12 mins
## Battery Specification
One CR2477 (for Samsung SmartThings Motion Sensor) / CR123A (SmartSense Motion Sensor) 3V battery is required.
## 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 different motion sensors from SmartThings can be found in the following links
for the different models:
* [SmartSense Motion Sensor (original model) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200903280-SmartSense-Motion-Sensor-original-model-)
* [SmartSense Motion Sensor (2014 model) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/203077520-SmartSense-Motion-Sensor-2014-model-)
* [Samsung SmartThings Motion Sensor (2015 model) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/205957580-Samsung-SmartThings-Motion-Sensor-2015-model-)
Other troubleshooting tips are listed as follows:
* [Troubleshooting: Samsung SmartThings Motion Sensor is stuck showing "Motion Detected" or "No Motion"](https://support.smartthings.com/hc/en-us/articles/200961130-Troubleshooting-Samsung-SmartThings-Motion-Sensor-is-stuck-showing-Motion-Detected-or-No-Motion-)
* [Troubleshooting: Samsung SmartThings Motion Sensor wont pair after removing pull-tab](https://support.smartthings.com/hc/en-us/articles/204966616-Troubleshooting-Samsung-SmartThings-device-won-t-pair-after-removing-pull-tab)

View File

@@ -13,15 +13,18 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
metadata {
definition (name: "SmartSense Motion Sensor", namespace: "smartthings", author: "SmartThings", category: "C2") {
definition (name: "SmartSense Motion Sensor", namespace: "smartthings", author: "SmartThings") {
capability "Motion Sensor"
capability "Configuration"
capability "Battery"
capability "Temperature Measurement"
capability "Refresh"
capability "Health Check"
capability "Sensor"
command "enrollResponse"
@@ -119,19 +122,37 @@ private Map parseCatchAllMessage(String description) {
if (shouldProcessMessage(cluster)) {
switch(cluster.clusterId) {
case 0x0001:
resultMap = getBatteryResult(cluster.data.last())
// 0x07 - configure reporting
if (cluster.command != 0x07) {
resultMap = getBatteryResult(cluster.data.last())
}
break
case 0x0402:
// temp is last 2 data values. reverse to swap endian
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
def value = getTemperature(temp)
resultMap = getTemperatureResult(value)
if (cluster.command == 0x07) {
if (cluster.data[0] == 0x00) {
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
}
}
else {
// temp is last 2 data values. reverse to swap endian
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
def value = getTemperature(temp)
resultMap = getTemperatureResult(value)
}
break
case 0x0406:
log.debug 'motion'
resultMap.name = 'motion'
// 0x07 - configure reporting
if (cluster.command != 0x07) {
log.debug 'motion'
resultMap.name = 'motion'
}
break
}
}
@@ -141,10 +162,8 @@ private Map parseCatchAllMessage(String description) {
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
// 0x07 is bind message
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
cluster.command == 0x07 ||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
return !ignoredMessage
}
@@ -182,52 +201,18 @@ private Map parseCustomMessage(String description) {
}
private Map parseIasMessage(String description) {
List parsedMsg = description.split(' ')
String msgCode = parsedMsg[2]
ZoneStatus zs = zigbee.parseZoneStatus(description)
Map resultMap = [:]
switch(msgCode) {
case '0x0020': // Closed/No Motion/Dry
resultMap = getMotionResult('inactive')
break
case '0x0021': // Open/Motion/Wet
resultMap = getMotionResult('active')
break
case '0x0022': // Tamper Alarm
log.debug 'motion with tamper alarm'
resultMap = getMotionResult('active')
break
case '0x0023': // Battery Alarm
break
case '0x0024': // Supervision Report
log.debug 'no motion with tamper alarm'
resultMap = getMotionResult('inactive')
break
case '0x0025': // Restore Report
break
case '0x0026': // Trouble/Failure
log.debug 'motion with failure alarm'
resultMap = getMotionResult('active')
break
case '0x0028': // Test Mode
break
}
return resultMap
// Some sensor models that use this DTH use alarm1 and some use alarm2 to signify motion
return (zs.isAlarm1Set() || zs.isAlarm2Set()) ? getMotionResult('active') : getMotionResult('inactive')
}
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16).shortValue() / 100
if(getTemperatureScale() == "C"){
return celsius
return Math.round(celsius)
} else {
return celsiusToFahrenheit(celsius) as Integer
return Math.round(celsiusToFahrenheit(celsius))
}
}
@@ -271,7 +256,10 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
}
}
@@ -297,7 +285,8 @@ private Map getTemperatureResult(value) {
name: 'temperature',
value: value,
descriptionText: descriptionText,
translatable: true
translatable: true,
unit: temperatureScale
]
}
@@ -312,6 +301,13 @@ private Map getMotionResult(value) {
]
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
}
def refresh() {
log.debug "refresh called"
def refreshCmds = [
@@ -323,24 +319,13 @@ def refresh() {
}
def configure() {
sendEvent(name: "checkInterval", value: 7200, displayed: false)
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 1 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 1 0x20 0x20 30 21600 {01}", //checkin time 6 hrs
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 0x402 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
]
return configCmds + refresh() // send refresh cmds as part of config
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
// battery minReport 30 seconds, maxReportTime 6 hrs by default
return refresh() + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config
}
def enrollResponse() {

View File

@@ -15,6 +15,7 @@
*/
//DEPRECATED - Using the smartsense-motion-sensor.groovy DTH for this device. Users need to be moved before deleting this DTH
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
metadata {
definition (name: "SmartSense Motion/Temp Sensor", namespace: "smartthings", author: "SmartThings") {
@@ -24,7 +25,7 @@ metadata {
capability "Temperature Measurement"
capability "Refresh"
capability "Sensor"
command "enrollResponse"
}
@@ -73,7 +74,7 @@ metadata {
def parse(String description) {
log.debug "description: $description"
Map map = [:]
if (description?.startsWith('catchall:')) {
map = parseCatchAllMessage(description)
@@ -87,10 +88,10 @@ def parse(String description) {
else if (description?.startsWith('zone status')) {
map = parseIasMessage(description)
}
log.debug "Parse returned $map"
def result = map ? createEvent(map) : null
if (description?.startsWith('enroll request')) {
List cmds = enrollResponse()
log.debug "enroll response: ${cmds}"
@@ -128,7 +129,7 @@ private Map parseCatchAllMessage(String description) {
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
// 0x07 is bind message
boolean ignoredMessage = cluster.profileId != 0x0104 ||
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
cluster.command == 0x07 ||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
@@ -141,7 +142,7 @@ private Map parseReportAttributeMessage(String description) {
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
}
log.debug "Desc Map: $descMap"
Map resultMap = [:]
if (descMap.cluster == "0402" && descMap.attrId == "0000") {
def value = getTemperature(descMap.value)
@@ -153,11 +154,11 @@ private Map parseReportAttributeMessage(String description) {
else if (descMap.cluster == "0406" && descMap.attrId == "0000") {
def value = descMap.value.endsWith("01") ? "active" : "inactive"
resultMap = getMotionResult(value)
}
}
return resultMap
}
private Map parseCustomMessage(String description) {
Map resultMap = [:]
if (description?.startsWith('temperature: ')) {
@@ -168,44 +169,8 @@ private Map parseCustomMessage(String description) {
}
private Map parseIasMessage(String description) {
List parsedMsg = description.split(' ')
String msgCode = parsedMsg[2]
Map resultMap = [:]
switch(msgCode) {
case '0x0020': // Closed/No Motion/Dry
resultMap = getMotionResult('inactive')
break
case '0x0021': // Open/Motion/Wet
resultMap = getMotionResult('active')
break
case '0x0022': // Tamper Alarm
log.debug 'motion with tamper alarm'
resultMap = getMotionResult('active')
break
case '0x0023': // Battery Alarm
break
case '0x0024': // Supervision Report
log.debug 'no motion with tamper alarm'
resultMap = getMotionResult('inactive')
break
case '0x0025': // Restore Report
break
case '0x0026': // Trouble/Failure
log.debug 'motion with failure alarm'
resultMap = getMotionResult('active')
break
case '0x0028': // Test Mode
break
}
return resultMap
ZoneStatus zs = zigbee.parseZoneStatus(description)
return (zs.isAlarm1Set() || zs.isAlarm2Set()) ? getMotionResult('active') : getMotionResult('inactive')
}
def getTemperature(value) {
@@ -240,7 +205,10 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}
}
@@ -260,7 +228,8 @@ private Map getTemperatureResult(value) {
return [
name: 'temperature',
value: value,
descriptionText: descriptionText
descriptionText: descriptionText,
unit: temperatureScale
]
}
@@ -286,13 +255,9 @@ def refresh() {
}
def configure() {
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 1 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 1 0x20 0x20 30 21600 {01}", //checkin time 6 hrs
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
@@ -301,7 +266,7 @@ def configure() {
"zcl global send-me-a-report 0x402 0 0x29 30 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
]
return configCmds + refresh() // send refresh cmds as part of config
return refresh() + configCmds // send refresh cmds as part of config
}
def enrollResponse() {

View File

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

View File

@@ -0,0 +1,45 @@
# Smartsense Multi Sensor
Works with:
* [Samsung SmartThings Multi Sensor](https://shop.smartthings.com/#!/products/smartsense-multi)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Battery](#battery-specification)
## Capabilities
* **Three Axis** - monitors the state of a single axis
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Battery** - defines device uses a battery
* **Sensor** - detects sensor events
* **Contact Sensor** - can detect contact (possible values: open,closed)
* **Acceleration Sensor** - allows for acceleration detection.
* **Refresh** - _refresh()_ command for status updates
* **Temperature Measurement** - defines device measures current temperature
* **Health Check** - indicates ability to get device health notifications
## Device Health
A Category C2 multi sensor with maxReportTime of 5 mins.
Check-in interval is double the value of maxReportTime.
This gives the device twice the amount of time to respond before it is marked as offline.
Check-in interval = 12 mins
## Battery Specification
One CR2450 (for Samsung SmartThings Multipurpose Sensor) battery / Two AAAA (for SmartSense Multi Sensor) batteries required.
## Troubleshooting
If the sensor 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.
Other troubleshooting tips are listed as follows:
* [Troubleshooting: Samsung SmartThings Multipurpose Sensor is stuck on "open" or "closed"](https://support.smartthings.com/hc/en-us/articles/200955940-Troubleshooting-Samsung-SmartThings-Multipurpose-Sensor-is-stuck-on-open-or-closed-)
* [Troubleshooting: Temperature reading for the Samsung SmartThings Multipurpose Sensor is off](https://support.smartthings.com/hc/en-us/articles/200756845-Troubleshooting-Temperature-reading-for-the-Samsung-SmartThings-Multipurpose-Sensor-is-off)
* [Troubleshooting: Samsung SmartThings Multipurpose Sensor wont pair after removing pull-tab](https://support.smartthings.com/hc/en-us/articles/204966616-Troubleshooting-Samsung-SmartThings-device-won-t-pair-after-removing-pull-tab)

View File

@@ -13,9 +13,10 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
metadata {
definition (name: "SmartSense Multi Sensor", namespace: "smartthings", author: "SmartThings", category: "C2") {
definition (name: "SmartSense Multi Sensor", namespace: "smartthings", author: "SmartThings") {
capability "Three Axis"
capability "Battery"
@@ -146,20 +147,33 @@ private Map parseCatchAllMessage(String description) {
if (shouldProcessMessage(cluster)) {
switch(cluster.clusterId) {
case 0x0001:
resultMap = getBatteryResult(cluster.data.last())
// 0x07 - configure reporting
if (cluster.command != 0x07) {
resultMap = getBatteryResult(cluster.data.last())
}
break
case 0xFC02:
log.debug 'ACCELERATION'
log.debug 'ACCELERATION'
break
case 0x0402:
log.debug 'TEMP'
// temp is last 2 data values. reverse to swap endian
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
def value = getTemperature(temp)
resultMap = getTemperatureResult(value)
break
if (cluster.command == 0x07) {
if(cluster.data[0] == 0x00) {
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
}
}
else {
// temp is last 2 data values. reverse to swap endian
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
def value = getTemperature(temp)
resultMap = getTemperatureResult(value)
}
break
}
}
@@ -168,10 +182,8 @@ private Map parseCatchAllMessage(String description) {
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
// 0x07 is bind message
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
cluster.command == 0x07 ||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
return !ignoredMessage
}
@@ -224,47 +236,13 @@ private Map parseCustomMessage(String description) {
}
private Map parseIasMessage(String description) {
List parsedMsg = description.split(' ')
String msgCode = parsedMsg[2]
ZoneStatus zs = zigbee.parseZoneStatus(description)
Map resultMap = [:]
switch(msgCode) {
case '0x0020': // Closed/No Motion/Dry
if (garageSensor != "Yes"){
resultMap = getContactResult('closed')
resultMap = zs.isAlarm1Set() ? getContactResult('open') : getContactResult('closed')
}
break
case '0x0021': // Open/Motion/Wet
if (garageSensor != "Yes"){
resultMap = getContactResult('open')
}
break
case '0x0022': // Tamper Alarm
break
case '0x0023': // Battery Alarm
break
case '0x0024': // Supervision Report
if (garageSensor != "Yes"){
resultMap = getContactResult('closed')
}
break
case '0x0025': // Restore Report
if (garageSensor != "Yes"){
resultMap = getContactResult('open')
}
break
case '0x0026': // Trouble/Failure
break
case '0x0028': // Test Mode
break
}
return resultMap
}
@@ -294,9 +272,9 @@ def updated() {
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16).shortValue() / 100
if(getTemperatureScale() == "C"){
return celsius
return Math.round(celsius)
} else {
return celsiusToFahrenheit(celsius) as Integer
return Math.round(celsiusToFahrenheit(celsius))
}
}
@@ -338,7 +316,10 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "{{ device.displayName }} battery was {{ value }}%"
}
}
@@ -358,10 +339,11 @@ private Map getTemperatureResult(value) {
'{{ device.displayName }} was {{ value }}°F'
return [
name: 'temperature',
value: value,
descriptionText: descriptionText,
translatable: true
name: 'temperature',
value: value,
descriptionText: descriptionText,
translatable: true,
unit: temperatureScale
]
}
@@ -396,6 +378,13 @@ private getAccelerationResult(numValue) {
]
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
}
def refresh() {
log.debug "Refreshing Values "
@@ -423,19 +412,22 @@ def refresh() {
}
def configure() {
sendEvent(name: "checkInterval", value: 7200, displayed: false)
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
log.debug "Configuring Reporting"
def configCmds = enrollResponse() +
zigbee.batteryConfig() +
zigbee.temperatureConfig() +
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
// battery minReport 30 seconds, maxReportTime 6 hrs by default
def configCmds = zigbee.batteryConfig() +
zigbee.temperatureConfig(30, 300) +
zigbee.configureReporting(0xFC02, 0x0010, 0x18, 10, 3600, 0x01, [mfgCode: manufacturerCode]) +
zigbee.configureReporting(0xFC02, 0x0012, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) +
zigbee.configureReporting(0xFC02, 0x0013, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) +
zigbee.configureReporting(0xFC02, 0x0014, 0x29, 1, 3600, 0x0001, [mfgCode: manufacturerCode])
return configCmds + refresh()
return refresh() + configCmds
}
private getEndpointId() {

View File

@@ -14,6 +14,7 @@
*
*/
//DEPRECATED - Using the smartsense-multi-sensor.groovy DTH for this device. Users need to be moved before deleting this DTH
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
metadata {
definition (name: "SmartSense Open/Closed Accelerometer Sensor", namespace: "smartthings", author: "SmartThings", category: "C2") {
@@ -24,6 +25,7 @@
capability "Refresh"
capability "Temperature Measurement"
capability "Health Check"
capability "Sensor"
command "enrollResponse"
}
@@ -171,40 +173,9 @@ private Map parseCustomMessage(String description) {
}
private Map parseIasMessage(String description) {
List parsedMsg = description.split(' ')
String msgCode = parsedMsg[2]
ZoneStatus zs = zigbee.parseZoneStatus(description)
Map resultMap = [:]
switch(msgCode) {
case '0x0020': // Closed/No Motion/Dry
resultMap = getContactResult('closed')
break
case '0x0021': // Open/Motion/Wet
resultMap = getContactResult('open')
break
case '0x0022': // Tamper Alarm
break
case '0x0023': // Battery Alarm
break
case '0x0024': // Supervision Report
resultMap = getContactResult('closed')
break
case '0x0025': // Restore Report
resultMap = getContactResult('open')
break
case '0x0026': // Trouble/Failure
break
case '0x0028': // Test Mode
break
}
return resultMap
return zs.isAlarm1Set() ? getContactResult('open') : getContactResult('closed')
}
def getTemperature(value) {
@@ -234,7 +205,10 @@ def getTemperature(value) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}
@@ -251,9 +225,10 @@ def getTemperature(value) {
}
def descriptionText = "${linkText} was ${value}°${temperatureScale}"
return [
name: 'temperature',
value: value,
descriptionText: descriptionText
name: 'temperature',
value: value,
descriptionText: descriptionText,
unit: temperatureScale
]
}
@@ -302,12 +277,8 @@ def getTemperature(value) {
def configure() {
sendEvent(name: "checkInterval", value: 7200, displayed: false)
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 1 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 1 0x20 0x20 30 21600 {01}", //checkin time 6 hrs
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
@@ -320,7 +291,7 @@ def configure() {
"zcl global send-me-a-report 0xFC02 2 0x18 30 3600 {01}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
]
return configCmds + refresh() // send refresh cmds as part of config
return refresh() + configCmds // send refresh cmds as part of config
}
def enrollResponse() {

View File

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

View File

@@ -0,0 +1,41 @@
# Smartsense Open/Closed Sensor
Works with:
* [Samsung SmartThings Open/Closed Sensor](https://shop.smartthings.com/#!/packs/smartsense-open-closed-sensor/)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Battery](#battery-specification)
## Capabilities
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Battery** - defines device uses a battery
* **Contact Sensor** - can detect contact (possible values: open,closed)
* **Refresh** - _refresh()_ command for status updates
* **Temperature Measurement** - defines device measures current temperature
* **Health Check** - indicates ability to get device health notifications
* **Sensor** - detects sensor events
## Device Health
A Category C2 open/closed sensor with maxReportTime of 5 mins.
Check-in interval is double the value of maxReportTime.
This gives the device twice the amount of time to respond before it is marked as offline.
Check-in interval = 12 mins
## Battery Specification
One CR2 3V battery required.
## Troubleshooting
If the sensor 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 sensor from SmartThings can be found in the following link:
* [SmartSense Open/Closed Sensor Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/202836844-SmartSense-Open-Closed-Sensor)

View File

@@ -13,33 +13,35 @@
* for the specific language governing permissions and limitations under the License.
*
*/
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
metadata {
definition (name: "SmartSense Open/Closed Sensor", namespace: "smartthings", author: "SmartThings", category: "C2") {
definition (name: "SmartSense Open/Closed Sensor", namespace: "smartthings", author: "SmartThings") {
capability "Battery"
capability "Configuration"
capability "Contact Sensor"
capability "Refresh"
capability "Temperature Measurement"
capability "Health Check"
capability "Sensor"
command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3300-S"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3300"
fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3320-L", deviceJoinName: "Iris Contact Sensor"
}
simulator {
}
preferences {
input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
input "tempOffset", "number", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
}
tiles(scale: 2) {
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
@@ -72,10 +74,10 @@ metadata {
details(["contact","temperature","battery","refresh"])
}
}
def parse(String description) {
log.debug "description: $description"
Map map = [:]
if (description?.startsWith('catchall:')) {
map = parseCatchAllMessage(description)
@@ -89,10 +91,10 @@ def parse(String description) {
else if (description?.startsWith('zone status')) {
map = parseIasMessage(description)
}
log.debug "Parse returned $map"
def result = map ? createEvent(map) : null
if (description?.startsWith('enroll request')) {
List cmds = enrollResponse()
log.debug "enroll response: ${cmds}"
@@ -100,22 +102,35 @@ def parse(String description) {
}
return result
}
private Map parseCatchAllMessage(String description) {
Map resultMap = [:]
def cluster = zigbee.parse(description)
if (shouldProcessMessage(cluster)) {
switch(cluster.clusterId) {
case 0x0001:
resultMap = getBatteryResult(cluster.data.last())
// 0x07 - configure reporting
if (cluster.command != 0x07) {
resultMap = getBatteryResult(cluster.data.last())
}
break
case 0x0402:
log.debug 'TEMP'
// temp is last 2 data values. reverse to swap endian
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
def value = getTemperature(temp)
resultMap = getTemperatureResult(value)
if (cluster.command == 0x07){
if (cluster.data[0] == 0x00) {
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
}
}
else {
// temp is last 2 data values. reverse to swap endian
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
def value = getTemperature(temp)
resultMap = getTemperatureResult(value)
}
break
}
}
@@ -125,10 +140,8 @@ private Map parseCatchAllMessage(String description) {
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
// 0x07 is bind message
boolean ignoredMessage = cluster.profileId != 0x0104 ||
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
cluster.command == 0x07 ||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
return !ignoredMessage
}
@@ -136,14 +149,14 @@ private boolean shouldProcessMessage(cluster) {
private int getHumidity(value) {
return Math.round(Double.parseDouble(value))
}
private Map parseReportAttributeMessage(String description) {
Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
}
log.debug "Desc Map: $descMap"
Map resultMap = [:]
if (descMap.cluster == "0402" && descMap.attrId == "0000") {
def value = getTemperature(descMap.value)
@@ -152,10 +165,10 @@ private Map parseReportAttributeMessage(String description) {
else if (descMap.cluster == "0001" && descMap.attrId == "0020") {
resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16))
}
return resultMap
}
private Map parseCustomMessage(String description) {
Map resultMap = [:]
if (description?.startsWith('temperature: ')) {
@@ -166,42 +179,10 @@ private Map parseCustomMessage(String description) {
}
private Map parseIasMessage(String description) {
List parsedMsg = description.split(' ')
String msgCode = parsedMsg[2]
Map resultMap = [:]
switch(msgCode) {
case '0x0020': // Closed/No Motion/Dry
resultMap = getContactResult('closed')
break
case '0x0021': // Open/Motion/Wet
resultMap = getContactResult('open')
break
case '0x0022': // Tamper Alarm
break
case '0x0023': // Battery Alarm
break
case '0x0024': // Supervision Report
resultMap = getContactResult('closed')
break
case '0x0025': // Restore Report
resultMap = getContactResult('open')
break
case '0x0026': // Trouble/Failure
break
case '0x0028': // Test Mode
break
}
return resultMap
ZoneStatus zs = zigbee.parseZoneStatus(description)
return zs.isAlarm1Set() ? getContactResult('open') : getContactResult('closed')
}
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16).shortValue() / 100
if(getTemperatureScale() == "C"){
@@ -214,11 +195,11 @@ def getTemperature(value) {
private Map getBatteryResult(rawValue) {
log.debug 'Battery'
def linkText = getLinkText(device)
def result = [
name: 'battery'
]
def volts = rawValue / 10
def descriptionText
if (rawValue == 0 || rawValue == 255) {}
@@ -229,7 +210,10 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}
@@ -248,7 +232,8 @@ private Map getTemperatureResult(value) {
return [
name: 'temperature',
value: value,
descriptionText: descriptionText
descriptionText: descriptionText,
unit: temperatureScale
]
}
@@ -263,6 +248,13 @@ private Map getContactResult(value) {
]
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
}
def refresh() {
log.debug "Refreshing Temperature and Battery"
def refreshCmds = [
@@ -274,23 +266,15 @@ def refresh() {
}
def configure() {
sendEvent(name: "checkInterval", value: 7200, displayed: false)
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 1 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 1 0x20 0x20 30 21600 {01}", //checkin time 6 hrs
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zdo bind 0x${device.deviceNetworkId} ${endpointId} 1 0x402 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 0x402 0 0x29 30 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500"
]
return configCmds + refresh() // send refresh cmds as part of config
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
// battery minReport 30 seconds, maxReportTime 6 hrs by default
return refresh() + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config
}
def enrollResponse() {

View File

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

View File

@@ -0,0 +1,41 @@
# SmartSense Temp/Humidity Sensor
Works with:
* [Samsung SmartSense Temp/Humidity Sensor](https://shop.smartthings.com/#!/products/smartsense-temp-humidity-sensor)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Battery](#battery-specification)
## Capabilities
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Battery** - defines device uses a battery
* **Relative Humidity Measurement** - defines device measures relative humidity
* **Refresh** - _refresh()_ command for status updates
* **Temperature Measurement** - defines device measures current temperature
* **Health Check** - indicates ability to get device health notifications
* **Sensor** - detects sensor events
## Device Health
A Category C2 SmartSense Temp/Humidity Sensor with maxReportTime of 5 mins.
Check-in interval is double the value of maxReportTime.
This gives the device twice the amount of time to respond before it is marked as offline.
Check-in interval = 12 mins
## Battery Specification
One CR2 battery is required.
## Troubleshooting
If the sensor 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 by placing the sensor closer to the hub.
Instructions related to pairing, resetting and removing the sensor from SmartThings can be found in the following link:
* [Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/203040294)

View File

@@ -14,13 +14,14 @@
*
*/
metadata {
definition (name: "SmartSense Temp/Humidity Sensor",namespace: "smartthings", author: "SmartThings", category: "C2") {
definition (name: "SmartSense Temp/Humidity Sensor",namespace: "smartthings", author: "SmartThings") {
capability "Configuration"
capability "Battery"
capability "Refresh"
capability "Temperature Measurement"
capability "Relative Humidity Measurement"
capability "Health Check"
capability "Sensor"
fingerprint endpointId: "01", inClusters: "0001,0003,0020,0402,0B05,FC45", outClusters: "0019,0003"
}
@@ -92,20 +93,37 @@ private Map parseCatchAllMessage(String description) {
if (shouldProcessMessage(cluster)) {
switch(cluster.clusterId) {
case 0x0001:
resultMap = getBatteryResult(cluster.data.last())
// 0x07 - configure reporting
if (cluster.command != 0x07) {
resultMap = getBatteryResult(cluster.data.last())
}
break
case 0x0402:
// temp is last 2 data values. reverse to swap endian
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
def value = getTemperature(temp)
resultMap = getTemperatureResult(value)
break
if (cluster.command == 0x07) {
if (cluster.data[0] == 0x00){
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "TEMP REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
}
}
else {
// temp is last 2 data values. reverse to swap endian
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
def value = getTemperature(temp)
resultMap = getTemperatureResult(value)
}
break
case 0xFC45:
String pctStr = cluster.data[-1, -2].collect { Integer.toHexString(it) }.join('')
String display = Math.round(Integer.valueOf(pctStr, 16) / 100)
resultMap = getHumidityResult(display)
// 0x07 - configure reporting
if (cluster.command != 0x07) {
String pctStr = cluster.data[-1, -2].collect { Integer.toHexString(it) }.join('')
String display = Math.round(Integer.valueOf(pctStr, 16) / 100)
resultMap = getHumidityResult(display)
}
break
}
}
@@ -115,10 +133,8 @@ private Map parseCatchAllMessage(String description) {
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
// 0x07 is bind message
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
cluster.command == 0x07 ||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
return !ignoredMessage
}
@@ -205,7 +221,10 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
if (roundedPct <= 0)
roundedPct = 1
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}
@@ -224,51 +243,47 @@ private Map getTemperatureResult(value) {
return [
name: 'temperature',
value: value,
descriptionText: descriptionText
descriptionText: descriptionText,
unit: temperatureScale
]
}
private Map getHumidityResult(value) {
log.debug 'Humidity'
return [
name: 'humidity',
value: value,
unit: '%'
]
return value ? [name: 'humidity', value: value, unit: '%'] : [:]
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.readAttribute(0x001, 0x0020) // Read the Battery Level
}
def refresh()
{
log.debug "refresh temperature, humidity, and battery"
[
"zcl mfg-code 0xC2DF", "delay 1000",
"zcl global read 0xFC45 0", "delay 1000",
"send 0x${device.deviceNetworkId} 1 1", "delay 1000",
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
"st rattr 0x${device.deviceNetworkId} 1 1 0x20"
]
return zigbee.readAttribute(0xFC45, 0x0000, ["mfgCode": 0xC2DF]) + // Original firmware
zigbee.readAttribute(0xFC45, 0x0000, ["mfgCode": 0x104E]) + // New firmware
zigbee.readAttribute(0x0402, 0x0000) +
zigbee.readAttribute(0x0001, 0x0020)
}
def configure() {
sendEvent(name: "checkInterval", value: 7200, displayed: false)
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
log.debug "Configuring Reporting and Bindings."
def configCmds = [
"zdo bind 0x${device.deviceNetworkId} 1 1 1 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 1 0x20 0x20 30 21600 {01}", //checkin time 6 hrs
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 1 0x402 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 0x402 0 0x29 30 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500",
def humidityConfigCmds = [
"zdo bind 0x${device.deviceNetworkId} 1 1 0xFC45 {${device.zigbeeId}} {}", "delay 500",
"zcl global send-me-a-report 0xFC45 0 0x29 30 3600 {6400}",
"send 0x${device.deviceNetworkId} 1 1", "delay 500"
]
return configCmds + refresh() // send refresh cmds as part of config
// temperature minReportTime 30 seconds, maxReportTime 5 min. Reporting interval if no activity
// battery minReport 30 seconds, maxReportTime 6 hrs by default
return refresh() + humidityConfigCmds + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) // send refresh cmds as part of config
}
private hex(value) {

View File

@@ -16,6 +16,8 @@
metadata {
definition (name: "Simulated Alarm", namespace: "smartthings/testing", author: "SmartThings") {
capability "Alarm"
capability "Sensor"
capability "Actuator"
}
simulator {

View File

@@ -1,6 +1,8 @@
metadata {
definition (name: "Simulated Color Control", namespace: "smartthings/testing", author: "SmartThings") {
capability "Color Control"
capability "Sensor"
capability "Actuator"
}
simulator {

View File

@@ -15,6 +15,7 @@ metadata {
// Automatically generated. Make future change here.
definition (name: "Simulated Contact Sensor", namespace: "smartthings/testing", author: "bob") {
capability "Contact Sensor"
capability "Sensor"
command "open"
command "close"

View File

@@ -15,6 +15,8 @@ metadata {
// Automatically generated. Make future change here.
definition (name: "Simulated Lock", namespace: "smartthings/testing", author: "bob") {
capability "Lock"
capability "Sensor"
capability "Actuator"
}
// Simulated lock

View File

@@ -15,6 +15,7 @@ metadata {
// Automatically generated. Make future change here.
definition (name: "Simulated Motion Sensor", namespace: "smartthings/testing", author: "bob") {
capability "Motion Sensor"
capability "Sensor"
command "active"
command "inactive"

View File

@@ -15,6 +15,7 @@ metadata {
// Automatically generated. Make future change here.
definition (name: "Simulated Presence Sensor", namespace: "smartthings/testing", author: "bob") {
capability "Presence Sensor"
capability "Sensor"
command "arrived"
command "departed"

View File

@@ -16,6 +16,8 @@ metadata {
definition (name: "Simulated Switch", namespace: "smartthings/testing", author: "bob") {
capability "Switch"
capability "Relay Switch"
capability "Sensor"
capability "Actuator"
command "onPhysical"
command "offPhysical"

View File

@@ -16,6 +16,7 @@ metadata {
definition (name: "Simulated Temperature Sensor", namespace: "smartthings/testing", author: "SmartThings") {
capability "Temperature Measurement"
capability "Switch Level"
capability "Sensor"
command "up"
command "down"

View File

@@ -16,6 +16,8 @@ metadata {
definition (name: "Simulated Thermostat", namespace: "smartthings/testing", author: "SmartThings") {
capability "Thermostat"
capability "Relative Humidity Measurement"
capability "Sensor"
capability "Actuator"
command "tempUp"
command "tempDown"

View File

@@ -15,6 +15,7 @@ metadata {
// Automatically generated. Make future change here.
definition (name: "Simulated Water Sensor", namespace: "smartthings/testing", author: "SmartThings") {
capability "Water Sensor"
capability "Sensor"
command "wet"
command "dry"

View File

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

View File

@@ -0,0 +1,42 @@
# Tyco Door Window Sensor
Works with:
* [Tyco Door Window Sensor](https://support.smartthings.com/hc/en-us/articles/204834100-Tyco-Door-Window-Sensor)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Battery](#battery-specification)
## Capabilities
* **Battery** - defines device uses a battery
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Contact Sensor** - can detect contact (open/close)
* **Refresh** - _refresh()_ command for status updates
* **Temperature Measurement** - can measure the device temperature
* **Health Check** - indicates ability to get device health notifications
## Device Health
Contact sensor with maxReportTime of 5 mins.
Check-in interval is double the value of maxReportTime for Zigbee device.
This gives the device twice the amount of time to respond before it is marked as offline.
Check-in interval = 12 min
## Battery Specification
3V CR2032 battery is required.
## Troubleshooting
If the device doesn't pair when trying from the SmartThings mobile app, it is possible that either the sensor needs to be reseted or the sensor is out of range.
Reset needs to be done by inserting the battery in the sensor and then quickly pressing the adjacent black button 10 times. Pairing should be tried again now.
It may happen that sensor is out of range, then pairing needs to be tried again by placing the sensor closer to the hub.
Instructions related to pairing, resetting and removing the different motion sensors from SmartThings can be found in the following links
for the different models:
* [Tyco Door Window Sensor (MCT-340)](https://support.smartthings.com/hc/en-us/articles/204834100-Tyco-Door-Window-Sensor)

View File

@@ -13,7 +13,8 @@
* for the specific language governing permissions and limitations under the License.
*
*/
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
metadata {
definition (name: "Tyco Door/Window Sensor", namespace: "smartthings", author: "SmartThings") {
capability "Battery"
@@ -21,28 +22,29 @@ metadata {
capability "Contact Sensor"
capability "Refresh"
capability "Temperature Measurement"
capability "Health Check"
command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "Visonic", model: "MCT-340 SMA"
}
simulator {
}
preferences {
input title: "Temperature Offset", description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
input "tempOffset", "number", title: "Degrees", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
}
tiles {
standardTile("contact", "device.contact", width: 2, height: 2) {
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
}
valueTile("temperature", "device.temperature", inactiveLabel: false) {
state "temperature", label:'${currentValue}°',
backgroundColors:[
@@ -58,23 +60,23 @@ metadata {
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) {
state "battery", label:'${currentValue}% battery', unit:""
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat") {
state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
}
standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat") {
state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
}
main (["contact", "temperature"])
details(["contact","temperature","battery","refresh","configure"])
}
}
def parse(String description) {
log.debug "description: $description"
Map map = [:]
if (description?.startsWith('catchall:')) {
map = parseCatchAllMessage(description)
@@ -88,10 +90,10 @@ def parse(String description) {
else if (description?.startsWith('zone status')) {
map = parseIasMessage(description)
}
log.debug "Parse returned $map"
def result = map ? createEvent(map) : null
if (description?.startsWith('enroll request')) {
List cmds = enrollResponse()
log.debug "enroll response: ${cmds}"
@@ -99,7 +101,7 @@ def parse(String description) {
}
return result
}
private Map parseCatchAllMessage(String description) {
Map resultMap = [:]
def cluster = zigbee.parse(description)
@@ -125,20 +127,20 @@ private Map parseCatchAllMessage(String description) {
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
// 0x07 is bind message
boolean ignoredMessage = cluster.profileId != 0x0104 ||
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
cluster.command == 0x07 ||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
return !ignoredMessage
}
private Map parseReportAttributeMessage(String description) {
Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
}
log.debug "Desc Map: $descMap"
Map resultMap = [:]
if (descMap.cluster == "0402" && descMap.attrId == "0000") {
def value = getTemperature(descMap.value)
@@ -147,10 +149,10 @@ private Map parseReportAttributeMessage(String description) {
else if (descMap.cluster == "0001" && descMap.attrId == "0020") {
resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16))
}
return resultMap
}
private Map parseCustomMessage(String description) {
Map resultMap = [:]
if (description?.startsWith('temperature: ')) {
@@ -161,42 +163,11 @@ private Map parseCustomMessage(String description) {
}
private Map parseIasMessage(String description) {
List parsedMsg = description.split(' ')
String msgCode = parsedMsg[2]
Map resultMap = [:]
switch(msgCode) {
case '0x0020': // Closed/No Motion/Dry
resultMap = getContactResult('closed')
break
ZoneStatus zs = zigbee.parseZoneStatus(description)
case '0x0021': // Open/Motion/Wet
resultMap = getContactResult('open')
break
case '0x0022': // Tamper Alarm
break
case '0x0023': // Battery Alarm
break
case '0x0024': // Supervision Report
resultMap = getContactResult('closed')
break
case '0x0025': // Restore Report
resultMap = getContactResult('open')
break
case '0x0026': // Trouble/Failure
break
case '0x0028': // Test Mode
break
}
return resultMap
return zs.isAlarm1Set() ? getContactResult('open') : getContactResult('closed')
}
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16).shortValue() / 100
if(getTemperatureScale() == "C"){
@@ -209,11 +180,11 @@ def getTemperature(value) {
private Map getBatteryResult(rawValue) {
log.debug 'Battery'
def linkText = getLinkText(device)
def result = [
name: 'battery'
]
def volts = rawValue / 10
def descriptionText
if (volts > 3.5) {
@@ -223,7 +194,8 @@ private Map getBatteryResult(rawValue) {
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def roundedPct = Math.round(pct * 100)
result.value = Math.min(100, roundedPct)
result.descriptionText = "${linkText} battery was ${result.value}%"
}
@@ -242,7 +214,8 @@ private Map getTemperatureResult(value) {
return [
name: 'temperature',
value: value,
descriptionText: descriptionText
descriptionText: descriptionText,
unit: temperatureScale
]
}
@@ -257,53 +230,51 @@ private Map getContactResult(value) {
]
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.readAttribute(0x0402, 0x0000) // Read the Temperature Cluster
}
def refresh()
{
log.debug "Refreshing Temperature and Battery"
[
def refreshCmds = [
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
"st rattr 0x${device.deviceNetworkId} 1 1 0x20"
]
return refreshCmds + enrollResponse()
}
def configure() {
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [
def enrollCmds = [
"delay 1000",
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global send-me-a-report 1 0x20 0x20 600 3600 {01}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zcl global send-me-a-report 0x402 0 0x29 300 3600 {6400}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
//"raw 0x500 {01 23 00 00 00}", "delay 200",
//"send 0x${device.deviceNetworkId} 1 1", "delay 1500",
"zdo bind 0x${device.deviceNetworkId} 1 1 0x402 {${device.zigbeeId}} {}", "delay 500",
"zdo bind 0x${device.deviceNetworkId} 1 1 1 {${device.zigbeeId}} {}",
"delay 500"
]
return configCmds + enrollResponse() + refresh() // send refresh cmds as part of config
return enrollCmds + zigbee.batteryConfig() + zigbee.temperatureConfig(30, 300) + refresh() // send refresh cmds as part of config
}
def enrollResponse() {
log.debug "Sending enroll response"
[
[
"raw 0x500 {01 23 00 00 00}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1"
]
}
private hex(value) {

View File

@@ -1,8 +1,7 @@
/**
* Iris Smart Fob
* ZigBee Button
*
* Copyright 2015 Mitch Pond
* Presence code adapted from SmartThings Arrival Sensor HA device type
*
* 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:
@@ -14,181 +13,229 @@
* for the specific language governing permissions and limitations under the License.
*
*/
metadata {
definition (name: "ZigBee Button", namespace: "smartthings", author: "Mitch Pond") {
capability "Battery"
capability "Button"
definition (name: "ZigBee Button", namespace: "smartthings", author: "Mitch Pond") {
capability "Actuator"
capability "Battery"
capability "Button"
capability "Configuration"
capability "Presence Sensor"
capability "Sensor"
//fingerprint endpointId: "01", profileId: "0104", inClusters: "0000,0001,0003,0007,0020,0B05", outClusters: "0003,0006,0019", model:"3450-L", manufacturer: "CentraLite"
}
preferences{
input ("holdTime", "number", title: "Minimum time in seconds for a press to count as \"held\"",
defaultValue: 3, displayDuringSetup: false)
input "checkInterval", "enum", title: "Presence timeout (minutes)",
defaultValue:"2", options: ["2", "3", "5"], displayDuringSetup: false
input "logging", "bool", title: "Enable debug logging",
defaultValue: false, displayDuringSetup: false
capability "Refresh"
capability "Sensor"
command "enrollResponse"
fingerprint inClusters: "0000, 0001, 0003, 0020, 0402, 0B05", outClusters: "0003, 0006, 0008, 0019", manufacturer: "OSRAM", model: "LIGHTIFY Dimming Switch", deviceJoinName: "OSRAM LIGHTIFY Dimming Switch"
//fingerprint inClusters: "0000, 0001, 0003, 0020, 0500", outClusters: "0003,0019", manufacturer: "CentraLite", model: "3455-L", deviceJoinName: "Iris Care Pendant"
//fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0402, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model: "3460-L", deviceJoinName: "Iris Smart Button"
//fingerprint inClusters: "0000, 0001, 0003, 0007, 0020, 0B05", outClusters: "0003, 0006, 0019", manufacturer: "CentraLite", model:"3450-L", deviceJoinName: "Iris KeyFob"
}
tiles(scale: 2) {
standardTile("presence", "device.presence", width: 4, height: 4, canChangeBackground: true) {
state "present", label: "Present", labelIcon:"st.presence.tile.present", backgroundColor:"#53a7c0"
state "not present", labelIcon:"st.presence.tile.not-present", backgroundColor:"#ffffff"
}
standardTile("button", "device.button", decoration: "flat", width: 2, height: 2) {
state "default", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffffff"
}
valueTile("battery", "device.battery", decoration: "flat", width: 2, height: 2) {
state "battery", label:'${currentValue}% battery', unit:""
}
simulator {}
main (["presence"])
details(["presence","button","battery"])
}
preferences {
section {
input ("holdTime", "number", title: "Minimum time in seconds for a press to count as \"held\"", defaultValue: 1, displayDuringSetup: false)
}
}
tiles {
standardTile("button", "device.button", width: 2, height: 2) {
state "default", label: "", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffffff"
state "button 1 pushed", label: "pushed #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#79b821"
}
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false) {
state "battery", label:'${currentValue}% battery', unit:""
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat") {
state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
}
main (["button"])
details(["button", "battery", "refresh"])
}
}
def parse(String description) {
def descMap = zigbee.parseDescriptionAsMap(description)
logIt descMap
state.lastCheckin = now()
logIt "lastCheckin = ${state.lastCheckin}"
handlePresenceEvent(true)
def results = []
if (description?.startsWith('catchall:'))
results = parseCatchAllMessage(descMap)
else if (description?.startsWith('read attr -'))
results = parseReportAttributeMessage(descMap)
else logIt(descMap, "trace")
return results;
log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
sendEvent(event)
}
else {
if ((description?.startsWith("catchall:")) || (description?.startsWith("read attr -"))) {
def descMap = zigbee.parseDescriptionAsMap(description)
if (descMap.clusterInt == 0x0001 && descMap.attrInt == 0x0020) {
event = getBatteryResult(zigbee.convertHexToInt(descMap.value))
}
else if (descMap.clusterInt == 0x0006 || descMap.clusterInt == 0x0008) {
event = parseNonIasButtonMessage(descMap)
}
}
else if (description?.startsWith('zone status')) {
event = parseIasButtonMessage(description)
}
log.debug "Parse returned $event"
def result = event ? createEvent(event) : []
if (description?.startsWith('enroll request')) {
List cmds = enrollResponse()
result = cmds?.collect { new physicalgraph.device.HubAction(it) }
}
return result
}
}
private Map parseIasButtonMessage(String description) {
def zs = zigbee.parseZoneStatus(description)
return zs.isAlarm2Set() ? getButtonResult("press") : getButtonResult("release")
}
private Map getBatteryResult(rawValue) {
log.debug 'Battery'
def volts = rawValue / 10
if (volts > 3.0 || volts == 0 || rawValue == 0xFF) {
return [:]
}
else {
def result = [
name: 'battery'
]
def minVolts = 2.1
def maxVolts = 3.0
def pct = (volts - minVolts) / (maxVolts - minVolts)
result.value = Math.min(100, (int) pct * 100)
def linkText = getLinkText(device)
result.descriptionText = "${linkText} battery was ${result.value}%"
return result
}
}
private Map parseNonIasButtonMessage(Map descMap){
def buttonState = ""
def buttonNumber = 0
if (((device.getDataValue("model") == "3460-L") || (device.getDataValue("model") == "3450-L"))
&&(descMap.clusterInt == 0x0006)) {
if (descMap.command == "01") {
getButtonResult("press")
}
else if (descMap.command == "00") {
getButtonResult("release")
}
}
else if (descMap.clusterInt == 0x0006) {
buttonState = "pushed"
if (descMap.command == "01") {
buttonNumber = 1
}
else if (descMap.command == "00") {
buttonNumber = 2
}
if (buttonNumber !=0) {
def descriptionText = "$device.displayName button $buttonNumber was $buttonState"
return createEvent(name: "button", value: buttonState, data: [buttonNumber: buttonNumber], descriptionText: descriptionText, isStateChange: true)
}
else {
return [:]
}
}
else if (descMap.clusterInt == 0x0008) {
if (descMap.command == "05") {
state.buttonNumber = 1
getButtonResult("press", 1)
}
else if (descMap.command == "01") {
state.buttonNumber = 2
getButtonResult("press", 2)
}
else if (descMap.command == "03") {
getButtonResult("release", state.buttonNumber)
}
}
}
def refresh() {
log.debug "Refreshing Battery"
return zigbee.readAttribute(0x0001, 0x20) +
zigbee.enrollResponse()
}
def configure() {
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def cmds = []
if (device.getDataValue("model") == "3450-L") {
cmds << [
"zdo bind 0x${device.deviceNetworkId} 1 1 6 {${device.zigbeeId}} {}", "delay 300",
"zdo bind 0x${device.deviceNetworkId} 2 1 6 {${device.zigbeeId}} {}", "delay 300",
"zdo bind 0x${device.deviceNetworkId} 3 1 6 {${device.zigbeeId}} {}", "delay 300",
"zdo bind 0x${device.deviceNetworkId} 4 1 6 {${device.zigbeeId}} {}", "delay 300"
]
}
return zigbee.onOffConfig() +
zigbee.levelConfig() +
zigbee.configureReporting(0x0001, 0x20, 0x20, 30, 21600, 0x01) +
zigbee.enrollResponse() +
zigbee.readAttribute(0x0001, 0x20) +
cmds
}
private Map getButtonResult(buttonState, buttonNumber = 1) {
if (buttonState == 'release') {
log.debug "Button was value : $buttonState"
def timeDiff = now() - state.pressTime
log.info "timeDiff: $timeDiff"
def holdPreference = holdTime ?: 1
log.info "holdp1 : $holdPreference"
holdPreference = (holdPreference as int) * 1000
log.info "holdp2 : $holdPreference"
if (timeDiff > 10000) { //timeDiff>10sec check for refresh sending release value causing actions to be executed
return [:]
}
else {
if (timeDiff < holdPreference) {
buttonState = "pushed"
}
else {
buttonState = "held"
}
def descriptionText = "$device.displayName button $buttonNumber was $buttonState"
return createEvent(name: "button", value: buttonState, data: [buttonNumber: buttonNumber], descriptionText: descriptionText, isStateChange: true)
}
}
else if (buttonState == 'press') {
log.debug "Button was value : $buttonState"
state.pressTime = now()
log.info "presstime: ${state.pressTime}"
return [:]
}
}
def installed() {
initialize()
}
def updated() {
startTimer()
configure()
initialize()
}
def configure(){
logIt "Configuring Smart Fob..."
[
"zdo bind 0x${device.deviceNetworkId} 1 1 6 {${device.zigbeeId}} {}", "delay 200",
"zdo bind 0x${device.deviceNetworkId} 2 1 6 {${device.zigbeeId}} {}", "delay 200",
"zdo bind 0x${device.deviceNetworkId} 3 1 6 {${device.zigbeeId}} {}", "delay 200",
"zdo bind 0x${device.deviceNetworkId} 4 1 6 {${device.zigbeeId}} {}", "delay 200",
"zdo bind 0x${device.deviceNetworkId} 1 1 1 {${device.zigbeeId}} {}", "delay 200"
] +
zigbee.configureReporting(0x0001,0x0020,0x20,20,20,0x01)
}
def parseCatchAllMessage(descMap) {
if (descMap?.clusterId == "0006" && descMap?.command == "01") //button pressed
handleButtonPress(descMap.sourceEndpoint as int)
else if (descMap?.clusterId == "0006" && descMap?.command == "00") //button released
handleButtonRelease(descMap.sourceEndpoint as int)
else logIt("Parse: Unhandled message: ${descMap}","trace")
}
def parseReportAttributeMessage(descMap) {
if (descMap?.cluster == "0001" && descMap?.attrId == "0020") createBatteryEvent(getBatteryLevel(descMap.value))
else logIt descMap
}
private createBatteryEvent(percent) {
logIt "Battery level at " + percent
return createEvent([name: "battery", value: percent])
}
//this method determines if a press should count as a push or a hold and returns the relevant event type
private handleButtonRelease(button) {
logIt "lastPress state variable: ${state.lastPress}"
def sequenceError = {logIt("Uh oh...missed a message? Dropping this event.", "error"); state.lastPress = null; return []}
if (!state.lastPress) return sequenceError()
else if (state.lastPress.button != button) return sequenceError()
def currentTime = now()
def startOfPress = state.lastPress?.time
def timeDif = currentTime - startOfPress
def holdTimeMillisec = (settings.holdTime?:3).toInteger() * 1000
state.lastPress = null //we're done with this. clear it to make error conditions easier to catch
if (timeDif < 0)
//likely a message sequence issue or dropped packet. Drop this press and wait for another.
return sequenceError()
else if (timeDif < holdTimeMillisec)
return createButtonEvent(button,"pushed")
else
return createButtonEvent(button,"held")
}
private handleButtonPress(button) {
state.lastPress = [button: button, time: now()]
}
private createButtonEvent(button,action) {
logIt "Button ${button} ${action}"
return createEvent([
name: "button",
value: action,
data:[buttonNumber: button],
descriptionText: "${device.displayName} button ${button} was ${action}",
isStateChange: true,
displayed: true])
}
private getBatteryLevel(rawValue) {
def intValue = Integer.parseInt(rawValue,16)
def min = 2.1
def max = 3.0
def vBatt = intValue / 10
return ((vBatt - min) / (max - min) * 100) as int
}
private handlePresenceEvent(present) {
def wasPresent = device.currentState("presence")?.value == "present"
if (!wasPresent && present) {
logIt "Sensor is present"
startTimer()
} else if (!present) {
logIt "Sensor is not present"
stopTimer()
def initialize() {
if ((device.getDataValue("manufacturer") == "OSRAM") && (device.getDataValue("model") == "LIGHTIFY Dimming Switch")) {
sendEvent(name: "numberOfButtons", value: 2)
}
def linkText = getLinkText(device)
def eventMap = [
name: "presence",
value: present ? "present" : "not present",
linkText: linkText,
descriptionText: "${linkText} has ${present ? 'arrived' : 'left'}",
]
logIt "Creating presence event: ${eventMap}"
sendEvent(eventMap)
}
private startTimer() {
logIt "Scheduling periodic timer"
schedule("0 * * * * ?", checkPresenceCallback)
}
private stopTimer() {
logIt "Stopping periodic timer"
unschedule()
}
def checkPresenceCallback() {
def timeSinceLastCheckin = (now() - state.lastCheckin) / 1000
def theCheckInterval = (checkInterval ? checkInterval as int : 2) * 60
logIt "Sensor checked in ${timeSinceLastCheckin} seconds ago"
if (timeSinceLastCheckin >= theCheckInterval) {
handlePresenceEvent(false)
else if ((device.getDataValue("manufacturer") == "CentraLite") &&
((device.getDataValue("model") == "3455-L") || (device.getDataValue("model") == "3460-L"))) {
sendEvent(name: "numberOfButtons", value: 1)
}
else if ((device.getDataValue("manufacturer") == "CentraLite") && (device.getDataValue("model") == "3450-L")) {
sendEvent(name: "numberOfButtons", value: 4)
}
else {
//default. can be changed
sendEvent(name: "numberOfButtons", value: 4)
}
}
// ****** Utility functions ******
private logIt(str, logLevel = 'debug') {if (settings.logging) log."$logLevel"(str) }

View File

@@ -93,5 +93,5 @@ def refresh() {
def configure() {
log.debug "Configuring Reporting and Bindings."
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.simpleMeteringPowerConfig() + zigbee.electricMeasurementPowerConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.simpleMeteringPowerRefresh() + zigbee.electricMeasurementPowerRefresh()
refresh()
}

View File

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

View File

@@ -0,0 +1,36 @@
# OSRAM Lightify LED On/Off/Dim
Works with:
* [OSRAM Lightify LED On/Off/Dim](https://shop.smartthings.com/#!/products/osram-led-smart-bulb-on-off-dim)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Battery](#battery-specification)
## Capabilities
* **Actuator** - represents that a Device has commands
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Refresh** - _refresh()_ command for status updates
* **Switch** - can detect state (possible values: on/off)
* **Switch Level** - represents current light level, usually 0-100 in percent
* **Health Check** - indicates ability to get device health notifications
## Device Health
A Category C1 Zigbee dimmer with maxReportTime of 5 mins.
Check-in interval is double the value of maxReportTime.
This gives the device twice the amount of time to respond before it is marked as offline.
Check-in interval = 12 mins
## 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.
Other troubleshooting tips are listed as follows:
* [Troubleshooting:](https://support.smartthings.com/hc/en-us/articles/207191763-OSRAM-LIGHTIFY-LED-Smart-Connected-Light-A19-On-Off-Dim)

View File

@@ -19,6 +19,7 @@ metadata {
capability "Refresh"
capability "Switch"
capability "Switch Level"
capability "Health Check"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008"
@@ -53,11 +54,27 @@ def parse(String description) {
def event = zigbee.getEvent(description)
if (event) {
sendEvent(event)
if (event.name=="level" && event.value==0) {}
else {
sendEvent(event)
}
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug zigbee.parseDescriptionAsMap(description)
def cluster = zigbee.parse(description)
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
if (cluster.data[0] == 0x00) {
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
}
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug "${cluster}"
}
}
}
@@ -72,12 +89,23 @@ def on() {
def setLevel(value) {
zigbee.setLevel(value)
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.onOffRefresh()
}
def refresh() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig() + zigbee.levelConfig()
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig()
}
def configure() {
log.debug "Configuring Reporting and Bindings."
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig()
}

View File

@@ -31,7 +31,8 @@
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0009,000A,0101,0020", outClusters: "000A,0019", manufacturer: "Yale", model: "YRD210 PB DB", deviceJoinName: "Yale Push Button Deadbolt Lock"
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0009,000A,0101,0020", outClusters: "000A,0019", manufacturer: "Yale", model: "YRD220/240 TSDB", deviceJoinName: "Yale Touch Screen Deadbolt Lock"
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0009,000A,0101,0020", outClusters: "000A,0019", manufacturer: "Yale", model: "YRL210 PB LL", deviceJoinName: "Yale Push Button Lever Lock"
}
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0009,000A,0101,0020", outClusters: "000A,0019", manufacturer: "Yale", model: "YRD226/246 TSDB", deviceJoinName: "Yale Touch Screen Deadbolt Lock"
}
tiles(scale: 2) {
multiAttributeTile(name:"toggle", type:"generic", width:6, height:4){
@@ -89,7 +90,7 @@ def configure() {
zigbee.configureReporting(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING,
TYPE_U8, 600, 21600, 0x01)
log.info "configure() --- cmds: $cmds"
return cmds + refresh() // send refresh cmds as part of config
return refresh() + cmds // send refresh cmds as part of config
}
def refresh() {

View File

@@ -0,0 +1,154 @@
/**
* Copyright 2016 SmartThings
*
* 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.
*
* Author: SmartThings
* Date: 2016-01-19
*
* This DTH should serve as the generic DTH to handle RGB ZigBee HA devices (For color bulbs with no color temperature)
*/
metadata {
definition (name: "ZigBee RGB Bulb", namespace: "smartthings", author: "SmartThings") {
capability "Actuator"
capability "Color Control"
capability "Configuration"
capability "Polling"
capability "Refresh"
capability "Switch"
capability "Switch Level"
capability "Health Check"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Gardenspot RGB", deviceJoinName: "OSRAM LIGHTIFY Gardenspot mini RGB"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY Gardenspot RGB", deviceJoinName: "OSRAM LIGHTIFY Gardenspot mini RGB"
}
// UI tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel"
}
tileAttribute ("device.color", key: "COLOR_CONTROL") {
attributeState "color", action:"color control.setColor"
}
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
main(["switch"])
details(["switch", "refresh"])
}
}
//Globals
private getATTRIBUTE_HUE() { 0x0000 }
private getATTRIBUTE_SATURATION() { 0x0001 }
private getHUE_COMMAND() { 0x00 }
private getSATURATION_COMMAND() { 0x03 }
private getCOLOR_CONTROL_CLUSTER() { 0x0300 }
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
log.debug event
if (event.name=="level" && event.value==0) {}
else {
sendEvent(event)
}
}
else {
def zigbeeMap = zigbee.parseDescriptionAsMap(description)
def cluster = zigbee.parse(description)
if (zigbeeMap?.clusterInt == COLOR_CONTROL_CLUSTER) {
if(zigbeeMap.attrInt == ATTRIBUTE_HUE){ //Hue Attribute
def hueValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 100)
sendEvent(name: "hue", value: hueValue, descriptionText: "Color has changed")
}
else if(zigbeeMap.attrInt == ATTRIBUTE_SATURATION){ //Saturation Attribute
def saturationValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 100)
sendEvent(name: "saturation", value: saturationValue, descriptionText: "Color has changed", displayed: false)
}
}
else if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
if (cluster.data[0] == 0x00){
log.debug "ON/OFF REPORTING CONFIG RESPONSE: $cluster"
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
}
}
else {
log.info "DID NOT PARSE MESSAGE for description : $description"
log.debug zigbeeMap
}
}
}
def on() {
zigbee.on()
}
def off() {
zigbee.off()
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.onOffRefresh()
}
def refresh() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01)
}
def configure() {
log.debug "Configuring Reporting and Bindings."
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION)
}
def setLevel(value) {
zigbee.setLevel(value)
}
def setColor(value){
log.trace "setColor($value)"
zigbee.on() + setHue(value.hue) + "delay 500" + setSaturation(value.saturation)
}
def setHue(value) {
def scaledHueValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2)
zigbee.command(COLOR_CONTROL_CLUSTER, HUE_COMMAND, scaledHueValue, "00", "0500") //payload-> hue value, direction (00-> shortest distance), transition time (1/10th second) (0500 in U16 reads 5)
}
def setSaturation(value) {
def scaledSatValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2)
zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") + "delay 1000" + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION)
}

View File

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

View File

@@ -0,0 +1,42 @@
# OSRAM LIGHTIFY LED RGBW Bulb
Works with:
* [OSRAM LIGHTIFY LED RGBW Bulb](https://support.smartthings.com/hc/en-us/articles/207728173-OSRAM-LIGHTIFY-LED-Smart-Connected-Light-A19-RGBW)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Battery](#battery-specification)
## Capabilities
* **Actuator** - It represents that a device has commands.
* **Color Control** - It represents that the color attributes of a device can be controlled (hue, saturation, color value).
* **Color Temperature** - It represents color temperature capability measured in degree Kelvin.
* **Polling** - It represents that a device can be polled.
* **Switch** - can detect state (possible values: on/off)
* **Switch Level** - can detect current light level (0-100 in percent)
* **Configuration** - _configure()_ command called when device is installed or device preferences updated
* **Refresh** - _refresh()_ command for status updates
* **Health Check** - indicates ability to get device health notifications
## Device Health
A Category C6 OSRAM LIGHTIFY LED RGBW Bulb with maxReportTime of 5 mins.
Check-in interval is double the value of maxReportTime.
This gives the device twice the amount of time to respond before it is marked as offline.
Check-in interval = 12 mins
## 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:
* [Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/207728173-OSRAM-LIGHTIFY-LED-Smart-Connected-Light-A19-RGBW)

View File

@@ -27,6 +27,10 @@ metadata {
capability "Refresh"
capability "Switch"
capability "Switch Level"
capability "Health Check"
attribute "colorName", "string"
command "setGenericName"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY Flex RGBW", deviceJoinName: "OSRAM LIGHTIFY LED FLEXIBLE STRIP RGBW"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0300,0B04,FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Flex RGBW", deviceJoinName: "OSRAM LIGHTIFY LED FLEXIBLE STRIP RGBW"
@@ -54,15 +58,15 @@ metadata {
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..6500)") {
state "colorTemperature", action:"color temperature.setColorTemperature"
}
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "colorTemperature", label: '${currentValue} K'
valueTile("colorName", "device.colorName", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "colorName", label: '${currentValue}'
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
main(["switch"])
details(["switch", "colorTempSliderControl", "colorTemp", "refresh"])
details(["switch", "colorTempSliderControl", "colorName", "refresh"])
}
}
@@ -78,27 +82,43 @@ private getATTRIBUTE_COLOR_TEMPERATURE() { 0x0007 }
def parse(String description) {
log.debug "description is $description"
def finalResult = zigbee.getEvent(description)
if (finalResult) {
log.debug finalResult
sendEvent(finalResult)
def event = zigbee.getEvent(description)
if (event) {
log.debug event
if (event.name=="level" && event.value==0) {}
else {
if (event.name=="colorTemperature") {
setGenericName(event.value)
}
sendEvent(event)
}
}
else {
def zigbeeMap = zigbee.parseDescriptionAsMap(description)
log.trace "zigbeeMap : $zigbeeMap"
def cluster = zigbee.parse(description)
if (zigbeeMap?.clusterInt == COLOR_CONTROL_CLUSTER) {
if(zigbeeMap.attrInt == ATTRIBUTE_HUE){ //Hue Attribute
def hueValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 360)
sendEvent(name: "hue", value: hueValue, displayed:false)
def hueValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 100)
sendEvent(name: "hue", value: hueValue, descriptionText: "Color has changed")
}
else if(zigbeeMap.attrInt == ATTRIBUTE_SATURATION){ //Saturation Attribute
def saturationValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 100)
sendEvent(name: "saturation", value: saturationValue, displayed:false)
sendEvent(name: "saturation", value: saturationValue, descriptionText: "Color has changed", displayed: false)
}
}
else if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
if (cluster.data[0] == 0x00){
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
}
}
else {
log.info "DID NOT PARSE MESSAGE for description : $description"
log.debug zigbeeMap
}
}
}
@@ -110,20 +130,49 @@ def on() {
def off() {
zigbee.off()
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.onOffRefresh()
}
def refresh() {
zigbee.readAttribute(0x0006, 0x00) + zigbee.readAttribute(0x0008, 0x00) + zigbee.readAttribute(0x0300, 0x00) + zigbee.readAttribute(0x0300, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.readAttribute(0x0300, ATTRIBUTE_HUE) + zigbee.readAttribute(0x0300, ATTRIBUTE_SATURATION) + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01)
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01)
}
def configure() {
log.debug "Configuring Reporting and Bindings."
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01) + zigbee.readAttribute(0x0006, 0x00) + zigbee.readAttribute(0x0008, 0x00) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, 0x00) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_COLOR_TEMPERATURE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION)
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
refresh()
}
def setColorTemperature(value) {
setGenericName(value)
zigbee.setColorTemperature(value)
}
//Naming based on the wiki article here: http://en.wikipedia.org/wiki/Color_temperature
def setGenericName(value){
if (value != null) {
def genericName = "White"
if (value < 3300) {
genericName = "Soft White"
} else if (value < 4150) {
genericName = "Moonlight"
} else if (value <= 5000) {
genericName = "Cool White"
} else if (value >= 5000) {
genericName = "Daylight"
}
sendEvent(name: "colorName", value: genericName)
}
}
def setLevel(value) {
zigbee.setLevel(value)
}
@@ -140,5 +189,5 @@ def setHue(value) {
def setSaturation(value) {
def scaledSatValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2)
zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") //payload-> sat value, transition time
zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") + "delay 1000" + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION)
}

View File

@@ -82,5 +82,5 @@ def refresh() {
def configure() {
log.debug "Configuring Reporting and Bindings."
zigbee.onOffConfig() + zigbee.simpleMeteringPowerConfig() + zigbee.electricMeasurementPowerConfig() + zigbee.onOffRefresh() + zigbee.simpleMeteringPowerRefresh() + zigbee.electricMeasurementPowerRefresh()
refresh()
}

View File

@@ -20,6 +20,7 @@ metadata {
capability "Switch"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0006", outClusters: "0003, 0006, 0019, 0406", manufacturer: "Leviton", model: "ZSS-10", deviceJoinName: "Leviton Switch"
}
// simulator metadata
@@ -77,5 +78,5 @@ def refresh() {
def configure() {
log.debug "Configuring Reporting and Bindings."
zigbee.onOffConfig() + zigbee.onOffRefresh()
zigbee.onOffRefresh() + zigbee.onOffConfig()
}

View File

@@ -1,5 +1,5 @@
/**
* Copyright 2015 SmartThings
* Copyright 2016 SmartThings
*
* 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:
@@ -11,100 +11,128 @@
* for the specific language governing permissions and limitations under the License.
*
*/
/*
* Capabilities
* - Battery
* - Configuration
* - Refresh
* - Switch
* - Valve
*/
metadata {
definition (name: "Zigbee Valve", namespace: "smartthings", author: "SmartThings") {
capability "Battery"
capability "Configuration"
capability "Refresh"
capability "Switch"
capability "Valve"
definition (name: "ZigBee Valve", namespace: "smartthings", author: "SmartThings") {
capability "Actuator"
capability "Battery"
capability "Configuration"
capability "Power Source"
capability "Refresh"
capability "Valve"
fingerprint profileId: "0104", inClusters: "0000,0001,0003,0004,0005,0020,0006,0B02", outClusters: "0003"
}
fingerprint profileId: "0104", inClusters: "0000, 0001, 0003, 0006, 0020, 0B02, FC02", outClusters: "0019", manufacturer: "WAXMAN", model: "leakSMART Water Valve v2.10", deviceJoinName: "leakSMART Valve"
fingerprint profileId: "0104", inClusters: "0000, 0001, 0003, 0004, 0005, 0006, 0008, 000F, 0020, 0B02", outClusters: "0003, 0019", manufacturer: "WAXMAN", model: "House Water Valve - MDL-TBD", deviceJoinName: "Waxman House Water Valve"
}
// simulator metadata
simulator {
// status messages
status "on": "on/off: 1"
status "off": "on/off: 0"
// simulator metadata
simulator {
// status messages
status "on": "on/off: 1"
status "off": "on/off: 0"
// reply messages
reply "zcl on-off on": "on/off: 1"
reply "zcl on-off off": "on/off: 0"
}
// reply messages
reply "zcl on-off on": "on/off: 1"
reply "zcl on-off off": "on/off: 0"
}
// UI tile definitions
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: 'closed', action: "switch.on", icon: "st.Outdoor.outdoor16", backgroundColor: "#e86d13"
state "on", label: 'open', action: "switch.off", icon: "st.Outdoor.outdoor16", backgroundColor: "#53a7c0"
}
main "switch"
details(["switch"])
}
tiles(scale: 2) {
multiAttributeTile(name:"valve", 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: "#53a7c0", nextState:"closing"
attributeState "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#e86d13", nextState:"opening"
attributeState "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#53a7c0", nextState:"closing"
attributeState "closing", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#e86d13", nextState:"opening"
}
tileAttribute ("powerSource", key: "SECONDARY_CONTROL") {
attributeState "powerSource", label:'Power Source: ${currentValue}'
}
}
valueTile("battery", "device.battery", inactiveLabel:false, decoration:"flat", width:2, height:2) {
state "battery", label:'${currentValue}% battery', unit:""
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
main(["valve"])
details(["valve", "battery", "refresh"])
}
}
private getCLUSTER_BASIC() { 0x0000 }
private getBASIC_ATTR_POWER_SOURCE() { 0x0007 }
private getCLUSTER_POWER() { 0x0001 }
private getPOWER_ATTR_BATTERY_PERCENTAGE_REMAINING() { 0x0021 }
private getTYPE_U8() { 0x20 }
private getTYPE_ENUM8() { 0x30 }
// Parse incoming device messages to generate events
def parse(String description) {
log.info description
if (description?.startsWith("catchall:")) {
def value = name == "switch" ? (description?.endsWith(" 1") ? "on" : "off") : null
def result = createEvent(name: name, value: value)
def msg = zigbee.parse(description)
log.debug "Parse returned ${result?.descriptionText}"
return result
log.trace msg
log.trace "data: $msg.data"
}
else {
def name = description?.startsWith("on/off: ") ? "switch" : null
def value = name == "switch" ? (description?.endsWith(" 1") ? "on" : "off") : null
def result = createEvent(name: name, value: value)
log.debug "Parse returned ${result?.descriptionText}"
return result
}
}
// Commands to device
def on() {
log.debug "on()"
sendEvent(name: "switch", value: "on")
"st cmd 0x${device.deviceNetworkId} 1 6 1 {}"
}
def off() {
log.debug "off()"
sendEvent(name: "switch", value: "off")
"st cmd 0x${device.deviceNetworkId} 1 6 0 {}"
log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
if(event.name == "switch") {
event.name = "contact" //0006 cluster in valve is tied to contact
if(event.value == "on") {
event.value = "open"
}
else if(event.value == "off") {
event.value = "closed"
}
}
sendEvent(event)
}
else {
def descMap = zigbee.parseDescriptionAsMap(description)
if (descMap.clusterInt == CLUSTER_BASIC && descMap.attrInt == BASIC_ATTR_POWER_SOURCE){
def value = descMap.value
if (value == "01" || value == "02") {
sendEvent(name: "powerSource", value: "Mains")
}
else if (value == "03") {
sendEvent(name: "powerSource", value: "Battery")
}
else if (value == "04") {
sendEvent(name: "powerSource", value: "DC")
}
else {
sendEvent(name: "powerSource", value: "Unknown")
}
}
else if (descMap.clusterInt == CLUSTER_POWER && descMap.attrInt == POWER_ATTR_BATTERY_PERCENTAGE_REMAINING) {
event.name = "battery"
event.value = Math.round(Integer.parseInt(descMap.value, 16) / 2)
sendEvent(event)
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug descMap
}
}
}
def open() {
log.debug "on()"
sendEvent(name: "switch", value: "on")
"st cmd 0x${device.deviceNetworkId} 1 6 1 {}"
zigbee.on()
}
def close() {
log.debug "off()"
sendEvent(name: "switch", value: "off")
"st cmd 0x${device.deviceNetworkId} 1 6 0 {}"
zigbee.off()
}
def refresh() {
log.debug "sending refresh command"
"st rattr 0x${device.deviceNetworkId} 1 6 0"
log.debug "refresh called"
zigbee.onOffRefresh() +
zigbee.readAttribute(CLUSTER_BASIC, BASIC_ATTR_POWER_SOURCE) +
zigbee.readAttribute(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING) +
zigbee.onOffConfig() +
zigbee.configureReporting(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING, TYPE_U8, 600, 21600, 1) +
zigbee.configureReporting(CLUSTER_BASIC, BASIC_ATTR_POWER_SOURCE, TYPE_ENUM8, 5, 21600, 1)
}
def configure() {
"zdo bind 0x${device.deviceNetworkId} 1 1 6 {${device.zigbeeId}} {}"
log.debug "Configuring Reporting and Bindings."
refresh()
}

View File

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

View File

@@ -0,0 +1,37 @@
# OSRAM Lightify Tunable 60 White
Works with:
* [OSRAM Lightify Tunable 60 White](http://www.osram.com/osram_com/tools-and-services/tools/lightify---smart-connected-light/lightify-for-home---what-is-light-to-you/lightify-products/lightify-classic-a60-tunable-white/index.jsp)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Battery](#battery-specification)
## Capabilities
* **Actuator** - represents that a Device has commands
* **Color Temperature** - represents color temperature, measured in degrees Kelvin.
* **Configuration** - _configure()_ command called when device is installed or device preferences updated.
* **Refresh** - _refresh()_ command for status updates
* **Switch** - can detect state (possible values: on/off)
* **Switch Level** - represents current light level, usually 0-100 in percent
* **Health Check** - indicates ability to get device health notifications
## Device Health
A Category C1 OSRAM Lightify Tunable 60 White with maxReportTime of 5 mins.
Check-in interval is double the value of maxReportTime.
This gives the device twice the amount of time to respond before it is marked as offline.
Check-in interval = 12 mins
## 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.
Other troubleshooting tips are listed as follows:
* [Troubleshooting:](https://support.smartthings.com/hc/en-us/articles/204576454-OSRAM-LIGHTIFY-Tunable-White-60-Bulb)

View File

@@ -22,6 +22,7 @@ metadata {
capability "Actuator"
capability "Color Temperature"
capability "Configuration"
capability "Health Check"
capability "Refresh"
capability "Switch"
capability "Switch Level"
@@ -35,6 +36,7 @@ metadata {
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY RT Tunable White", deviceJoinName: "OSRAM LIGHTIFY LED Recessed Kit RT 5/6 Tunable White"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Classic A60 TW", deviceJoinName: "OSRAM LIGHTIFY LED Tunable White 60W"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY A19 Tunable White", deviceJoinName: "OSRAM LIGHTIFY LED Tunable White 60W"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Classic B40 TW - LIGHTIFY", deviceJoinName: "OSRAM LIGHTIFY Classic B40 Tunable White"
}
// UI tile definitions
@@ -49,9 +51,6 @@ metadata {
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel"
}
tileAttribute ("colorName", key: "SECONDARY_CONTROL") {
attributeState "colorName", label:'${currentValue}'
}
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
@@ -61,12 +60,12 @@ metadata {
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..6500)") {
state "colorTemperature", action:"color temperature.setColorTemperature"
}
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "colorTemperature", label: '${currentValue} K'
valueTile("colorName", "device.colorName", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "colorName", label: '${currentValue}'
}
main(["switch"])
details(["switch", "colorTempSliderControl", "colorTemp", "refresh"])
details(["switch", "colorTempSliderControl", "colorName", "refresh"])
}
}
@@ -75,11 +74,30 @@ def parse(String description) {
log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
sendEvent(event)
if (event.name=="level" && event.value==0) {}
else {
if (event.name=="colorTemperature") {
setGenericName(event.value)
}
sendEvent(event)
}
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug zigbee.parseDescriptionAsMap(description)
def cluster = zigbee.parse(description)
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
if (cluster.data[0] == 0x00) {
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
}
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug "${cluster}"
}
}
}
@@ -95,13 +113,25 @@ def setLevel(value) {
zigbee.setLevel(value)
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.onOffRefresh()
}
def refresh() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig()
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig() + zigbee.colorTemperatureConfig()
}
def configure() {
log.debug "Configuring Reporting and Bindings."
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
// Device-Watch allows 3 check-in misses from device (plus 1 min lag time)
// enrolls with default periodic reporting until newer 5 min interval is confirmed
sendEvent(name: "checkInterval", value: 3 * 10 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
// OnOff minReportTime 0 seconds, maxReportTime 5 min. Reporting interval if no activity
refresh()
}
def setColorTemperature(value) {

View File

@@ -11,6 +11,9 @@
* for the specific language governing permissions and limitations under the License.
*
*/
import groovy.transform.Field
@Field Boolean hasConfiguredHealthCheck = false
metadata {
definition (name: "ZLL Dimmer Bulb", namespace: "smartthings", author: "SmartThings") {
@@ -21,6 +24,7 @@ metadata {
capability "Refresh"
capability "Switch"
capability "Switch Level"
capability "Health Check"
//fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000", outClusters: "0000,0019"
fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000", outClusters: "0019"
@@ -96,7 +100,38 @@ def poll() {
refresh()
}
def configure() {
log.debug "Configuring Reporting and Bindings."
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.levelRefresh()
}
def healthPoll() {
log.debug "healthPoll()"
def cmds = refresh()
cmds.each{ sendHubCommand(new physicalgraph.device.HubAction(it))}
}
def configureHealthCheck() {
Integer hcIntervalMinutes = 12
if (!hasConfiguredHealthCheck) {
log.debug "Configuring Health Check, Reporting"
unschedule("healthPoll")
runEvery5Minutes("healthPoll")
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: hcIntervalMinutes * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
hasConfiguredHealthCheck = true
}
}
def configure() {
log.debug "configure()"
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()
configureHealthCheck()
}
def updated() {
log.debug "updated()"
configureHealthCheck()
}

View File

@@ -0,0 +1,134 @@
/**
* Copyright 2016 SmartThings
*
* 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: "ZLL RGB Bulb", namespace: "smartthings", author: "SmartThings") {
capability "Actuator"
capability "Color Control"
capability "Configuration"
capability "Polling"
capability "Refresh"
capability "Switch"
capability "Switch Level"
}
// UI tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel"
}
tileAttribute ("device.color", key: "COLOR_CONTROL") {
attributeState "color", action:"color control.setColor"
}
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
main(["switch"])
details(["switch", "refresh"])
}
}
//Globals
private getATTRIBUTE_HUE() { 0x0000 }
private getATTRIBUTE_SATURATION() { 0x0001 }
private getHUE_COMMAND() { 0x00 }
private getSATURATION_COMMAND() { 0x03 }
private getCOLOR_CONTROL_CLUSTER() { 0x0300 }
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
def finalResult = zigbee.getEvent(description)
if (finalResult) {
log.debug finalResult
sendEvent(finalResult)
}
else {
def zigbeeMap = zigbee.parseDescriptionAsMap(description)
log.trace "zigbeeMap : $zigbeeMap"
if (zigbeeMap?.clusterInt == COLOR_CONTROL_CLUSTER) {
if(zigbeeMap.attrInt == ATTRIBUTE_HUE){ //Hue Attribute
def hueValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 360)
sendEvent(name: "hue", value: hueValue, displayed:false)
}
else if(zigbeeMap.attrInt == ATTRIBUTE_SATURATION){ //Saturation Attribute
def saturationValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 100)
sendEvent(name: "saturation", value: saturationValue, displayed:false)
}
}
else {
log.info "DID NOT PARSE MESSAGE for description : $description"
}
}
}
def on() {
zigbee.on() + ["delay 1500"] + zigbee.onOffRefresh()
}
def off() {
zigbee.off() + ["delay 1500"] + zigbee.onOffRefresh()
}
def refresh() {
refreshAttributes() + configureAttributes()
}
def poll() {
refreshAttributes()
}
def configure() {
log.debug "Configuring Reporting and Bindings."
configureAttributes() + refreshAttributes()
}
def configureAttributes() {
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01)
}
def refreshAttributes() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION)
}
def setLevel(value) {
zigbee.setLevel(value) + ["delay 1500"] + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report
}
def setColor(value){
log.trace "setColor($value)"
zigbee.on() + setHue(value.hue) + ["delay 300"] + setSaturation(value.saturation) + ["delay 2000"] + refreshAttributes()
}
def setHue(value) {
def scaledHueValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2)
zigbee.command(COLOR_CONTROL_CLUSTER, HUE_COMMAND, scaledHueValue, "00", "0500") + ["delay 1500"] + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) //payload-> hue value, direction (00-> shortest distance), transition time (1/10th second) (0500 in U16 reads 5)
}
def setSaturation(value) {
def scaledSatValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2)
zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") + ["delay 1500"] + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) //payload-> sat value, transition time
}

View File

@@ -123,7 +123,7 @@ def configureAttributes() {
}
def refreshAttributes() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() + zigbee.readAttribute(0x0300, 0x00) + zigbee.readAttribute(0x0300, ATTRIBUTE_HUE) + zigbee.readAttribute(0x0300, ATTRIBUTE_SATURATION)
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION)
}
def setColorTemperature(value) {
@@ -141,10 +141,10 @@ def setColor(value){
def setHue(value) {
def scaledHueValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2)
zigbee.command(COLOR_CONTROL_CLUSTER, HUE_COMMAND, scaledHueValue, "00", "0500") //payload-> hue value, direction (00-> shortest distance), transition time (1/10th second) (0500 in U16 reads 5)
zigbee.command(COLOR_CONTROL_CLUSTER, HUE_COMMAND, scaledHueValue, "00", "0500") + ["delay 1500"] + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE) //payload-> hue value, direction (00-> shortest distance), transition time (1/10th second) (0500 in U16 reads 5)
}
def setSaturation(value) {
def scaledSatValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2)
zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") //payload-> sat value, transition time
zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") + ["delay 1500"] + zigbee.readAttribute(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION) //payload-> sat value, transition time
}

View File

@@ -11,6 +11,9 @@
* for the specific language governing permissions and limitations under the License.
*
*/
import groovy.transform.Field
@Field Boolean hasConfiguredHealthCheck = false
metadata {
definition (name: "ZLL White Color Temperature Bulb", namespace: "smartthings", author: "SmartThings") {
@@ -22,6 +25,7 @@ metadata {
capability "Refresh"
capability "Switch"
capability "Switch Level"
capability "Health Check"
attribute "colorName", "string"
command "setGenericName"
@@ -96,9 +100,41 @@ def poll() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
return zigbee.levelRefresh()
}
def healthPoll() {
log.debug "healthPoll()"
def cmds = zigbee.onOffRefresh() + zigbee.levelRefresh()
cmds.each{ sendHubCommand(new physicalgraph.device.HubAction(it))}
}
def configureHealthCheck() {
Integer hcIntervalMinutes = 12
if (!hasConfiguredHealthCheck) {
log.debug "Configuring Health Check, Reporting"
unschedule("healthPoll")
runEvery5Minutes("healthPoll")
// Device-Watch allows 2 check-in misses from device
sendEvent(name: "checkInterval", value: hcIntervalMinutes * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
hasConfiguredHealthCheck = true
}
}
def configure() {
log.debug "Configuring Reporting and Bindings."
log.debug "configure()"
configureHealthCheck()
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
}
def updated() {
log.debug "updated()"
configureHealthCheck()
}
def setColorTemperature(value) {

View File

@@ -0,0 +1,205 @@
/**
* Copyright 2015 SmartThings
*
* 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: "Z-Wave Dimmer Switch Generic", namespace: "smartthings", author: "SmartThings") {
capability "Switch Level"
capability "Actuator"
capability "Switch"
capability "Polling"
capability "Refresh"
capability "Sensor"
fingerprint inClusters: "0x26", deviceJoinName: "Z-Wave Dimmer"
}
simulator {
status "on": "command: 2003, payload: FF"
status "off": "command: 2003, payload: 00"
status "09%": "command: 2003, payload: 09"
status "10%": "command: 2003, payload: 0A"
status "33%": "command: 2003, payload: 21"
status "66%": "command: 2003, payload: 42"
status "99%": "command: 2003, payload: 63"
// reply messages
reply "2001FF,delay 5000,2602": "command: 2603, payload: FF"
reply "200100,delay 5000,2602": "command: 2603, payload: 00"
reply "200119,delay 5000,2602": "command: 2603, payload: 19"
reply "200132,delay 5000,2602": "command: 2603, payload: 32"
reply "20014B,delay 5000,2602": "command: 2603, payload: 4B"
reply "200163,delay 5000,2602": "command: 2603, payload: 63"
}
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "off", 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:"#79b821", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel"
}
}
standardTile("refresh", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
valueTile("level", "device.level", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "level", label:'${currentValue} %', unit:"%", backgroundColor:"#ffffff"
}
main(["switch"])
details(["switch", "level", "refresh"])
}
}
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])
if (cmd) {
result = zwaveEvent(cmd)
}
}
if (result?.name == 'hail' && hubFirmwareLessThan("000.011.00602")) {
result = [result, response(zwave.basicV1.basicGet())]
log.debug "Was hailed: requesting state update"
} else {
log.debug "Parse returned ${result?.descriptionText}"
}
return result
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
dimmerEvents(cmd)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
dimmerEvents(cmd)
}
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd) {
dimmerEvents(cmd)
}
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelSet cmd) {
dimmerEvents(cmd)
}
private dimmerEvents(physicalgraph.zwave.Command cmd) {
def value = (cmd.value ? "on" : "off")
def result = [createEvent(name: "switch", value: value)]
if (cmd.value && cmd.value <= 100) {
result << createEvent(name: "level", value: cmd.value, unit: "%")
}
return result
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
log.debug "ConfigurationReport $cmd"
def value = "when off"
if (cmd.configurationValue[0] == 1) {value = "when on"}
if (cmd.configurationValue[0] == 2) {value = "never"}
createEvent([name: "indicatorStatus", value: value])
}
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
createEvent([name: "hail", value: "hail", descriptionText: "Switch button was pressed", displayed: false])
}
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
log.debug "manufacturerId: ${cmd.manufacturerId}"
log.debug "manufacturerName: ${cmd.manufacturerName}"
log.debug "productId: ${cmd.productId}"
log.debug "productTypeId: ${cmd.productTypeId}"
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
updateDataValue("MSR", msr)
updateDataValue("manufacturer", cmd.manufacturerName)
createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false])
}
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStopLevelChange cmd) {
[createEvent(name:"switch", value:"on"), response(zwave.switchMultilevelV1.switchMultilevelGet().format())]
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren't interested in
[:]
}
def on() {
delayBetween([
zwave.basicV1.basicSet(value: 0xFF).format(),
zwave.switchMultilevelV1.switchMultilevelGet().format()
],5000)
}
def off() {
delayBetween([
zwave.basicV1.basicSet(value: 0x00).format(),
zwave.switchMultilevelV1.switchMultilevelGet().format()
],5000)
}
def setLevel(value) {
log.debug "setLevel >> value: $value"
def valueaux = value as Integer
def level = Math.max(Math.min(valueaux, 99), 0)
if (level > 0) {
sendEvent(name: "switch", value: "on")
} else {
sendEvent(name: "switch", value: "off")
}
sendEvent(name: "level", value: level, unit: "%")
delayBetween ([zwave.basicV1.basicSet(value: level).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}
def setLevel(value, duration) {
log.debug "setLevel >> value: $value, duration: $duration"
def valueaux = value as Integer
def level = Math.max(Math.min(valueaux, 99), 0)
def dimmingDuration = duration < 128 ? duration : 128 + Math.round(duration / 60)
def getStatusDelay = duration < 128 ? (duration*1000)+2000 : (Math.round(duration / 60)*60*1000)+2000
delayBetween ([zwave.switchMultilevelV2.switchMultilevelSet(value: level, dimmingDuration: dimmingDuration).format(),
zwave.switchMultilevelV1.switchMultilevelGet().format()], getStatusDelay)
}
def poll() {
zwave.switchMultilevelV1.switchMultilevelGet().format()
}
def refresh() {
log.debug "refresh() is called"
def commands = []
commands << zwave.switchMultilevelV1.switchMultilevelGet().format()
if (getDataValue("MSR") == null) {
commands << zwave.manufacturerSpecificV1.manufacturerSpecificGet().format()
}
delayBetween(commands,100)
}
def invertSwitch(invert=true) {
if (invert) {
zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 4, size: 1).format()
}
else {
zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 4, size: 1).format()
}
}

View File

@@ -28,7 +28,6 @@ metadata {
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x98"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x98", outClusters: "0x5A,0x82"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x80,0x71,0x85,0x70,0x72,0x86,0x30,0x31,0x84,0x59,0x73,0x5A,0x8F,0x98,0x7A", outClusters:"0x20" // Philio multi+
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x72,0x5A,0x80,0x73,0x84,0x85,0x59,0x71,0x70,0x7A,0x98" // Vision door/window
}
// simulator metadata
@@ -36,6 +35,7 @@ metadata {
// status messages
status "open": "command: 2001, payload: FF"
status "closed": "command: 2001, payload: 00"
status "wake up": "command: 8407, payload: "
}
// UI tile definitions
@@ -83,12 +83,12 @@ def updated() {
cmds = [
command(zwave.manufacturerSpecificV2.manufacturerSpecificGet()),
"delay 1200",
zwave.wakeUpV1.wakeUpNoMoreInformation()
zwave.wakeUpV1.wakeUpNoMoreInformation().format()
]
} else if (!state.lastbat) {
cmds = []
} else {
cmds = [zwave.wakeUpV1.wakeUpNoMoreInformation()]
cmds = [zwave.wakeUpV1.wakeUpNoMoreInformation().format()]
}
response(cmds)
}
@@ -175,7 +175,7 @@ def zwaveEvent(physicalgraph.zwave.commands.wakeupv1.WakeUpNotification cmd)
if (!state.lastbat || now() - state.lastbat > 53*60*60*1000) {
cmds << command(zwave.batteryV1.batteryGet())
} else {
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation()
cmds << zwave.wakeUpV1.wakeUpNoMoreInformation().format()
}
[event, response(cmds)]
}

View File

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

View File

@@ -0,0 +1,39 @@
# Z-wave Switch
Works with:
* [Leviton Appliance Module (DZPA1-1LW)](https://support.smartthings.com/hc/en-us/articles/205881176-Leviton-Appliance-Module-DZPA1-1LW-)
* [GE Plug-In Outdoor Smart Switch (GE 12720) (Z-Wave)](https://support.smartthings.com/hc/en-us/articles/200903080-GE-Plug-In-Outdoor-Smart-Switch-GE-12720-Z-Wave-)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
## Capabilities
* **Actuator** - represents that a Device has commands
* **Health Check** - indicates ability to get device health notifications
* **Switch** - can detect state (possible values: on/off)
* **Polling** - represents that poll() can be implemented for the device
* **Refresh** - _refresh()_ command for status updates
* **Sensor** - detects sensor events
## Device Health
A Category C5 Leviton Appliance Module (DZPA1-1LW) and GE Plug-In Outdoor Smart Switch (GE 12720) (Z-Wave) 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.
## 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:
* [Leviton Appliance Module (DZPA1-1LW) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/205881176-Leviton-Appliance-Module-DZPA1-1LW-)
* [GE Plug-In Outdoor Smart Switch (GE 12720) (Z-Wave) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200903080-GE-Plug-In-Outdoor-Smart-Switch-GE-12720-Z-Wave-)

View File

@@ -0,0 +1,158 @@
/**
* Copyright 2015 SmartThings
*
* 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: "Z-Wave Switch Generic", namespace: "smartthings", author: "SmartThings") {
capability "Actuator"
capability "Health Check"
capability "Switch"
capability "Polling"
capability "Refresh"
capability "Sensor"
fingerprint inClusters: "0x25", deviceJoinName: "Z-Wave Switch"
fingerprint mfr:"001D", prod:"1A02", deviceJoinName: "Z-Wave Switch"
fingerprint mfr:"0063", prod:"4F50", deviceJoinName: "Z-Wave Switch"
}
// simulator metadata
simulator {
status "on": "command: 2003, payload: FF"
status "off": "command: 2003, payload: 00"
// reply messages
reply "2001FF,delay 100,2502": "command: 2503, payload: FF"
reply "200100,delay 100,2502": "command: 2503, payload: 00"
}
// tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
}
standardTile("refresh", "device.switch", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
main "switch"
details(["switch","refresh"])
}
}
def updated(){
// Device-Watch simply pings if no device events received for checkInterval duration of 32min = 2 * 15min + 2min lag time
sendEvent(name: "checkInterval", value: 2 * 15 * 60 + 2 * 60, displayed: false, data: [protocol: "zwave", hubHardwareId: device.hub.hardwareID])
}
def parse(String description) {
def result = null
def cmd = zwave.parse(description, [0x20: 1, 0x70: 1])
if (cmd) {
result = createEvent(zwaveEvent(cmd))
}
if (result?.name == 'hail' && hubFirmwareLessThan("000.011.00602")) {
result = [result, response(zwave.basicV1.basicGet())]
log.debug "Was hailed: requesting state update"
} else {
log.debug "Parse returned ${result?.descriptionText}"
}
return result
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
[name: "switch", value: cmd.value ? "on" : "off", type: "physical"]
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
[name: "switch", value: cmd.value ? "on" : "off", type: "physical"]
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd) {
[name: "switch", value: cmd.value ? "on" : "off", type: "digital"]
}
def zwaveEvent(physicalgraph.zwave.commands.configurationv1.ConfigurationReport cmd) {
def value = "when off"
if (cmd.configurationValue[0] == 1) {value = "when on"}
if (cmd.configurationValue[0] == 2) {value = "never"}
[name: "indicatorStatus", value: value, display: false]
}
def zwaveEvent(physicalgraph.zwave.commands.hailv1.Hail cmd) {
[name: "hail", value: "hail", descriptionText: "Switch button was pressed", displayed: false]
}
def zwaveEvent(physicalgraph.zwave.commands.manufacturerspecificv2.ManufacturerSpecificReport cmd) {
log.debug "manufacturerId: ${cmd.manufacturerId}"
log.debug "manufacturerName: ${cmd.manufacturerName}"
log.debug "productId: ${cmd.productId}"
log.debug "productTypeId: ${cmd.productTypeId}"
def msr = String.format("%04X-%04X-%04X", cmd.manufacturerId, cmd.productTypeId, cmd.productId)
updateDataValue("MSR", msr)
updateDataValue("manufacturer", cmd.manufacturerName)
createEvent([descriptionText: "$device.displayName MSR: $msr", isStateChange: false])
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
// Handles all Z-Wave commands we aren't interested in
[:]
}
def on() {
delayBetween([
zwave.basicV1.basicSet(value: 0xFF).format(),
zwave.switchBinaryV1.switchBinaryGet().format()
])
}
def off() {
delayBetween([
zwave.basicV1.basicSet(value: 0x00).format(),
zwave.switchBinaryV1.switchBinaryGet().format()
])
}
def poll() {
delayBetween([
zwave.switchBinaryV1.switchBinaryGet().format(),
zwave.manufacturerSpecificV1.manufacturerSpecificGet().format()
])
}
/**
* PING is used by Device-Watch in attempt to reach the Device
* */
def ping() {
refresh()
}
def refresh() {
delayBetween([
zwave.switchBinaryV1.switchBinaryGet().format(),
zwave.manufacturerSpecificV1.manufacturerSpecificGet().format()
])
}
def invertSwitch(invert=true) {
if (invert) {
zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 4, size: 1).format()
}
else {
zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 4, size: 1).format()
}
}

View File

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

View File

@@ -0,0 +1,49 @@
# Z-Wave Switch
Works with:
* [GE Z-Wave Plug-In Smart Switch (12719)](http://products.z-wavealliance.org/products/1193)
* [GE Z-Wave In-Wall Smart Outlet (12721)](http://products.z-wavealliance.org/products/1195)
* [GE Z-Wave In-Wall Smart Switch (12722)](http://products.z-wavealliance.org/products/1196)
* [GE Z-Wave In-Wall Smart Toggle Switch (12727)](http://products.z-wavealliance.org/products/1200)
## Table of contents
* [Capabilities](#capabilities)
* [Health](#device-health)
* [Troubleshooting](#Troubleshooting)
## Capabilities
* **Actuator** - represents that a Device has commands
* **Indicator** - gives you the ability to set the indicator LED light on a Z-Wave switch
* **Switch** - can detect state (possible values: on/off)
* **Polling** - represents that poll() can be implemented for the device
* **Refresh** - _refresh()_ command for status updates
* **Sensor** - detects sensor events
* **Health Check** - indicates ability to get device health notifications
## Device Health
Z-Wave Switches (Plug-In, In-Wall(Toggle Switch, Switch, Outlet)) are 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.
## 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:
* [General Z-Wave Dimmer/Switch Troubleshooting](https://support.smartthings.com/hc/en-us/articles/200955890-Troubleshooting-GE-in-wall-switch-or-dimmer-won-t-respond-to-commands-or-automations-Z-Wave-)
* [GE Z-Wave Plug-In Smart Switch (12719) Troubleshooting](https://support.smartthings.com/hc/en-us/articles/200903070-GE-Plug-In-Smart-Switch-GE-12719-Z-Wave)
* [GE Z-Wave In-Wall Smart Outlet (12721) Troubleshooting](https://support.smartthings.com/hc/en-us/articles/200903020-GE-In-Wall-Smart-Outlet-GE-12721-Z-Wave)
* [GE Z-Wave In-Wall Smart Switch (12722) Troubleshooting](https://support.smartthings.com/hc/en-us/articles/200902540-GE-In-Wall-Smart-Switch-GE-12722-Z-Wave)
* [GE Z-Wave In-Wall Smart Toggle Switch (12727) Troubleshooting](https://support.smartthings.com/hc/en-us/articles/207568933-GE-In-Wall-Smart-Toggle-Switch-GE-12727-Z-Wave)

View File

@@ -15,12 +15,16 @@ metadata {
definition (name: "Z-Wave Switch", namespace: "smartthings", author: "SmartThings") {
capability "Actuator"
capability "Indicator"
capability "Switch"
capability "Switch"
capability "Polling"
capability "Refresh"
capability "Sensor"
capability "Health Check"
fingerprint inClusters: "0x25"
fingerprint mfr:"0063", prod:"4952", deviceJoinName: "Z-Wave Wall Switch"
fingerprint mfr:"0063", prod:"5257", deviceJoinName: "Z-Wave Wall Switch"
fingerprint mfr:"0063", prod:"5052", deviceJoinName: "Z-Wave Plug-In Switch"
fingerprint mfr:"0113", prod:"5257", deviceJoinName: "Z-Wave Wall Switch"
}
// simulator metadata
@@ -33,6 +37,10 @@ metadata {
reply "200100,delay 100,2502": "command: 2503, payload: 00"
}
preferences {
input "ledIndicator", "enum", title: "LED Indicator", description: "Turn LED indicator... ", required: false, options:["on": "When On", "off": "When Off", "never": "Never"], defaultValue: "off"
}
// tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
@@ -52,10 +60,29 @@ metadata {
}
main "switch"
details(["switch","refresh","indicator"])
details(["switch","refresh"])
}
}
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])
switch (ledIndicator) {
case "on":
indicatorWhenOn()
break
case "off":
indicatorWhenOff()
break
case "never":
indicatorNever()
break
default:
indicatorWhenOn()
break
}
}
def parse(String description) {
def result = null
def cmd = zwave.parse(description, [0x20: 1, 0x70: 1])
@@ -132,6 +159,13 @@ def poll() {
])
}
/**
* PING is used by Device-Watch in attempt to reach the Device
**/
def ping() {
refresh()
}
def refresh() {
delayBetween([
zwave.switchBinaryV1.switchBinaryGet().format(),
@@ -139,19 +173,19 @@ def refresh() {
])
}
def indicatorWhenOn() {
void indicatorWhenOn() {
sendEvent(name: "indicatorStatus", value: "when on", display: false)
zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format()
sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [1], parameterNumber: 3, size: 1).format()))
}
def indicatorWhenOff() {
void indicatorWhenOff() {
sendEvent(name: "indicatorStatus", value: "when off", display: false)
zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format()
sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [0], parameterNumber: 3, size: 1).format()))
}
def indicatorNever() {
void indicatorNever() {
sendEvent(name: "indicatorStatus", value: "never", display: false)
zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 3, size: 1).format()
sendHubCommand(new physicalgraph.device.HubAction(zwave.configurationV1.configurationSet(configurationValue: [2], parameterNumber: 3, size: 1).format()))
}
def invertSwitch(invert=true) {

View File

@@ -24,17 +24,24 @@ definition(
iconX3Url: "http://www.gidjit.com/appicon@3x.png",
oauth: [displayName: "Gidjit", displayLink: "www.gidjit.com"])
preferences(oauthPage: "deviceAuthorization") {
// deviceAuthorization page is simply the devices to authorize
page(name: "deviceAuthorization", title: "Device Authorization", nextPage: "instructionPage",
install: false, uninstall: true) {
section ("Allow Gidjit to have access, thereby allowing you to quickly control and monitor your following devices. Privacy Policy can be found at http://priv.gidjit.com/privacy.html") {
input "switches", "capability.switch", title: "Control/Monitor your switches", multiple: true, required: false
input "thermostats", "capability.thermostat", title: "Control/Monitor your thermostats", multiple: true, required: false
input "windowShades", "capability.windowShade", title: "Control/Monitor your window shades", multiple: true, required: false //windowShade
}
preferences {
section ("Allow Gidjit to have access, there by allowing you to quickly control and monitor the following devices") {
input "switches", "capability.switch", title: "Control/Monitor your switches", multiple: true, required: false
input "thermostats", "capability.thermostat", title: "Control/Monitor your thermostats", multiple: true, required: false
input "windowShades", "capability.windowShade", title: "Control/Monitor your window shades", multiple: true, required: false //windowShade
//input "bulbs", "capability.colorControl", title: "Control your lights", multiple: true, required: false //windowShade
}
}
page(name: "instructionPage", title: "Device Discovery", install: true) {
section() {
paragraph "Now the process is complete return to the Devices section of the Detected Screen. From there and you can add actions to each of your device panels, including launching SmartThings routines."
}
}
}
mappings {
path("/structureinfo") {
action: [

View File

@@ -65,7 +65,16 @@ void updateSwitch() {
private void updateAll(devices) {
def command = request.JSON?.command
if (command) {
devices."$command"()
switch(command) {
case "on":
devices.on()
break
case "off":
devices.off()
break
default:
httpError(403, "Access denied. This command is not supported by current capability.")
}
}
}
@@ -77,7 +86,16 @@ private void update(devices) {
if (!device) {
httpError(404, "Device not found")
} else {
device."$command"()
switch(command) {
case "on":
device.on()
break
case "off":
device.off()
break
default:
httpError(403, "Access denied. This command is not supported by current capability.")
}
}
}
}

View File

@@ -58,7 +58,7 @@ def authPage() {
if (canInstallLabs()) {
def redirectUrl = getBuildRedirectUrl()
log.debug "Redirect url = ${redirectUrl}"
// log.debug "Redirect url = ${redirectUrl}"
if (state.authToken) {
description = "Tap 'Next' to proceed"
@@ -113,13 +113,13 @@ def oauthInitUrl() {
scope: "read_station"
]
log.debug "REDIRECT URL: ${getVendorAuthPath() + toQueryString(oauthParams)}"
// log.debug "REDIRECT URL: ${getVendorAuthPath() + toQueryString(oauthParams)}"
redirect (location: getVendorAuthPath() + toQueryString(oauthParams))
}
def callback() {
log.debug "callback()>> params: $params, params.code ${params.code}"
// log.debug "callback()>> params: $params, params.code ${params.code}"
def code = params.code
def oauthState = params.state
@@ -135,7 +135,7 @@ def callback() {
scope: "read_station"
]
log.debug "TOKEN URL: ${getVendorTokenPath() + toQueryString(tokenParams)}"
// log.debug "TOKEN URL: ${getVendorTokenPath() + toQueryString(tokenParams)}"
def tokenUrl = getVendorTokenPath()
def params = [
@@ -144,7 +144,7 @@ def callback() {
body: tokenParams
]
log.debug "PARAMS: ${params}"
// log.debug "PARAMS: ${params}"
httpPost(params) { resp ->
@@ -156,7 +156,7 @@ def callback() {
state.refreshToken = data.refresh_token
state.authToken = data.access_token
state.tokenExpires = now() + (data.expires_in * 1000)
log.debug "swapped token: $resp.data"
// log.debug "swapped token: $resp.data"
}
}
@@ -292,7 +292,7 @@ def refreshToken() {
response.data.each {key, value ->
def data = slurper.parseText(key);
log.debug "Data: $data"
// log.debug "Data: $data"
state.refreshToken = data.refresh_token
state.accessToken = data.access_token

View File

@@ -78,7 +78,7 @@ def humidityHandler(evt) {
log.debug "Notification already sent within the last ${deltaMinutes} minutes"
} else {
log.debug "Humidity Rose Above ${tooHumid}: sending SMS to $phone1 and activating ${mySwitch}"
log.debug "Humidity Rose Above ${tooHumid}: sending SMS and activating ${mySwitch}"
send("${humiditySensor1.label} sensed high humidity level of ${evt.value}")
switch1?.on()
}
@@ -91,7 +91,7 @@ def humidityHandler(evt) {
log.debug "Notification already sent within the last ${deltaMinutes} minutes"
} else {
log.debug "Humidity Fell Below ${notHumidEnough}: sending SMS to $phone1 and activating ${mySwitch}"
log.debug "Humidity Fell Below ${notHumidEnough}: sending SMS and activating ${mySwitch}"
send("${humiditySensor1.label} sensed high humidity level of ${evt.value}")
switch1?.off()
}

Some files were not shown because too many files have changed in this diff Show More