Compare commits

...

158 Commits

Author SHA1 Message Date
Richard Goldberg b63f07ab42 MSA-1818: Yamaha Receiver and Zones 2017-03-04 07:54:50 -08:00
Vinay Rao a777c298ca Merge pull request #1743 from dbradmit/shabbat-zipcode-fix
Update shabbat-and-holiday-modes.groovy
2017-03-03 04:04:00 -08:00
Vinay Rao 65ae2c0ddf Merge pull request #1736 from SmartThingsCommunity/staging
Rolling down staging to master
2017-03-01 11:02:45 -08:00
Vinay Rao 7e806275ce Merge pull request #1735 from SmartThingsCommunity/revert-1071-MSA-1408-1
Revert "MSA-1408: initial submission for Curb"
2017-03-01 11:02:15 -08:00
Vinay Rao 1ed57aab45 Revert "MSA-1408: initial submission for Curb" 2017-03-01 11:01:00 -08:00
Vinay Rao 4eea7ff90f Merge pull request #1731 from tpmanley/bugfix/motion-reporting
DVCSMP-2484 smartsense-motion-sensor: fix motion event reporting for some devices
2017-03-01 09:37:00 -08:00
Vinay Rao b2264538c9 Merge pull request #1733 from SmartThingsCommunity/master
Rolling up master to staging
2017-03-01 07:57:20 -08:00
Vinay Rao 2f786f7ecd Merge pull request #1732 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2017-03-01 07:56:42 -08:00
Tom Manley f45ab69045 smartsense-motion-sensor: fix motion event reporting for some devices
The motion event reporting for any device that used the Occupancy Sensor
cluster for reporting motion was broken. I'm not sure if any devices using
this DTH actually use this cluster. I think all the officially supported
devices report motion throug the IAS Zone cluster.

https://smartthings.atlassian.net/browse/DVCSMP-2484
2017-03-01 09:31:01 -06:00
Vinay Rao 91762f6a46 Merge pull request #1730 from workingmonk/bug/osram_wemo_dimming
ICP-375 Dimming level reporting with osram and wemo f/w bug
2017-02-28 14:36:05 -08:00
Vinay Rao b55c650637 ICP-375 Dimming level reporting with osram and wemo f/w bug 2017-02-28 14:29:02 -08:00
Vinay Rao e391ee5f53 Merge pull request #1729 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2017-02-28 14:12:17 -08:00
Jack Chi 7b1b9a46bc Merge pull request #1725 from pchomal/dth_ux_page5
[DVCSMP-2444] Standardize Page 5 of DTH UX Improvements
2017-02-28 08:50:54 -08:00
Jack Chi a9a0d296ee Merge pull request #1724 from pchomal/dth_ux_page4
[DVCSMP-2443] Standardize Page 4 of DTH UX Improvements
2017-02-28 08:50:37 -08:00
Jack Chi 905096b381 Merge pull request #1723 from pchomal/dth_ux_page3
[DVCSMP-2442] Standardize Page 3 of DTH UX Improvements
2017-02-28 08:46:45 -08:00
Jack Chi e23bed148d Merge pull request #1700 from parijatdas/dth_ux_page13
[DVCSMP-2452] Standardize Page 13 of DTH UX Improvements
2017-02-28 08:45:53 -08:00
Jack Chi 3b7dd3dd91 Merge pull request #1698 from parijatdas/dth_ux_page12
[DVCSMP-2451] Standardize Page 12 of DTH UX Improvements
2017-02-28 08:45:31 -08:00
Jack Chi ca404bc2a2 Merge pull request #1697 from parijatdas/dth_ux_page11
[DVCSMP-2450] Standardize Page 11 of DTH UX Improvements
2017-02-28 08:44:09 -08:00
Jack Chi 44702cd5fe Merge pull request #1695 from pchomal/dth_ux_page2
[DVCSMP-2441] Standardize Page 2 of DTH UX Improvements
2017-02-28 08:43:55 -08:00
Jack Chi 993f8199d6 Merge pull request #1665 from skt123/readme
[CHF-523] Added Readme files for DTHs
2017-02-28 08:43:02 -08:00
Jack Chi ccfe5dabdf Merge pull request #1685 from skt123/dth_ux_6
[DVCSMP-2445] Standardize Page 6 of DTH UX Improvements
2017-02-28 08:41:11 -08:00
Jack Chi f054cb4de1 Merge pull request #1696 from skt123/dth_ux_7
[DVCSMP-2446] Standardize Page 7 of DTH UX Improvements
2017-02-28 08:40:03 -08:00
Jack Chi d47a4de072 Merge pull request #1720 from skt123/dth_ux_8
[DVCSMP-2447] Standardize Page 8 of DTH UX Improvements
2017-02-28 08:39:39 -08:00
Jack Chi 4c5787fff0 Merge pull request #1721 from skt123/dth_ux_9
[DVCSMP-2448] Standardize Page 9 of DTH UX Improvements
2017-02-28 08:31:40 -08:00
Jack Chi b2f90954ae Merge pull request #1722 from skt123/dth_ux_10
[DVCSMP-2449] Standardize Page 10 of DTH UX Improvements
2017-02-28 08:30:16 -08:00
Tom Manley 8a9c38d38e Merge pull request #1726 from tpmanley/feature/motionv5-fingerprint
DVCSMP-2481 Add fingerprint for motionv5
2017-02-28 10:14:09 -06:00
Tom Manley 28c0cc9619 Add fingerprint for motionv5
https://smartthings.atlassian.net/browse/DVCSMP-2481
2017-02-28 09:53:09 -06:00
piyush.c cb6304530e [DVCSMP-2442] Standardize Page 3 of DTH UX Improvements 2017-02-28 19:12:34 +05:30
piyush.c fe5a965f6f [DVCSMP-2444] Standardize Page 5 of DTH UX Improvements 2017-02-28 19:07:03 +05:30
piyush.c 72c75882cf [DVCSMP-2443] Standardize Page 4 of DTH UX Improvements 2017-02-28 18:32:02 +05:30
sushant.k1 a006799ad3 [DVCSMP-2449]
DTH UX Improvements for the following DTHs:
1. Hue Bulb
2. Lifx Color Bulb
3. Lifx White Bulb
4. Smartpower Outlet
5. Zigbee Dimmer Power
6. ZLL RGBW Bulb
7. ZLL White Color Temperature Bulb
2017-02-28 17:35:31 +05:30
sushant.k1 2610f00a82 [DVCSMP-2448]
DTH UX Improvements for the following DTHs:
1. Aeon Illuminator Module
2. Foscam
3. Secure Dimmer
4. WeMo Bulb
5. Z- wave Metering Dimmer
6. TCP Bulb
2017-02-28 17:23:13 +05:30
sushant.k1 6381580e44 [DVCSMP-2447]
DTH UX Improvements for the following DTHs:
1. Harmony Activity
2. Hue Bridge
3. Smartsense Garage Door Multi
4. Smartsense Garage Door Sensor Button
5. WeMo Motion
6. ZigBee Dimmer
7. ZigBee RGB Bulb
8. ZigBee Lock
9. ZLL RGB Bulb
10. Smart Block
2017-02-28 16:22:14 +05:30
Jack Chi 79aebafdc4 Merge pull request #1694 from pchomal/dth_ux_page1
[DVCSMP-2438] Standardize Page 1 of DTH UX Improvements
2017-02-27 21:09:27 -08:00
Jason Botello 1c83a27c40 DVCSMP-2475 Netatmo Fixes (#1717)
- Adds logic to invalidate auth tokens
- Adds checks for auth tokens before making API requests
- Improves SmartApp logic to fix execution timeout exceptions
- Improves refresh token logic
- Fixes API response parsing bugs
- Adds auth and refresh token to atomicState rather than state
- Preference / OAuth wording changes
2017-02-27 11:51:06 -08:00
Ryan Applegate 4a66eca03c Merge pull request #1715 from rappleg/AddJitterToArrivalSensorHA
DVCSMP-2474 Arrival Sensor HA schedule needs jitter to avoid all firing at top of minute
2017-02-26 18:35:59 -06:00
rappleg 31c037e7ab DVCSMP-2474 Arrival Sensor HA schedule needs jitter to avoid all firing at top of minute 2017-02-25 11:05:08 -06:00
bflorian d6c85436d2 Merge pull request #1714 from juano2310/translate
nb-NO to no-NO
2017-02-24 15:33:12 -05:00
juano2310 e822e7137e nb-NO to no-NO 2017-02-24 15:30:24 -05:00
bflorian 967e1798d5 Merge pull request #1713 from juano2310/translate
Rename from _ to -
2017-02-24 14:57:46 -05:00
juano2310 6ef49e92bb Rename from _ to - 2017-02-24 14:06:50 -05:00
Vinay Rao e528b61ace Merge pull request #1705 from juano2310/translate
DVCSMP-2288 - DVCSMP-2290 - Localization
2017-02-23 19:08:32 -08:00
SmartThings, Inc a192b75e4c Merge pull request #1071 from SmartThingsCommunity/MSA-1408-1
Merged publication request 'initial submission for Curb'
2017-02-23 14:39:32 -08:00
Vinay Rao f97a0a4072 Merge pull request #1710 from SmartThingsCommunity/staging
Rolling down staging to master
2017-02-23 11:51:47 -08:00
Vinay Rao dd0aba3dc9 Merge pull request #1708 from workingmonk/bug/wemo_dimmer
ICP-375 CON-90 fix for wemo dimming issue
2017-02-23 11:43:45 -08:00
Vinay Rao e787afd165 updated with more devices 2017-02-23 11:31:49 -08:00
Vinay Rao 12be259779 CON-90 fix for wemo dimming issue 2017-02-23 02:41:20 -08:00
piyush.c 379e70b343 [DVCSMP-2441] Standardize Page 2 of DTH UX Improvements 2017-02-23 14:50:30 +05:30
Vinay Rao 9cb0ce716b Merge pull request #1707 from SmartThingsCommunity/master
Rolling up master to staging
2017-02-22 13:53:53 -08:00
juano2310 400c55f4ba DVCSMP-2288 - DVCSMP-2290 - Localization 2017-02-22 11:18:59 -05:00
Vinay Rao 023b9aad2d Merge pull request #1704 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2017-02-21 12:44:13 -08:00
Vinay Rao ccb7b6e49d Merge pull request #1703 from scottvlaminck/hue_bridge_use_bridge_cap
CON-79 Update Hue Bridge to use new Bridge marker capability
2017-02-21 12:29:28 -08:00
Scott Vlaminck 34f77a2989 update Hue Bridge to use new Bridge marker capability 2017-02-21 13:42:19 -06:00
Vinay Rao 318cdedaec Merge pull request #1702 from scottvlaminck/add_outlet_capability
add Outlet capability
2017-02-21 10:28:12 -08:00
Jack Chi 011a5ddc74 Merge pull request #1607 from jackchi/hue-enrollment-fix
[CHF-508] Hue bulbs hides enrollment events
2017-02-21 10:13:45 -08:00
Scott Vlaminck 649ed033d0 add Outlet capability 2017-02-21 11:07:51 -06:00
Parijat Das e687e76b3e DTH UX Improvements for Page 13 of DTHs:
From Rgbw-Light... to ...Smartsense-Virtual-Open-Closed
2017-02-21 11:28:27 +05:30
Parijat Das 1d2fe8af22 DTH UX Improvements for Page 12 of DTHs:
From ZWave-Relay... to ...Pet-feeder-shield
2017-02-20 18:41:46 +05:30
sushant.k1 6e94220e9e [DVCSMP-2446]
DTH UX Improvements for the following DTHs:
1. Cree Bulb
2. ZigBee Switch Power
3. Ecobee Sensor
4. Mobile Presence
5. On-Off Shield
6. Life360 User
7. WeMo Light Switch
8. Coopboss h3vx
9. Smartsense Moisture
2017-02-20 18:08:12 +05:30
Parijat Das e54a8644c3 DTH UX Improvements for Page 11 of DTHs:
From Danalock ... to ...ZWave-Virtual-MomentaryContactSwitch
2017-02-20 17:39:27 +05:30
piyush.c 0d4b681971 [DVCSMP-2438] Standardize Page 1 of DTH UX Improvements 2017-02-20 15:35:27 +05:30
sushant.k1 0aabce9fa3 [DVCSMP-2445]
DTH UX Improvements for the following DTHs:
1. Quirky Wink Powerstrip
2. Momentary Button Tile
3. Beaconthing
4. Unknown
5. Zwave Water Valve
6. Zen Thermostat
7. Zigbee Valve
8. Hue Bloom
2017-02-17 18:21:16 +05:30
Vinay Rao 843d8800ac Merge pull request #1662 from juano2310/LIFX_exceptions
DVCSMP-2425 - LIFX Exceptions
2017-02-15 15:24:24 -08:00
juano2310 bcc680ee5d DVCSMP-2425 - LIFX Exceptions
Adding comment
2017-02-15 18:21:26 -05:00
Vinay Rao 245e85f850 Merge pull request #1680 from varzac/fix-smartpower-outlet-power-usage
[PROB-1518] Properly create event for outlet power
2017-02-15 14:11:05 -08:00
Vinay Rao af16720528 Merge pull request #1681 from SmartThingsCommunity/master
Rolling up master to staging
2017-02-15 13:58:58 -08:00
Zach Varberg c6d6ba85f5 Properly create event for outlet power
We were not properly creating the event before returning it, causing us
to not actually generate the power event.

This resolves: https://smartthings.atlassian.net/browse/PROB-1518
2017-02-15 13:49:47 -06:00
Jack Chi 51832c8db2 Merge pull request #1671 from skt123/zwave_device_filtering
[DVCSMP-2433] Device Filtering change for Z-wave devices
2017-02-14 15:14:07 -08:00
Jack Chi f001eb0792 Merge pull request #1672 from pchomal/devicefiltering1
[DVCSMP-2431] DTH Device Filtering change for ZigBee Devices
2017-02-14 15:13:26 -08:00
Vinay Rao 81550ee25c Merge pull request #1673 from larsfinander/ICP-280_Instruction_for_Phlips_Hue_staging
ICP-280 Instruction for Phlips Hue
2017-02-14 13:58:38 -08:00
Vinay Rao 1cc9d8a90b Merge pull request #1675 from SmartThingsCommunity/master
Rolling up master to staging
2017-02-14 12:11:03 -08:00
Lars Finander 9b6e7d3be8 ICP-280 Instruction for Phlips Hue
-Added instructions to tell user to setup in Hue app first
-Fix a null printout and some whitespace
2017-02-14 11:23:27 -07:00
piyush.c 7c5734b752 [DVCSMP-2431] DTH Device Filtering change for ZigBee Devices 2017-02-14 15:26:50 +05:30
Jack Chi 2a3c393534 Merge pull request #1670 from pchomal/devicefiltering1
[DVCSMP-2436] DTH Device Filtering change for Lifx Bulbs
2017-02-14 01:53:48 -08:00
Jack Chi 91763e7b4d Merge pull request #1591 from parijatdas/leviton_receptacle
[CHF-504] [CHF-505] Implementation of HealthCheck for Leviton 5A Incandescent Switch (VRS05-1LZ) and Leviton 15A Split Duplex Receptacle (VRR15-1LZ)
2017-02-14 01:52:34 -08:00
sushant.k1 1263b72a72 [DVCSMP-2433]
Adding "Light" capability to the following Z-wave DTHs:
1. Z-Wave Metering Dimmer
2. Z-Wave Metering Switch
3. Z-Wave Dimmer Switch Generic
4. Z-Wave Switch
5. Z-Wave Switch Generic
6. MimoLite Garage Door Controller
2017-02-14 15:13:28 +05:30
piyush.c bf45430061 [DVCSMP-2436] DTH Device Filtering change for Lifx Bulbs 2017-02-14 15:01:17 +05:30
Jack Chi 054ccbeffe Merge pull request #1590 from pchomal/dimmerswitch_generic
[CHF-477] Health Check implementation for Z-Wave Dimmer Switch Generic
2017-02-13 14:22:54 -08:00
sushant.k1 5cb84a269d [CHF-523]
Adding Readme files for the following DTH:

1. Z-Wave Switch Generic
a) Leviton 15A Switch VRS15-1LZ (Z-Wave)
b) Enerwave Duplex Receptacle ZW15R (Z-Wave)
c) Enerwave On/Off Switch ZW15S (Z-Wave)

2. Dimmer Switch
a) 1,000-Watt In-Wall Smart Dimmer Switch (GE 12725)
b) In-Wall Smart Fan Control (GE 12730)

3. ZigBee RGB Bulb
a) OSRAM LIGHTIFY Gardenspot mini RGB

4. ZigBee RGBW Bulb
a) OSRAM LIGHTIFY Flex RGBW strips
2017-02-13 16:21:24 +05:30
piyush.c 6e28d83e96 [CHF-477]
Health Check implementation for Z-Wave Dimmer Switch Generic
2017-02-13 12:36:32 +05:30
Vinay Rao 2d82b05f90 Merge pull request #1660 from SmartThingsCommunity/staging
Rolling down staging hotfixes to master
2017-02-09 17:54:06 -06:00
Vinay Rao 1611fd0144 Merge pull request #1640 from skt123/device_filtering_1
[CHANGE-840] Adding new capabilities to DTHs
2017-02-09 17:51:50 -06:00
Vinay Rao c416c39ac4 Merge pull request #1639 from pchomal/devicefiltering1
[CHANGE-839] Adding New Capabilities (Light & Outlet)
2017-02-09 17:51:19 -06:00
Vinay Rao bc0f849dad Merge pull request #1655 from SmartThingsCommunity/master
Rolling up master to staging
2017-02-07 14:24:23 -08:00
Vinay Rao 459e69607b Merge pull request #1654 from SmartThingsCommunity/staging
Rolling down staging to master
2017-02-07 14:23:24 -08:00
Juan Pablo Risso cfdc61d72a DVCSMP-2290 - Ecobee Localization (#1628)
Split Files

Updated
2017-02-07 14:11:38 -06:00
Zach Varberg 0c26d75792 Merge pull request #1652 from varzac/dimmer-fixes
DPROT-242 Properly handle setLevel for zigbee-dimmer
2017-02-07 13:07:30 -06:00
Zach Varberg bf491270a9 Properly handle setLevel for zigbee-dimmer
This works around a few devices that use this DTH that do not properly
handle the setLevel command.

This resolves: https://smartthings.atlassian.net/browse/DPROT-242
2017-02-07 13:06:26 -06:00
Vinay Rao 871d75aea6 Merge pull request #1650 from larsfinander/DVCSMP-2395_Update_OPenT2T_staging
DVCSMP-2395 Update OpenT2T with bugfixes
2017-02-06 11:44:13 -08:00
Lars Finander 3905d48235 DVCSMP-2395 Update OpenT2T with bugfixes 2017-02-06 12:34:00 -07:00
Vinay Rao d91c02b970 Merge pull request #1644 from varzac/fix-zigbee-dimmer-set-level
DPROT-238 Fix typo on toInteger zigbee dimmer power
2017-02-03 16:35:48 -08:00
Zach Varberg e019d22aff Fix typo on toInteger zigbee dimmer power
This relates to: https://smartthings.atlassian.net/browse/DPROT-238
2017-02-03 16:22:20 -06:00
Vinay Rao 900ab9f70e Merge pull request #1638 from dkirker/DEVC-488
DEVC-488 Add fingerprint for DL15S In-wall Switch
2017-02-03 13:53:48 -08:00
Vinay Rao a8f95cc0b9 Merge pull request #1636 from workingmonk/bug/zigbee_button_iris
DVCSMP-2391 Iris 4 button device mapping to button 1 only
2017-02-03 13:51:07 -08:00
Vinay Rao e8d205c775 Merge pull request #1643 from varzac/fix-zigbee-dimmer-set-level
[DPROT-238] Manually call on with setLevel
2017-02-03 13:14:14 -08:00
Zach Varberg 06e4b7d9f0 Merge pull request #1507 from varzac/remove-deprecated-zonetype19
[DPROT-167] Remove calls to ZoneType19 methods
2017-02-03 13:46:40 -06:00
Zach Varberg 16d7da81f1 Remove calls to ZoneType19 methods
We want to move toward the deprecation of these methods, and it starts
with the removal of calls to those methods from our DTHs.

This relates to: https://smartthings.atlassian.net/browse/DPROT-167
2017-02-03 13:37:25 -06:00
Zach Varberg 1800ea2bad Manually call on with setLevel
This is to work around misbehaving devices that don't properly honor the
move to level with on off command.

This resolves: https://smartthings.atlassian.net/browse/DPROT-238
2017-02-03 13:01:05 -06:00
sushant.k1 f164b8832c [CHANGE-840]
Added new capabilities for following DTHs:
1. Dimmer Switch
2. Zigbee RGB Bulb
3. Zigbee Dimmer
2017-02-03 16:33:30 +05:30
piyush.c 2d3fa22e07 [CHANGE-839]
Adding New Capabilities (Light & Outlet) to the DTHs
2017-02-03 16:22:56 +05:30
Donald Kirker 54a4620c9b DEVC-488 Add fingerprint for DL15S In-wall Switch 2017-02-02 22:00:49 -08:00
Vinay Rao 8e6d009d67 changes suggested by Tom and Zach 2017-02-02 18:52:23 -08:00
Vinay Rao d8c89f6c6a DVCSMP-2391 Iris 4 button device mapping to button 1 only 2017-02-02 18:10:34 -08:00
Vinay Rao ddc15172d6 Merge pull request #1635 from SmartThingsCommunity/staging
Rolling down staging to master
2017-02-02 12:54:22 -08:00
Vinay Rao c27904acfb Merge pull request #1377 from varzac/update-dths-zigbee-library
[DPROT-183, DPROT-217, DPROT-221, DVCSMP-2250] Update dths zigbee library
2017-02-02 11:57:28 -08:00
Zach Varberg 1e02387387 Update to use multi attr parsing in zigbee library
With the addition of the ability for parseDescriptionAsMap to hanle the
return of multiple read attribute responses, we can be a little more
explicit with how we interpret and parse the responses.
2017-02-01 09:12:17 -06:00
Zach Varberg 65d4a811b0 Clean up smartsense DTHs
This continues an effort to clean up the SmartSense DTHs and move as
much of the logic as possible into the library.  This simplifies the DTH
and has the advantage of having only a single location where issues need
to be fixed.
2017-02-01 09:12:15 -06:00
Zach Varberg db4f161e5d Update DTHs to use zigbee library
This change updates the core DTHs to use the
zigbee library where appropriate instead of having its own zigbee
command strings.
2017-02-01 09:08:08 -06:00
Vinay Rao ff6e543a2e Merge pull request #1631 from SmartThingsCommunity/master
Rolling up master to staging for next week deploy
2017-01-31 13:48:38 -08:00
Vinay Rao de1894bfbf Merge pull request #1630 from SmartThingsCommunity/staging
Rolling down staging to master
2017-01-31 13:47:45 -08:00
Jason Botello d0f8ec87bd Merge pull request #1616 from jasonbio/plantlink-exceptions
Plant link Exceptions
2017-01-30 15:01:18 -08:00
Jason Botello 1383ab1e07 Merge pull request #1615 from jasonbio/netatmo-exceptions
Netatmo Exceptions
2017-01-30 15:01:05 -08:00
Vinay Rao d4f21b95d7 Merge pull request #1621 from varzac/zll-bulb-reporting
[DPROT-227] Manually refresh on/off status after setLevel
2017-01-27 16:37:34 -08:00
Zach Varberg be2e19e406 Manually refresh on/off status after setLevel
This is because ZLL bulbs do not report or allow for configuration of
reporting of attributes.  As a result if we change a value, we have to
manually call a read of that attribute to update our status.

This is a part of: https://smartthings.atlassian.net/browse/DPROT-227
2017-01-26 11:27:51 -06:00
Vinay Rao 54da556c17 Merge pull request #1620 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2017-01-25 15:48:58 -08:00
Vinay Rao 8611d2e2d2 Merge pull request #1618 from workingmonk/feature/light_capability
ICP-203 Adding Light Capability to hue lights
2017-01-25 04:13:47 -08:00
Vinay Rao c650047f31 ICP-203 Adding Light Capability to hue lights 2017-01-25 04:12:42 -08:00
dbradmit a15ca97988 Update shabbat-and-holiday-modes.groovy 2017-01-24 19:16:10 -07:00
Jason Botello 41adc9777a Plant link Exceptions
Adding try/catch blocks to reduce HTTP exceptions due to rate limits or
unauthorized errors.
2017-01-24 14:53:23 -08:00
Jason Botello f334f6505a Netatmo Exceptions
Adding try/catch blocks to reduce HTTP exceptions due to rate limits or
unauthorized errors. Also updating the “devicelist” endpoint to
“getstationdata” as the former is deprecated
2017-01-24 14:30:59 -08:00
Vinay Rao ded7501b84 Merge pull request #1614 from SmartThingsCommunity/master
Rolling up master to staging
2017-01-24 13:21:44 -08:00
Vinay Rao eb4d5dcfb8 Merge pull request #1613 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2017-01-24 13:19:33 -08:00
Vinay Rao 6385443f20 Merge pull request #1612 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2017-01-24 12:48:34 -08:00
Vinay Rao fd1ad51880 Merge branch 'staging' into production 2017-01-24 12:48:21 -08:00
Vinay Rao 550214ceb5 Merge pull request #1610 from dkirker/DEVC-490
DEVC-490: Add Leviton Dimmer DL1KD fingerprint
2017-01-23 11:53:01 -08:00
Donald Kirker a36500a216 DEVC-490: Add Leviton Dimmer DL1KD fingerprint 2017-01-23 11:45:05 -08:00
Juan Pablo Risso 445c115c14 DVCSMP-2324 - Centralite Thermostat handle multiple attributes (#1606)
- Curly braces
- remove parseDescriptionAsMap
- descMap to it
- Appended to the result list
- Convert to list and appended
2017-01-20 17:49:15 -05:00
bflorian 9900e532a4 Merge pull request #1608 from juano2310/sim_fix
DVCSMP-2325 - Remove parse method from simulated Switch
2017-01-20 14:27:08 -08:00
juano2310 7648fd4a17 DVCSMP-2325 - Remove parse method from simulated Switch
sin string
2017-01-20 17:22:10 -05:00
jackchi a5d0c1d80a [CHF-508] Hue bulbs hides enrollment events 2017-01-20 11:33:14 -08:00
Vinay Rao 9686f3770b Merge pull request #1604 from workingmonk/feature/device_lab_cert_work
DEVC-492 DEVC-493 DEVC-494 DEVC-526 Device Certification approved new fingerprints
2017-01-19 15:02:07 -08:00
Vinay Rao de37d0c813 Device Certification approved new fingerprints 2017-01-19 14:38:59 -08:00
Vinay Rao bd3367fe0e Merge pull request #1598 from SmartThingsCommunity/staging
Rolling down staging to master
2017-01-18 15:18:08 -08:00
Vinay Rao 30511d74af Merge pull request #1597 from SmartThingsCommunity/staging
Rolling up staging to production
2017-01-18 13:27:50 -08:00
Vinay Rao f0f02a2c00 Merge pull request #1596 from SmartThingsCommunity/production
Rolling down production to staging
2017-01-18 13:26:38 -08:00
Parijat Das 61356ec8a7 Added fingerprints for the following devices:
1. Leviton 5A Incandescent Switch (VRS05-1LZ)
2. Leviton 15A Split Duplex Receptacle (VRR15-1LZ)
2017-01-17 19:17:41 +05:30
Vinay Rao 57d20e2fca Merge pull request #1575 from larsfinander/DVCSMP-2298_Philips_Hue_Reduce_daily_exceptions_staging
DVCSMP-2298 Philips Hue: Reduce number of daily exceptions
2017-01-12 11:14:01 -08:00
Vinay Rao 3216f63cc0 Merge pull request #1581 from larsfinander/MSA-1577_OpenT2T_staging
MSA-1577: OpenT2T
2017-01-11 15:59:25 -08:00
Vinay Rao 7cbc2d1780 Merge pull request #1585 from SmartThingsCommunity/master
Rolling up master to staging
2017-01-10 16:25:33 -08:00
Vinay Rao 5ad20fbd2a Merge pull request #1584 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2017-01-10 16:08:36 -08:00
Vinay Rao a17971d68c Merge pull request #1583 from SmartThingsCommunity/staging
Rolling up staging to production for deploy
2017-01-10 15:01:44 -08:00
Vinay Rao 076ffecd19 Merge pull request #1582 from SmartThingsCommunity/production
Rolling down production hotfix to staging
2017-01-10 15:00:27 -08:00
Duncan McKee 52357e4c50 Merge pull request #1580 from SmartThingsCommunity/DEVC-533
Add fingerprint for GE Smart Motion Sensor DEVC-533
2017-01-10 16:40:43 -05:00
Lars Finander 03a7991279 MSA-1577: OpenT2T
This SmartApp enables the end-to-end SmartThings scenarios
via OpenT2T. More information on OpenT2T can be found at
http://www.opentranslatorstothings.org/#/
2017-01-10 12:32:49 -07:00
Duncan McKee f969027191 Add fingerprint for GE Smart Motion Sensor DEVC-533 2017-01-10 12:55:13 -05:00
Vinay Rao 8db0556696 Merge pull request #1562 from varzac/increase-delays
DPROT-223 Increase zigbee message delays
2017-01-10 09:35:46 -08:00
Juan Pablo Risso 5607a3e346 DVCSMP-2309 - Wemo Exceptions (#1579) 2017-01-10 12:29:53 -05:00
Lars Finander bd44027038 DVCSMP-2298 Philips Hue: Reduce number of daily exceptions
-Stop retry when broken data received
-Time out on light discovery if nothing is found
-Avoid div/0 in color temp logic
2017-01-09 15:32:01 -07:00
Vinay Rao 490ec329cb Merge pull request #1570 from workingmonk/feature/iris_button
DEVC-520 DEVC-525 Adding Iris Button after clearing certification
2017-01-06 09:34:49 -08:00
Vinay Rao 3109049122 Merge pull request #1569 from workingmonk/feature/certification_work
DEVC-518 Iris Smart Water Sensor
2017-01-06 09:34:25 -08:00
Zach Varberg 930c4ed914 Increase zigbee message delays
This changes our smartsense DTHs that don't use the ZigBee library for
everything to have larger delays between ZigBee messages.  This is to
reduce the network load to try to work around some of the poorer
behaving ZigBee routers we support.

This resolves: https://smartthings.atlassian.net/browse/DPROT-223
2017-01-06 10:45:13 -06:00
Vinay Rao 259516f21f DEVC-520 DEVC-525 Adding Iris Button after clearing certification 2017-01-05 16:54:46 -08:00
Vinay Rao b7a08a88e0 DEVC-518 Iris Smart Water Sensor 2017-01-05 16:41:50 -08:00
bflorian 76e139153a Merge pull request #1532 from tslagle13/fix-color-coordinator-NPE
[DVCSMP-2273] Fix for NPE for slave/master settings
2016-12-15 17:11:01 -05:00
tslagle13 a4bc248006 One further fix for NPEs 2016-12-14 11:40:02 -08:00
tslagle13 e7eb461b4e [DVCSMP-2273] Fix for NPE for slave/master settings 2016-12-13 14:37:49 -08:00
Vinay Rao 083ed7cc9a Merge pull request #1518 from SmartThingsCommunity/staging
Rolling up staging to prod for deploy
2016-12-07 12:41:33 -08:00
Curb Operations 1674dc7339 MSA-1408: it exposes a customer's smart thing switches, and allows the user to toggle them from the Curb app. 2016-07-22 10:39:53 -05:00
205 changed files with 3376 additions and 2193 deletions
@@ -23,8 +23,8 @@ metadata {
tiles {
standardTile("acceleration", "device.acceleration", width: 2, height: 2) {
state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff")
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0")
state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#cccccc")
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#00A0DC")
}
main "acceleration"
@@ -23,8 +23,8 @@ metadata {
tiles {
standardTile("contact", "device.contact", width: 2, height: 2) {
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00A0DC")
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13")
}
main "contact"
details "contact"
@@ -27,7 +27,7 @@ metadata {
tiles {
standardTile("toggle", "device.lock", width: 2, height: 2) {
state "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff"
state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#79b821"
state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#00A0DC"
}
standardTile("lock", "device.lock", inactiveLabel: false, decoration: "flat") {
state "default", label:'lock', action:"lock.lock", icon:"st.locks.lock.locked"
@@ -29,7 +29,7 @@ metadata {
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "on"
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
}
main "switch"
details "switch"
@@ -24,7 +24,7 @@ metadata {
tiles {
standardTile("motion", "device.motion", width: 2, height: 2) {
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff")
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0")
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC")
}
main "motion"
details "motion"
@@ -24,7 +24,7 @@ metadata {
tiles {
standardTile("presence", "device.presence", width: 2, height: 2) {
state("not present", label:'not present', icon:"st.presence.tile.not-present", backgroundColor:"#ffffff")
state("present", label:'present', icon:"st.presence.tile.present", backgroundColor:"#53a7c0")
state("present", label:'present', icon:"st.presence.tile.present", backgroundColor:"#00A0DC")
}
main "presence"
details "presence"
@@ -31,7 +31,7 @@ metadata {
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
}
main "switch"
details "switch"
@@ -35,8 +35,8 @@ metadata {
tiles {
standardTile("switch", "device.switch", width: 2, height: 2) {
state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
state "turningOn", label:'${name}', icon:"st.switches.switch.on", backgroundColor:"#79b821"
state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff"
state "turningOn", label:'${name}', icon:"st.switches.switch.on", backgroundColor:"#00A0DC"
state "turningOff", label:'${name}', icon:"st.switches.switch.off", backgroundColor:"#ffffff"
}
controlTile("levelSliderControl", "device.level", "slider", height: 2, width: 1, inactiveLabel: false) {
@@ -79,8 +79,8 @@ metadata {
standardTile("mode", "device.thermostatMode", inactiveLabel: false, decoration: "flat") {
state "off", label:'${name}', action:"thermostat.emergencyHeat", backgroundColor:"#ffffff"
state "emergencyHeat", label:'${name}', action:"thermostat.heat", backgroundColor:"#e86d13"
state "heat", label:'${name}', action:"thermostat.cool", backgroundColor:"#ffc000"
state "cool", label:'${name}', action:"thermostat.off", backgroundColor:"#269bd2"
state "heat", label:'${name}', action:"thermostat.cool", backgroundColor:"#e86d13"
state "cool", label:'${name}', action:"thermostat.off", backgroundColor:"#00A0DC"
}
standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false, decoration: "flat") {
state "fanAuto", label:'${name}', action:"thermostat.fanOn", backgroundColor:"#ffffff"
@@ -24,7 +24,7 @@ metadata {
tiles {
standardTile("water", "device.water", width: 2, height: 2) {
state "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
state "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0"
state "wet", icon:"st.alarm.water.wet", backgroundColor:"#00A0DC"
}
main "water"
@@ -37,7 +37,7 @@ metadata {
tiles {
standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) {
state("present", labelIcon:"st.presence.tile.present", backgroundColor:"#53a7c0")
state("present", labelIcon:"st.presence.tile.present", backgroundColor:"#00A0DC")
state("not present", labelIcon:"st.presence.tile.not-present", backgroundColor:"#ffffff")
}
valueTile("inRange", "device.inRangeFriendly", inactiveLabel: true, height:1, width:3, decoration: "flat") {
@@ -38,7 +38,7 @@ metadata {
// Main
standardTile("main", "device.status", width: 1, height: 1, canChangeIcon: true) {
state "paused", label:'Paused', action:"music Player.play", icon:"st.Electronics.electronics19", nextState:"playing", backgroundColor:"#ffffff"
state "playing", label:'Playing', action:"music Player.pause", icon:"st.Electronics.electronics19", nextState:"paused", backgroundColor:"#79b821"
state "playing", label:'Playing', action:"music Player.pause", icon:"st.Electronics.electronics19", nextState:"paused", backgroundColor:"#00A0DC"
}
// Row 1
@@ -34,8 +34,8 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"FGK", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app
tileAttribute("device.contact", key:"PRIMARY_CONTROL") {
attributeState("open", icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
attributeState("closed", icon:"st.contact.contact.closed", backgroundColor:"#79b821")
attributeState("open", icon:"st.contact.contact.open", backgroundColor:"#e86d13")
attributeState("closed", icon:"st.contact.contact.closed", backgroundColor:"#00a0dc")
}
tileAttribute("device.tamper", key:"SECONDARY_CONTROL") {
@@ -44,7 +44,7 @@ metadata {
}
}
valueTile("battery", "device.battery", inactiveLabel: false, , width: 2, height: 2, decoration: "flat") {
valueTile("battery", "device.battery", inactiveLabel: false, width: 2, height: 2, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""
}
@@ -31,8 +31,8 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"FGK", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app
tileAttribute("device.contact", key:"PRIMARY_CONTROL") {
attributeState("open", icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
attributeState("closed", icon:"st.contact.contact.closed", backgroundColor:"#79b821")
attributeState("open", icon:"st.contact.contact.open", backgroundColor:"#e86d13")
attributeState("closed", icon:"st.contact.contact.closed", backgroundColor:"#00a0dc")
}
tileAttribute("device.tamper", key:"SECONDARY_CONTROL") {
@@ -41,7 +41,7 @@ metadata {
}
}
valueTile("battery", "device.battery", inactiveLabel: false, , width: 2, height: 2, decoration: "flat") {
valueTile("battery", "device.battery", inactiveLabel: false, width: 2, height: 2, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""
}
@@ -32,13 +32,13 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"FGFS", type:"lighting", width:6, height:4) {//with generic type secondary control text is not displayed in Android app
tileAttribute("device.water", key:"PRIMARY_CONTROL") {
attributeState("dry", icon:"st.alarm.water.dry", backgroundColor:"#79b821")
attributeState("wet", icon:"st.alarm.water.wet", backgroundColor:"#ffa81e")
attributeState("dry", icon:"st.alarm.water.dry", backgroundColor:"#00a0dc")
attributeState("wet", icon:"st.alarm.water.wet", backgroundColor:"#e86d13")
}
tileAttribute("device.tamper", key:"SECONDARY_CONTROL") {
attributeState("active", label:'tamper active', backgroundColor:"#53a7c0")
attributeState("inactive", label:'tamper inactive', backgroundColor:"#ffffff")
attributeState("active", label:'tamper active', backgroundColor:"#00a0dc")
attributeState("inactive", label:'tamper inactive', backgroundColor:"#cccccc")
}
}
@@ -38,8 +38,8 @@ metadata {
}
tileAttribute("device.tamper", key:"SECONDARY_CONTROL") {
attributeState("active", label:'tamper active', backgroundColor:"#53a7c0")
attributeState("inactive", label:'tamper inactive', backgroundColor:"#ffffff")
attributeState("active", label:'tamper active', backgroundColor:"#00a0dc")
attributeState("inactive", label:'tamper inactive', backgroundColor:"#cccccc")
}
}
@@ -112,10 +112,10 @@ metadata {
multiAttributeTile(name:"dtlsDoorCtrl", type:"generic", width:6, height:4) {tileAttribute("device.doorState", key: "PRIMARY_CONTROL")
{
attributeState "unknown", label: '${name}', action:"openDoor", icon: "st.secondary.tools", nextState:"Sent"
attributeState "open", label: '${name}', action:"closeDoor", icon: "st.doors.garage.garage-open", backgroundColor: "#0000ff", nextState:"Sent"
attributeState "opening", label: '${name}', action:"closeDoor", icon: "st.doors.garage.garage-opening", backgroundColor: "#ffa81e"
attributeState "closed", label: '${name}', action:"openDoor", icon: "st.doors.garage.garage-closed", backgroundColor: "#79b821", nextState:"Sent"
attributeState "closing", label: '${name}', action:"openDoor", icon: "st.doors.garage.garage-closing", backgroundColor: "#ffa81e"
attributeState "open", label: '${name}', action:"closeDoor", icon: "st.doors.garage.garage-open", backgroundColor: "#00A0DC", nextState:"Sent"
attributeState "opening", label: '${name}', action:"closeDoor", icon: "st.doors.garage.garage-opening", backgroundColor: "#00A0DC"
attributeState "closed", label: '${name}', action:"openDoor", icon: "st.doors.garage.garage-closed", backgroundColor: "#ffffff", nextState:"Sent"
attributeState "closing", label: '${name}', action:"openDoor", icon: "st.doors.garage.garage-closing", backgroundColor: "#ffffff"
attributeState "jammed", label: '${name}', action:"closeDoorHiI", icon: "st.doors.garage.garage-open", backgroundColor: "#ff0000", nextState:"Sent"
attributeState "forced close", label: "forced", action:"openDoor", icon: "st.doors.garage.garage-closed", backgroundColor: "#ff8000", nextState:"Sent"
attributeState "fault", label: 'FAULT', action:"openDoor", icon: "st.secondary.tools", backgroundColor: "#ff0000", nextState:"Sent"
@@ -24,7 +24,7 @@ metadata {
tiles {
standardTile("sleeping", "device.sleeping", width: 1, height: 1, canChangeIcon: false, canChangeBackground: false) {
state("sleeping", label: "Sleeping", icon:"st.Bedroom.bedroom12", backgroundColor:"#ffffff")
state("not sleeping", label: "Awake", icon:"st.Health & Wellness.health12", backgroundColor:"#79b821")
state("not sleeping", label: "Awake", icon:"st.Health & Wellness.health12", backgroundColor:"#00A0DC")
}
standardTile("steps", "device.steps", width: 2, height: 2, canChangeIcon: false, canChangeBackground: false) {
state("steps", label: '${currentValue} Steps', icon:"st.Health & Wellness.health11", backgroundColor:"#ffffff")
@@ -122,13 +122,13 @@ metadata {
state "raintoday", label: 'Rain Today', icon: "st.custom.wuk.nt_chancerain"
state "rainy", label: 'Previous Rain', icon: "st.custom.wuk.nt_chancerain"
state "raintom", label: 'Rain Tomorrow', icon: "st.custom.wuk.nt_chancerain"
state "donewweek", label: 'Spruce Finished', icon: "st.Outdoor.outdoor5", backgroundColor: "#52c435"
state "donewweek", label: 'Spruce Finished', icon: "st.Outdoor.outdoor5", backgroundColor: "#00A0DC"
state "skipping", label: 'Skip Today', icon: "st.Outdoor.outdoor20", backgroundColor: "#36cfe3"
state "moisture", label: '', icon: "st.Weather.weather2", backgroundColor: "#36cfe3"
state "pause", label: 'PAUSE', icon: "st.contact.contact.open", backgroundColor: "#f2a51f"
state "pause", label: 'PAUSE', icon: "st.contact.contact.open", backgroundColor: "#e86d13"
state "active", label: 'Active', icon: "st.Outdoor.outdoor12", backgroundColor: "#3DC72E"
state "season", label: 'Seasonal Adjustment', icon: "st.Outdoor.outdoor17", backgroundColor: "#ffb900"
state "disable", label: 'Disabled', icon: "st.secondary.off", backgroundColor: "#888888"
state "disable", label: 'Disabled', icon: "st.secondary.off", backgroundColor: "#cccccc"
state "warning", label: '', icon: "st.categories.damageAndDanger", backgroundColor: "#ffff7f"
state "alarm", label: 'Alarm', icon: "st.categories.damageAndDanger", backgroundColor: "#f9240c"
}
@@ -144,67 +144,67 @@ metadata {
}
standardTile("switch1", "device.switch1") {
state "z1off", label: '1', action: "z1on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z1on", label: '1', action: "z1off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z1on", label: '1', action: "z1off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch2", "device.switch2") {
state "z2off", label: '2', action: "z2on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z2on", label: '2', action: "z2off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z2on", label: '2', action: "z2off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch3", "device.switch3", inactiveLabel: false) {
state "z3off", label: '3', action: "z3on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z3on", label: '3', action: "z3off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z3on", label: '3', action: "z3off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch4", "device.switch4", inactiveLabel: false) {
state "z4off", label: '4', action: "z4on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z4on", label: '4', action: "z4off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z4on", label: '4', action: "z4off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch5", "device.switch5", inactiveLabel: false) {
state "z5off", label: '5', action: "z5on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z5on", label: '5', action: "z5off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z5on", label: '5', action: "z5off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch6", "device.switch6", inactiveLabel: false) {
state "z6off", label: '6', action: "z6on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z6on", label: '6', action: "z6off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z6on", label: '6', action: "z6off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch7", "device.switch7", inactiveLabel: false) {
state "z7off", label: '7', action: "z7on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z7on", label: '7', action: "z7off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z7on", label: '7', action: "z7off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch8", "device.switch8", inactiveLabel: false) {
state "z8off", label: '8', action: "z8on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z8on", label: '8', action: "z8off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z8on", label: '8', action: "z8off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch9", "device.switch9", inactiveLabel: false) {
state "z9off", label: '9', action: "z9on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z9on", label: '9', action: "z9off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z9on", label: '9', action: "z9off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch10", "device.switch10", inactiveLabel: false) {
state "z10off", label: '10', action: "z10on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z10on", label: '10', action: "z10off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z10on", label: '10', action: "z10off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch11", "device.switch11", inactiveLabel: false) {
state "z11off", label: '11', action: "z11on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z11on", label: '11', action: "z11off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z11on", label: '11', action: "z11off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch12", "device.switch12", inactiveLabel: false) {
state "z12off", label: '12', action: "z12on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z12on", label: '12', action: "z12off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z12on", label: '12', action: "z12off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch13", "device.switch13", inactiveLabel: false) {
state "z13off", label: '13', action: "z13on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z13on", label: '13', action: "z13off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z13on", label: '13', action: "z13off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch14", "device.switch14", inactiveLabel: false) {
state "z14off", label: '14', action: "z14on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z14on", label: '14', action: "z14off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z14on", label: '14', action: "z14off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch15", "device.switch15", inactiveLabel: false) {
state "z15off", label: '15', action: "z15on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z15on", label: '15', action: "z15off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z15on", label: '15', action: "z15off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("switch16", "device.switch16", inactiveLabel: false) {
state "z16off", label: '16', action: "z16on", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "z16on", label: '16', action: "z16off", icon: "st.valves.water.open", backgroundColor: "#46c2e8"
state "z16on", label: '16', action: "z16off", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
state "default", action: "refresh", icon:"st.secondary.refresh"
@@ -0,0 +1,282 @@
/**
* SmartThings Device Handler: Yamaha Zone
*
* Author: redloro@gmail.com
*
* 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: "Yamaha Zone", namespace: "redloro-smartthings", author: "redloro@gmail.com") {
/**
* List our capabilties. Doing so adds predefined command(s) which
* belong to the capability.
*/
capability "Music Player"
capability "Switch"
capability "Switch Level"
capability "Refresh"
capability "Polling"
/**
* Define all commands, ie, if you have a custom action not
* covered by a capability, you NEED to define it here or
* the call will not be made.
*
* To call a capability function, just prefix it with the name
* of the capability, for example, refresh would be "refresh.refresh"
*/
command "source0"
command "source1"
command "source2"
command "source3"
command "source4"
command "source5"
command "mutedOn"
command "mutedOff"
command "partyModeOn"
command "partyModeOff"
command "zone"
}
/**
* Define the various tiles and the states that they can be in.
* The 2nd parameter defines an event which the tile listens to,
* if received, it tries to map it to a state.
*
* You can also use ${currentValue} for the value of the event
* or ${name} for the name of the event. Just make SURE to use
* single quotes, otherwise it will only be interpreted at time of
* launch, instead of every time the event triggers.
*/
tiles(scale: 2) {
multiAttributeTile(name:"state", type:"lighting", width:6, height:4) {
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label:'On', action:"switch.off", icon:"st.Electronics.electronics16", backgroundColor:"#79b821", nextState:"off"
attributeState "off", label:'Off', action:"switch.on", icon:"st.Electronics.electronics16", backgroundColor:"#ffffff", nextState:"on"
}
tileAttribute ("source", key: "SECONDARY_CONTROL") {
attributeState "source", label:'${currentValue}'
}
}
// row
//controlTile("volume", "device.volume", "slider", height: 1, width: 6, range:"(0..100)") {
controlTile("volume", "device.volume", "slider", height: 1, width: 6, range:"(-80..16)") {
state "volume", label: "Volume", action:"music Player.setLevel", backgroundColor:"#00a0dc"
}
// row
standardTile("0", "device.source0", decoration: "flat", width: 2, height: 2) {
state("off", label:"AV1", action:"source0", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
state("on", label:"AV1", action:"source0", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("1", "device.source1", decoration: "flat", width: 2, height: 2) {
state("off", label:"AV2", action:"source1", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
state("on", label:"AV2", action:"source1", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("2", "device.source2", decoration: "flat", width: 2, height: 2) {
state("off", label:"AV3", action:"source2", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
state("on", label:"AV3", action:"source2", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("3", "device.source3", decoration: "flat", width: 2, height: 2) {
state("off", label:"AV4", action:"source3", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
state("on", label:"AV4", action:"source3", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("4", "device.source4", decoration: "flat", width: 2, height: 2) {
state("off", label:"AV5", action:"source4", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
state("on", label:"AV5", action:"source4", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
standardTile("5", "device.source5", decoration: "flat", width: 2, height: 2) {
state("off", label:"AV6", action:"source5", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff")
state("on", label:"AV6", action:"source5", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-green.png", backgroundColor:"#ffffff")
}
// row
standardTile("muted", "device.muted", decoration: "flat", width: 2, height: 2) {
state("off", label:'Muted', action:"mutedOn", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff", nextState:"on")
state("on", label:'Muted', action:"mutedOff", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-mute.png", backgroundColor:"#ffffff", nextState:"off")
}
standardTile("partyMode", "device.partyMode", decoration: "flat", width: 2, height: 2, inactiveLabel: false) {
state("off", label:'Party Mode', action:"partyModeOn", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-gray.png", backgroundColor:"#ffffff", nextState:"on")
state("on", label:'Party Mode', action:"partyModeOff", icon:"https://raw.githubusercontent.com/redloro/smartthings/master/images/indicator-dot-party.png", backgroundColor:"#ffffff", nextState:"off")
}
standardTile("refresh", "device.status", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
state "default", label:"Refresh", action:"refresh.refresh", icon:"st.secondary.refresh-icon", backgroundColor:"#ffffff"
}
// Defines which tile to show in the overview
main "state"
// Defines which tile(s) to show when user opens the detailed view
details([
"state",
"volume",
"0","1","2","3","4","5",
"muted", "partyMode","refresh"
])
}
preferences {
input name: "source0", type: "text", title: "Source 1", defaultValue: "AV1"
input name: "source1", type: "text", title: "Source 2", defaultValue: "AV2"
input name: "source2", type: "text", title: "Source 3", defaultValue: "AV3"
input name: "source3", type: "text", title: "Source 4", defaultValue: "AV4"
input name: "source4", type: "text", title: "Source 5", defaultValue: "AV5"
input name: "source5", type: "text", title: "Source 6", defaultValue: "AV6"
}
}
/**************************************************************************
* The following section simply maps the actions as defined in
* the metadata into onAction() calls.
*
* This is preferred since some actions can be dealt with more
* efficiently this way. Also keeps all user interaction code in
* one place.
*
*/
def on() {
sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Power_Control><Power>On</Power></Power_Control></${getZone()}></YAMAHA_AV>")
sendEvent(name: "switch", value: "on")
}
def off() {
sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Power_Control><Power>Standby</Power></Power_Control></${getZone()}></YAMAHA_AV>")
sendEvent(name: "switch", value: "off")
}
def setLevel(value) {
//sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Volume><Lvl><Val>${(Math.round(value * 9 / 5) * 5 - 800).intValue()}</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Volume></${getZone()}></YAMAHA_AV>")
sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Volume><Lvl><Val>${(value * 10).intValue()}</Val><Exp>1</Exp><Unit>dB</Unit></Lvl></Volume></${getZone()}></YAMAHA_AV>")
sendEvent(name: "volume", value: value)
}
def source0() {
setSource(0)
}
def source1() {
setSource(1)
}
def source2() {
setSource(2)
}
def source3() {
setSource(3)
}
def source4() {
setSource(4)
}
def source5() {
setSource(5)
}
def mutedOn() {
sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Volume><Mute>On</Mute></Volume></${getZone()}></YAMAHA_AV>")
sendEvent(name: "muted", value: "on")
}
def mutedOff() {
sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Volume><Mute>Off</Mute></Volume></${getZone()}></YAMAHA_AV>")
sendEvent(name: "muted", value: "off")
}
def partyModeOn() {
sendCommand("<YAMAHA_AV cmd=\"PUT\"><System><Party_Mode><Mode>On</Mode></Party_Mode></System></YAMAHA_AV>")
sendEvent(name: "partyMode", value: "on")
}
def partyModeOff() {
sendCommand("<YAMAHA_AV cmd=\"PUT\"><System><Party_Mode><Mode>Off</Mode></Party_Mode></System></YAMAHA_AV>")
sendEvent(name: "partyMode", value: "off")
}
def refresh() {
sendCommand("<YAMAHA_AV cmd=\"GET\"><${getZone()}><Basic_Status>GetParam</Basic_Status></${getZone()}></YAMAHA_AV>")
sendCommand("<YAMAHA_AV cmd=\"GET\"><System><Party_Mode><Mode>GetParam</Mode></Party_Mode></System></YAMAHA_AV>")
}
/**************************************************************************/
/**
* Called every so often (every 5 minutes actually) to refresh the
* tiles so the user gets the correct information.
*/
def poll() {
refresh()
}
def parse(String description) {
return
}
def setSource(id) {
//log.debug "source: "+getSourceName(id)
sendCommand("<YAMAHA_AV cmd=\"PUT\"><${getZone()}><Input><Input_Sel>"+getSourceName(id)+"</Input_Sel></Input></${getZone()}></YAMAHA_AV>")
setSourceTile(getSourceName(id))
}
def getSourceName(id) {
if (settings) {
return settings."source${id}"
} else {
return ['AV1', 'AV2', 'AV3', 'AV4', 'AV5', 'AV6'].get(id)
}
}
def setSourceTile(name) {
sendEvent(name: "source", value: "Source: ${name}")
for (def i = 0; i < 6; i++) {
if (name == getSourceName(i)) {
sendEvent(name: "source${i}", value: "on")
}
else {
sendEvent(name: "source${i}", value: "off")
}
}
}
def zone(evt) {
/*
* Zone On/Off
*/
if (evt.Basic_Status.Power_Control.Power.text()) {
sendEvent(name: "switch", value: (evt.Basic_Status.Power_Control.Power.text() == "On") ? "on" : "off")
}
/*
* Zone Volume
*/
if (evt.Basic_Status.Volume.Lvl.Val.text()) {
def int volLevel = evt.Basic_Status.Volume.Lvl.Val.toInteger() ?: -250
//sendEvent(name: "volume", value: ((volLevel + 800) / 9).intValue())
sendEvent(name: "volume", value: (volLevel / 10).intValue())
}
/*
* Zone Muted
*/
if (evt.Basic_Status.Volume.Mute.text()) {
sendEvent(name: "muted", value: (evt.Basic_Status.Volume.Mute.text() == "On") ? "on" : "off")
}
/*
* Zone Source
*/
if (evt.Basic_Status.Input.Input_Sel.text()) {
setSourceTile(evt.Basic_Status.Input.Input_Sel.text())
}
/*
* Party Mode
*/
if (evt.Party_Mode.Mode.text()) {
sendEvent(name: "partyMode", value: (evt.Party_Mode.Mode.text() == "On") ? "on" : "off")
}
}
private sendCommand(body) {
parent.sendCommand(body)
}
private getZone() {
return new String(device.deviceNetworkId).tokenize('|')[2]
}
@@ -47,9 +47,9 @@ metadata {
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff"
state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
state "turningOn", label:'${name}', icon:"st.switches.switch.on", backgroundColor:"#79b821"
state "turningOn", label:'${name}', icon:"st.switches.switch.on", backgroundColor:"#00A0DC"
state "turningOff", label:'${name}', icon:"st.switches.switch.off", backgroundColor:"#ffffff"
}
controlTile("levelSliderControl", "device.level", "slider", height: 2, width: 1, inactiveLabel: false) {
@@ -37,14 +37,14 @@ metadata {
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"
state "button 2 pushed", label: "pushed #2", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#79b821"
state "button 3 pushed", label: "pushed #3", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#79b821"
state "button 4 pushed", label: "pushed #4", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#79b821"
state "button 1 held", label: "held #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffa81e"
state "button 2 held", label: "held #2", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffa81e"
state "button 3 held", label: "held #3", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffa81e"
state "button 4 held", label: "held #4", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#ffa81e"
state "button 1 pushed", label: "pushed #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#00A0DC"
state "button 2 pushed", label: "pushed #2", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#00A0DC"
state "button 3 pushed", label: "pushed #3", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#00A0DC"
state "button 4 pushed", label: "pushed #4", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#00A0DC"
state "button 1 held", label: "held #1", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#e86d13"
state "button 2 held", label: "held #2", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#e86d13"
state "button 3 held", label: "held #3", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#e86d13"
state "button 4 held", label: "held #4", icon: "st.unknown.zwave.remote-controller", backgroundColor: "#e86d13"
}
valueTile("battery", "device.battery", inactiveLabel: false, decoration: "flat") {
state "battery", label:'${currentValue}% battery', unit:""
@@ -37,9 +37,9 @@ metadata {
}
standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) {
state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00a0dc", nextState:"turningOff"
state "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
state "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
state "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00a0dc", nextState:"turningOff"
state "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
}
standardTile("reset", "device.reset", inactiveLabel: false, decoration: "flat") {
@@ -45,7 +45,7 @@ metadata {
// tile definitions
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00a0dc"
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
valueTile("energy", "device.energy", decoration: "flat") {
@@ -60,7 +60,7 @@ metadata {
// tile definitions
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00a0dc"
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
valueTile("power", "device.power", decoration: "flat") {
@@ -78,7 +78,7 @@ metadata {
(1..4).each { n ->
standardTile("switch$n", "switch$n", canChangeIcon: true) {
state "on", label: '${name}', action: "off$n", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${name}', action: "off$n", icon: "st.switches.switch.on", backgroundColor: "#00a0dc"
state "off", label: '${name}', action: "on$n", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
valueTile("power$n", "power$n", decoration: "flat") {
@@ -11,7 +11,6 @@
* for the specific language governing permissions and limitations under the License.
*
*/
metadata {
definition (name: "Arrival Sensor HA", namespace: "smartthings", author: "SmartThings") {
capability "Tone"
@@ -40,7 +39,7 @@ metadata {
tiles {
standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) {
state "present", labelIcon:"st.presence.tile.present", backgroundColor:"#53a7c0"
state "present", labelIcon:"st.presence.tile.present", backgroundColor:"#00a0dc"
state "not present", labelIcon:"st.presence.tile.not-present", backgroundColor:"#ffffff"
}
standardTile("beep", "device.beep", decoration: "flat") {
@@ -60,7 +59,7 @@ def updated() {
}
def configure() {
def cmds = zigbee.configureReporting(0x0001, 0x0020, 0x20, 20, 20, 0x01)
def cmds = zigbee.batteryConfig(20, 20, 0x01)
log.debug "configure -- cmds: ${cmds}"
return cmds
}
@@ -152,7 +151,7 @@ private handlePresenceEvent(present) {
private startTimer() {
log.debug "Scheduling periodic timer"
schedule("0 * * * * ?", checkPresenceCallback)
runEvery1Minute("checkPresenceCallback")
}
private stopTimer() {
@@ -55,13 +55,13 @@ metadata {
state "fanOn", label:'${name}', action:"thermostat.setThermostatFanMode"
}
controlTile("heatSliderControl", "device.heatingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) {
state "setHeatingSetpoint", action:"thermostat.setHeatingSetpoint", backgroundColor:"#d04e00"
state "setHeatingSetpoint", action:"thermostat.setHeatingSetpoint", backgroundColor:"#e86d13"
}
valueTile("heatingSetpoint", "device.heatingSetpoint", inactiveLabel: false, decoration: "flat") {
state "heat", label:'${currentValue}° heat', unit:"F", backgroundColor:"#ffffff"
}
controlTile("coolSliderControl", "device.coolingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) {
state "setCoolingSetpoint", action:"thermostat.setCoolingSetpoint", backgroundColor: "#1e9cbb"
state "setCoolingSetpoint", action:"thermostat.setCoolingSetpoint", backgroundColor: "#00a0dc"
}
valueTile("coolingSetpoint", "device.coolingSetpoint", inactiveLabel: false, decoration: "flat") {
state "cool", label:'${currentValue}° cool', unit:"F", backgroundColor:"#ffffff"
@@ -81,49 +81,45 @@ metadata {
// parse events into attributes
def parse(String description) {
log.debug "Parse description $description"
def map = [:]
if (description?.startsWith("read attr -")) {
def descMap = parseDescriptionAsMap(description)
List result = []
def descMap = zigbee.parseDescriptionAsMap(description)
log.debug "Desc Map: $descMap"
if (descMap.cluster == "0201" && descMap.attrId == "0000") {
List attrData = [[cluster: descMap.cluster ,attrId: descMap.attrId, value: descMap.value]]
descMap.additionalAttrs.each {
attrData << [cluster: descMap.cluster, attrId: it.attrId, value: it.value]
}
attrData.each {
def map = [:]
if (it.cluster == "0201" && it.attrId == "0000") {
log.debug "TEMP"
map.name = "temperature"
map.value = getTemperature(descMap.value)
map.value = getTemperature(it.value)
map.unit = temperatureScale
} else if (descMap.cluster == "0201" && descMap.attrId == "0011") {
} else if (it.cluster == "0201" && it.attrId == "0011") {
log.debug "COOLING SETPOINT"
map.name = "coolingSetpoint"
map.value = getTemperature(descMap.value)
map.value = getTemperature(it.value)
map.unit = temperatureScale
} else if (descMap.cluster == "0201" && descMap.attrId == "0012") {
} else if (it.cluster == "0201" && it.attrId == "0012") {
log.debug "HEATING SETPOINT"
map.name = "heatingSetpoint"
map.value = getTemperature(descMap.value)
map.value = getTemperature(it.value)
map.unit = temperatureScale
} else if (descMap.cluster == "0201" && descMap.attrId == "001c") {
} else if (it.cluster == "0201" && it.attrId == "001c") {
log.debug "MODE"
map.name = "thermostatMode"
map.value = getModeMap()[descMap.value]
} else if (descMap.cluster == "0202" && descMap.attrId == "0000") {
map.value = getModeMap()[it.value]
} else if (it.cluster == "0202" && it.attrId == "0000") {
log.debug "FAN MODE"
map.name = "thermostatFanMode"
map.value = getFanModeMap()[descMap.value]
map.value = getFanModeMap()[it.value]
}
}
def result = null
if (map) {
result = createEvent(map)
result << createEvent(map)
}
log.debug "Parse returned $map"
return result
}
def parseDescriptionAsMap(description) {
(description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
}
return result
}
def getModeMap() { [
@@ -36,7 +36,7 @@ metadata {
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: '${name}', action: "switch.on", icon: "st.Home.home30", backgroundColor: "#ffffff"
state "on", label: '${name}', action: "switch.off", icon: "st.Home.home30", backgroundColor: "#79b821"
state "on", label: '${name}', action: "switch.off", icon: "st.Home.home30", backgroundColor: "#00a0dc"
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
@@ -23,6 +23,7 @@ metadata {
capability "Switch"
capability "Switch Level"
capability "Health Check"
capability "Light"
fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,1000", outClusters: "0000,0019"
}
@@ -42,9 +43,9 @@ metadata {
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.light.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
@@ -82,7 +83,7 @@ def on() {
}
def setLevel(value) {
zigbee.setLevel(value) + ["delay 500"] + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report
zigbee.setLevel(value) + zigbee.onOffRefresh() + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report
}
/**
@@ -33,10 +33,10 @@ metadata {
tiles {
standardTile("toggle", "device.lock", width: 2, height: 2) {
state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#79b821", nextState:"unlocking"
state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#00a0dc", nextState:"unlocking"
state "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff", nextState:"locking"
state "unknown", label:"unknown", action:"lock.lock", icon:"st.locks.lock.unknown", backgroundColor:"#ffffff", nextState:"locking"
state "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#79b821"
state "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#00a0dc"
state "unlocking", label:'unlocking', icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff"
}
standardTile("lock", "device.lock", inactiveLabel: false, decoration: "flat") {
@@ -7,6 +7,8 @@ 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)
* [GE 1,000-Watt In-Wall Smart Dimmer Switch (GE 12725)](http://products.z-wavealliance.org/products/1198)
* [GE In-Wall Smart Fan Control (GE 12730)](http://products.z-wavealliance.org/products/1202)
## Table of contents
@@ -27,7 +29,7 @@ Works with:
## Device Health
Z-Wave Smart Dimmers (In-Wall, In-Wall(Toggle), Plug-In) are polled by the hub.
Z-Wave Smart Dimmers (In-Wall, In-Wall(Toggle), Plug-In), 1000-watt In-Wall Smart Dimmer Switch and In-Wall Smart Fan Control 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
@@ -45,3 +47,5 @@ Instructions related to pairing, resetting and removing the device from SmartThi
* [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-)
* [GE 1,000-Watt In-Wall Smart Dimmer Switch (GE 12725) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200879274)
* [GE In-Wall Smart Fan Control (GE 12730) Troubleshooting Tips](https://support.smartthings.com/hc/en-us/articles/200879274)
@@ -21,6 +21,7 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Light"
fingerprint mfr:"0063", prod:"4457", deviceJoinName: "GE In-Wall Smart Dimmer "
fingerprint mfr:"0063", prod:"4944", deviceJoinName: "GE In-Wall Smart Dimmer "
@@ -53,9 +54,9 @@ metadata {
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 "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00a0dc", 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 "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00a0dc", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
@@ -47,8 +47,8 @@ metadata {
}
standardTile("motion", "device.motion") {
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff")
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0")
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc")
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC")
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat") {
@@ -33,7 +33,7 @@ metadata {
multiAttributeTile(name:"water", type: "generic", width: 6, height: 4){
tileAttribute ("device.water", key: "PRIMARY_CONTROL") {
attributeState "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
attributeState "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0"
attributeState "wet", icon:"st.alarm.water.wet", backgroundColor:"#00a0dc"
}
}
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
@@ -89,9 +89,9 @@
state "whiteLevel", action:"setWhiteLevel", label:'White Level'
}
standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) {
state "on", label:'${name}', action:"switch.off", icon:"st.illuminance.illuminance.bright", backgroundColor:"#79b821", nextState:"turningOff"
state "on", label:'${name}', action:"switch.off", icon:"st.illuminance.illuminance.bright", backgroundColor:"#00A0DC", nextState:"turningOff"
state "off", label:'${name}', action:"switch.on", icon:"st.illuminance.illuminance.dark", backgroundColor:"#ffffff", nextState:"turningOn"
state "turningOn", label:'${name}', icon:"st.illuminance.illuminance.bright", backgroundColor:"#79b821"
state "turningOn", label:'${name}', icon:"st.illuminance.illuminance.bright", backgroundColor:"#00A0DC"
state "turningOff", label:'${name}', icon:"st.illuminance.illuminance.dark", backgroundColor:"#ffffff"
}
valueTile("power", "device.power", decoration: "flat") {
@@ -34,10 +34,10 @@ metadata {
// tile definitions
tiles {
standardTile("contact", "device.contact", width: 2, height: 2, canChangeIcon: true) {
state "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#53a7c0", nextState:"closing"
state "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#e86d13", nextState:"opening"
state "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#ffe71e"
state "closing", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffe71e"
state "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC", nextState:"closing"
state "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff", nextState:"opening"
state "opening", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
state "closing", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
@@ -41,7 +41,7 @@
standardTile("take", "device.image", width: 1, height: 1, canChangeIcon: false, inactiveLabel: true, canChangeBackground: false) {
state "take", label: "Take", action: "Image Capture.take", icon: "st.camera.dropcam", backgroundColor: "#FFFFFF", nextState:"taking"
state "taking", label:'Taking', action: "", icon: "st.camera.dropcam", backgroundColor: "#53a7c0"
state "taking", label:'Taking', action: "", icon: "st.camera.dropcam", backgroundColor: "#00A0DC"
state "image", label: "Take", action: "Image Capture.take", icon: "st.camera.dropcam", backgroundColor: "#FFFFFF", nextState:"taking"
}
@@ -61,9 +61,9 @@ metadata {
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.light.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00a0dc", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00a0dc", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
@@ -99,7 +99,7 @@ def parse(String description) {
def poll() {
def refreshCmds = [
"st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 500"
"st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 2000"
]
return refreshCmds + zigbee.onOffRefresh() + zigbee.levelRefresh()
@@ -197,7 +197,7 @@ def off() {
def refresh() {
def refreshCmds = [
"st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 500"
"st wattr 0x${device.deviceNetworkId} 1 8 0x10 0x21 {${state?.dOnOff ?: '0000'}}", "delay 2000"
]
return refreshCmds + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig()
@@ -31,7 +31,7 @@ metadata {
tileAttribute("sessionStatus", key: "PRIMARY_CONTROL") {
attributeState "cancelled", action: "timed session.start", icon: "http://f.cl.ly/items/322n181j2K3f281r2s0A/playbutton.png", backgroundColor: "#ffffff", nextState: "running"
attributeState "stopped", action: "timed session.start", icon: "http://f.cl.ly/items/322n181j2K3f281r2s0A/playbutton.png", backgroundColor: "#ffffff", nextState: "cancelled"
attributeState "running", action: "timed session.stop", icon: "http://f.cl.ly/items/0B3y3p2V3X2l3P3y3W09/stopbutton.png", backgroundColor: "#79b821", nextState: "cancelled"
attributeState "running", action: "timed session.stop", icon: "http://f.cl.ly/items/0B3y3p2V3X2l3P3y3W09/stopbutton.png", backgroundColor: "#00A0DC", nextState: "cancelled"
}
tileAttribute("timeRemaining", key: "SECONDARY_CONTROL") {
attributeState "timeRemaining", label:'${currentValue} remaining'
@@ -45,7 +45,7 @@ metadata {
standardTile("sessionStatusTile", "sessionStatus", width: 1, height: 1, canChangeIcon: true) {
state "cancelled", label: "Stopped", action: "timed session.start", backgroundColor: "#ffffff", icon: "http://f.cl.ly/items/1J1g0H2P0S1G1f2O1s1s/icon.png"
state "stopped", label: "Stopped", action: "timed session.start", backgroundColor: "#ffffff", icon: "http://f.cl.ly/items/1J1g0H2P0S1G1f2O1s1s/icon.png"
state "running", label: "Running", action: "timed session.stop", backgroundColor: "#79b821", icon: "http://f.cl.ly/items/1J1g0H2P0S1G1f2O1s1s/icon.png"
state "running", label: "Running", action: "timed session.stop", backgroundColor: "#00A0DC", icon: "http://f.cl.ly/items/1J1g0H2P0S1G1f2O1s1s/icon.png"
}
// duration
@@ -32,7 +32,7 @@ metadata {
tiles {
standardTile("button", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: 'Off', action: "switch.on", icon: "st.harmony.harmony-hub-icon", backgroundColor: "#ffffff", nextState: "on"
state "on", label: 'On', action: "switch.off", icon: "st.harmony.harmony-hub-icon", backgroundColor: "#79b821", nextState: "off"
state "on", label: 'On', action: "switch.off", icon: "st.harmony.harmony-hub-icon", backgroundColor: "#00A0DC", nextState: "off"
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
@@ -17,6 +17,7 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Light"
command "setAdjustedColor"
command "reset"
@@ -30,9 +31,9 @@ metadata {
tiles (scale: 2){
multiAttributeTile(name:"rich-control", 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 "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", 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 "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", 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") {
@@ -57,7 +58,7 @@ metadata {
}
void installed() {
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}")
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false)
}
// parse events into attributes
@@ -7,6 +7,7 @@
metadata {
// Automatically generated. Make future change here.
definition (name: "Hue Bridge", namespace: "smartthings", author: "SmartThings") {
capability "Bridge"
capability "Health Check"
attribute "networkAddress", "string"
@@ -26,7 +27,7 @@ metadata {
multiAttributeTile(name:"rich-control"){
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"
attributeState "Online", label: '${currentValue}', action: "", icon: "st.Lighting.light99-hue", backgroundColor: "#00A0DC"
}
}
valueTile("doNotRemove", "v", decoration: "flat", height: 2, width: 6, inactiveLabel: false) {
@@ -45,7 +46,7 @@ metadata {
}
void installed() {
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}")
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false)
}
// parse events into attributes
@@ -18,6 +18,7 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Light"
command "setAdjustedColor"
command "reset"
@@ -31,9 +32,9 @@ metadata {
tiles (scale: 2){
multiAttributeTile(name:"rich-control", 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 "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", 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 "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", 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") {
@@ -66,7 +67,7 @@ metadata {
}
void installed() {
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}")
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false)
}
// parse events into attributes
@@ -15,6 +15,7 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Light"
command "refresh"
}
@@ -26,9 +27,9 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"rich-control", type: "lighting", 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 "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", 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 "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", 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") {
@@ -50,7 +51,7 @@ metadata {
}
void installed() {
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}")
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false)
}
// parse events into attributes
@@ -16,6 +16,7 @@ metadata {
capability "Switch"
capability "Refresh"
capability "Health Check"
capability "Light"
command "refresh"
}
@@ -27,9 +28,9 @@ metadata {
tiles (scale: 2){
multiAttributeTile(name:"rich-control", 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 "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", 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 "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", 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") {
@@ -55,7 +56,7 @@ metadata {
}
void installed() {
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}")
sendEvent(name: "DeviceWatch-Enroll", value: "{\"protocol\": \"LAN\", \"scheme\":\"untracked\", \"hubHardwareId\": \"${device.hub.hardwareID}\"}", displayed: false)
}
// parse events into attributes
@@ -29,7 +29,7 @@ metadata {
tiles {
standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) {
state("present", labelIcon:"st.presence.tile.mobile-present", backgroundColor:"#53a7c0")
state("present", labelIcon:"st.presence.tile.mobile-present", backgroundColor:"#00A0DC")
state("not present", labelIcon:"st.presence.tile.mobile-not-present", backgroundColor:"#ffffff")
}
@@ -14,6 +14,7 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Light"
}
simulator {
@@ -23,9 +24,9 @@ metadata {
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:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "on", label:'${name}', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"http://hosted.lifx.co/smartthings/v1/196xOff.png", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'Turning on', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOn", label:'Turning on', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "turningOff", label:'Turning off', action:"switch.on", icon:"http://hosted.lifx.co/smartthings/v1/196xOff.png", backgroundColor:"#ffffff", nextState:"turningOn"
}
@@ -13,6 +13,7 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Light"
}
simulator {
@@ -22,9 +23,9 @@ metadata {
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:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "on", label:'${name}', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"http://hosted.lifx.co/smartthings/v1/196xOff.png", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'Turning on', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOn", label:'Turning on', action:"switch.off", icon:"http://hosted.lifx.co/smartthings/v1/196xOn.png", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "turningOff", label:'Turning off', action:"switch.on", icon:"http://hosted.lifx.co/smartthings/v1/196xOff.png", backgroundColor:"#ffffff", nextState:"turningOn"
}
@@ -36,6 +36,7 @@ metadata {
capability "Switch"
capability "Refresh"
capability "Contact Sensor"
capability "Light"
attribute "powered", "string"
@@ -53,11 +54,11 @@ metadata {
// UI tile definitions
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "doorClosed", label: "Closed", action: "on", icon: "st.doors.garage.garage-closed", backgroundColor: "#79b821"
state "doorOpen", label: "Open", action: "on", icon: "st.doors.garage.garage-open", backgroundColor: "#ffa81e"
state "doorOpening", label: "Opening", action: "on", icon: "st.doors.garage.garage-opening", backgroundColor: "#ffa81e"
state "doorClosing", label: "Closing", action: "on", icon: "st.doors.garage.garage-closing", backgroundColor: "#ffa81e"
state "on", label: "Actuate", action: "off", icon: "st.doors.garage.garage-closed", backgroundColor: "#53a7c0"
state "doorClosed", label: "Closed", action: "on", icon: "st.doors.garage.garage-closed", backgroundColor: "#00A0DC"
state "doorOpen", label: "Open", action: "on", icon: "st.doors.garage.garage-open", backgroundColor: "#e86d13"
state "doorOpening", label: "Opening", action: "on", icon: "st.doors.garage.garage-opening", backgroundColor: "#e86d13"
state "doorClosing", label: "Closing", action: "on", icon: "st.doors.garage.garage-closing", backgroundColor: "#00A0DC"
state "on", label: "Actuate", action: "off", icon: "st.doors.garage.garage-closed", backgroundColor: "#00A0DC"
state "off", label: '${name}', action: "on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
standardTile("contact", "device.contact", inactiveLabel: false) {
@@ -27,8 +27,8 @@ metadata {
tiles {
standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) {
state("present", labelIcon:"st.presence.tile.mobile-present", backgroundColor:"#53a7c0")
state("not present", labelIcon:"st.presence.tile.mobile-not-present", backgroundColor:"#ebeef2")
state("present", labelIcon:"st.presence.tile.mobile-present", backgroundColor:"#00A0DC")
state("not present", labelIcon:"st.presence.tile.mobile-not-present", backgroundColor:"#ffffff")
}
main "presence"
details "presence"
@@ -32,7 +32,7 @@ metadata {
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: 'Push', action: "momentary.push", backgroundColor: "#ffffff", nextState: "on"
state "on", label: 'Push', action: "momentary.push", backgroundColor: "#53a7c0"
state "on", label: 'Push', action: "momentary.push", backgroundColor: "#00A0DC"
}
main "switch"
details "switch"
@@ -28,8 +28,8 @@ metadata {
// UI tile definitions
tiles {
standardTile("motion", "device.motion", width: 2, height: 2) {
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0")
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff")
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC")
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc")
}
main "motion"
@@ -31,7 +31,7 @@ metadata {
tiles {
standardTile("button", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: 'Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "on"
state "on", label: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "off"
state "on", label: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC", nextState: "off"
}
main "button"
details "button"
@@ -31,7 +31,7 @@ metadata {
// UI tile definitions
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true, canChangeBackground: true) {
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
@@ -29,8 +29,8 @@ metadata {
// UI tile definitions
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"
state "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#e86d13"
state "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#00A0DC"
}
main "contact"
@@ -40,14 +40,11 @@ metadata {
// Parse incoming device messages to generate events
def parse(String description) {
def name = null
def value = description
if (zigbee.isZoneType19(description)) {
name = "contact"
value = zigbee.translateStatusZoneType19(description) ? "open" : "closed"
def resMap
if (description.startsWith("zone")) {
resMap = createEvent(name: "contact", value: zigbee.parseZoneStatus(description).isAlarm1Set() ? "open" : "closed")
}
def result = createEvent(name: name, value: value)
log.debug "Parse returned ${result?.descriptionText}"
return result
log.debug "Parse returned $resMap"
return resMap
}
@@ -37,9 +37,9 @@ metadata {
}
standardTile("switch", "device.switch", width: 1, height: 1, canChangeIcon: true) {
state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
state "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00a0dc", nextState:"turningOff"
state "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
state "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
state "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00a0dc", nextState:"turningOff"
state "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
}
standardTile("reset", "device.reset", inactiveLabel: false, decoration: "flat") {
@@ -42,9 +42,9 @@ metadata {
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff"
state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff"
state "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 3, inactiveLabel: false) {
@@ -24,6 +24,7 @@ metadata {
capability "Refresh"
capability "Actuator"
capability "Sensor"
capability "Outlet"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "4257050-ZHAC"
@@ -69,288 +70,36 @@ metadata {
def parse(String description) {
log.debug "description is $description"
def event = [:]
def finalResult = isKnownDescription(description)
if (finalResult) {
log.info finalResult
if (finalResult.type == "update") {
log.info "$device updates: ${finalResult.value}"
event = null
}
else if (finalResult.type == "power") {
def powerValue = (finalResult.value as Integer)/10
event = createEvent(name: "power", value: powerValue)
/*
Dividing by 10 as the Divisor is 10000 and unit is kW for the device. AttrId: 0302 and 0300. Simplifying to 10
power level is an integer. The exact power level with correct units needs to be handled in the device type
to account for the different Divisor value (AttrId: 0302) and POWER Unit (AttrId: 0300). CLUSTER for simple metering is 0702
*/
}
else {
event = createEvent(name: finalResult.type, value: finalResult.value)
}
}
else {
def event = zigbee.getEvent(description)
if (!event) {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug parseDescriptionAsMap(description)
log.debug zigbee.parseDescriptionAsMap(description)
} else if (event.name == "power") {
/*
Dividing by 10 as the Divisor is 10000 and unit is kW for the device. Simplifying to 10 power level is an integer.
*/
event.value = event.value / 10
}
return event
}
// Commands to device
def zigbeeCommand(cluster, attribute){
"st cmd 0x${device.deviceNetworkId} ${endpointId} ${cluster} ${attribute} {}"
}
def off() {
zigbeeCommand("6", "0")
}
def on() {
zigbeeCommand("6", "1")
return event ? createEvent(event) : event
}
def setLevel(value) {
value = value as Integer
if (value == 0) {
off()
}
else {
if (device.latestValue("switch") == "off") {
sendEvent(name: "switch", value: "on")
}
sendEvent(name: "level", value: value)
setLevelWithRate(value, "0000") //value is between 0 to 100
}
zigbee.setLevel(value)
}
def off() {
zigbee.off()
}
def on() {
zigbee.on()
}
def refresh() {
[
"st rattr 0x${device.deviceNetworkId} ${endpointId} 6 0", "delay 500",
"st rattr 0x${device.deviceNetworkId} ${endpointId} 8 0", "delay 500",
"st rattr 0x${device.deviceNetworkId} ${endpointId} 0x0B04 0x050B", "delay 500"
]
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.electricMeasurementPowerRefresh()
}
def configure() {
refresh() + onOffConfig() + levelConfig() + powerConfig()
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
private hex(value, width=2) {
def s = new BigInteger(Math.round(value).toString()).toString(16)
while (s.size() < width) {
s = "0" + s
}
s
}
private String swapEndianHex(String hex) {
reverseArray(hex.decodeHex()).encodeHex()
}
private Integer convertHexToInt(hex) {
Integer.parseInt(hex,16)
}
//Need to reverse array of size 2
private byte[] reverseArray(byte[] array) {
byte tmp;
tmp = array[1];
array[1] = array[0];
array[0] = tmp;
return array
}
def parseDescriptionAsMap(description) {
if (description?.startsWith("read attr -")) {
(description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
map += [(nameAndValue[0].trim()): nameAndValue[1].trim()]
}
}
else if (description?.startsWith("catchall: ")) {
def seg = (description - "catchall: ").split(" ")
def zigbeeMap = [:]
zigbeeMap += [raw: (description - "catchall: ")]
zigbeeMap += [profileId: seg[0]]
zigbeeMap += [clusterId: seg[1]]
zigbeeMap += [sourceEndpoint: seg[2]]
zigbeeMap += [destinationEndpoint: seg[3]]
zigbeeMap += [options: seg[4]]
zigbeeMap += [messageType: seg[5]]
zigbeeMap += [dni: seg[6]]
zigbeeMap += [isClusterSpecific: Short.valueOf(seg[7], 16) != 0]
zigbeeMap += [isManufacturerSpecific: Short.valueOf(seg[8], 16) != 0]
zigbeeMap += [manufacturerId: seg[9]]
zigbeeMap += [command: seg[10]]
zigbeeMap += [direction: seg[11]]
zigbeeMap += [data: seg.size() > 12 ? seg[12].split("").findAll { it }.collate(2).collect {
it.join('')
} : []]
zigbeeMap
}
}
def isKnownDescription(description) {
if ((description?.startsWith("catchall:")) || (description?.startsWith("read attr -"))) {
def descMap = parseDescriptionAsMap(description)
if (descMap.cluster == "0006" || descMap.clusterId == "0006") {
isDescriptionOnOff(descMap)
}
else if (descMap.cluster == "0008" || descMap.clusterId == "0008"){
isDescriptionLevel(descMap)
}
else if (descMap.cluster == "0B04" || descMap.clusterId == "0B04"){
isDescriptionPower(descMap)
}
else {
return [:]
}
}
else if(description?.startsWith("on/off:")) {
def switchValue = description?.endsWith("1") ? "on" : "off"
return [type: "switch", value : switchValue]
}
else {
return [:]
}
}
def isDescriptionOnOff(descMap) {
def switchValue = "undefined"
if (descMap.cluster == "0006") { //cluster info from read attr
value = descMap.value
if (value == "01"){
switchValue = "on"
}
else if (value == "00"){
switchValue = "off"
}
}
else if (descMap.clusterId == "0006") {
//cluster info from catch all
//command 0B is Default response and the last two bytes are [on/off][success]. on/off=00, success=00
//command 01 is Read attr response. the last two bytes are [datatype][value]. boolean datatype=10; on/off value = 01/00
if ((descMap.command=="0B" && descMap.raw.endsWith("0100")) || (descMap.command=="01" && descMap.raw.endsWith("1001"))){
switchValue = "on"
}
else if ((descMap.command=="0B" && descMap.raw.endsWith("0000")) || (descMap.command=="01" && descMap.raw.endsWith("1000"))){
switchValue = "off"
}
else if(descMap.command=="07"){
return [type: "update", value : "switch (0006) capability configured successfully"]
}
}
if (switchValue != "undefined"){
return [type: "switch", value : switchValue]
}
else {
return [:]
}
}
//@return - false or "success" or level [0-100]
def isDescriptionLevel(descMap) {
def dimmerValue = -1
if (descMap.cluster == "0008"){
//TODO: the message returned with catchall is command 0B with clusterId 0008. That is just a confirmation message
def value = convertHexToInt(descMap.value)
dimmerValue = Math.round(value * 100 / 255)
if(dimmerValue==0 && value > 0) {
dimmerValue = 1 //handling for non-zero hex value less than 3
}
}
else if(descMap.clusterId == "0008") {
if(descMap.command=="0B"){
return [type: "update", value : "level updated successfully"] //device updating the level change was successful. no value sent.
}
else if(descMap.command=="07"){
return [type: "update", value : "level (0008) capability configured successfully"]
}
}
if (dimmerValue != -1){
return [type: "level", value : dimmerValue]
}
else {
return [:]
}
}
def isDescriptionPower(descMap) {
def powerValue = "undefined"
if (descMap.cluster == "0B04") {
if (descMap.attrId == "050b") {
if(descMap.value!="ffff")
powerValue = convertHexToInt(descMap.value)
}
}
else if (descMap.clusterId == "0B04") {
if(descMap.command=="07"){
return [type: "update", value : "power (0B04) capability configured successfully"]
}
}
if (powerValue != "undefined"){
return [type: "power", value : powerValue]
}
else {
return [:]
}
}
def onOffConfig() {
[
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 6 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 6 0 0x10 0 600 {01}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 1500"
]
}
//level config for devices with min reporting interval as 5 seconds and reporting interval if no activity as 1hour (3600s)
//min level change is 01
def levelConfig() {
[
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 8 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 8 0 0x20 5 3600 {01}",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 1500"
]
}
//power config for devices with min reporting interval as 1 seconds and reporting interval if no activity as 10min (600s)
//min change in value is 05
def powerConfig() {
[
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 0x0B04 0x050B 0x29 1 600 {05 00}", //The send-me-a-report is custom to the attribute type for CentraLite
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
]
}
def setLevelWithRate(level, rate) {
if(rate == null){
rate = "0000"
}
level = convertToHexString(level * 255 / 100) //Converting the 0-100 range to 0-FF range in hex
"st cmd 0x${device.deviceNetworkId} ${endpointId} 8 4 {$level $rate}"
}
String convertToHexString(value, width=2) {
def s = new BigInteger(Math.round(value).toString()).toString(16)
while (s.size() < width) {
s = "0" + s
}
s
refresh() + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.electricMeasurementPowerConfig()
}
@@ -4,6 +4,7 @@ metadata {
capability "Actuator"
capability "Switch"
capability "Sensor"
capability "Outlet"
fingerprint profileId: "0104", inClusters: "0006, 0004, 0003, 0000, 0005", outClusters: "0019", manufacturer: "Compacta International, Ltd", model: "ZBMPlug15", deviceJoinName: "SmartPower Outlet V1"
}
@@ -23,7 +24,7 @@ metadata {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
attributeState "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
}
}
main "switch"
@@ -51,7 +52,7 @@ def on() {
'zcl on-off on',
'delay 200',
"send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}",
'delay 500'
'delay 2000'
]
@@ -62,6 +63,6 @@ def off() {
'zcl on-off off',
'delay 200',
"send 0x${zigbee.deviceNetworkId} 0x01 0x${zigbee.endpointId}",
'delay 500'
'delay 2000'
]
}
@@ -13,10 +13,9 @@
* License for the specific language governing permissions and limitations
* under the License.
*/
metadata {
// Automatically generated. Make future change here.
definition (name: "SmartPower Outlet", namespace: "smartthings", author: "SmartThings") {
definition(name: "SmartPower Outlet", namespace: "smartthings", author: "SmartThings") {
capability "Actuator"
capability "Switch"
capability "Power Meter"
@@ -24,6 +23,8 @@ metadata {
capability "Refresh"
capability "Sensor"
capability "Health Check"
capability "Light"
capability "Outlet"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3200", deviceJoinName: "Outlet"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0B04,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3200-Sgb", deviceJoinName: "Outlet"
@@ -53,24 +54,24 @@ metadata {
// 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: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "turningOff"
multiAttributeTile(name: "switch", type: "lighting", width: 6, height: 4, canChangeIcon: true) {
tileAttribute("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label: 'On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC", nextState: "turningOff"
attributeState "off", label: 'Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
attributeState "turningOn", label: 'Turning On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821", nextState: "turningOff"
attributeState "turningOn", label: 'Turning On', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC", nextState: "turningOff"
attributeState "turningOff", label: 'Turning Off', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff", nextState: "turningOn"
}
tileAttribute ("power", key: "SECONDARY_CONTROL") {
attributeState "power", label:'${currentValue} W'
tileAttribute("power", key: "SECONDARY_CONTROL") {
attributeState "power", label: '${currentValue} W'
}
}
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
state "default", label: '', action: "refresh.refresh", icon: "st.secondary.refresh"
}
main "switch"
details(["switch","refresh"])
details(["switch", "refresh"])
}
}
@@ -78,52 +79,33 @@ metadata {
def parse(String description) {
log.debug "description is $description"
def finalResult = zigbee.getKnownDescription(description)
def event = [:]
def event = zigbee.getEvent(description)
//TODO: Remove this after getKnownDescription can parse it automatically
if (!finalResult && description!="updated")
finalResult = getPowerDescription(zigbee.parseDescriptionAsMap(description))
if (finalResult) {
log.info "final result = $finalResult"
if (finalResult.type == "update") {
log.info "$device updates: ${finalResult.value}"
event = null
if (event) {
if (event.name == "power") {
def value = (event.value as Integer) / 10
event = createEvent(name: event.name, value: value, descriptionText: '{{ device.displayName }} power is {{ value }} Watts', translatable: true)
} else if (event.name == "switch") {
def descriptionText = event.value == "on" ? '{{ device.displayName }} is On' : '{{ device.displayName }} is Off'
event = createEvent(name: event.name, value: event.value, descriptionText: descriptionText, translatable: true)
}
else if (finalResult.type == "power") {
def powerValue = (finalResult.value as Integer)/10
event = createEvent(name: "power", value: powerValue, descriptionText: '{{ device.displayName }} power is {{ value }} Watts', translatable: true)
/*
Dividing by 10 as the Divisor is 10000 and unit is kW for the device. AttrId: 0302 and 0300. Simplifying to 10
power level is an integer. The exact power level with correct units needs to be handled in the device type
to account for the different Divisor value (AttrId: 0302) and POWER Unit (AttrId: 0300). CLUSTER for simple metering is 0702
*/
}
else {
def descriptionText = finalResult.value == "on" ? '{{ device.displayName }} is On' : '{{ device.displayName }} is Off'
event = createEvent(name: finalResult.type, value: finalResult.value, descriptionText: descriptionText, translatable: true)
}
}
else {
} else {
def cluster = zigbee.parse(description)
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07){
if (cluster && cluster.clusterId == 0x0006 && cluster.command == 0x07) {
if (cluster.data[0] == 0x00) {
log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
event = createEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
}
else {
} else {
log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
event = null
}
}
else {
} else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug "${cluster}"
}
}
return event
return event ? createEvent(event) : event
}
def off() {
@@ -150,42 +132,6 @@ def configure() {
sendEvent(name: "checkInterval", value: 2 * 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()
refresh() + zigbee.onOffConfig(0, 300) + zigbee.electricMeasurementPowerConfig()
}
//power config for devices with min reporting interval as 1 seconds and reporting interval if no activity as 10min (600s)
//min change in value is 01
def powerConfig() {
[
"zdo bind 0x${device.deviceNetworkId} 1 ${endpointId} 0x0B04 {${device.zigbeeId}} {}", "delay 200",
"zcl global send-me-a-report 0x0B04 0x050B 0x29 1 600 {05 00}", //The send-me-a-report is custom to the attribute type for CentraLite
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500"
]
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
//TODO: Remove this after getKnownDescription can parse it automatically
def getPowerDescription(descMap) {
def powerValue = "undefined"
if (descMap.cluster == "0B04") {
if (descMap.attrId == "050b") {
if(descMap.value!="ffff")
powerValue = zigbee.convertHexToInt(descMap.value)
}
}
else if (descMap.clusterId == "0B04") {
if(descMap.command=="07"){
return [type: "update", value : "power (0B04) capability configured successfully"]
}
}
if (powerValue != "undefined"){
return [type: "power", value : powerValue]
}
else {
return [:]
}
}
@@ -50,18 +50,18 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"status", type: "generic", width: 6, height: 4){
tileAttribute ("device.status", key: "PRIMARY_CONTROL") {
attributeState "closed", label:'${name}', icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821", nextState:"opening"
attributeState "open", label:'${name}', icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e", nextState:"closing"
attributeState "opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#ffe71e"
attributeState "closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#ffe71e"
attributeState "closed", label:'${name}', icon:"st.doors.garage.garage-closed", backgroundColor:"#00A0DC", nextState:"opening"
attributeState "open", label:'${name}', icon:"st.doors.garage.garage-open", backgroundColor:"#e86d13", nextState:"closing"
attributeState "opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#e86d13"
attributeState "closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#00A0DC"
}
}
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")
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00A0DC")
}
standardTile("acceleration", "device.acceleration", decoration: "flat", width: 2, height: 2) {
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0")
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#00A0DC")
state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff")
}
valueTile("temperature", "device.temperature", decoration: "flat", width: 2, height: 2) {
@@ -88,7 +88,7 @@ def parse(String description) {
log.debug "parse($description)"
def results = [:]
if (!isSupportedDescription(description) || zigbee.isZoneType19(description)) {
if (!isSupportedDescription(description) || description.startsWith("zone")) {
// Ignore this in favor of orientation-based state
// results = parseSingleMessage(description)
}
@@ -50,17 +50,17 @@ metadata {
tiles {
standardTile("status", "device.status", width: 2, height: 2) {
state("closed", label:'${name}', icon:"st.doors.garage.garage-closed", action: "actuate", backgroundColor:"#79b821", nextState:"opening")
state("open", label:'${name}', icon:"st.doors.garage.garage-open", action: "actuate", backgroundColor:"#ffa81e", nextState:"closing")
state("opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#ffe71e")
state("closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#ffe71e")
state("closed", label:'${name}', icon:"st.doors.garage.garage-closed", action: "actuate", backgroundColor:"#00A0DC", nextState:"opening")
state("open", label:'${name}', icon:"st.doors.garage.garage-open", action: "actuate", backgroundColor:"#e86d13", nextState:"closing")
state("opening", label:'${name}', icon:"st.doors.garage.garage-opening", backgroundColor:"#e86d13")
state("closing", label:'${name}', icon:"st.doors.garage.garage-closing", backgroundColor:"#00A0DC")
}
standardTile("contact", "device.contact") {
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
}
standardTile("acceleration", "device.acceleration", decoration: "flat") {
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0")
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#00A0DC")
state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff")
}
valueTile("temperature", "device.temperature", decoration: "flat") {
@@ -117,7 +117,7 @@ def parse(String description) {
log.debug "parse($description)"
def results = null
if (!isSupportedDescription(description) || zigbee.isZoneType19(description)) {
if (!isSupportedDescription(description) || description.startsWith("zone")) {
// Ignore this in favor of orientation-based state
// results = parseSingleMessage(description)
}
@@ -17,7 +17,7 @@ import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
metadata {
definition (name: "SmartSense Moisture Sensor",namespace: "smartthings", author: "SmartThings") {
definition(name: "SmartSense Moisture Sensor", namespace: "smartthings", author: "SmartThings") {
capability "Configuration"
capability "Battery"
capability "Refresh"
@@ -32,6 +32,7 @@ metadata {
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-S", deviceJoinName: "Water Leak Sensor"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-Seu", deviceJoinName: "Water Leak Sensor"
fingerprint inClusters: "0000,0001,0003,0020,0402,0500,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3315-L", deviceJoinName: "Iris Smart Water Sensor"
fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "moisturev4", deviceJoinName: "Water Leak Sensor"
}
@@ -54,15 +55,15 @@ metadata {
}
tiles(scale: 2) {
multiAttributeTile(name:"water", type: "generic", width: 6, height: 4){
tileAttribute ("device.water", key: "PRIMARY_CONTROL") {
attributeState "dry", label: "Dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
attributeState "wet", label: "Wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0"
multiAttributeTile(name: "water", type: "generic", width: 6, height: 4) {
tileAttribute("device.water", key: "PRIMARY_CONTROL") {
attributeState "dry", label: "Dry", icon: "st.alarm.water.dry", backgroundColor: "#ffffff"
attributeState "wet", label: "Wet", icon: "st.alarm.water.wet", backgroundColor: "#53a7c0"
}
}
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
state "temperature", label:'${currentValue}°',
backgroundColors:[
state "temperature", label: '${currentValue}°',
backgroundColors: [
[value: 31, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
@@ -73,13 +74,13 @@ metadata {
]
}
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
state "battery", label:'${currentValue}% battery', unit:""
state "battery", label: '${currentValue}% battery', unit: ""
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
state "default", action: "refresh.refresh", icon: "st.secondary.refresh"
}
main (["water", "temperature"])
main(["water", "temperature"])
details(["water", "temperature", "battery", "refresh"])
}
}
@@ -87,117 +88,43 @@ metadata {
def parse(String description) {
log.debug "description: $description"
Map map = [:]
if (description?.startsWith('catchall:')) {
map = parseCatchAllMessage(description)
}
else if (description?.startsWith('read attr -')) {
map = parseReportAttributeMessage(description)
}
else if (description?.startsWith('temperature: ')) {
map = parseCustomMessage(description)
}
else if (description?.startsWith('zone status')) {
// getEvent will handle temperature and humidity
Map map = zigbee.getEvent(description)
if (!map) {
if (description?.startsWith('zone status')) {
map = parseIasMessage(description)
} else {
Map descMap = zigbee.parseDescriptionAsMap(description)
if (descMap.clusterInt == 0x0001 && descMap.commandInt != 0x07 && descMap?.value) {
map = getBatteryResult(Integer.parseInt(descMap.value, 16))
} else if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) {
if (descMap.data[0] == "00") {
log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap"
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
} else {
log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}"
}
}
}
}
log.debug "Parse returned $map"
def result = map ? createEvent(map) : [:]
if (description?.startsWith('enroll request')) {
List cmds = enrollResponse()
List cmds = zigbee.enrollResponse()
log.debug "enroll response: ${cmds}"
result = cmds?.collect { new physicalgraph.device.HubAction(it) }
}
return result
}
private Map parseCatchAllMessage(String description) {
Map resultMap = [:]
def cluster = zigbee.parse(description)
if (shouldProcessMessage(cluster)) {
switch(cluster.clusterId) {
case 0x0001:
// 0x07 - configure reporting
if (cluster.command != 0x07) {
resultMap = getBatteryResult(cluster.data.last())
}
break
case 0x0402:
if (cluster.command == 0x07) {
if (cluster.data[0] == 0x00){
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
resultMap = [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
}
}
return resultMap
}
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
(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)
resultMap = getTemperatureResult(value)
}
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: ')) {
def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale())
resultMap = getTemperatureResult(value)
}
return resultMap
}
private Map parseIasMessage(String description) {
ZoneStatus zs = zigbee.parseZoneStatus(description)
return zs.isAlarm1Set() ? getMoistureResult('wet') : getMoistureResult('dry')
}
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16).shortValue() / 100
if(getTemperatureScale() == "C"){
return Math.round(celsius)
} else {
return Math.round(celsiusToFahrenheit(celsius))
}
}
private Map getBatteryResult(rawValue) {
log.debug "Battery rawValue = ${rawValue}"
def linkText = getLinkText(device)
@@ -238,40 +165,18 @@ private Map getBatteryResult(rawValue) {
return result
}
private Map getTemperatureResult(value) {
log.debug 'TEMP'
if (tempOffset) {
def offset = tempOffset as int
def v = value as int
value = v + offset
}
def descriptionText
if ( temperatureScale == 'C' )
descriptionText = '{{ device.displayName }} was {{ value }}°C'
else
descriptionText = '{{ device.displayName }} was {{ value }}°F'
return [
name: 'temperature',
value: value,
descriptionText: descriptionText,
translatable: true,
unit: temperatureScale
]
}
private Map getMoistureResult(value) {
log.debug "water"
def descriptionText
if ( value == "wet" )
if (value == "wet")
descriptionText = '{{ device.displayName }} is wet'
else
descriptionText = '{{ device.displayName }} is dry'
return [
name: 'water',
value: value,
name : 'water',
value : value,
descriptionText: descriptionText,
translatable: true
translatable : true
]
}
@@ -284,12 +189,10 @@ def ping() {
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", "delay 200"
]
def refreshCmds = zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) +
zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020)
return refreshCmds + enrollResponse()
return refreshCmds + zigbee.enrollResponse()
}
def configure() {
@@ -301,42 +204,3 @@ def configure() {
// 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() {
log.debug "Sending enroll response"
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
[
//Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response
"raw 0x500 {01 23 00 00 00}",
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
]
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
private hex(value) {
new BigInteger(Math.round(value).toString()).toString(16)
}
private String swapEndianHex(String hex) {
reverseArray(hex.decodeHex()).encodeHex()
}
private byte[] reverseArray(byte[] array) {
int i = 0;
int j = array.length - 1;
byte tmp;
while (j > i) {
tmp = array[j];
array[j] = array[i];
array[i] = tmp;
j--;
i++;
}
return array
}
@@ -37,13 +37,13 @@ metadata {
multiAttributeTile(name:"water", type: "generic", width: 6, height: 4){
tileAttribute ("device.water", key: "PRIMARY_CONTROL") {
attributeState "dry", label: "Dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff"
attributeState "wet", label: "Wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0"
attributeState "wet", label: "Wet", icon:"st.alarm.water.wet", backgroundColor:"#00A0DC"
}
}
standardTile("temperatureState", "device.temperature", width: 2, height: 2) {
state "normal", icon:"st.alarm.temperature.normal", backgroundColor:"#ffffff"
state "freezing", icon:"st.alarm.temperature.freeze", backgroundColor:"#53a7c0"
state "overheated", icon:"st.alarm.temperature.overheat", backgroundColor:"#F80000"
state "freezing", icon:"st.alarm.temperature.freeze", backgroundColor:"#00A0DC"
state "overheated", icon:"st.alarm.temperature.overheat", backgroundColor:"#e86d13"
}
valueTile("temperature", "device.temperature", width: 2, height: 2) {
state("temperature", label:'${currentValue}°',
@@ -17,7 +17,7 @@ import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
metadata {
definition (name: "SmartSense Motion Sensor", namespace: "smartthings", author: "SmartThings") {
definition(name: "SmartSense Motion Sensor", namespace: "smartthings", author: "SmartThings") {
capability "Motion Sensor"
capability "Configuration"
capability "Battery"
@@ -35,6 +35,7 @@ metadata {
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3326"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05", outClusters: "0019", manufacturer: "CentraLite", model: "3326-L", deviceJoinName: "Iris Motion Sensor"
fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "motionv4", deviceJoinName: "Motion Sensor"
fingerprint inClusters: "0000,0001,0003,000F,0020,0402,0500", outClusters: "0019", manufacturer: "SmartThings", model: "motionv5", deviceJoinName: "Motion Sensor"
}
simulator {
@@ -57,15 +58,15 @@ metadata {
}
tiles(scale: 2) {
multiAttributeTile(name:"motion", type: "generic", width: 6, height: 4){
tileAttribute ("device.motion", key: "PRIMARY_CONTROL") {
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
multiAttributeTile(name: "motion", type: "generic", width: 6, height: 4) {
tileAttribute("device.motion", key: "PRIMARY_CONTROL") {
attributeState "active", label: 'motion', icon: "st.motion.motion.active", backgroundColor: "#53a7c0"
attributeState "inactive", label: 'no motion', icon: "st.motion.motion.inactive", backgroundColor: "#ffffff"
}
}
valueTile("temperature", "device.temperature", width: 2, height: 2) {
state("temperature", label:'${currentValue}°', unit:"F",
backgroundColors:[
state("temperature", label: '${currentValue}°', unit: "F",
backgroundColors: [
[value: 31, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
@@ -77,10 +78,10 @@ metadata {
)
}
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
state "battery", label:'${currentValue}% battery', unit:""
state "battery", label: '${currentValue}% battery', unit: ""
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
state "default", action: "refresh.refresh", icon: "st.secondary.refresh"
}
main(["motion", "temperature"])
@@ -90,116 +91,40 @@ metadata {
def parse(String description) {
log.debug "description: $description"
Map map = [:]
if (description?.startsWith('catchall:')) {
map = parseCatchAllMessage(description)
}
else if (description?.startsWith('read attr -')) {
map = parseReportAttributeMessage(description)
}
else if (description?.startsWith('temperature: ')) {
map = parseCustomMessage(description)
}
else if (description?.startsWith('zone status')) {
Map map = zigbee.getEvent(description)
if (!map) {
if (description?.startsWith('zone status')) {
map = parseIasMessage(description)
} else {
Map descMap = zigbee.parseDescriptionAsMap(description)
if (descMap?.clusterInt == 0x0001 && descMap.commandInt != 0x07 && descMap?.value) {
map = getBatteryResult(Integer.parseInt(descMap.value, 16))
} else if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) {
if (descMap.data[0] == "00") {
log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap"
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
} else {
log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}"
}
} else if (descMap.clusterInt == 0x0406 && descMap.attrInt == 0x0000) {
def value = descMap.value.endsWith("01") ? "active" : "inactive"
log.debug "Doing a read attr motion event"
map = getMotionResult(value)
}
}
}
log.debug "Parse returned $map"
def result = map ? createEvent(map) : [:]
if (description?.startsWith('enroll request')) {
List cmds = enrollResponse()
List cmds = zigbee.enrollResponse()
log.debug "enroll response: ${cmds}"
result = cmds?.collect { new physicalgraph.device.HubAction(it) }
}
return result
}
private Map parseCatchAllMessage(String description) {
Map resultMap = [:]
def cluster = zigbee.parse(description)
if (shouldProcessMessage(cluster)) {
switch(cluster.clusterId) {
case 0x0001:
// 0x07 - configure reporting
if (cluster.command != 0x07) {
resultMap = getBatteryResult(cluster.data.last())
}
break
case 0x0402:
if (cluster.command == 0x07) {
if (cluster.data[0] == 0x00) {
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
resultMap = [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:
// 0x07 - configure reporting
if (cluster.command != 0x07) {
log.debug 'motion'
resultMap.name = 'motion'
}
break
}
}
return resultMap
}
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
(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)
resultMap = getTemperatureResult(value)
}
else if (descMap.cluster == "0001" && descMap.attrId == "0020") {
resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16))
}
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: ')) {
def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale())
resultMap = getTemperatureResult(value)
}
return resultMap
}
private Map parseIasMessage(String description) {
ZoneStatus zs = zigbee.parseZoneStatus(description)
@@ -207,15 +132,6 @@ private Map parseIasMessage(String description) {
return (zs.isAlarm1Set() || zs.isAlarm2Set()) ? getMotionResult('active') : getMotionResult('inactive')
}
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16).shortValue() / 100
if(getTemperatureScale() == "C"){
return Math.round(celsius)
} else {
return Math.round(celsiusToFahrenheit(celsius))
}
}
private Map getBatteryResult(rawValue) {
log.debug "Battery rawValue = ${rawValue}"
def linkText = getLinkText(device)
@@ -255,36 +171,14 @@ private Map getBatteryResult(rawValue) {
return result
}
private Map getTemperatureResult(value) {
log.debug 'TEMP'
if (tempOffset) {
def offset = tempOffset as int
def v = value as int
value = v + offset
}
def descriptionText
if ( temperatureScale == 'C' )
descriptionText = '{{ device.displayName }} was {{ value }}°C'
else
descriptionText = '{{ device.displayName }} was {{ value }}°F'
return [
name: 'temperature',
value: value,
descriptionText: descriptionText,
translatable: true,
unit: temperatureScale
]
}
private Map getMotionResult(value) {
log.debug 'motion'
String descriptionText = value == 'active' ? "{{ device.displayName }} detected motion" : "{{ device.displayName }} motion has stopped"
return [
name: 'motion',
value: value,
name : 'motion',
value : value,
descriptionText: descriptionText,
translatable: true
translatable : true
]
}
@@ -292,17 +186,16 @@ 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
return zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) // Read the Battery Level
}
def refresh() {
log.debug "refresh called"
def refreshCmds = [
"st rattr 0x${device.deviceNetworkId} 1 0x402 0", "delay 200",
"st rattr 0x${device.deviceNetworkId} 1 1 0x20", "delay 200"
]
return refreshCmds + enrollResponse()
def refreshCmds = zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) +
zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000)
return refreshCmds + zigbee.enrollResponse()
}
def configure() {
@@ -314,42 +207,3 @@ def configure() {
// 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() {
log.debug "Sending enroll response"
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
[
//Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response
"raw 0x500 {01 23 00 00 00}",
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
]
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
private hex(value) {
new BigInteger(Math.round(value).toString()).toString(16)
}
private String swapEndianHex(String hex) {
reverseArray(hex.decodeHex()).encodeHex()
}
private byte[] reverseArray(byte[] array) {
int i = 0;
int j = array.length - 1;
byte tmp;
while (j > i) {
tmp = array[j];
array[j] = array[i];
array[i] = tmp;
j--;
i++;
}
return array
}
@@ -45,7 +45,7 @@ metadata {
def parse(String description) {
def results = [:]
if (isZoneType19(description) || !isSupportedDescription(description)) {
if (description.startsWith("zone") || !isSupportedDescription(description)) {
results = parseBasicMessage(description)
}
else if (isMotionStatusMessage(description)){
@@ -87,16 +87,12 @@ private String parseName(String description) {
}
private String parseValue(String description) {
if (isZoneType19(description)) {
if (translateStatusZoneType19(description)) {
return "active"
}
else {
return "inactive"
}
}
def zs = zigbee.parseZoneStatus(description)
if (zs) {
zs.isAlarm1Set() ? "active" : "inactive"
} else {
description
}
}
private parseDescriptionText(String linkText, String value, String description) {
@@ -14,9 +14,10 @@
* under the License.
*/
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
import physicalgraph.zigbee.zcl.DataType
metadata {
definition (name: "SmartSense Multi Sensor", namespace: "smartthings", author: "SmartThings") {
definition(name: "SmartSense Multi Sensor", namespace: "smartthings", author: "SmartThings") {
capability "Three Axis"
capability "Battery"
@@ -73,25 +74,25 @@ metadata {
}
tiles(scale: 2) {
multiAttributeTile(name:"status", type: "generic", width: 6, height: 4){
tileAttribute ("device.status", key: "PRIMARY_CONTROL") {
attributeState "open", label:'Open', icon:"st.contact.contact.open", backgroundColor:"#ffa81e"
attributeState "closed", label:'Closed', icon:"st.contact.contact.closed", backgroundColor:"#79b821"
attributeState "garage-open", label:'Open', icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e"
attributeState "garage-closed", label:'Closed', icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821"
multiAttributeTile(name: "status", type: "generic", width: 6, height: 4) {
tileAttribute("device.status", key: "PRIMARY_CONTROL") {
attributeState "open", label: 'Open', icon: "st.contact.contact.open", backgroundColor: "#e86d13"
attributeState "closed", label: 'Closed', icon: "st.contact.contact.closed", backgroundColor: "#00a0dc"
attributeState "garage-open", label: 'Open', icon: "st.doors.garage.garage-open", backgroundColor: "#e86d13"
attributeState "garage-closed", label: 'Closed', icon: "st.doors.garage.garage-closed", backgroundColor: "#00a0dc"
}
}
standardTile("contact", "device.contact", width: 2, height: 2) {
state("open", label:'Open', icon:"st.contact.contact.open", backgroundColor:"#ffa81e")
state("closed", label:'Closed', icon:"st.contact.contact.closed", backgroundColor:"#79b821")
state("open", label: 'Open', icon: "st.contact.contact.open", backgroundColor: "#e86d13")
state("closed", label: 'Closed', icon: "st.contact.contact.closed", backgroundColor: "#00a0dc")
}
standardTile("acceleration", "device.acceleration", width: 2, height: 2) {
state("active", label:'Active', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0")
state("inactive", label:'Inactive', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff")
state("active", label: 'Active', icon: "st.motion.acceleration.active", backgroundColor: "#53a7c0")
state("inactive", label: 'Inactive', icon: "st.motion.acceleration.inactive", backgroundColor: "#ffffff")
}
valueTile("temperature", "device.temperature", width: 2, height: 2) {
state("temperature", label:'${currentValue}°',
backgroundColors:[
state("temperature", label: '${currentValue}°',
backgroundColors: [
[value: 31, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
@@ -103,181 +104,140 @@ metadata {
)
}
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
state "battery", label:'${currentValue}% battery', unit:""
state "battery", label: '${currentValue}% battery', unit: ""
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
state "default", action: "refresh.refresh", icon: "st.secondary.refresh"
}
main(["status", "acceleration", "temperature"])
details(["status", "acceleration", "temperature", "battery", "refresh"])
}
}
}
def parse(String description) {
Map map = [:]
if (description?.startsWith('catchall:')) {
map = parseCatchAllMessage(description)
def maps = []
maps << zigbee.getEvent(description)
if (!maps[0]) {
maps = []
if (description?.startsWith('zone status')) {
maps += parseIasMessage(description)
} else {
Map descMap = zigbee.parseDescriptionAsMap(description)
if (descMap?.clusterInt == 0x0001 && descMap.commandInt != 0x07 && descMap?.value) {
maps << getBatteryResult(Integer.parseInt(descMap.value, 16))
} else if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) {
if (descMap.data[0] == "00") {
log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap"
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
} else {
log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}"
}
else if (description?.startsWith('temperature: ')) {
map = parseCustomMessage(description)
} else {
maps += handleAcceleration(descMap)
}
else if (description?.startsWith('zone status')) {
map = parseIasMessage(description)
}
} else if (maps[0].name == "temperature") {
def map = maps[0]
if (tempOffset) {
map.value = (int) map.value + (int) tempOffset
}
map.descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C' : '{{ device.displayName }} was {{ value }}°F'
map.translatable = true
}
def result = map ? createEvent(map) : [:]
def result = maps.inject([]) {acc, it ->
if (it) {
acc << createEvent(it)
}
}
if (description?.startsWith('enroll request')) {
List cmds = enrollResponse()
List cmds = zigbee.enrollResponse()
log.debug "enroll response: ${cmds}"
result = cmds?.collect { new physicalgraph.device.HubAction(it) }
}
else if (description?.startsWith('read attr -')) {
result = parseReportAttributeMessage(description).each { createEvent(it) }
return result
}
private List<Map> handleAcceleration(descMap) {
def result = []
if (descMap.clusterInt == 0xFC02 && descMap.attrInt == 0x0010) {
def value = descMap.value == "01" ? "active" : "inactive"
log.debug "Acceleration $value"
result << [
name : "acceleration",
value : value,
descriptionText: "{{ device.displayName }} was $value",
isStateChange : isStateChange(device, "acceleration", value),
translatable : true
]
if (descMap.additionalAttrs) {
result += parseAxis(descMap.additionalAttrs)
}
} else if (descMap.clusterInt == 0xFC02 && descMap.attrInt == 0x0012) {
def addAttrs = descMap.additionalAttrs
addAttrs << ["attrInt": descMap.attrInt, "value": descMap.value]
result += parseAxis(addAttrs)
}
return result
}
private Map parseCatchAllMessage(String description) {
Map resultMap = [:]
def cluster = zigbee.parse(description)
log.debug cluster
if (shouldProcessMessage(cluster)) {
switch(cluster.clusterId) {
case 0x0001:
// 0x07 - configure reporting
if (cluster.command != 0x07) {
resultMap = getBatteryResult(cluster.data.last())
}
break
private List<Map> parseAxis(List<Map> attrData) {
def results = []
def x = hexToSignedInt(attrData.find { it.attrInt == 0x0012 }?.value)
def y = hexToSignedInt(attrData.find { it.attrInt == 0x0013 }?.value)
def z = hexToSignedInt(attrData.find { it.attrInt == 0x0014 }?.value)
case 0xFC02:
log.debug 'ACCELERATION'
break
case 0x0402:
if (cluster.command == 0x07) {
if(cluster.data[0] == 0x00) {
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
resultMap = [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
}
}
return resultMap
}
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
return !ignoredMessage
}
private List parseReportAttributeMessage(String description) {
Map descMap = (description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
}
List result = []
if (descMap.cluster == "0402" && descMap.attrId == "0000") {
def value = getTemperature(descMap.value)
result << getTemperatureResult(value)
}
else if (descMap.cluster == "FC02" && descMap.attrId == "0010") {
if (descMap.value.size() == 32) {
// value will look like 00ae29001403e2290013001629001201
// breaking this apart and swapping byte order where appropriate, this breaks down to:
// X (0x0012) = 0x0016
// Y (0x0013) = 0x03E2
// Z (0x0014) = 0x00AE
// note that there is a known bug in that the x,y,z attributes are interpreted in the wrong order
// this will be fixed in a future update
def threeAxisAttributes = descMap.value[0..-9]
result << parseAxis(threeAxisAttributes)
descMap.value = descMap.value[-2..-1]
}
result << getAccelerationResult(descMap.value)
}
else if (descMap.cluster == "FC02" && descMap.attrId == "0012" && descMap.value.size() == 24) {
// The size is checked to ensure the attribute report contains X, Y and Z values
// If all three axis are not included then the attribute report is ignored
result << parseAxis(descMap.value)
}
else if (descMap.cluster == "0001" && descMap.attrId == "0020") {
result << getBatteryResult(Integer.parseInt(descMap.value, 16))
}
return result
}
private Map parseCustomMessage(String description) {
Map resultMap = [:]
if (description?.startsWith('temperature: ')) {
def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale())
resultMap = getTemperatureResult(value)
}
return resultMap
}
private Map parseIasMessage(String description) {
ZoneStatus zs = zigbee.parseZoneStatus(description)
Map resultMap = [:]
if (garageSensor != "Yes"){
resultMap = zs.isAlarm1Set() ? getContactResult('open') : getContactResult('closed')
}
return resultMap
}
def updated() {
log.debug "updated called"
log.info "garage value : $garageSensor"
if (garageSensor == "Yes") {
def descriptionText = "Updating device to garage sensor"
if (device.latestValue("status") == "open") {
sendEvent(name: 'status', value: 'garage-open', descriptionText: descriptionText, translatable: true)
}
else if (device.latestValue("status") == "closed") {
sendEvent(name: 'status', value: 'garage-closed', descriptionText: descriptionText, translatable: true)
}
}
else {
def descriptionText = "Updating device to open/close sensor"
if (device.latestValue("status") == "garage-open") {
sendEvent(name: 'status', value: 'open', descriptionText: descriptionText, translatable: true)
}
else if (device.latestValue("status") == "garage-closed") {
sendEvent(name: 'status', value: 'closed', descriptionText: descriptionText, translatable: true)
}
}
}
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16).shortValue() / 100
if(getTemperatureScale() == "C"){
return Math.round(celsius)
def xyzResults = [:]
if (device.getDataValue("manufacturer") == "SmartThings") {
// This mapping matches the current behavior of the Device Handler for the Centralite sensors
xyzResults.x = z
xyzResults.y = y
xyzResults.z = -x
} else {
return Math.round(celsiusToFahrenheit(celsius))
// The axises reported by the Device Handler differ from the axises reported by the sensor
// This may change in the future
xyzResults.x = z
xyzResults.y = x
xyzResults.z = y
}
log.debug "parseAxis -- ${xyzResults}"
if (garageSensor == "Yes")
results += garageEvent(xyzResults.z)
def value = "${xyzResults.x},${xyzResults.y},${xyzResults.z}"
results << [
name : "threeAxis",
value : value,
linkText : getLinkText(device),
descriptionText: "${getLinkText(device)} was ${value}",
handlerName : name,
isStateChange : isStateChange(device, "threeAxis", value),
displayed : false
]
results
}
private List<Map> parseIasMessage(String description) {
ZoneStatus zs = zigbee.parseZoneStatus(description)
List<Map> results = []
if (garageSensor != "Yes") {
def value = zs.isAlarm1Set() ? 'open' : 'closed'
log.debug "Contact: ${device.displayName} value = ${value}"
def descriptionText = value == 'open' ? '{{ device.displayName }} was opened' : '{{ device.displayName }} was closed'
results << [name: 'contact', value: value, descriptionText: descriptionText, displayed: false, translatable: true]
results << [name: 'status', value: value, descriptionText: descriptionText, translatable: true]
}
return results
}
private Map getBatteryResult(rawValue) {
log.debug "Battery rawValue = ${rawValue}"
@@ -316,54 +276,24 @@ private Map getBatteryResult(rawValue) {
return result
}
private Map getTemperatureResult(value) {
log.debug "Temperature"
if (tempOffset) {
def offset = tempOffset as int
def v = value as int
value = v + offset
List<Map> garageEvent(zValue) {
List<Map> results = []
def absValue = zValue.abs()
def contactValue = null
def garageValue = null
if (absValue > 900) {
contactValue = 'closed'
garageValue = 'garage-closed'
} else if (absValue < 100) {
contactValue = 'open'
garageValue = 'garage-open'
}
def descriptionText = temperatureScale == 'C' ? '{{ device.displayName }} was {{ value }}°C':
'{{ device.displayName }} was {{ value }}°F'
return [
name: 'temperature',
value: value,
descriptionText: descriptionText,
translatable: true,
unit: temperatureScale
]
}
private Map getContactResult(value) {
log.debug "Contact: ${device.displayName} value = ${value}"
def descriptionText = value == 'open' ? '{{ device.displayName }} was opened' : '{{ device.displayName }} was closed'
sendEvent(name: 'contact', value: value, descriptionText: descriptionText, displayed: false, translatable: true)
return [name: 'status', value: value, descriptionText: descriptionText, translatable: true]
}
private getAccelerationResult(numValue) {
log.debug "Acceleration"
def name = "acceleration"
def value
def descriptionText
if ( numValue.endsWith("1") ) {
value = "active"
descriptionText = '{{ device.displayName }} was active'
} else {
value = "inactive"
descriptionText = '{{ device.displayName }} was inactive'
if (contactValue != null) {
def descriptionText = contactValue == 'open' ? '{{ device.displayName }} was opened' : '{{ device.displayName }} was closed'
results << [name: 'contact', value: contactValue, descriptionText: descriptionText, displayed: false, translatable: true]
results << [name: 'status', value: garageValue, descriptionText: descriptionText, translatable: true]
}
def isStateChange = isStateChange(device, name, value)
return [
name: name,
value: value,
descriptionText: descriptionText,
isStateChange: isStateChange,
translatable: true
]
results
}
/**
@@ -376,27 +306,12 @@ def ping() {
def refresh() {
log.debug "Refreshing Values "
def refreshCmds = []
def refreshCmds = zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) +
zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) +
zigbee.readAttribute(0xFC02, 0x0010, [mfgCode: manufacturerCode]) +
zigbee.enrollResponse()
if (device.getDataValue("manufacturer") == "SmartThings") {
log.debug "Refreshing Values for manufacturer: SmartThings "
/* These values of Motion Threshold Multiplier(0x01) and Motion Threshold (0x0276)
seem to be giving pretty accurate results for the XYZ co-ordinates for this manufacturer.
Separating these out in a separate if-else because I do not want to touch Centralite part
as of now.
*/
refreshCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x01, [mfgCode: manufacturerCode])
refreshCmds += zigbee.writeAttribute(0xFC02, 0x0002, 0x21, 0x0276, [mfgCode: manufacturerCode])
} else {
refreshCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x02, [mfgCode: manufacturerCode])
}
//Common refresh commands
refreshCmds += zigbee.readAttribute(0x0402, 0x0000) +
zigbee.readAttribute(0x0001, 0x0020) +
zigbee.readAttribute(0xFC02, 0x0010, [mfgCode: manufacturerCode])
return refreshCmds + enrollResponse()
return refreshCmds
}
def configure() {
@@ -405,61 +320,54 @@ def configure() {
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
log.debug "Configuring Reporting"
def configCmds = []
if (device.getDataValue("manufacturer") == "SmartThings") {
log.debug "Refreshing Values for manufacturer: SmartThings "
/* These values of Motion Threshold Multiplier(0x01) and Motion Threshold (0x0276)
seem to be giving pretty accurate results for the XYZ co-ordinates for this manufacturer.
Separating these out in a separate if-else because I do not want to touch Centralite part
as of now.
*/
configCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x01, [mfgCode: manufacturerCode])
configCmds += zigbee.writeAttribute(0xFC02, 0x0002, 0x21, 0x0276, [mfgCode: manufacturerCode])
} else {
// Write a motion threshold of 2 * .063g = .126g
// Currently due to a Centralite firmware issue, this will cause a read attribute response that
// indicates acceleration even when there isn't.
configCmds += zigbee.writeAttribute(0xFC02, 0x0000, 0x20, 0x02, [mfgCode: manufacturerCode])
}
// 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() +
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])
zigbee.configureReporting(0xFC02, 0x0010, DataType.BITMAP8, 10, 3600, 0x01, [mfgCode: manufacturerCode]) +
zigbee.configureReporting(0xFC02, 0x0012, DataType.INT16, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) +
zigbee.configureReporting(0xFC02, 0x0013, DataType.INT16, 1, 3600, 0x0001, [mfgCode: manufacturerCode]) +
zigbee.configureReporting(0xFC02, 0x0014, DataType.INT16, 1, 3600, 0x0001, [mfgCode: manufacturerCode])
return refresh() + configCmds
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
def enrollResponse() {
log.debug "Sending enroll response"
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
[
//Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response
"raw 0x500 {01 23 00 00 00}", "delay 200",
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
]
}
private Map parseAxis(String description) {
def z = hexToSignedInt(description[0..3])
def y = hexToSignedInt(description[10..13])
def x = hexToSignedInt(description[20..23])
def xyzResults = [x: x, y: y, z: z]
if (device.getDataValue("manufacturer") == "SmartThings") {
// This mapping matches the current behavior of the Device Handler for the Centralite sensors
xyzResults.x = z
xyzResults.y = y
xyzResults.z = -x
} else {
// The axises reported by the Device Handler differ from the axises reported by the sensor
// This may change in the future
xyzResults.x = z
xyzResults.y = x
xyzResults.z = y
def updated() {
log.debug "updated called"
log.info "garage value : $garageSensor"
if (garageSensor == "Yes") {
def descriptionText = "Updating device to garage sensor"
if (device.latestValue("status") == "open") {
sendEvent(name: 'status', value: 'garage-open', descriptionText: descriptionText, translatable: true)
} else if (device.latestValue("status") == "closed") {
sendEvent(name: 'status', value: 'garage-closed', descriptionText: descriptionText, translatable: true)
}
} else {
def descriptionText = "Updating device to open/close sensor"
if (device.latestValue("status") == "garage-open") {
sendEvent(name: 'status', value: 'open', descriptionText: descriptionText, translatable: true)
} else if (device.latestValue("status") == "garage-closed") {
sendEvent(name: 'status', value: 'closed', descriptionText: descriptionText, translatable: true)
}
}
log.debug "parseAxis -- ${xyzResults}"
if (garageSensor == "Yes")
garageEvent(xyzResults.z)
getXyzResult(xyzResults, description)
}
private hexToSignedInt(hexVal) {
@@ -467,44 +375,6 @@ private hexToSignedInt(hexVal) {
unsignedVal > 32767 ? unsignedVal - 65536 : unsignedVal
}
def garageEvent(zValue) {
def absValue = zValue.abs()
def contactValue = null
def garageValue = null
if (absValue>900) {
contactValue = 'closed'
garageValue = 'garage-closed'
}
else if (absValue < 100) {
contactValue = 'open'
garageValue = 'garage-open'
}
if (contactValue != null){
def descriptionText = contactValue == 'open' ? '{{ device.displayName }} was opened' :'{{ device.displayName }} was closed'
sendEvent(name: 'contact', value: contactValue, descriptionText: descriptionText, displayed:false, translatable: true)
sendEvent(name: 'status', value: garageValue, descriptionText: descriptionText, translatable: true)
}
}
private Map getXyzResult(results, description) {
def name = "threeAxis"
def value = "${results.x},${results.y},${results.z}"
def linkText = getLinkText(device)
def descriptionText = "$linkText was $value"
def isStateChange = isStateChange(device, name, value)
[
name: name,
value: value,
unit: null,
linkText: linkText,
descriptionText: descriptionText,
handlerName: name,
isStateChange: isStateChange,
displayed: false
]
}
private getManufacturerCode() {
if (device.getDataValue("manufacturer") == "SmartThings") {
return "0x110A"
@@ -516,25 +386,3 @@ private getManufacturerCode() {
private hexToInt(value) {
new BigInteger(value, 16)
}
private hex(value) {
new BigInteger(Math.round(value).toString()).toString(16)
}
private String swapEndianHex(String hex) {
reverseArray(hex.decodeHex()).encodeHex()
}
private byte[] reverseArray(byte[] array) {
int i = 0;
int j = array.length - 1;
byte tmp;
while (j > i) {
tmp = array[j];
array[j] = array[i];
array[i] = tmp;
j--;
i++;
}
return array
}
@@ -86,7 +86,7 @@ metadata {
def parse(String description) {
def results
if (!isSupportedDescription(description) || zigbee.isZoneType19(description)) {
if (!isSupportedDescription(description) || description.startsWith("zone")) {
results = parseSingleMessage(description)
}
else if (description == 'updated') {
@@ -488,12 +488,7 @@ private String parseValue(String description) {
if (!isSupportedDescription(description)) {
return description
}
else if (zigbee.translateStatusZoneType19(description)) {
return "open"
}
else {
return "closed"
}
return zigbee.parseZoneStatus(description)?.isAlarm1Set() ? "open" : "closed"
}
private parseDescriptionText(String linkText, String value, String description) {
@@ -16,7 +16,7 @@
import physicalgraph.zigbee.clusters.iaszone.ZoneStatus
metadata {
definition (name: "SmartSense Open/Closed Sensor", namespace: "smartthings", author: "SmartThings") {
definition(name: "SmartSense Open/Closed Sensor", namespace: "smartthings", author: "SmartThings") {
capability "Battery"
capability "Configuration"
capability "Contact Sensor"
@@ -43,16 +43,16 @@ metadata {
}
tiles(scale: 2) {
multiAttributeTile(name:"contact", type: "generic", width: 6, height: 4){
tileAttribute ("device.contact", key: "PRIMARY_CONTROL") {
attributeState "open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e"
attributeState "closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821"
multiAttributeTile(name: "contact", type: "generic", width: 6, height: 4) {
tileAttribute("device.contact", key: "PRIMARY_CONTROL") {
attributeState "open", label: '${name}', icon: "st.contact.contact.open", backgroundColor: "#ffa81e"
attributeState "closed", label: '${name}', icon: "st.contact.contact.closed", backgroundColor: "#79b821"
}
}
valueTile("temperature", "device.temperature", inactiveLabel: false, width: 2, height: 2) {
state "temperature", label:'${currentValue}°',
backgroundColors:[
state "temperature", label: '${currentValue}°',
backgroundColors: [
[value: 31, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
@@ -63,135 +63,57 @@ metadata {
]
}
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
state "battery", label:'${currentValue}% battery', unit:""
state "battery", label: '${currentValue}% battery', unit: ""
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
state "default", action: "refresh.refresh", icon: "st.secondary.refresh"
}
main (["contact", "temperature"])
details(["contact","temperature","battery","refresh"])
main(["contact", "temperature"])
details(["contact", "temperature", "battery", "refresh"])
}
}
def parse(String description) {
log.debug "description: $description"
Map map = [:]
if (description?.startsWith('catchall:')) {
map = parseCatchAllMessage(description)
}
else if (description?.startsWith('read attr -')) {
map = parseReportAttributeMessage(description)
}
else if (description?.startsWith('temperature: ')) {
map = parseCustomMessage(description)
}
else if (description?.startsWith('zone status')) {
Map map = zigbee.getEvent(description)
if (!map) {
if (description?.startsWith('zone status')) {
map = parseIasMessage(description)
} else {
Map descMap = zigbee.parseDescriptionAsMap(description)
if (descMap?.clusterInt == 0x0001 && descMap.commandInt != 0x07 && descMap?.value) {
map = getBatteryResult(Integer.parseInt(descMap.value, 16))
} else if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) {
if (descMap.data[0] == "00") {
log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap"
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
} else {
log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}"
}
}
}
}
log.debug "Parse returned $map"
def result = map ? createEvent(map) : [:]
if (description?.startsWith('enroll request')) {
List cmds = enrollResponse()
List cmds = zigbee.enrollResponse()
log.debug "enroll response: ${cmds}"
result = cmds?.collect { new physicalgraph.device.HubAction(it) }
}
return result
}
private Map parseCatchAllMessage(String description) {
Map resultMap = [:]
def cluster = zigbee.parse(description)
if (shouldProcessMessage(cluster)) {
switch(cluster.clusterId) {
case 0x0001:
// 0x07 - configure reporting
if (cluster.command != 0x07) {
resultMap = getBatteryResult(cluster.data.last())
}
break
case 0x0402:
if (cluster.command == 0x07){
if (cluster.data[0] == 0x00) {
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
resultMap = [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
}
}
return resultMap
}
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
(cluster.data.size() > 0 && cluster.data.first() == 0x3e)
return !ignoredMessage
}
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)
resultMap = getTemperatureResult(value)
}
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: ')) {
def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale())
resultMap = getTemperatureResult(value)
}
return resultMap
}
private Map parseIasMessage(String description) {
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"){
return celsius
} else {
return celsiusToFahrenheit(celsius) as Integer
}
}
private Map getBatteryResult(rawValue) {
log.debug 'Battery'
def linkText = getLinkText(device)
@@ -214,30 +136,13 @@ private Map getBatteryResult(rawValue) {
return result
}
private Map getTemperatureResult(value) {
log.debug 'TEMP'
def linkText = getLinkText(device)
if (tempOffset) {
def offset = tempOffset as int
def v = value as int
value = v + offset
}
def descriptionText = "${linkText} was ${value}°${temperatureScale}"
return [
name: 'temperature',
value: value,
descriptionText: descriptionText,
unit: temperatureScale
]
}
private Map getContactResult(value) {
log.debug 'Contact Status'
def linkText = getLinkText(device)
def descriptionText = "${linkText} was ${value == 'open' ? 'opened' : 'closed'}"
return [
name: 'contact',
value: value,
name : 'contact',
value : value,
descriptionText: descriptionText
]
}
@@ -251,12 +156,10 @@ def ping() {
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", "delay 200"
]
def refreshCmds = zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) +
zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020)
return refreshCmds + enrollResponse()
return refreshCmds + zigbee.enrollResponse()
}
def configure() {
@@ -270,42 +173,3 @@ def configure() {
// 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() {
log.debug "Sending enroll response"
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
[
//Resending the CIE in case the enroll request is sent before CIE is written
"zcl global write 0x500 0x10 0xf0 {${zigbeeEui}}", "delay 200",
"send 0x${device.deviceNetworkId} 1 ${endpointId}", "delay 500",
//Enroll Response
"raw 0x500 {01 23 00 00 00}",
"send 0x${device.deviceNetworkId} 1 1", "delay 200"
]
}
private getEndpointId() {
new BigInteger(device.endpointId, 16).toString()
}
private hex(value) {
new BigInteger(Math.round(value).toString()).toString(16)
}
private String swapEndianHex(String hex) {
reverseArray(hex.decodeHex()).encodeHex()
}
private byte[] reverseArray(byte[] array) {
int i = 0;
int j = array.length - 1;
byte tmp;
while (j > i) {
tmp = array[j];
array[j] = array[i];
array[i] = tmp;
j--;
i++;
}
return array
}
@@ -13,8 +13,10 @@
* for the specific language governing permissions and limitations under the License.
*
*/
import physicalgraph.zigbee.zcl.DataType
metadata {
definition (name: "SmartSense Temp/Humidity Sensor",namespace: "smartthings", author: "SmartThings") {
definition(name: "SmartSense Temp/Humidity Sensor", namespace: "smartthings", author: "SmartThings") {
capability "Configuration"
capability "Battery"
capability "Refresh"
@@ -40,10 +42,10 @@ metadata {
}
tiles(scale: 2) {
multiAttributeTile(name:"temperature", type: "generic", width: 6, height: 4){
tileAttribute ("device.temperature", key: "PRIMARY_CONTROL") {
attributeState "temperature", label:'${currentValue}°',
backgroundColors:[
multiAttributeTile(name: "temperature", type: "generic", width: 6, height: 4) {
tileAttribute("device.temperature", key: "PRIMARY_CONTROL") {
attributeState "temperature", label: '${currentValue}°',
backgroundColors: [
[value: 31, color: "#153591"],
[value: 44, color: "#1e9cbb"],
[value: 59, color: "#90d2a7"],
@@ -55,13 +57,13 @@ metadata {
}
}
valueTile("humidity", "device.humidity", inactiveLabel: false, width: 2, height: 2) {
state "humidity", label:'${currentValue}% humidity', unit:""
state "humidity", label: '${currentValue}% humidity', unit: ""
}
valueTile("battery", "device.battery", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
state "battery", label:'${currentValue}% battery'
state "battery", label: '${currentValue}% battery'
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
state "default", action: "refresh.refresh", icon: "st.secondary.refresh"
}
main "temperature", "humidity"
@@ -72,137 +74,26 @@ metadata {
def parse(String description) {
log.debug "description: $description"
Map map = [:]
if (description?.startsWith('catchall:')) {
map = parseCatchAllMessage(description)
// getEvent will handle temperature and humidity
Map map = zigbee.getEvent(description)
if (!map) {
Map descMap = zigbee.parseDescriptionAsMap(description)
if (descMap.clusterInt == 0x0001 && descMap.commandInt != 0x07 && descMap?.value) {
map = getBatteryResult(Integer.parseInt(descMap.value, 16))
} else if (descMap?.clusterInt == zigbee.TEMPERATURE_MEASUREMENT_CLUSTER && descMap.commandInt == 0x07) {
if (descMap.data[0] == "00") {
log.debug "TEMP REPORTING CONFIG RESPONSE: $descMap"
sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
} else {
log.warn "TEMP REPORTING CONFIG FAILED- error code: ${descMap.data[0]}"
}
else if (description?.startsWith('read attr -')) {
map = parseReportAttributeMessage(description)
}
else if (description?.startsWith('temperature: ') || description?.startsWith('humidity: ')) {
map = parseCustomMessage(description)
}
log.debug "Parse returned $map"
return map ? createEvent(map) : [:]
}
private Map parseCatchAllMessage(String description) {
Map resultMap = [:]
def cluster = zigbee.parse(description)
if (shouldProcessMessage(cluster)) {
switch(cluster.clusterId) {
case 0x0001:
// 0x07 - configure reporting
if (cluster.command != 0x07) {
resultMap = getBatteryResult(cluster.data.last())
}
break
case 0x0402:
if (cluster.command == 0x07) {
if (cluster.data[0] == 0x00){
log.debug "TEMP REPORTING CONFIG RESPONSE" + cluster
resultMap = [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:
// 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
}
}
return resultMap
}
private boolean shouldProcessMessage(cluster) {
// 0x0B is default response indicating message got through
boolean ignoredMessage = cluster.profileId != 0x0104 ||
cluster.command == 0x0B ||
(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)
resultMap = getTemperatureResult(value)
}
else if (descMap.cluster == "0001" && descMap.attrId == "0020") {
resultMap = getBatteryResult(Integer.parseInt(descMap.value, 16))
}
else if (descMap.cluster == "FC45" && descMap.attrId == "0000") {
def value = getReportAttributeHumidity(descMap.value)
resultMap = getHumidityResult(value)
}
return resultMap
}
def getReportAttributeHumidity(String value) {
def humidity = null
if (value?.trim()) {
try {
// value is hex with no decimal
def pct = Integer.parseInt(value.trim(), 16) / 100
humidity = String.format('%.0f', pct)
} catch(NumberFormatException nfe) {
log.debug "Error converting $value to humidity"
}
}
return humidity
}
private Map parseCustomMessage(String description) {
Map resultMap = [:]
if (description?.startsWith('temperature: ')) {
def value = zigbee.parseHATemperatureValue(description, "temperature: ", getTemperatureScale())
resultMap = getTemperatureResult(value)
}
else if (description?.startsWith('humidity: ')) {
def pct = (description - "humidity: " - "%").trim()
if (pct.isNumber()) {
def value = Math.round(new BigDecimal(pct)).toString()
resultMap = getHumidityResult(value)
} else {
log.error "invalid humidity: ${pct}"
}
}
return resultMap
}
def getTemperature(value) {
def celsius = Integer.parseInt(value, 16).shortValue() / 100
if(getTemperatureScale() == "C"){
return celsius
} else {
return celsiusToFahrenheit(celsius) as Integer
}
}
private Map getBatteryResult(rawValue) {
log.debug 'Battery'
def linkText = getLinkText(device)
@@ -226,41 +117,22 @@ private Map getBatteryResult(rawValue) {
return result
}
private Map getTemperatureResult(value) {
log.debug 'TEMP'
def linkText = getLinkText(device)
if (tempOffset) {
def offset = tempOffset as int
def v = value as int
value = v + offset
}
def descriptionText = "${linkText} was ${value}°${temperatureScale}"
return [
name: 'temperature',
value: value,
descriptionText: descriptionText,
unit: temperatureScale
]
}
private Map getHumidityResult(value) {
log.debug 'Humidity'
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
return zigbee.readAttribute(0x0001, 0x0020) // Read the Battery Level
}
def refresh()
{
def refresh() {
log.debug "refresh temperature, humidity, and battery"
return zigbee.readAttribute(0xFC45, 0x0000, ["mfgCode": 0xC2DF]) + // Original firmware
zigbee.readAttribute(0x0402, 0x0000) +
zigbee.readAttribute(0x0001, 0x0020)
return zigbee.readAttribute(0xFC45, 0x0000, ["mfgCode": 0x104E]) + // New firmware
zigbee.readAttribute(0xFC45, 0x0000, ["mfgCode": 0xC2DF]) + // Original firmware
zigbee.readAttribute(zigbee.TEMPERATURE_MEASUREMENT_CLUSTER, 0x0000) +
zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x0020) +
zigbee.configureReporting(0xFC45, 0x0000, DataType.INT16, 30, 3600, 100) +
zigbee.batteryConfig() +
zigbee.temperatureConfig(30, 300)
}
def configure() {
@@ -269,35 +141,8 @@ def configure() {
sendEvent(name: "checkInterval", value: 2 * 60 * 60 + 1 * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
log.debug "Configuring Reporting and Bindings."
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"
]
// 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) {
new BigInteger(Math.round(value).toString()).toString(16)
}
private String swapEndianHex(String hex) {
reverseArray(hex.decodeHex()).encodeHex()
}
private byte[] reverseArray(byte[] array) {
int i = 0;
int j = array.length - 1;
byte tmp;
while (j > i) {
tmp = array[j];
array[j] = array[i];
array[i] = tmp;
j--;
i++;
}
return array
return refresh()
}
@@ -51,12 +51,12 @@ metadata {
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")
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00a0dc")
}
standardTile("acceleration", "device.acceleration") {
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#53a7c0")
state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#ffffff")
state("active", label:'${name}', icon:"st.motion.acceleration.active", backgroundColor:"#00a0dc")
state("inactive", label:'${name}', icon:"st.motion.acceleration.inactive", backgroundColor:"#cccccc")
}
valueTile("temperature", "device.temperature") {
state("temperature", label:'${currentValue}°',
@@ -96,7 +96,7 @@ metadata {
def parse(String description) {
def results
if (!isSupportedDescription(description) || zigbee.isZoneType19(description)) {
if (!isSupportedDescription(description) || description.startsWith("zone")) {
// Ignore this in favor of orientation-based state
// results = parseSingleMessage(description)
}
@@ -20,7 +20,7 @@ metadata {
// tile definitions
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
}
@@ -36,7 +36,7 @@ metadata {
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: '${name}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${name}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00a0dc"
}
controlTile("levelSliderControl", "device.level", "slider", height: 2, width: 1, inactiveLabel: false) {
state "level", action:"switch level.setLevel"
@@ -28,8 +28,8 @@ metadata {
tiles {
standardTile("contact", "device.contact", width: 2, height: 2) {
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#79b821", action: "open")
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#ffa81e", action: "close")
state("closed", label:'${name}', icon:"st.contact.contact.closed", backgroundColor:"#00A0DC", action: "open")
state("open", label:'${name}', icon:"st.contact.contact.open", backgroundColor:"#e86d13", action: "close")
}
main "contact"
details "contact"
@@ -29,10 +29,10 @@ metadata {
tiles {
standardTile("toggle", "device.door", width: 2, height: 2) {
state("closed", label:'${name}', action:"door control.open", icon:"st.doors.garage.garage-closed", backgroundColor:"#79b821", nextState:"opening")
state("open", label:'${name}', action:"door control.close", icon:"st.doors.garage.garage-open", backgroundColor:"#ffa81e", nextState:"closing")
state("opening", label:'${name}', icon:"st.doors.garage.garage-closed", backgroundColor:"#ffe71e")
state("closing", label:'${name}', icon:"st.doors.garage.garage-open", backgroundColor:"#ffe71e")
state("closed", label:'${name}', action:"door control.open", icon:"st.doors.garage.garage-closed", backgroundColor:"#00A0DC", nextState:"opening")
state("open", label:'${name}', action:"door control.close", icon:"st.doors.garage.garage-open", backgroundColor:"#e86d13", nextState:"closing")
state("opening", label:'${name}', icon:"st.doors.garage.garage-closed", backgroundColor:"#e86d13")
state("closing", label:'${name}', icon:"st.doors.garage.garage-open", backgroundColor:"#00A0DC")
}
standardTile("open", "device.door", inactiveLabel: false, decoration: "flat") {
@@ -23,7 +23,7 @@ metadata {
tiles {
standardTile("toggle", "device.lock", width: 2, height: 2) {
state "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff"
state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#79b821"
state "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#00A0DC"
}
standardTile("lock", "device.lock", inactiveLabel: false, decoration: "flat") {
state "default", label:'lock', action:"lock.lock", icon:"st.locks.lock.locked"
@@ -28,8 +28,8 @@ metadata {
tiles {
standardTile("motion", "device.motion", width: 2, height: 2) {
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff", action: "active")
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0", action: "inactive")
state("inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc", action: "active")
state("active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC", action: "inactive")
}
main "motion"
details "motion"
@@ -29,7 +29,7 @@ metadata {
tiles {
standardTile("presence", "device.presence", width: 2, height: 2, canChangeBackground: true) {
state("not present", label:'not present', icon:"st.presence.tile.not-present", backgroundColor:"#ffffff", action:"arrived")
state("present", label:'present', icon:"st.presence.tile.present", backgroundColor:"#53a7c0", action:"departed")
state("present", label:'present', icon:"st.presence.tile.present", backgroundColor:"#00A0DC", action:"departed")
}
main "presence"
details "presence"
@@ -26,7 +26,7 @@ metadata {
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: '${currentValue}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
state "on", label: '${currentValue}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${currentValue}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
}
standardTile("on", "device.switch", decoration: "flat") {
state "default", label: 'On', action: "onPhysical", backgroundColor: "#ffffff"
@@ -39,9 +39,7 @@ metadata {
}
}
def parse(String description) {
def pair = description.split(":")
createEvent(name: pair[0].trim(), value: pair[1].trim())
def parse(description) {
}
def on() {
@@ -101,9 +101,9 @@ metadata {
standardTile("mode", "device.thermostatMode", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
state "off", label:'${name}', action:"thermostat.heat", backgroundColor:"#ffffff"
state "heat", label:'${name}', action:"thermostat.cool", backgroundColor:"#ffa81e"
state "cool", label:'${name}', action:"thermostat.auto", backgroundColor:"#269bd2"
state "auto", label:'${name}', action:"thermostat.off", backgroundColor:"#79b821"
state "heat", label:'${name}', action:"thermostat.cool", backgroundColor:"#e86d13"
state "cool", label:'${name}', action:"thermostat.auto", backgroundColor:"#00A0DC"
state "auto", label:'${name}', action:"thermostat.off", backgroundColor:"#00A0DC"
}
standardTile("fanMode", "device.thermostatFanMode", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
state "fanAuto", label:'${name}', action:"thermostat.fanOn", backgroundColor:"#ffffff"
@@ -112,8 +112,8 @@ metadata {
}
standardTile("operatingState", "device.thermostatOperatingState", width: 2, height: 2) {
state "idle", label:'${name}', backgroundColor:"#ffffff"
state "heating", label:'${name}', backgroundColor:"#ffa81e"
state "cooling", label:'${name}', backgroundColor:"#269bd2"
state "heating", label:'${name}', backgroundColor:"#e86d13"
state "cooling", label:'${name}', backgroundColor:"#00A0DC"
}
main("thermostatMulti")
@@ -29,7 +29,7 @@ metadata {
tiles {
standardTile("water", "device.water", width: 2, height: 2) {
state "dry", icon:"st.alarm.water.dry", backgroundColor:"#ffffff", action: "wet"
state "wet", icon:"st.alarm.water.wet", backgroundColor:"#53a7c0", action: "dry"
state "wet", icon:"st.alarm.water.wet", backgroundColor:"#00A0DC", action: "dry"
}
standardTile("wet", "device.water", inactiveLabel: false, decoration: "flat") {
state "default", label:'Wet', action:"wet", icon: "st.alarm.water.wet"
@@ -21,8 +21,8 @@ metadata {
// tile definitions
tiles {
standardTile("contact", "device.contact", width: 2, height: 2, canChangeIcon: true) {
state "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#e86d13"
state "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#53a7c0"
state "closed", label: '${name}', action: "valve.open", icon: "st.valves.water.closed", backgroundColor: "#ffffff"
state "open", label: '${name}', action: "valve.close", icon: "st.valves.water.open", backgroundColor: "#00A0DC"
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
@@ -41,9 +41,9 @@ metadata {
attributeState("default", label:'${currentValue}%', unit:"%")
}
tileAttribute("device.thermostatOperatingState", key: "OPERATING_STATE") {
attributeState("idle", backgroundColor:"#44b621")
attributeState("heating", backgroundColor:"#ffa81e")
attributeState("cooling", backgroundColor:"#269bd2")
attributeState("idle", backgroundColor:"#ffffff")
attributeState("heating", backgroundColor:"#e86d13")
attributeState("cooling", backgroundColor:"#00a0dc")
}
tileAttribute("device.thermostatMode", key: "THERMOSTAT_MODE") {
attributeState("off", label:'${name}')
@@ -26,8 +26,8 @@ metadata {
tiles(scale: 2) {
// You only get a presence tile view when the size is 3x3 otherwise it's a value tile
standardTile("presence", "device.presence", width: 3, height: 3, canChangeBackground: true) {
state("present", labelIcon:"st.presence.tile.mobile-present", backgroundColor:"#53a7c0")
state("not present", labelIcon:"st.presence.tile.mobile-not-present", backgroundColor:"#ebeef2")
state("present", labelIcon:"st.presence.tile.mobile-present", backgroundColor:"#00A0DC")
state("not present", labelIcon:"st.presence.tile.mobile-not-present", backgroundColor:"#cccccc")
}
standardTile("notPresentBtn", "device.fake", width: 3, height: 3, decoration: "flat") {
@@ -35,7 +35,7 @@ metadata {
}
standardTile("presentBtn", "device.fake", width: 3, height: 3, decoration: "flat") {
state("present", label:'present', backgroundColor:"#53a7c0", action:"arrived")
state("present", label:'present', backgroundColor:"#00A0DC", action:"arrived")
}
main("presence")
@@ -24,19 +24,19 @@ metadata {
// standard tile with actions
standardTile("actionRings", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: '${currentValue}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
state "on", label: '${currentValue}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${currentValue}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
}
// standard flat tile with actions
standardTile("actionFlat", "device.switch", width: 2, height: 2, canChangeIcon: true, decoration: "flat") {
state "off", label: '${currentValue}', action: "switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
state "on", label: '${currentValue}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${currentValue}', action: "switch.off", icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
}
// standard flat tile without actions
standardTile("noActionFlat", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "off", label: '${currentValue}',icon: "st.switches.switch.off", backgroundColor: "#ffffff"
state "on", label: '${currentValue}', icon: "st.switches.switch.on", backgroundColor: "#79b821"
state "on", label: '${currentValue}', icon: "st.switches.switch.on", backgroundColor: "#00A0DC"
}
// standard flat tile with only a label
@@ -25,7 +25,7 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name:"basicTile", type:"generic", width:6, height:4) {
tileAttribute("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", 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"
@@ -33,7 +33,7 @@ metadata {
}
multiAttributeTile(name:"sliderTile", type:"generic", width:6, height:4) {
tileAttribute("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label:'${name}', backgroundColor:"#79b821", nextState:"turningOff"
attributeState "on", label:'${name}', backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "off", label:'${name}', backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOff", label:'${name}', backgroundColor:"#ffffff", nextState:"turningOn"
@@ -57,7 +57,7 @@ metadata {
]
}
tileAttribute("device.switch", key: "SECONDARY_CONTROL") {
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'…', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOff", label:'…', action:"switch.on", backgroundColor:"#ffffff", nextState:"turningOn"
@@ -33,9 +33,9 @@ metadata {
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 "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", 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 "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.power", key: "SECONDARY_CONTROL") {
@@ -51,9 +51,9 @@ metadata {
multiAttributeTile(name:"switchNoPower", 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 "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", 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 "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", 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") {
@@ -66,9 +66,9 @@ metadata {
multiAttributeTile(name:"switchNoSlider", 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 "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", 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 "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.power", key: "SECONDARY_CONTROL") {
@@ -81,9 +81,9 @@ metadata {
multiAttributeTile(name:"switchNoSliderOrColor", 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 "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", 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 "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.power", key: "SECONDARY_CONTROL") {
@@ -42,9 +42,9 @@ metadata {
attributeState("humidity", label:'${currentValue}%', unit:"%", defaultState: true)
}
tileAttribute("device.thermostatOperatingState", key: "OPERATING_STATE") {
attributeState("idle", backgroundColor:"#44b621")
attributeState("heating", backgroundColor:"#ffa81e")
attributeState("cooling", backgroundColor:"#269bd2")
attributeState("idle", backgroundColor:"#00A0DC")
attributeState("heating", backgroundColor:"#e86d13")
attributeState("cooling", backgroundColor:"#00A0DC")
}
tileAttribute("device.thermostatMode", key: "THERMOSTAT_MODE") {
attributeState("off", label:'${name}')
@@ -69,9 +69,9 @@ metadata {
attributeState("VALUE_DOWN", action: "tempDown")
}
tileAttribute("device.thermostatOperatingState", key: "OPERATING_STATE") {
attributeState("idle", backgroundColor:"#44b621")
attributeState("heating", backgroundColor:"#ffa81e")
attributeState("cooling", backgroundColor:"#269bd2")
attributeState("idle", backgroundColor:"#00A0DC")
attributeState("heating", backgroundColor:"#e86d13")
attributeState("cooling", backgroundColor:"#00A0DC")
}
tileAttribute("device.thermostatMode", key: "THERMOSTAT_MODE") {
attributeState("off", label:'${name}')
@@ -148,9 +148,9 @@ metadata {
standardTile("mode", "device.thermostatMode", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
state "off", label:'${name}', action:"thermostat.heat", backgroundColor:"#ffffff"
state "heat", label:'${name}', action:"thermostat.cool", backgroundColor:"#ffa81e"
state "cool", label:'${name}', action:"thermostat.auto", backgroundColor:"#269bd2"
state "auto", label:'${name}', action:"thermostat.off", backgroundColor:"#79b821"
state "heat", label:'${name}', action:"thermostat.cool", backgroundColor:"#e86d13"
state "cool", label:'${name}', action:"thermostat.auto", backgroundColor:"#00A0DC"
state "auto", label:'${name}', action:"thermostat.off", backgroundColor:"#00A0DC"
}
standardTile("fanMode", "device.thermostatFanMode", width: 2, height: 2, inactiveLabel: false, decoration: "flat") {
state "fanAuto", label:'${name}', action:"thermostat.fanOn", backgroundColor:"#ffffff"
@@ -159,8 +159,8 @@ metadata {
}
standardTile("operatingState", "device.thermostatOperatingState", width: 2, height: 2) {
state "idle", label:'${name}', backgroundColor:"#ffffff"
state "heating", label:'${name}', backgroundColor:"#ffa81e"
state "cooling", label:'${name}', backgroundColor:"#269bd2"
state "heating", label:'${name}', backgroundColor:"#e86d13"
state "cooling", label:'${name}', backgroundColor:"#00A0DC"
}
@@ -34,10 +34,10 @@ metadata {
tiles(scale: 2) {
multiAttributeTile(name: "videoPlayer", type: "videoPlayer", width: 6, height: 4) {
tileAttribute("device.switch", key: "CAMERA_STATUS") {
attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", action: "switch.off", backgroundColor: "#79b821", defaultState: true)
attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", action: "switch.off", backgroundColor: "#00A0DC", defaultState: true)
attributeState("off", label: "Inactive", icon: "st.camera.dlink-indoor", action: "switch.on", backgroundColor: "#ffffff")
attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#53a7c0")
attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", action: "refresh.refresh", backgroundColor: "#F22000")
attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#00A0DC")
attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", action: "refresh.refresh", backgroundColor: "#cccccc")
}
tileAttribute("device.errorMessage", key: "CAMERA_ERROR_MESSAGE") {
@@ -45,10 +45,10 @@ metadata {
}
tileAttribute("device.camera", key: "PRIMARY_CONTROL") {
attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", backgroundColor: "#79b821", defaultState: true)
attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", backgroundColor: "#00A0DC", defaultState: true)
attributeState("off", label: "Inactive", icon: "st.camera.dlink-indoor", backgroundColor: "#ffffff")
attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#53a7c0")
attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", backgroundColor: "#F22000")
attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#00A0DC")
attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", backgroundColor: "#cccccc")
}
tileAttribute("device.startLive", key: "START_LIVE") {
@@ -72,10 +72,10 @@ metadata {
multiAttributeTile(name: "videoPlayerMin", type: "videoPlayer", width: 6, height: 4) {
tileAttribute("device.switch", key: "CAMERA_STATUS") {
attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", action: "switch.off", backgroundColor: "#79b821", defaultState: true)
attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", action: "switch.off", backgroundColor: "#00A0DC", defaultState: true)
attributeState("off", label: "Inactive", icon: "st.camera.dlink-indoor", action: "switch.on", backgroundColor: "#ffffff")
attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#53a7c0")
attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", action: "refresh.refresh", backgroundColor: "#F22000")
attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#00A0DC")
attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", action: "refresh.refresh", backgroundColor: "#cccccc")
}
tileAttribute("device.errorMessage", key: "CAMERA_ERROR_MESSAGE") {
@@ -83,10 +83,10 @@ metadata {
}
tileAttribute("device.camera", key: "PRIMARY_CONTROL") {
attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", backgroundColor: "#79b821", defaultState: true)
attributeState("on", label: "Active", icon: "st.camera.dlink-indoor", backgroundColor: "#00A0DC", defaultState: true)
attributeState("off", label: "Inactive", icon: "st.camera.dlink-indoor", backgroundColor: "#ffffff")
attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#53a7c0")
attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", backgroundColor: "#F22000")
attributeState("restarting", label: "Connecting", icon: "st.camera.dlink-indoor", backgroundColor: "#00A0DC")
attributeState("unavailable", label: "Unavailable", icon: "st.camera.dlink-indoor", backgroundColor: "#cccccc")
}
tileAttribute("device.startLive", key: "START_LIVE") {
@@ -23,7 +23,7 @@ metadata {
// UI tile definitions
tiles {
standardTile("unknown", "device.unknown", width: 2, height: 2) {
state(name:"default", icon:"st.unknown.unknown.unknown", backgroundColor:"#767676", label: "Unknown")
state(name:"default", icon:"st.unknown.unknown.unknown", backgroundColor:"#ffffff", label: "Unknown")
}
main "unknown"
@@ -43,9 +43,9 @@ metadata {
// UI tile definitions
tiles {
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
state "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff"
state "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
state "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff"
state "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
@@ -52,11 +52,11 @@ metadata {
}
standardTile("switch", "device.switch", width: 2, height: 2, canChangeIcon: true) {
state "on", label:'${name}', action:"switch.off", icon:"st.Home.home30", backgroundColor:"#79b821", nextState:"turningOff"
state "on", label:'${name}', action:"switch.off", icon:"st.Home.home30", backgroundColor:"#00A0DC", nextState:"turningOff"
state "off", label:'${name}', action:"switch.on", icon:"st.Home.home30", backgroundColor:"#ffffff", nextState:"turningOn"
state "turningOn", label:'${name}', action:"switch.off", icon:"st.Home.home30", backgroundColor:"#79b821", nextState:"turningOff"
state "turningOn", label:'${name}', action:"switch.off", icon:"st.Home.home30", backgroundColor:"#00A0DC", nextState:"turningOff"
state "turningOff", label:'${name}', action:"switch.on", icon:"st.Home.home30", backgroundColor:"#ffffff", nextState:"turningOn"
state "offline", label:'${name}', icon:"st.Home.home30", backgroundColor:"#ff0000"
state "offline", label:'${name}', icon:"st.Home.home30", backgroundColor:"#cccccc"
}
standardTile("refresh", "device.switch", inactiveLabel: false, height: 2, width: 2, decoration: "flat") {
@@ -86,7 +86,7 @@ def parse(String description) {
def bodyString = msg.body
if (bodyString) {
unschedule("setOffline")
def body = new XmlSlurper().parseText(bodyString)
def body = new XmlSlurper().parseText(bodyString.replaceAll("[^\\x20-\\x7e]", ""))
if (body?.property?.TimeSyncRequest?.text()) {
log.trace "Got TimeSyncRequest"
@@ -36,9 +36,9 @@
tiles(scale: 2) {
multiAttributeTile(name:"rich-control", type: "motion", canChangeIcon: true){
tileAttribute ("device.motion", key: "PRIMARY_CONTROL") {
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#53a7c0"
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#ffffff"
attributeState "offline", label:'${name}', icon:"st.motion.motion.active", backgroundColor:"#ff0000"
attributeState "active", label:'motion', icon:"st.motion.motion.active", backgroundColor:"#00A0DC"
attributeState "inactive", label:'no motion', icon:"st.motion.motion.inactive", backgroundColor:"#cccccc"
attributeState "offline", label:'${name}', icon:"st.motion.motion.active", backgroundColor:"#cccccc"
}
tileAttribute ("currentIP", key: "SECONDARY_CONTROL") {
attributeState "currentIP", label: ''
@@ -78,7 +78,7 @@ def parse(String description) {
def bodyString = msg.body
if (bodyString) {
unschedule("setOffline")
def body = new XmlSlurper().parseText(bodyString)
def body = new XmlSlurper().parseText(bodyString.replaceAll("[^\\x20-\\x7e]", ""))
if (body?.property?.TimeSyncRequest?.text()) {
log.trace "Got TimeSyncRequest"
result << timeSyncResponse()
@@ -84,7 +84,7 @@ def parse(String description) {
def bodyString = msg.body
if (bodyString) {
unschedule("setOffline")
def body = new XmlSlurper().parseText(bodyString)
def body = new XmlSlurper().parseText(bodyString.replaceAll("[^\\x20-\\x7e]", ""))
if (body?.property?.TimeSyncRequest?.text()) {
log.trace "Got TimeSyncRequest"
result << timeSyncResponse()
@@ -13,6 +13,7 @@
* for the specific language governing permissions and limitations under the License.
*
*/
import physicalgraph.zigbee.zcl.DataType
metadata {
definition (name: "ZigBee Button", namespace: "smartthings", author: "Mitch Pond") {
@@ -28,8 +29,8 @@ metadata {
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"
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"
}
simulator {}
@@ -82,7 +83,7 @@ def parse(String description) {
def result = event ? createEvent(event) : []
if (description?.startsWith('enroll request')) {
List cmds = enrollResponse()
List cmds = zigbee.enrollResponse()
result = cmds?.collect { new physicalgraph.device.HubAction(it) }
}
return result
@@ -117,15 +118,38 @@ private Map getBatteryResult(rawValue) {
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") {
if ((device.getDataValue("model") == "3460-L") &&(descMap.clusterInt == 0x0006)) {
if (descMap.commandInt == 1) {
getButtonResult("press")
}
else if (descMap.command == "00") {
else if (descMap.commandInt == 0) {
getButtonResult("release")
}
}
else if ((device.getDataValue("model") == "3450-L") && (descMap.clusterInt == 0x0006)) {
if (descMap.commandInt == 1) {
getButtonResult("press")
}
else if (descMap.commandInt == 0) {
def button = 1
switch(descMap.sourceEndpoint) {
case "01":
button = 4
break
case "02":
button = 3
break
case "03":
button = 1
break
case "04":
button = 2
break
}
getButtonResult("release", button)
}
}
else if (descMap.clusterInt == 0x0006) {
buttonState = "pushed"
if (descMap.command == "01") {
@@ -160,7 +184,7 @@ private Map parseNonIasButtonMessage(Map descMap){
def refresh() {
log.debug "Refreshing Battery"
return zigbee.readAttribute(0x0001, 0x20) +
return zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x20) +
zigbee.enrollResponse()
}
@@ -177,9 +201,9 @@ def configure() {
}
return zigbee.onOffConfig() +
zigbee.levelConfig() +
zigbee.configureReporting(0x0001, 0x20, 0x20, 30, 21600, 0x01) +
zigbee.configureReporting(zigbee.POWER_CONFIGURATION_CLUSTER, 0x20, DataType.UINT8, 30, 21600, 0x01) +
zigbee.enrollResponse() +
zigbee.readAttribute(0x0001, 0x20) +
zigbee.readAttribute(zigbee.POWER_CONFIGURATION_CLUSTER, 0x20) +
cmds
}
@@ -23,6 +23,7 @@ Works with:
* **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
* **Light** - indicates that the device belongs to Light category.
## Device Health
@@ -22,6 +22,7 @@ metadata {
capability "Switch"
capability "Switch Level"
capability "Health Check"
capability "Light"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B04"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702"
@@ -33,9 +34,9 @@ metadata {
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 "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", 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 "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
@@ -97,7 +98,7 @@ def on() {
}
def setLevel(value) {
zigbee.setLevel(value)
zigbee.setLevel(value) + (value?.toInteger() > 0 ? zigbee.on() : [])
}
/**
@@ -20,6 +20,7 @@ metadata {
capability "Switch"
capability "Switch Level"
capability "Health Check"
capability "Light"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008"
@@ -28,14 +29,18 @@ metadata {
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B05", outClusters: "0019", manufacturer: "OSRAM SYLVANIA", model: "iQBR30", deviceJoinName: "Sylvania Ultra iQ"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY PAR38 ON/OFF/DIM", deviceJoinName: "SYLVANIA Smart PAR38 Soft White"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "LIGHTIFY BR ON/OFF/DIM", deviceJoinName: "SYLVANIA Smart BR30 Soft White"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0702, 0B05", outClusters: "0019", manufacturer: "sengled", model: "E11-G13", deviceJoinName: "Sengled Element Classic"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL6HD", deviceJoinName: "Leviton Dimmer Switch"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL3HL", deviceJoinName: "Leviton Lumina RF Plug-In Dimmer"
fingerprint profileId: "0104", inClusters: "0000, 0003, 0004, 0005, 0006, 0008", outClusters: "0003, 0006, 0008, 0019, 0406", manufacturer: "Leviton", model: "DL1KD", deviceJoinName: "Leviton Lumina RF Dimmer Switch"
}
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.light.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#00A0DC", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
@@ -89,7 +94,13 @@ def on() {
}
def setLevel(value) {
zigbee.setLevel(value)
def additionalCmds = []
if (device.getDataValue("model") == "iQBR30" && value.toInteger() > 0) { // Handle iQ bulb not following spec
additionalCmds = zigbee.on()
} else if (device.getDataValue("manufacturer") == "MRVL") { // Handle marvel stack not reporting
additionalCmds = refresh()
}
zigbee.setLevel(value) + additionalCmds
}
/**
* PING is used by Device-Watch in attempt to reach the Device
@@ -99,7 +110,15 @@ def ping() {
}
def refresh() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig()
zigbee.onOffRefresh() + zigbee.levelRefresh()
}
def installed() {
if (((device.getDataValue("manufacturer") == "MRVL") && (device.getDataValue("model") == "MZ100")) || (device.getDataValue("manufacturer") == "OSRAM SYLVANIA") || (device.getDataValue("manufacturer") == "OSRAM")) {
if ((device.currentState("level")?.value == null) || (device.currentState("level")?.value == 0)) {
sendEvent(name: "level", value: 100)
}
}
}
def configure() {
@@ -109,5 +128,5 @@ def configure() {
sendEvent(name: "checkInterval", value: 2 * 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()
refresh() + zigbee.onOffConfig(0, 300) + zigbee.levelConfig()
}
@@ -13,6 +13,8 @@
* for the specific language governing permissions and limitations under the License.
*
*/
import physicalgraph.zigbee.zcl.DataType
metadata {
definition (name: "ZigBee Lock", namespace: "smartthings", author: "SmartThings")
{
@@ -37,10 +39,10 @@
tiles(scale: 2) {
multiAttributeTile(name:"toggle", type:"generic", width:6, height:4){
tileAttribute ("device.lock", key:"PRIMARY_CONTROL") {
attributeState "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#79b821", nextState:"unlocking"
attributeState "locked", label:'locked', action:"lock.unlock", icon:"st.locks.lock.locked", backgroundColor:"#00A0DC", nextState:"unlocking"
attributeState "unlocked", label:'unlocked', action:"lock.lock", icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff", nextState:"locking"
attributeState "unknown", label:"unknown", action:"lock.lock", icon:"st.locks.lock.unknown", backgroundColor:"#ffffff", nextState:"locking"
attributeState "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#79b821"
attributeState "locking", label:'locking', icon:"st.locks.lock.locked", backgroundColor:"#00A0DC"
attributeState "unlocking", label:'unlocking', icon:"st.locks.lock.unlocked", backgroundColor:"#ffffff"
}
}
@@ -71,9 +73,6 @@ private getDOORLOCK_CMD_UNLOCK_DOOR() { 0x01 }
private getDOORLOCK_ATTR_LOCKSTATE() { 0x0000 }
private getPOWER_ATTR_BATTERY_PERCENTAGE_REMAINING() { 0x0021 }
private getTYPE_U8() { 0x20 }
private getTYPE_ENUM8() { 0x30 }
// Public methods
def installed() {
log.trace "installed()"
@@ -86,9 +85,9 @@ def uninstalled() {
def configure() {
def cmds =
zigbee.configureReporting(CLUSTER_DOORLOCK, DOORLOCK_ATTR_LOCKSTATE,
TYPE_ENUM8, 0, 3600, null) +
DataType.ENUM8, 0, 3600, null) +
zigbee.configureReporting(CLUSTER_POWER, POWER_ATTR_BATTERY_PERCENTAGE_REMAINING,
TYPE_U8, 600, 21600, 0x01)
DataType.UINT8, 600, 21600, 0x01)
log.info "configure() --- cmds: $cmds"
return refresh() + cmds // send refresh cmds as part of config
}
@@ -0,0 +1,2 @@
.st-ignore
README.md

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