Compare commits

...

62 Commits

Author SHA1 Message Date
Elnar Hajiyev
970e5404ac MSA-1277: I'd like to submit significant capability updates to 2 device handlers widely used in UK (and EU): Fibaro Dimmer 1 and Fibaro Dimmer 2. There are 2 main additions to the original code developed by SmartThings team:
1)Addition of "scene" attribute to enable dimmer devices to emit scene activations to SmartThings hub, which can be listened upon by and reacted to by smartapps. This is a significant capability, which was omitted in the existing device handlers because it allows the use of double and triple clicks, secondary switch single/double/triple clicks to perform additional actions. A good example, when in a bedroom normal clicks to turn on/off lights would control main bedroom lights, while double clicks or clicks of the secondary switch S2 could control small table lights which are connected to SmartThings hub. Other examples can be activating Good Night or Good Morning routines, etc.

2)I also added the full list of hardware parameters for both switches to be controllable directly in the SmartThings App UI - settings of the device. This allows users with no coding skills to modify hardware parameters of Fibaro Dimmers without having to fiddle with any code changes. This also makes it possible to have different configurations for different dimmers by using just one device handler, as opposed to creating multiple copies of it depending on the set of parameters that one needs to set.

In addition to extensions of the device handlers I am also submitting a demo smartapp that can be used to subscribe to scene activations of Fibaro Dimmers. Its a very simple app, but one that is necessary to be able to take advantage of newly added functionality of Fibaro Dimmers on SmartThings platform.
2016-05-12 02:52:47 -05:00
Lars Finander
a5da182bf4 Merge pull request #861 from larsfinander/DVCSMP-1738_Phillips_HUE_brightness_level
DVCSMP-1738 Philips HUE: Detail page showing the Brightness level twice
2016-05-11 15:25:36 -07:00
Dwight Liu
32f8d2d944 Merge pull request #863 from dwightatsmartthings/DVCSMP-1719-aeon-home-energy-meter-c3-npe-fix
null zwave event check in storeGraphData
2016-05-10 14:29:02 -07:00
Dwight Liu
e1de599668 make sure reformat the storeGraphData 2016-05-10 14:23:46 -07:00
Dwight Liu
0e01cbed06 make descriptive comment and add space in else condition 2016-05-10 13:40:52 -07:00
Jim Anderson
bf476940e9 Merge pull request #857 from jimmyjames/fix-generic-tile
fix parse signature for generic multiattribute example tile
2016-05-09 12:28:27 -05:00
Jack Chi
a219f37035 Merge pull request #835 from jackchi/add-healthcheck-smartsense
[CHF-131] Add checkInterval values to SmartSense DTHs
2016-05-07 20:29:55 +08:00
Dwight Liu
8821c68e9c null zwave event check in storeGraphData 2016-05-06 12:50:02 -07:00
Lars Finander
27c05f4e5b DVCSMP-1738 Philips HUE: Detail page showing the Brightness level twice
-Removed secondary control from all Hue DTH
2016-05-06 09:29:41 -07:00
Tom Manley
7571c1b980 Merge pull request #858 from tpmanley/feature/ge_fingerprints
DVCSMP-1370: Added fingerprints for GE Link Daylight and SoftWhite bulbs
2016-05-05 23:01:52 -05:00
Tom Manley
bb65c4ce14 Added fingerprints for GE Link Daylight and SoftWhite bulbs
Resolves:
    https://smartthings.atlassian.net/browse/DVCSMP-1370
2016-05-05 22:54:30 -05:00
Jim Anderson
69ae9973da fix parse signature for generic multiattribute example tile 2016-05-05 15:36:08 -05:00
rohandesai
36c0af82fe Merge pull request #843 from rohandesai/rohan/PENG-157
Fixing the security issue in the IFTTT SmartApp
2016-05-04 16:52:47 -07:00
Rohan Desai
eba1f16ee1 added changes to address security loophole in the IFTTT app
addressed comments

PENG-157 IFTTT should not allow undefined commands
- added changes to address security loophole in the IFTTT app
- addressed comments
- removed an extra whitespace
2016-05-04 11:54:08 -07:00
Vinay Rao
f397691fdb Merge pull request #856 from workingmonk/bug/unnecessary_logs
DVCSMP-1748 Remove unncessary changelog from the file header
2016-05-04 11:52:51 -07:00
Vinay Rao
9a5be2c5db remove unncessary changelog from the file header 2016-05-04 11:49:59 -07:00
Vinay Rao
39ac9f9a8c Merge pull request #854 from workingmonk/feature/osram_fingerprint
INTL-532 Adding additional osram fingerprint
2016-05-04 10:19:03 -07:00
Vinay Rao
c353eeae17 adding additional osram fingerprint 2016-05-04 09:52:07 -07:00
Vinay Rao
467c6ff055 Merge pull request #852 from workingmonk/feature/zll_dth
DVCSMP-1743 INTL-532 Add zll dth equivalent
2016-05-03 21:56:44 -07:00
Vinay Rao
5beacf0ef2 add zll dth equivalent 2016-05-03 21:52:32 -07:00
Luke Bredeson
77f880af6e Merge pull request #841 from lbredeso/hue-connect-updated-failure
SHARD-174: Hue (Connect) updated() calls can fail in certain situations
2016-04-28 13:28:07 -05:00
Luke Bredeson
1c4386a67b SHARD-174: Hue (Connect) updated() calls can fail in certain situations 2016-04-28 11:09:52 -05:00
Matt Pennig
88dd510e72 Merge pull request #832 from SmartThingsCommunity/two-line-multiattribute-controls
Adding test cases for multi-line controls in multiattribute tiles
2016-04-26 13:49:57 -05:00
Vinay Rao
7786df3262 Merge pull request #837 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-04-26 11:25:59 -07:00
Matt Pennig
5ac08e5a92 adding multi-line text for standard and value tiles 2016-04-26 13:13:20 -05:00
Donald C. Kirker
6cdb80db1f Merge pull request #836 from mckeed/staging
Add auto-retyping for Astralink sensors SING-44
2016-04-25 17:41:32 -07:00
Duncan McKee
4db99824af Add Astralink sensors to zw door/window retypeBasedOnMSR 2016-04-25 16:40:47 -04:00
jackchi
d9f224fa6e [CHF-131] Add checkInterval values to SmartSense DTHs 2016-04-25 13:21:28 -07:00
Vinay Rao
72b51d50bc Merge pull request #834 from SmartThingsCommunity/staging
Rolling down hotfix for deploy tool to master
2016-04-25 12:33:13 -07:00
Vinay Rao
b2e245bd85 Merge pull request #833 from SmartThingsCommunity/production
Rolling down hotfix for deploy tool to staging
2016-04-25 12:28:55 -07:00
Vinay Rao
9a9854cf92 Merge pull request #831 from jord98716/DEVTOOLS-636-a
DEVTOOLS-636: Increment version of executable-deployment-scripts
2016-04-25 12:27:42 -07:00
Matt Pennig
1e27ff5d4a Adding test cases for multi-line controls in multiattribute tiles 2016-04-25 11:58:18 -05:00
Jordan Howe
37f1726ee6 DEVTOOLS-636: Increment version of executable-deployment-scripts 2016-04-25 09:57:53 -05:00
Jack Chi
c7e8079ff1 Merge pull request #757 from jackchi/add-healthcheck-smartsense
[CHF-112] Add Health Check capability to SmartThings SmartSense products
2016-04-22 11:11:59 -07:00
jackchi
481d13a571 [CHF-112] Add Health Check capability to SmartThings SmartSense products 2016-04-22 11:10:48 -07:00
Luke Bredeson
9d83b850ca Merge pull request #813 from lbredeso/updated-settings-state-fix
SHARD-159: Wemo (Connect) updated() fails in certain IP change scenarios
2016-04-20 16:31:36 -05:00
Luke Bredeson
84de336a1a SHARD-159: Wemo (Connect) updated() fails in certain IP change scenarios 2016-04-20 16:07:11 -05:00
Lars Finander
8b465b03b4 Merge pull request #808 from larsfinander/DVCSMP-1716_Philips_Hue_Invalid_parameter
DVCSMP-1716 Philips Hue: Invalid hue parameter used in setColor
2016-04-20 11:11:39 -07:00
Vinay Rao
2f81964479 Merge pull request #775 from motley74/nyce_hinge
Added fingerprint for NYCE door hinge sensor
2016-04-20 10:29:06 -07:00
Vinay Rao
d5ea735df7 Merge pull request #810 from SmartThingsCommunity/master
Rolling up master to staging
2016-04-19 15:50:22 -07:00
Vinay Rao
6428719c79 Merge pull request #809 from SmartThingsCommunity/staging
Rolling down staging hotfix to master
2016-04-19 15:41:56 -07:00
Lars Finander
327f8dfb00 DVCSMP-1716 Philips Hue: Invalid hue parameter used in setColor
-Replaced transition with transitiontime according to Hue API
2016-04-19 15:05:21 -07:00
Vinay Rao
e150ea4a59 Merge pull request #797 from SmartThingsCommunity/staging
Rolling up changes to production from staging 2016-04-19 Release
2016-04-19 14:41:39 -07:00
Donald C. Kirker
cdbcab6dad Merge pull request #806 from dkirker/CoopBoss
custom device types for the CoopBoss hardware version 3
2016-04-19 10:23:16 -07:00
John Rucker
dd99a024c2 custom device types for the CoopBoss hardware version 3
Prepping for submission to SmartThings.  Removed extra comments.

Submitting to public store for approval

Updated for new SmartThings interface

Release Candidate for CoopBoss H3V9

save

Update to fix invalid temperature reporting and added maxCurrentNE methods and attributes.

Made changes to defalutState:true to state "default" on smart tiles that had only one default state.  This was causing the Android version of the app to crash.

Updated comments

Added test for null values that were causing errors during join process

Fixed log errors during join process by testing for null values before init process.

Update fingerprint with Manufacturer data

SmartApps for CoopBoss hardware version 3

Updated Icons.

1

Updates to Prep for RC

Clean up

save
2016-04-19 10:06:33 -07:00
Lars Finander
810f3645d9 Merge pull request #784 from larsfinander/CHANGE-479-staging-hue-green-icon
CHANGE-479 Changing the lights on status for HUE DTH back to green
2016-04-15 13:25:07 -07:00
Lars Finander
2dcbcc84fc CHANGE-479 Changing the lights on status for HUE DTH back to green
-Change hue-bloom device type back to green
-Change hue-lux-bulb device type back to green
2016-04-14 20:49:59 -07:00
Yaima
33ef75091b Merge pull request #783 from Yaima/master
Fixes broken htmlTile
2016-04-14 16:05:55 -07:00
Yaima Valdivia
1bcad614ec Fixes broken htmlTile 2016-04-14 16:03:58 -07:00
Luke Bredeson
3ab83350f3 Merge pull request #761 from lbredeso/hue-event-subscription-improvements
EX-3: Improve Hue (Connect) event subscriptions
2016-04-14 16:58:01 -05:00
Vinay Rao
0c75c8806e Merge pull request #780 from SmartThingsCommunity/master
Rolling up master to staging
2016-04-13 23:35:44 -05:00
Vinay Rao
d91fea89df Merge pull request #779 from SmartThingsCommunity/staging
Rolling down hotfix from staging to master
2016-04-13 23:28:57 -05:00
Vinay Rao
d28d27c4ed Merge pull request #778 from SmartThingsCommunity/production
Rolling down hotfix from production to staging
2016-04-13 22:34:01 -05:00
Michael Hudson
235e3f5507 Added fingerprint for NYCE door hinge sensor 2016-04-12 18:23:28 -06:00
Vinay Rao
e7c1d88285 Merge pull request #773 from SmartThingsCommunity/fix-multi-thermostat-dth
Update tile-multiattribute-thermostat.groovy
2016-04-12 10:03:43 -07:00
Kyle LeNeau
74c334a0f7 Update tile-multiattribute-thermostat.groovy 2016-04-12 12:02:15 -05:00
Vinay Rao
6881f469f5 Merge pull request #768 from SmartThingsCommunity/staging
Rolling up changes to production from staging 2016-04-12 Release
2016-04-12 09:27:46 -07:00
Dylan Bijnagte
be8c84306a Merge pull request #770 from Bijnagte/INTL-525
INTL-525 translation refresh
2016-04-11 15:57:46 -05:00
dylanbijnagte
a6105188ea INTL-525 translation refresh 2016-04-11 13:44:40 -05:00
Vinay Rao
22f218c072 Merge pull request #769 from SmartThingsCommunity/master
Adding the mobile ux test changes to the release train
2016-04-07 17:15:11 -07:00
Vinay Rao
8b543d399b Merge pull request #767 from SmartThingsCommunity/master
Rolling up master to staging
2016-04-07 13:55:16 -07:00
Luke Bredeson
237d6a79e9 EX-3: Improve Hue (Connect) event subscriptions 2016-04-05 13:28:45 -05:00
42 changed files with 3117 additions and 286 deletions

View File

@@ -9,7 +9,7 @@ apply plugin: 'smartthings-slack'
buildscript {
dependencies {
classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.7"
classpath "com.smartthings.deployment:executable-deployment-scripts:1.0.8"
}
repositories {
mavenLocal()

View File

@@ -0,0 +1,795 @@
/**
* CoopBoss H3Vx
* 02/29/16 Fixed app crash with Android by changing the syntax of default state in tile definition.
* Fixed null value errors during join process. Added 3 new commands to refresh data.
*
* 01/18/16 Masked invalid temperature reporting when TempProbe1 is below 0C
* Added setBaseCurrentNE, readBaseCurrentNE, commands as well as baseCurrentNE attribute.
*
* Copyright 2016 John Rucker
*
* 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.
* Icon location = http://scripts.3dgo.net/smartthings/icons/
*/
metadata {
definition (name: "CoopBoss H3Vx", namespace: "JohnRucker", author: "John.Rucker@Solar-Current.com") {
capability "Refresh"
capability "Polling"
capability "Sensor"
capability "Actuator"
capability "Configuration"
capability "Temperature Measurement"
capability "Door Control"
capability "Switch"
command "closeDoor"
command "closeDoorHiI"
command "openDoor"
command "autoCloseOn"
command "autoCloseOff"
command "autoOpenOn"
command "autoOpenOff"
command "setCloseLevelTo"
command "setOpenLevelTo"
command "setSensitivityLevel"
command "Aux1On"
command "Aux1Off"
command "Aux2On"
command "Aux2Off"
command "updateTemp1"
command "updateTemp2"
command "updateSun"
command "setNewBaseCurrent"
command "setNewPhotoCalibration"
command "readNewPhotoCalibration"
command "readBaseCurrentNE"
command "setBaseCurrentNE"
command "updateSensitivity"
command "updateCloseLightLevel"
command "updateOpenLightLevel"
attribute "doorState","string"
attribute "currentLightLevel","number"
attribute "closeLightLevel","number"
attribute "openLightLevel","number"
attribute "autoCloseEnable","string"
attribute "autoOpenEnable","string"
attribute "TempProb1","number"
attribute "TempProb2","number"
attribute "dayOrNight","string"
attribute "doorSensitivity","number"
attribute "doorCurrent","number"
attribute "doorVoltage","number"
attribute "Aux1","string"
attribute "Aux2","string"
attribute "coopStatus","string"
attribute "baseDoorCurrent","number"
attribute "photoCalibration","number"
attribute "baseCurrentNE","string"
fingerprint profileId: "0104", inClusters: "0000,0101,0402", manufacturer: "Solar-Current", model: "Coop Boss"
}
// simulator metadata
simulator {
}
preferences {
input description: "This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter \"-5\". If 3 degrees too cold, enter \"+3\".", displayDuringSetup: false, type: "paragraph", element: "paragraph"
input "tempOffsetCoop", "number", title: "Coop Temperature Offset", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
input "tempOffsetOutside", "number", title: "Outside Temperature Offset", description: "Adjust temperature by this many degrees", range: "*..*", displayDuringSetup: false
}
// UI tile definitions
tiles(scale: 2){
multiAttributeTile(name:"doorCtrl", type:"generic", width:6, height:4) {tileAttribute("device.doorState", key: "PRIMARY_CONTROL")
{
attributeState "unknown", label: '${name}', action:"openDoor", icon: "st.Outdoor.outdoor20", nextState:"Sent"
attributeState "open", label: '${name}', action:"closeDoor", icon: "st.Outdoor.outdoor20", backgroundColor: "#0000ff" , nextState:"Sent"
attributeState "opening", label: '${name}', action:"closeDoor", icon: "st.Outdoor.outdoor20", backgroundColor: "#ffa81e"
attributeState "closed", label: '${name}', action:"openDoor", icon: "st.Outdoor.outdoor20", backgroundColor: "#79b821", nextState:"Sent"
attributeState "closing", label: '${name}', action:"openDoor", icon: "st.Outdoor.outdoor20", backgroundColor: "#ffa81e"
attributeState "jammed", label: '${name}', action:"closeDoorHiI", icon: "st.Outdoor.outdoor20", backgroundColor: "#ff0000", nextState:"Sent"
attributeState "forced close", label: 'forced\rclose', action:"openDoor", icon: "st.Outdoor.outdoor20", backgroundColor: "#ff8000", nextState:"Sent"
attributeState "fault", label: 'FAULT', action:"openDoor", icon: "st.Outdoor.outdoor20", backgroundColor: "#ff0000", nextState:"Sent"
attributeState "Sent", label: 'wait', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
}
tileAttribute ("device.coopStatus", key: "SECONDARY_CONTROL") {
attributeState "device.coopStatus", label:'${currentValue}'
}
}
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 "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"
attributeState "Sent", label: 'wait', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
}
tileAttribute ("device.doorState", key: "SECONDARY_CONTROL") {
attributeState "unknown", label: 'Door is in unknown state. Push to open.'
attributeState "open", label: 'Coop door is open. Push to close.'
attributeState "opening", label: 'Caution, door is opening!'
attributeState "closed", label: 'Coop door is closed. Push to open.'
attributeState "closing", label: 'Caution, door is closing!'
attributeState "jammed", label: 'Door open! Push for high-force close'
attributeState "forced close", label: "Door is closed. Push to open."
attributeState "fault", label: 'Door fault check electrical connection.'
attributeState "Sent", label: 'Command sent to CoopBoss...'
}
}
standardTile("autoClose", "device.autoCloseEnable", width: 2, height: 2){
state "on", label: 'Auto', action:"autoCloseOff", icon: "st.doors.garage.garage-closing", backgroundColor: "#79b821", nextState:"Sent"
state "off", label: 'Auto', action:"autoCloseOn", icon: "st.doors.garage.garage-closing", nextState:"Sent"
state "Sent", label: 'wait', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
}
standardTile("autoOpen", "device.autoOpenEnable", width: 2, height: 2){
state "on", label: 'Auto', action:"autoOpenOff", icon: "st.doors.garage.garage-opening", backgroundColor: "#79b821", nextState:"Sent"
state "off", label: 'Auto', action:"autoOpenOn", icon: "st.doors.garage.garage-opening", nextState:"Sent"
state "Sent", label: 'wait', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
}
valueTile("TempProb1", "device.TempProb1", width: 2, height: 2, decoration: "flat"){
state "default", label:'Coop\r${currentValue}°', unit:"F", action:"updateTemp1"}
valueTile("TempProb2", "device.TempProb2", width: 2, height: 2, decoration: "flat"){
state "default", label:'Outside\r${currentValue}°', unit:"F", action:"updateTemp2"}
valueTile("currentLevel", "device.currentLightLevel", width: 2, height: 2, decoration: "flat") {
state "default", label:'Sun\r${currentValue}', action:"updateSun"}
valueTile("dayOrNight", "device.dayOrNight", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
state "default", label:'${currentValue}.'
}
controlTile("SetClSlider", "device.closeLightLevel", "slider", height: 2, width: 4, inactiveLabel: false, range:"(1..100)") {
state "closeLightLevel", action:"setCloseLevelTo", backgroundColor:"#d04e00"
}
valueTile("SetClValue", "device.closeLightLevel", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
state "default", label:'Close\nSunlight\n${currentValue}', action:'updateCloseLightLevel'
}
controlTile("SetOpSlider", "device.openLightLevel", "slider", height: 2, width: 4, inactiveLabel: false, range:"(1..100)") {
state "openLightLevel", action:"setOpenLevelTo", backgroundColor:"#d04e00"
}
valueTile("SetOpValue", "device.openLightLevel", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
state "default", label:'Open\nSunlight\n${currentValue}', action:'updateOpenLightLevel'
}
controlTile("SetSensitivitySlider", "device.doorSensitivity", "slider", height: 2, width: 4, inactiveLabel: false, range:"(1..100)") {
state "openLightLevel", action:"setSensitivityLevel", backgroundColor:"#d04e00"
}
valueTile("SetSensitivityValue", "device.doorSensitivity", decoration: "flat", inactiveLabel: false, width: 2, height: 2) {
state "default", label:'Door\nSensitivity\n${currentValue}', action:'updateSensitivity'
}
standardTile("refresh", "device.refresh", width: 2, height: 2, decoration: "flat", inactiveLabel: false) {
state "default", label:'All', action:"refresh.refresh", icon:"st.secondary.refresh-icon"
}
standardTile("aux1", "device.Aux1", width: 2, height: 2, canChangeIcon: true) {
state "off", label:'Aux 1', action:"Aux1On", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"Sent"
state "on", label:'Aux 1', action:"Aux1Off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"Sent"
state "Sent", label: 'wait', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
}
standardTile("aux2", "device.Aux2", width: 2, height: 2, canChangeIcon: true) {
state "off", label:'Aux 2', action:"Aux2On", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"Sent"
state "on", label:'Aux 2', action:"Aux2Off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"Sent"
state "Sent", label: 'wait', icon: "st.motion.motion.active", backgroundColor: "#ffa81e"
}
main "doorCtrl"
details (["dtlsDoorCtrl", "TempProb1", "TempProb2", "currentLevel", "autoClose", "autoOpen", "dayOrNight",
"SetClSlider", "SetClValue", "SetOpSlider", "SetOpValue", "SetSensitivitySlider", "SetSensitivityValue",
"aux1", "aux2", "refresh"])
}
}
// Parse incoming device messages to generate events def parse(String description) {
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: ') || description?.startsWith('humidity: ')) {
map = parseCustomMessage(description)
}
log.debug map
//return map ? createEvent(map) : null
sendEvent(map)
callUpdateStatusTxt()
}
private Map parseCatchAllMessage(String description) {
Map resultMap = [:]
def cluster = zigbee.parse(description)
log.debug cluster
if (cluster.clusterId == 0x0402) {
switch(cluster.sourceEndpoint) {
case 0x39: // Endpoint 0x39 is the temperature of probe 1
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
resultMap.name = "TempProb1"
def celsius = Integer.valueOf(temp,16).shortValue()
if (celsius == -32768){ // This number is used to indicate an error in the temperature reading
resultMap.value = "---"
}else{
celsius = celsius / 100 // Temperature value is sent X 100.
resultMap.value = celsiusToFahrenheit(celsius)
if (tempOffsetOutside) {
def offset = tempOffsetOutside as int
resultMap.value = resultMap.value + offset
}
}
sendEvent(name: "temperature", value: resultMap.value, displayed: false) // set the temperatureMeasurment capability to temperature
break
case 0x40: // Endpoint 0x40 is the temperature of probe 2
String temp = cluster.data[-2..-1].reverse().collect { cluster.hex1(it) }.join()
resultMap.name = "TempProb2"
def celsius = Integer.valueOf(temp,16).shortValue()
//resultMap.descriptionText = "Prob2 celsius value = ${celsius}"
if (celsius == -32768){ // This number is used to indicate an error in the temperature reading
resultMap.value = "---"
}else{
celsius = celsius / 100 // Temperature value is sent X 100.
resultMap.value = celsiusToFahrenheit(celsius)
if (tempOffsetCoop) {
def offset = tempOffsetCoop as int
resultMap.value = resultMap.value + offset
}
}
break
}
}
if (cluster.clusterId == 0x0101 && cluster.command == 0x0b) { // This is a default response to a command sent to cluster 0x0101 door control
//log.debug "Default Response Data = $cluster.data"
switch(cluster.data) {
case "[10, 0]": // 0x0a turn auto close on command verified
resultMap.name = "autoCloseEnable"
resultMap.value = "on"
break
case "[11, 0]": // 0x0b turn auto close off command verified
resultMap.name = "autoCloseEnable"
resultMap.value = "off"
break
case "[12, 0]": // 0x0C turn auto open on command verified
resultMap.name = "autoOpenEnable"
resultMap.value = "on"
break
case "[13, 0]": // 0x0d turn auto open off command verified
resultMap.name = "autoOpenEnable"
resultMap.value = "off"
break
case "[20, 0]": // 0x14 Aux1 On command verified
log.info "verified Aux1 On"
sendEvent(name: "switch", value: "on", displayed: false)
resultMap.name = "Aux1"
resultMap.value = "on"
break
case "[21, 0]": // 0x15 Aux1 Off command verified
log.info "verified Aux1 Off"
sendEvent(name: "switch", value: "off", displayed: false)
resultMap.name = "Aux1"
resultMap.value = "off"
break
case "[22, 0]": // 0x16 Aux2 On command verified
log.info "verified Aux2 On"
resultMap.name = "Aux2"
resultMap.value = "on"
break
case "[23, 0]": // 0x17 Aux2 Off command verified
log.info "verified Aux2 Off"
resultMap.name = "Aux2"
resultMap.value = "off"
break
}
}
return resultMap
}
private Map parseReportAttributeMessage(String description) {
Map resultMap = [:]
def descMap = parseDescriptionAsMap(description)
//log.debug "read attr descMap --> $descMap"
if (descMap.cluster == "0101" && descMap.attrId == "0003") {
resultMap.name = "doorState"
if (descMap.value == "00"){
resultMap.value = "unknown"
sendEvent(name: "door", value: "unknown", displayed: false)
}else if(descMap.value == "01"){
resultMap.value = "closed"
sendEvent(name: "door", value: "closed", displayed: false)
}else if(descMap.value == "02"){
resultMap.value = "open"
sendEvent(name: "door", value: "open", displayed: false)
}else if(descMap.value == "03"){
resultMap.value = "jammed"
}else if(descMap.value == "04"){
resultMap.value = "forced close"
}else if(descMap.value == "05"){
resultMap.value = "forced close"
}else if(descMap.value == "06"){
resultMap.value = "closing"
sendEvent(name: "door", value: "closing", displayed: false)
}else if(descMap.value == "07"){
resultMap.value = "opening"
sendEvent(name: "door", value: "opening", displayed: false)
}else if(descMap.value == "08"){
resultMap.value = "fault"
}else {
resultMap.value = "unknown"
}
resultMap.descriptionText = "Door State Changed to ${resultMap.value}"
} else if (descMap.cluster == "0101" && descMap.attrId == "0400") {
resultMap.name = "currentLightLevel"
resultMap.value = (Integer.parseInt(descMap.value, 16))
resultMap.displayed = false
} else if (descMap.cluster == "0101" && descMap.attrId == "0401") {
resultMap.name = "closeLightLevel"
resultMap.value = (Integer.parseInt(descMap.value, 16))
} else if (descMap.cluster == "0101" && descMap.attrId == "0402") {
resultMap.name = "openLightLevel"
resultMap.value = (Integer.parseInt(descMap.value, 16))
} else if (descMap.cluster == "0101" && descMap.attrId == "0403") {
resultMap.name = "autoCloseEnable"
if (descMap.value == "01"){resultMap.value = "on"}
else{resultMap.value = "off"}
} else if (descMap.cluster == "0101" && descMap.attrId == "0404") {
resultMap.name = "autoOpenEnable"
if (descMap.value == "01"){resultMap.value = "on"}
else{resultMap.value = "off"}
} else if (descMap.cluster == "0101" && descMap.attrId == "0405") {
resultMap.name = "doorCurrent"
resultMap.value = (Integer.parseInt(descMap.value, 16))
resultMap.value = resultMap.value * 0.001
} else if (descMap.cluster == "0101" && descMap.attrId == "0408") {
resultMap.name = "doorSensitivity"
resultMap.value = (100 - Integer.parseInt(descMap.value, 16))
} else if (descMap.cluster == "0101" && descMap.attrId == "0409") {
resultMap.name = "baseDoorCurrent"
resultMap.value = (Integer.parseInt(descMap.value, 16))
resultMap.value = resultMap.value * 0.001
} else if (descMap.cluster == "0101" && descMap.attrId == "040a") {
resultMap.name = "doorVoltage"
resultMap.value = (Integer.parseInt(descMap.value, 16))
resultMap.value = resultMap.value * 0.001
} else if (descMap.cluster == "0101" && descMap.attrId == "040b") {
resultMap.name = "Aux1"
if(descMap.value == "01"){
resultMap.value = "on"
sendEvent(name: "switch", value: "on", displayed: false)
}else{
resultMap.value = "off"
sendEvent(name: "switch", value: "off", displayed: false)
}
} else if (descMap.cluster == "0101" && descMap.attrId == "040c") {
resultMap.name = "Aux2"
if(descMap.value == "01"){
resultMap.value = "on"
}else{
resultMap.value = "off"
}
} else if (descMap.cluster == "0101" && descMap.attrId == "040d") {
resultMap.name = "photoCalibration"
resultMap.value = (Integer.parseInt(descMap.value, 16))
} else if (descMap.cluster == "0101" && descMap.attrId == "040e") {
resultMap.name = "baseCurrentNE"
resultMap.value = (Integer.parseInt(descMap.value, 16))
}
return resultMap
}
private Map parseCustomMessage(String description) {
//log.info "ParseCustomMessage called with ${description}"
Map resultMap = [:]
if (description?.startsWith('temperature: ')) {
resultMap.name = "temperature"
def rawT = (description - "temperature: ").trim()
resultMap.descriptionText = "Temperature celsius value = ${rawT}"
def rawTint = Float.parseFloat(rawT)
if (rawTint > 65){
resultMap.name = null
resultMap.value = null
resultMap.descriptionText = "Temperature celsius value = ${rawT} is invalid not updating"
log.warn "Invalid temperature value detected! rawT = ${rawT}, description = ${description}"
}else if (rawT == -32768){ // This number is used to indicate an error in the temperature reading
resultMap.value = "ERR"
}else{
resultMap.value = celsiusToFahrenheit(rawT.toFloat()) as Float
sendEvent(name: "TempProb1", value: resultMap.value, displayed: false) // Workaround for lack of access to endpoint information for Temperature report
}
}
resultMap.displayed = false
log.info "Temperature reported = ${resultMap.value}"
return resultMap
}
def parseDescriptionAsMap(description) {
(description - "read attr - ").split(",").inject([:]) { map, param ->
def nameAndValue = param.split(":")
map += [(nameAndValue[0].trim()):nameAndValue[1].trim()]
}
}
// Added for Temeperature parse
def getFahrenheit(value) {
def celsius = Integer.parseInt(value, 16)
return celsiusToFahrenheit(celsius) as Integer
}
// Private methods
def callUpdateStatusTxt(){
def cTemp = device.currentState("TempProb1")?.value
def cLight = 0
def testNull = device.currentState("currentLightLevel")?.value
if (testNull != null){
cLight = device.currentState("currentLightLevel")?.value as int
}
updateStatusTxt(cTemp, cLight)
}
def updateStatusTxt(currentTemp, currentLight){
//log.info "called updateStatusTxt with ${currentTemp}, ${currentLight}"
def cTmp = currentTemp
def cLL = 10
def oLL = 10
def testNull = device.currentState("closeLightLevel")?.value
if (testNull != null){
cLL = device.currentState("closeLightLevel")?.value as int
}
testNull = device.currentState("openLightLevel")?.value
if (testNull != null){
oLL = device.currentState("openLightLevel")?.value as int
}
def aOpnEn = device.currentState("autoOpenEnable")?.value
def aClsEn = device.currentState("autoCloseEnable")?.value
if (currentLight < cLL){
if (aOpnEn == "on"){
sendEvent(name: "dayOrNight", value: "Sun must be > ${oLL} to auto open", displayed: false)
sendEvent(name: "coopStatus", value: "Sunlight ${currentLight} open at ${oLL}. Coop ${cTmp}°", displayed: false)
}else{
sendEvent(name: "dayOrNight", value: "Auto Open is turned off.", displayed: false)
sendEvent(name: "coopStatus", value: "Sunlight ${currentLight} auto open off. Coop ${cTmp}°", displayed: false)
}
}else {
if (aClsEn == "on"){
sendEvent(name: "dayOrNight", value: "Sun must be < ${cLL} to auto close", displayed: false)
sendEvent(name: "coopStatus", value: "Sunlight ${currentLight} close at ${cLL}. Coop ${cTmp}°", displayed: false)
}else{
sendEvent(name: "dayOrNight", value: "Auto Close is turned off.", displayed: false)
sendEvent(name: "coopStatus", value: "Sunlight ${currentLight} auto close off. Coop ${cTmp}°", displayed: false)
}
}
}
// Commands to device
def on() {
log.debug "on calling Aux1On"
Aux1On()
}
def off() {
log.debug "off calling Aux1Off"
Aux1Off()
}
def close() {
log.debug "close calling closeDoor"
closeDoor()
}
def open() {
log.debug "open calling openDoor"
openDoor()
}
def Aux1On(){
log.debug "Sending Aux1 = on command"
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x14 {}"
}
def Aux1Off(){
log.debug "Sending Aux1 = off command"
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x15 {}"
}
def Aux2On(){
log.debug "Sending Aux2 = on command"
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x16 {}"
}
def Aux2Off(){
log.debug "Sending Aux2 = off command"
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x17 {}"
}
def openDoor() {
log.debug "Sending Open command"
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x1 {}"
}
def closeDoor() {
log.debug "Sending Close command"
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x0 {}"
}
def closeDoorHiI() {
log.debug "Sending High Current Close command"
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x4 {}"
}
def autoOpenOn() {
log.debug "Setting Auto Open On"
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x0C {}"
}
def autoOpenOff() {
log.debug "Setting Auto Open Off"
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x0D {}"
}
def autoCloseOn() {
log.debug "Setting Auto Close On"
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x0A {}"
}
def autoCloseOff() {
log.debug "Setting Auto Close Off"
"st cmd 0x${device.deviceNetworkId} 0x38 0x0101 0x0B {}"
}
def setOpenLevelTo(cValue) {
def cX = cValue
log.debug "Setting Open Light Level to ${cX} Hex = 0x${Integer.toHexString(cX)}"
def cmd = []
cmd << "st wattr 0x${device.deviceNetworkId} 0x38 0x0101 0x402 0x23 {${Integer.toHexString(cX)}}"
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x402" // Read light value
cmd
}
def setCloseLevelTo(cValue) {
def cX = cValue
log.debug "Setting Close Light Level to ${cX} Hex = 0x${Integer.toHexString(cX)}"
def cmd = []
cmd << "st wattr 0x${device.deviceNetworkId} 0x38 0x0101 0x401 0x23 {${Integer.toHexString(cX)}}"
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x401" // Read light value
cmd
}
def setSensitivityLevel(cValue) {
def cX = 100 - cValue
log.debug "Setting Door sensitivity level to ${cX} Hex = 0x${Integer.toHexString(cX)}"
def cmd = []
cmd << "st wattr 0x${device.deviceNetworkId} 0x38 0x0101 0x408 0x23 {${Integer.toHexString(cX)}}" // Write attribute. 0x23 is a 32 bit integer value.
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x408" // Read attribute
cmd
}
def setNewBaseCurrent(cValue) {
def cX = cValue as int
log.info "Setting new BaseCurrent to ${cX} Hex = 0x${Integer.toHexString(cX)}"
def cmd = []
cmd << "st wattr 0x${device.deviceNetworkId} 0x38 0x0101 0x409 0x23 {${Integer.toHexString(cX)}}" // Write attribute. 0x23 is a 32 bit integer value.
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x409" // Read attribute
cmd
}
def setNewPhotoCalibration(cValue) {
def cX = cValue as int
log.info "Setting new Photoresister calibration to ${cX} Hex = 0x${Integer.toHexString(cX)}"
def cmd = []
cmd << "st wattr 0x${device.deviceNetworkId} 0x38 0x0101 0x40D 0x2B {${Integer.toHexString(cX)}}" // Write attribute. 0x2B is a 32 bit signed integer value.
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x40D" // Read attribute
cmd
}
def readNewPhotoCalibration() {
log.info "Requesting current Photoresister calibration "
def cmd = []
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x40D" // Read attribute
cmd
}
def readBaseCurrentNE() {
log.info "Requesting base current never exceed setting "
def cmd = []
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x40E" // Read attribute
cmd
}
def setBaseCurrentNE(cValue) {
def cX = cValue as int
log.info "Setting new base Current Never Exceed to ${cX} Hex = 0x${Integer.toHexString(cX)}"
def cmd = []
cmd << "st wattr 0x${device.deviceNetworkId} 0x38 0x0101 0x40E 0x23 {${Integer.toHexString(cX)}}" // Write attribute. 0x23 is a 32 bit unsigned integer value.
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x40E" // Read attribute
cmd
}
def poll(){
log.debug "Polling Device"
def cmd = []
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0003" // Read Door State
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0400" // Read Current Light Level
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x39 0x0402 0x0000" // Read probe 1 Temperature
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x40 0x0402 0x0000" // Read probe 2 Temperature
cmd
}
def updateTemp1() {
log.debug "Sending attribute read request for Temperature Probe1"
def cmd = []
cmd << "st rattr 0x${device.deviceNetworkId} 0x39 0x0402 0x0000" // Read Current Temperature from Coop Probe 1
cmd
}
def updateTemp2() {
log.debug "Sending attribute read request for Temperature Probe2"
def cmd = []
cmd << "st rattr 0x${device.deviceNetworkId} 0x40 0x0402 0x0000" // Read Current Temperature from Coop Probe 2
cmd
}
def updateSun() {
log.debug "Sending attribute read request for Sun Light Level"
def cmd = []
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0400" // Read Current Light Level
cmd
}
def updateSensitivity() {
log.debug "Sending attribute read request for door sensitivity"
def cmd = []
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0408" // Read Door sensitivity
cmd
}
def updateCloseLightLevel() {
log.debug "Sending attribute read close light level"
def cmd = []
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0401"
cmd
}
def updateOpenLightLevel() {
log.debug "Sending attribute read open light level"
def cmd = []
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0402"
cmd
}
def refresh() {
log.debug "sending refresh command"
def cmd = []
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0003" // Read Door State
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0400" // Read Current Light Level
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0401" // Read Door Close Light Level
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0402" // Read Door Open Light Level
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0403" // Read Auto Door Close Settings
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0404" // Read Auto Door Open Settings
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x39 0x0402 0x0000" // Read Current Temperature from Coop Probe 1
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0408" // Object detection sensitivity
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x40 0x0402 0x0000" // Read Current Temperature from Coop Probe 2
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x0405" // Current required to close door
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x040B" // Aux1 Status
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x040C" // Aux2 Status
cmd << "delay 150"
cmd << "st rattr 0x${device.deviceNetworkId} 0x38 0x0101 0x409" // Read Base current
cmd
}
def configure() {
log.debug "Binding SEP 0x38 DEP 0x01 Cluster 0x0101 Lock cluster to hub"
log.debug "Binding SEP 0x39 DEP 0x01 Cluster 0x0402 Temperature cluster to hub"
log.debug "Binding SEP 0x40 DEP 0x01 Cluster 0x0402 Temperature cluster to hub"
def cmd = []
cmd << "zdo bind 0x${device.deviceNetworkId} 0x38 0x01 0x0101 {${device.zigbeeId}} {}" // Bind to end point 0x38 and the lock cluster
cmd << "delay 150"
cmd << "zdo bind 0x${device.deviceNetworkId} 0x39 0x01 0x0402 {${device.zigbeeId}} {}" // Bind to end point 0x39 and the temperature cluster
cmd << "delay 150"
cmd << "zdo bind 0x${device.deviceNetworkId} 0x40 0x01 0x0402 {${device.zigbeeId}} {}" // Bind to end point 0x40 and the temperature cluster
cmd << "delay 1500"
log.info "Sending ZigBee Configuration Commands to Coop Control"
return cmd + refresh()
}

View File

@@ -94,11 +94,11 @@ def parse(String description) {
def cmd = zwave.parse(description, [0x31: 1, 0x32: 1, 0x60: 3])
if (cmd) {
result = createEvent(zwaveEvent(cmd))
log.debug "Parse returned ${result?.descriptionText}"
storeGraphData(result.name, result.value)
} else {
log.debug "zwave.parse returned null command. Cannot create event"
}
log.debug "Parse returned ${result?.descriptionText}"
storeGraphData(result.name, result.value)
return result
}

View File

@@ -12,16 +12,6 @@
*
*/
/*
* Purpose: Arrival Sensor HA DTH File
*
* Filename: Arrival-Sensor-HA.src/Arrival-Sensor-HA.groovy
*
* Change History:
* 1. 20160115 TW - Update/Edit to support i18n translations
* 2. 20160121 TW - Update to V4 battery calcs, added pref's page title translations
*/
metadata {
definition (name: "Arrival Sensor HA", namespace: "smartthings", author: "SmartThings") {
capability "Tone"

View File

@@ -1,4 +1,3 @@
#==============================================================================
# Copyright 2016 SmartThings
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -12,25 +11,16 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#==============================================================================
# Purpose: Arrival Sensor HA i18n Translation File
#
# Filename: Arrival-Sensor-HA.src/i18n/messages.properties
#
# Change History:
# 1. 20160115 TW Initial release with informal Korean translation.
# 2. 20160121 TW Added def preference section titles.
#==============================================================================
# Korean (ko)
# Device Preferences
'''Give your device a name'''.ko=기기 이름 바꾸기
'''Give your device a name'''.ko=기기 이름 설정
'''Set Device Image'''.ko=기기 이미지 설정
'''Presence timeout (minutes)'''.ko=시간 초과. 스마트폰 위치 정보
'''Presence timeout (minutes)'''.ko=알람 유예 시간 설정 (분)
'''Tap to set'''.ko=눌러서 설정
'''Arrival Sensor'''.ko=도착알림 센서
'''${currentValue}% battery'''.ko=${currentValue}% 배터리
# Events / Notifications
'''{{ linkText }} battery was {{ value }}'''.ko={{ linkText }}남아있는 배터리 {{ value }}입니다.
'''{{ linkText }} has arrived'''.ko={{ linkText }}집에 도착했습니다.
'''{{ linkText }} has left'''.ko={{ linkText }}집을 나갔습니다.
'''{{ linkText }} battery was {{ value }}'''.ko={{ linkText }}의 남은 배터리 {{ value }}
'''{{ linkText }} has arrived'''.ko={{ linkText }} 귀가
'''{{ linkText }} has left'''.ko={{ linkText }} 외출
#==============================================================================

View File

@@ -13,17 +13,19 @@
* for the specific language governing permissions and limitations under the License.
*
*/
//@Deprecated: Moved to ZLL Dimmer Bulb
metadata {
definition (name: "Cree Bulb", namespace: "smartthings", author: "SmartThings") {
capability "Actuator"
capability "Configuration"
capability "Polling"
capability "Refresh"
capability "Switch"
capability "Switch Level"
fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,1000", outClusters: "0000,0019"
//fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,1000", outClusters: "0000,0019"
}
// simulator metadata
@@ -88,6 +90,10 @@ def refresh() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.onOffConfig() + zigbee.levelConfig()
}
def poll() {
zigbee.onOffRefresh() + zigbee.levelRefresh()
}
def configure() {
log.debug "Configuring Reporting and Bindings."
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()

View File

@@ -0,0 +1,456 @@
/**
* Device Type Definition File
*
* Device Type: Fibaro Dimmer
* File Name: fibaro-dimmer.groovy
* Initial Release: 2015-06-00
* Author: SmartThings
*
* Copyright 2015 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
metadata {
// Automatically generated. Make future change here.
definition (name: "Fibaro Dimmer 1", namespace: "smartthings", author: "SmartThings, Elnar Hajiyev") {
capability "Switch Level"
capability "Actuator"
capability "Switch"
capability "Polling"
capability "Refresh"
capability "Sensor"
capability "Configuration"
//Extending Fibaro Dimmer 1 devices with scene attribute
attribute "scene", "number"
command "configureParams"
fingerprint deviceId: "0x1101", inClusters: "0x72,0x86,0x70,0x85,0x8E,0x26,0x7A,0x27,0x73,0xEF,0x26,0x2B"
}
simulator {
status "on": "command: 2003, payload: FF"
status "off": "command: 2003, payload: 00"
status "09%": "command: 2003, payload: 09"
status "10%": "command: 2003, payload: 0A"
status "33%": "command: 2003, payload: 21"
status "66%": "command: 2003, payload: 42"
status "99%": "command: 2003, payload: 63"
// reply messages
reply "2001FF,delay 5000,2602": "command: 2603, payload: FF"
reply "200100,delay 5000,2602": "command: 2603, payload: 00"
reply "200119,delay 5000,2602": "command: 2603, payload: 19"
reply "200132,delay 5000,2602": "command: 2603, payload: 32"
reply "20014B,delay 5000,2602": "command: 2603, payload: 4B"
reply "200163,delay 5000,2602": "command: 2603, payload: 63"
}
tiles {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel"
}
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
standardTile("configureParams", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "configure", label:'', action:"configureParams", icon:"st.secondary.configure"
}
main(["switch"])
details(["switch", "refresh",
"levelSliderControl",
"configureParams"
])
}
preferences {
input name: "param1", type: "enum", defaultValue: "255", required: true,
options: ["0" : "0",
"1" : "1",
"2" : "2",
"255" : "255"],
title: "1. Activate / deactivate functions ALL ON / ALL OFF.\n" +
"Available settings:\n" +
"0 = All ON not active, All OFF not active,\n" +
"1 = All ON not active, All OFF active,\n" +
"2 = All ON active, All OFF not active,\n" +
"255 = All ON active, All OFF active.\n" +
"Default value: 255."
input name: "param6", type: "number", range: "0..2", defaultValue: "0", required: true,
title: "6. Sending commands to control devices assigned to 1st association group (key no. 1).\n" +
"Available settings:\n" +
"0 = commands are sent when device is turned on and off.\n" +
"1 = commands are sent when device is turned off. Enabling device does not send control commands. Double-clicking key sends 'turn on' command, dimmers memorize the last saved state (e.g. 50% brightness).\n" +
"2 = commands are sent when device is turned off. Enabling device does not send control commands. Double-clicking key sends 'turn on' command and dimmers are set to 100% brightness.\n" +
"Default value: 1.\n\n" +
"NOTE: Parameter 15 value must be set to 1 to work properly. This activates the double-click functionality - dimmer/roller shutter control."
input name: "param7", type: "number", range: "0..1", defaultValue: "1", required: true,
title: "7. Checking the device status before sending a control frame from the key no. 2.\n" +
"Available settings:\n" +
"0 = Device status is not checked.\n" +
"1 = Device status is checked.\n" +
"Default value: 1.\n\n" +
"Info: Key no. 2 is not represented by any physical device expect of devices on association list. " +
"This functionality prevents of lack of reaction on pressing key no. 2 through polling devices from list one by one and checking thier actual states.\n" +
"It is not possible to check the device status before sending a control frame from the key no. 2 if roller blind switch is chosen in parameter 14 (value 2)\n" +
"If devices state is checked before sending asociation then parameter 19 should be set to value 0."
input name: "param8", type: "number", range: "1..99", defaultValue: "1", required: true,
title: "8. The percentage of a dimming step at automatic control.\n" +
"Available settings: 1-99\n" +
"Default value: 1."
input name: "param9", type: "number", range: "1..255", defaultValue: "5", required: true,
title: "9. Time of manually moving the Dimmer between the extreme dimming values.\n" +
"Available settings: 1-255 (10ms 2.5s)\n" +
"Default value: 5."
input name: "param10", type: "number", range: "0..255", defaultValue: "1", required: true,
title: "10. Time of Automatic moving the Dimmer between the extreme dimming values.\n" +
"Available settings: 0-255 (0ms 2.5s)\n" +
"0 - this value disables the smooth change in light intensity\n" +
"Default value: 1.\n\n" +
"NOTE value 0 is required for inductive and capacitive devices unsuitable for dimming, (e.g. fluorescent lamps , motors etc.)."
input name: "param11", type: "number", range: "1..99", defaultValue: "1", required: true,
title: "11. The percentage of a dimming step at manual control.\n" +
"Available settings: 1-99\n" +
"Default value: 1."
input name: "param12", type: "number", range: "2..99", defaultValue: "99", required: true,
title: "12. Maximum Dimmer level control.\n" +
"Available settings: 2-99\n" +
"Default value: 99."
input name: "param13", type: "number", range: "1..98", defaultValue: "2", required: true,
title: "13. Minimum Dimmer level control\n" +
"Available settings: 1-98\n" +
"Default value: 2.\n\n" +
"NOTE: The maximum level may not be lower than the minimum level.\n" +
"Recommended values of parameters 12 and 13 (max and min level) for controlling the devices are as follows:\n" +
"- AC motors [min 60%, max 99%]\n" +
"- fluorescent lamps, fluorescent tubes, LED [min 98%, max 99%] [parameter 10 set to 0]"
input name: "param14", type: "number", range: "0..2", defaultValue: "0", required: true,
title: "14. Switch type. Choose between momentary switch and toggle switch.\n" +
"Available settings:\n" +
"0 = momentary switch,\n" +
"1 = toggle switch,\n" +
"2 = Roller blind switch (UP / DOWN) - two switch keys operate the Dimmer.\n" +
"Default value: 0."
input name: "param15", type: "number", range: "0..1", defaultValue: "1", required: true,
title: "15. Double click option (set lightning at 100%).\n" +
"Available settings:\n" +
"0 = Double click disabled,\n" +
"1 = Double click enabled.\n" +
"Default value: 1."
input name: "param16", type: "number", range: "0..1", defaultValue: "1", required: true,
title: "16. Saving the state of the device after a power failure. The Dimmer will return to the last position before power failure.\n" +
"Available settings:\n" +
"0 = the Dimmer does not save the state after a power failure, it returns to 'off' position,\n" +
"1 = the Dimmer saves its state before power failure.\n" +
"Default value: 1."
input name: "param17", type: "number", range: "0..1", defaultValue: "0", required: true,
title: "17. The function of 3 - way switch, provides the option to double key no. 1. " +
"The Dimmer may control two toggle push-buttons or an infinite number of momentary push-buttons.\n" +
"Available settings:\n" +
"0 = the function of 3-way switch is disabled,\n" +
"1 = the function of 3-way switch is enabled.\n" +
"Default value: 0."
input name: "param18", type: "number", range: "0..1", defaultValue: "0", required: true,
title: "18. The function of synchronizing the light level for associated devices. The Dimmer communicates the position to the associated device.\n" +
"Available settings:\n" +
"0 = function disabled,\n" +
"1 = function enabled.\n" +
"Default value: 0."
input name: "param19", type: "number", range: "0..1", defaultValue: "0", required: true,
title: "19. Assigns bistable key status to the device status.\n" +
"Available settings:\n" +
"0 = [On / Off] device changes status on key status change.\n" +
"1 = Device status depends on key status: ON when the key is ON, OFF when the key is OFF.\n"
"Default value: 0.\n\n" +
"Info: Remote control from Fibaro System Is Still Possible. This function is useful When you want display status of external devices, e.g. Motion Sensor, in Fibaro System."
input name: "param30", type: "number", range: "0..3", defaultValue: "3", required: true,
title: "30. Alarm of any type (general alarm, water flooding alarm, smoke alarm: CO, CO2, temperature alarm).\n" +
"Available settings:\n" +
"0 = DEACTIVATION - the device does not respond to alarm data frames,\n" +
"1 = ALARM DIMMER ON - the device turns on after detecting an alarm,\n" +
"2 = ALARM DIMMER OFF - the device turns off after detecting an alarm,\n" +
"3 = ALARM FLASHING the device periodically changes its status to the opposite, when it detects an alarm within 10 min."
"Default value: 3."
input name: "param39", type: "number", range: "1..65535", defaultValue: "600", required: true,
title: "39. Active flashing alarm time.\n" +
"Available settings: [1-65535][ms]\n" +
"Default value: 600."
input name: "param41", type: "number", range: "0..1", defaultValue: "0", required: true,
title: "41. Scene activation functionality.\n" +
"The device offers the possibility of sending commands compatible with Command class scene activation. " +
"Information is sent to devices assigned to association group no. 3. " +
"Controllers such as Home Center 2 are able to interpret such commands and based on these commands they activate scenes, to which specific scene IDs have been assigned. " +
"The user may expand the functionality of the button connected to inputs S1 and S2 by distinguishing the actions of keys connected to those inputs. " +
"For example: double click would activate the scene “goodnight” and triple click would activate the scene “morning”.\n" +
"Available settings:\n" +
"0 = functionality deactivated,\n" +
"1 = functionality activated.\n" +
"Default value: 0.\n\n" +
"Scene ID is determined as follows:\n" +
"Momentary switch:\n" +
"Input S1: holding down ID 12 (option inactive in case of roller blind switch), " +
"releasing ID 13, double click ID 14 (depends on parameters 15 value - 1 = double click active), " +
"triple click ID 15, one click ID 16.\n" +
"Input S2: holding down ID 22 (option inactive in case of roller blind switch), " +
"releasing ID 23, double click ID 24 (depends on parameters 15 value - 1 = double click active) option inactive in case of roller blind switch, " +
"triple click ID 25, one click ID 26.\n\n" +
"Toggle switch:\n" +
"Input S1: holding down ID 12, releasing ID 13, double click ID 14 (depends on parameters 15 value - 1 = double click active), triple click ID 15. " +
"If parameter no. 19 is set to 0: single click ID16 is sent. If parameter no. 19 is set to 1 following IDs are sent: switch from “off” to “on” ID 10, switch from “on” to “off” ID 11.\n" +
"Input S2: holding down ID 22, releasing ID 23, double click ID 24, (depends on parameters 15 value - 1 = double click active), triple click ID 25. " +
"If parameter no.19 set to 0 (default), then one click ID 26 is sent. If parameter no.19 is set to 1 following IDs are sent: switch from “off” to “on” ID 20, switch from “on” to “off” ID 21.\n\n" +
"Roller blind switch:\n" +
"Input S1, Turning on the light: switch from “off” to “on” ID 10, double click ID 14 (depends of parameter 15 value 1 - double click functionality), " +
"triple click ID 15, brighten ID 17, releasing ID 13.\n" +
"Input S2, Turning off the light: switch from “on” to “off” ID 11, triple click ID 25, dim ID 18, releasing ID 13."
input name: "param20", type: "number", range: "101..170", defaultValue: "110", required: true,
title: "ADVANCED FUNCTION\n\n" +
"20. The function enabling the change of control impulse length. " +
"This function will enable decreasing the minimum level of the Dimmer by extending the control impulse. " +
"By changing the minimum level, the user may completely dim LED bulbs. Not all LED bulbs available on the market have the dimming option.\n" +
"Available settings:\n" +
"Default values: 110 for 50Hz (UK), 101 for 60Hz (USA).\n\n"+
"WARNING!\nWrong setting of the function may cause incorrect operation of the Dimmer."
input name: "paramAssociationGroup1", type: "bool", defaultValue: false, required: true,
title: "The Dimmer 1 provides the association of three groups.\n\n" +
"1 = 1st group is assigned to key no. 1,\n" +
"Default value: true"
input name: "paramAssociationGroup2", type: "bool", defaultValue: false, required: true,
title: "2nd group is assigned to key no. 2\n" +
"Default value: true"
input name: "paramAssociationGroup3", type: "bool", defaultValue: true, required: true,
title: "3rd group for controllers such Home Center for state reporting,\n" +
"Default value: false"
}
}
def parse(String description) {
def item1 = [
canBeCurrentState: false,
linkText: getLinkText(device),
isStateChange: false,
displayed: false,
descriptionText: description,
value: description
]
def result
def cmd = zwave.parse(description, [0x26: 1, 0x70: 2, 072: 2])
//log.debug "cmd: ${cmd}"
if (cmd) {
result = createEvent(cmd, item1)
}
else {
item1.displayed = displayed(description, item1.isStateChange)
result = [item1]
}
if(result?.descriptionText)
log.debug "Parse returned ${result?.descriptionText}"
result
}
def createEvent(physicalgraph.zwave.commands.sceneactivationv1.SceneActivationSet cmd, Map map) {
log.debug( "Scene ID: $cmd.sceneId")
log.debug( "Dimming Duration: $cmd.dimmingDuration")
sendEvent(name: "scene", value: "$cmd.sceneId", data: [switchType: "$settings.param20"], descriptionText: "Scene id $cmd.sceneId was activated", isStateChange: true)
log.debug( "Scene id $cmd.sceneId was activated" )
}
def createEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd, Map item1) {
def result = doCreateEvent(cmd, item1)
for (int i = 0; i < result.size(); i++) {
result[i].type = "physical"
}
result
}
def createEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd, Map item1) {
def result = doCreateEvent(cmd, item1)
for (int i = 0; i < result.size(); i++) {
result[i].type = "physical"
}
result
}
def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStartLevelChange cmd, Map item1) {
[]
}
def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelStopLevelChange cmd, Map item1) {
[response(zwave.basicV1.basicGet())]
}
def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelSet cmd, Map item1) {
def result = doCreateEvent(cmd, item1)
for (int i = 0; i < result.size(); i++) {
result[i].type = "physical"
}
result
}
def createEvent(physicalgraph.zwave.commands.switchmultilevelv1.SwitchMultilevelReport cmd, Map item1) {
def result = doCreateEvent(cmd, item1)
result[0].descriptionText = "${item1.linkText} is ${item1.value}"
result[0].handlerName = cmd.value ? "statusOn" : "statusOff"
for (int i = 0; i < result.size(); i++) {
result[i].type = "digital"
}
result
}
def doCreateEvent(physicalgraph.zwave.Command cmd, Map item1) {
def result = [item1]
item1.name = "switch"
item1.value = cmd.value ? "on" : "off"
item1.handlerName = item1.value
item1.descriptionText = "${item1.linkText} was turned ${item1.value}"
item1.canBeCurrentState = true
item1.isStateChange = isStateChange(device, item1.name, item1.value)
item1.displayed = item1.isStateChange
if (cmd.value >= 5) {
def item2 = new LinkedHashMap(item1)
item2.name = "level"
item2.value = cmd.value as String
item2.unit = "%"
item2.descriptionText = "${item1.linkText} dimmed ${item2.value} %"
item2.canBeCurrentState = true
item2.isStateChange = isStateChange(device, item2.name, item2.value)
item2.displayed = false
result << item2
}
result
}
def createEvent(physicalgraph.zwave.Command cmd, Map map) {
// Handles any Z-Wave commands we aren't interested in
log.debug "UNHANDLED COMMAND $cmd"
}
def on() {
log.info "on"
delayBetween([zwave.basicV1.basicSet(value: 0xFF).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}
def off() {
delayBetween ([zwave.basicV1.basicSet(value: 0x00).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}
def setLevel(value) {
def level = Math.min(value as Integer, 99)
delayBetween ([zwave.basicV1.basicSet(value: level).format(), zwave.switchMultilevelV1.switchMultilevelGet().format()], 5000)
}
def setLevel(value, duration) {
def level = Math.min(value as Integer, 99)
def dimmingDuration = duration < 128 ? duration : 128 + Math.round(duration / 60)
zwave.switchMultilevelV2.switchMultilevelSet(value: level, dimmingDuration: dimmingDuration).format()
}
def poll() {
zwave.switchMultilevelV1.switchMultilevelGet().format()
}
def refresh() {
zwave.switchMultilevelV1.switchMultilevelGet().format()
}
def createEvent(physicalgraph.zwave.commands.configurationv2.ConfigurationReport cmd, Map item1) {
log.debug "${device.displayName} parameter '${cmd.parameterNumber}' with a byte size of '${cmd.size}' is set to '${cmd.configurationValue}'"
}
def configureParams() {
log.debug "Configuring ${device.displayName} parameters"
def cmds = []
cmds << zwave.configurationV1.configurationSet(parameterNumber: 1, size: 1, scaledConfigurationValue: param1.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 6, size: 1, scaledConfigurationValue: param6.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 7, size: 1, scaledConfigurationValue: param7.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 8, size: 1, scaledConfigurationValue: param8.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 9, size: 1, scaledConfigurationValue: param9.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 10, size: 1, scaledConfigurationValue: param10.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 11, size: 1, scaledConfigurationValue: param11.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 13, size: 1, scaledConfigurationValue: param13.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 15, size: 1, scaledConfigurationValue: param15.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 16, size: 1, scaledConfigurationValue: param16.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 19, size: 1, scaledConfigurationValue: param19.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 20, size: 1, scaledConfigurationValue: param20.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 30, size: 1, scaledConfigurationValue: param30.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 39, size: 1, scaledConfigurationValue: param39.toInteger()).format()
cmds << zwave.configurationV1.configurationSet(parameterNumber: 41, size: 1, scaledConfigurationValue: param41.toInteger()).format()
// Register for Group 1
if(paramAssociationGroup1) {
cmds << zwave.associationV2.associationSet(groupingIdentifier:1, nodeId: [zwaveHubNodeId]).format()
}
else {
cmds << zwave.associationV2.associationRemove(groupingIdentifier:1, nodeId: [zwaveHubNodeId]).format()
}
// Register for Group 2
if(paramAssociationGroup2) {
cmds << zwave.associationV2.associationSet(groupingIdentifier:2, nodeId: [zwaveHubNodeId]).format()
}
else {
cmds << zwave.associationV2.associationRemove(groupingIdentifier:2, nodeId: [zwaveHubNodeId]).format()
}
// Register for Group 3
if(paramAssociationGroup3) {
cmds << zwave.associationV2.associationSet(groupingIdentifier:3, nodeId: [zwaveHubNodeId]).format()
}
else {
cmds << zwave.associationV2.associationRemove(groupingIdentifier:3, nodeId: [zwaveHubNodeId]).format()
}
delayBetween(cmds, 500)
}
def updated() {
log.debug "updated()"
response(["delay 2000"] + configureParams() + refresh())
}

View File

@@ -0,0 +1,787 @@
/**
* Copyright 2015 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
metadata {
definition (name: "Fibaro Dimmer 2", namespace: "smartthings", author: "Rajiv, Elnar Hajiyev") {
capability "Energy Meter"
capability "Actuator"
capability "Switch"
capability "Power Meter"
capability "Polling"
capability "Refresh"
capability "Sensor"
capability "Configuration"
capability "Switch Level"
//Extending Fibaro Dimmer 2 devices with scene attribute
attribute "scene", "number"
command "reset"
command "configureAfterSecure"
fingerprint deviceId: "0x1001", inClusters: "0x5E, 0x20, 0x86, 0x72, 0x26, 0x5A, 0x59, 0x85, 0x73, 0x98, 0x7A, 0x56, 0x70, 0x31, 0x32, 0x8E, 0x60, 0x75, 0x71, 0x27, 0x22, 0xEF, 0x2B"
}
// simulator metadata
simulator {
status "on": "command: 2003, payload: FF"
status "off": "command: 2003, payload: 00"
status "09%": "command: 2003, payload: 09"
status "10%": "command: 2003, payload: 0A"
status "33%": "command: 2003, payload: 21"
status "66%": "command: 2003, payload: 42"
status "99%": "command: 2003, payload: 63"
for (int i = 0; i <= 10000; i += 1000) {
status "power ${i} W": new physicalgraph.zwave.Zwave().meterV3.meterReport(
scaledMeterValue: i, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage()
}
for (int i = 0; i <= 100; i += 10) {
status "energy ${i} kWh": new physicalgraph.zwave.Zwave().meterV3.meterReport(
scaledMeterValue: i, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage()
}
["FF", "00", "09", "0A", "21", "42", "63"].each { val ->
reply "2001$val,delay 100,2602": "command: 2603, payload: $val"
}
}
// tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.switches.switch.on", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.switch.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel"
}
}
valueTile("power", "device.power", decoration: "flat", width: 2, height: 2) {
state "default", label:'${currentValue} W'
}
valueTile("energy", "device.energy", decoration: "flat", width: 2, height: 2) {
state "default", label:'${currentValue} kWh'
}
standardTile("reset", "device.energy", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'reset kWh', action:"reset"
}
standardTile("configureAfterSecure", "device.configure", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "configure", label:'', action:"configureAfterSecure", icon:"st.secondary.configure"
}
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
}
main(["switch","power","energy"])
details(["switch","power","energy","configureAfterSecure","refresh","reset"])
}
preferences {
def paragraph = "GROUP 0 - The Dimmer 2 behavior - Basic functionalities"
input name: "param1", type: "number", range: "1..98", defaultValue: "1", required: true,
title: paragraph + "\n\n" +
"1. Minimum brightness level. " +
"This parameter is set automatically during the calibration process. " +
"The parameter can be changed manually after the calibration.\n" +
"Available settings: 1-98 - percentage level of brightness.\n" +
"Default value: 1."
input name: "param2", type: "number", range: "2..99", defaultValue: "99", required: true,
title: "2. Maximum brightness level. " +
"This parameter is set automatically during the calibration process. " +
"The parameter can be changed manually after the calibration.\n" +
"Available settings: 2-99 - percentage level of brightness.\n" +
"Default value: 99."
input name: "param3", type: "number", range: "1..99", defaultValue: "1", required: true,
title: "3. Incandescence level of dimmable compact fluorescent lamps. " +
"Virtual value set as a percentage level between parameters MIN (1%) and MAX (99%). " +
"The Dimmer 2 will set to this value after first switch on. " +
"It is required for warming up and switching dimmable compact fluorescent lamps and certain types of light sources.\n" +
"Available settings: 1-99 - percentage level of brightness.\n" +
"Default value: 1."
input name: "param4", type: "number", range: "0..255", defaultValue: "0", required: true,
title: "4. Incandescence time of dimmable compact fluorescent lamps. " +
"This parameter determines the time required for switching compact fluorescent lamps and certain types of light sources. " +
"Setting this parameter to 0 will disable the incandescence functionality.\n" +
"Available settings: 0-255 (0-25.5s).\n" +
"Default value: 0."
input name: "param5", type: "number", range: "1..99", defaultValue: "1", required: true,
title: "5. Automatic control - dimming step size. " +
"This parameter defines the percentage value of dimming step during the automatic control.\n" +
"Available settings: 1-99 - dimming step percentage value.\n" +
"Default value: 1."
input name: "param6", type: "number", range: "0..255", defaultValue: "1", required: true,
title: "6. Automatic control - time of a dimming step. " +
"This parameter defines the time of single dimming step set in parameter 5 during the automatic control.\n" +
"Available settings: 0-255 (0-2.55s, in 10ms steps).\n" +
"Default value: 1."
input name: "param7", type: "number", range: "1..99", defaultValue: "1", required: true,
title: "7. Manual control - dimming step size. " +
"This parameter defines the percentage value of dimming step during the manual control.\n" +
"Available settings: 1-99 - dimming step percentage value.\n" +
"Default value: 1."
input name: "param8", type: "number", range: "0..255", defaultValue: "5", required: true,
title: "8. Manual control - time of a dimming step. " +
"This parameter defines the time of single dimming step set in parameter 7 during the manual control.\n" +
"Available settings: 0-255 (0-2.55s, in 10ms steps).\n" +
"Default value: 5."
input name: "param9", type: "number", range: "0..1", defaultValue: "1", required: true,
title: "9. State of the device after a power failure. " +
"The Dimmer 2 will return to the last state before power failure.\n" +
"Available settings:\n" +
"0 = the Dimmer 2 does not save the state before a power failure, it returns to „off” position,\n" +
"1 = the Dimmer 2 restores its state before power failure.\n" +
"Default value: 1."
input name: "param10", type: "number", range: "0..32767", defaultValue: "0", required: true,
title: "10. Timer functionality (auto - off). " +
"This parameter allows to automatically switch off the device after specified time from switching on the light source. " +
"It may be useful when the Dimmer 2 is installed in the stairway.\n" +
"Available settings: 0 - Function disabled,\n1-32767 - time to turn off measured in seconds (1s-9.1h).\n" +
"Default value: 0."
input name: "param11", type: "enum", defaultValue: "255", required: true,
options: ["0" : "0",
"1" : "1",
"2" : "2",
"255" : "255"],
title: "11. ALL ON/ALL OFF function. " +
"Parameter allows for activation/deactivation of Z-Wave commands enabling/disabling all devices located in direct range of the main controller.\n" +
"Available settings:\n" +
"0 = All ON not active, All OFF not active,\n" +
"1 = All ON not active, All OFF active,\n" +
"2 = All ON active, All OFF not active,\n" +
"255 = All ON active, All OFF active.\n" +
"Default value: 255."
input name: "param13", type: "number", range: "0..2", defaultValue: "0", required: true,
title: "13. Force auto-calibration. " +
"Changing value of this parameter will force the calibration process. " +
"During the calibration parameter is set to 1 or 2 and switched to 0 upon completion.\n" +
"Available settings:\n" +
"0 = readout,\n" +
"1 = force auto-calibration of the load without FIBARO Bypass 2,\n" +
"2 = force auto-calibration of the load with FIBARO Bypass 2.\n" +
"Default value: 0."
input name: "param15", type: "number", range: "0..99", defaultValue: "30", required: true,
title: "15. Burnt out bulb detection. " +
"Function based on the sudden power variation of a specific value, interpreted as a LOAD ERROR.\n" +
"Available settings:\n0 - function disabled,\n" +
"1-99 - percentage value of power variation, compared to standard power consumption, measured during the calibration procedure (to be interpreted as load error/burnt out bulb).\n" +
"Default value: 30."
input name: "param16", type: "number", range: "0..255", defaultValue: "5", required: true,
title: "16. Time delay of a burnt out bulb (parameter 15) or overload (parameter 39) detection. " +
"Time of delay (in seconds) for power variation detection, interpreted as a LOAD ERROR or OVERLOAD detection (too much power connected to the Dimmer 2).\n" +
"Available settings:\n0 - detection of a burnt out bulb disabled,\n1-255 - delay time in seconds.\n" +
"Default value: 5."
input name: "param19", type: "number", range: "0..99", defaultValue: "0", required: true,
title: "19. Forced switch on brightness level. " +
"If the parameter is active, switching on the Dimmer 2 (S1 single click) will always set this brightness level.\n" +
"Available settings:\n0 - function disabled,\n1-99 - percentage level of brightness.\n" +
"Default value: 0."
paragraph = "GROUP 20 - Dimmer 2 operation - Switches"
input name: "param20", type: "number", range: "0..2", defaultValue: "0", required: true,
title: paragraph + "\n\n" +
"20. Switch type. " +
"Choose between momentary, toggle and roller blind switch.\n" +
"Available settings:\n" +
"0 = momentary switch,\n1 = toggle switch,\n2 = roller blind switch - two switches operate the Dimmer 2 (S1 to brighten, S2 to dim).\n" +
"Default value: 0."
input name: "param21", type: "number", range: "0..1", defaultValue: "0", required: true,
title: "21. The value sent to associated devices on single click. " +
"This parameter defines the value sent to devices associated with Dimmer 2 after its enabling.\n" +
"Available settings:\n" +
"0 = 0xFF value is sent, which will set associated devices to their last saved state,\n" +
"1 = current Dimmer 2 state is sent, which will synchronize brightness level of associated devices (other dimmers for example).\n" +
"Default value: 0."
input name: "param22", type: "number", range: "0..1", defaultValue: "0", required: true,
title: "22. Assign toggle switch status to the device status. " +
"By default each change of toggle switch position results in action of Dimmer 2 (switch on/off) regardless the physical connection of contacts.\n" +
"Available settings:\n" +
"0 = device changes status on switch status change,\n1 = device status is synchronized with switch status.\n" +
"Default value: 0."
input name: "param23", type: "number", range: "0..1", defaultValue: "1", required: true,
title: "23. Double click option - set the brightness level to MAX.\n" +
"Available settings:\n" +
"0 = double click disabled,\n" +
"1 = double click enabled.\n" +
"Default value: 1."
input name: "param24", type: "enum", defaultValue: "0", required: true,
options: ["0" : "0",
"1" : "1",
"2" : "2",
"4" : "4",
"8" : "8",
"16" : "16"],
title: "24. Command frames sent in 2nd and 3rd association groups (S1 associations). " +
"Parameter determines, which actions will not result in sending frames to association groups.\n" +
"Available settings:\n" +
"0 = all actions send to association groups,\n" +
"1 = do not send when switching ON (single click),\n" +
"2 = do not send when switching OFF (single click),\n" +
"4 = do not send when changing dimming level (holding and releasing),\n" +
"8 = do not send on double click,\n" +
"16 = send 0xFF value on double click.\n" +
"Default value: 0."
input name: "param25", type: "enum", defaultValue: "0", required: true,
options: ["0" : "0",
"1" : "1",
"2" : "2",
"4" : "4",
"8" : "8",
"16" : "16"],
title: "25. Command frames sent in 4th and 5th association groups (S2 associations). " +
"Parameter determines, which actions will not result in sending frames to association groups.\n" +
"Available settings:\n" +
"0 = all actions send to association groups,\n" +
"1 = do not send when switching ON (single click),\n" +
"2 = do not send when switching OFF (single click),\n" +
"4 = do not send when changing dimming level (holding and releasing),\n" +
"8 = do not send on double click,\n" +
"16 = send 0xFF value on double click.\n" +
"Default value: 0."
input name: "param26", type: "number", range: "0..1", defaultValue: "0", required: true,
title: "26. The function of 3-way switch. " +
"Switch no. 2 controls the Dimmer 2 additionally (in 3-way switch mode). Function disabled for parameter 20 set to 2 (roller blind switch).\n" +
"Available settings:\n" +
"0 = 3-way switch function for S2 disabled,\n" +
"1 = 3-way switch function for S2 enabled.\n" +
"Default value: 0."
input name: "param27", type: "enum", defaultValue: "15", required: true,
options: ["0" : "0",
"1" : "1",
"2" : "2",
"4" : "4",
"8" : "8",
"15" : "15"],
title: "27. Associations in Z-Wave network security mode. " +
"This parameter defines how commands are sent in speci ed association groups: as secure or non-secure. " +
"Parameter is active only in Z-Wave network security mode. It does not apply to 1st lifeline group.\n" +
"Available settings:\n" +
"0 = all groups (II-V) sent as non-secure,\n" +
"1 = 2nd group sent as secure,\n" +
"2 = 3rd group sent as secure,\n" +
"4 = 4th group sent as secure,\n" +
"8 = 5th group sent as secure,\n" +
"15 = all groups (II-V) sent as secure.\n" +
"Default value: 15."
input name: "param28", type: "number", range: "0..1", defaultValue: "0", required: true,
title: "28. Scene activation functionality.\n" +
"Available settings:\n" +
"0 = functionality deactivated,\n" +
"1 = functionality activated.\n" +
"Default value: 0.\n\n" +
"SCENE ID depends on the switch type configurations.\n" +
"Momentary switches:\n" +
"SCENE ID: S1 input:\n\t16 : 1 x click\n\t14 : 2 x click\n\t-- : 3 x click\n\t12 : hold\n\t13 : release\n" +
"SCENE ID: S2 input:\n\t26 : 1 x click\n\t24 : 2 x click\n\t25 : 3 x click\n\t22 : hold\n\t23 : release\n\n" +
"Toggle switches:\n" +
"SCENE ID: S1 input:\n\t10 : OFF to ON\n\t11 : ON to OFF\n\t14 : 2 x click\n\t-- : 3 x click\n" +
"SCENE ID: S2 input:\n\t20 : OFF to ON\n\t21 : ON to OFF\n\t24 : 2 x click\n\t25 : 3 x click\n\n" +
"Roller blinds switches:\n" +
"SCENE ID: S1 input:\n\t10 : turn ON (1 x click)\n\t13 : release\n\t14 : 2 x click\n\t-- : 3 x click\n\t17 : brightening\n" +
"SCENE ID: S2 input:\n\t11 : turn OFF (1 x click)\n\t13 : release\n\t14 : 2 x click\n\t15 : 3 x click\n\t18 : dimming"
input name: "param29", type: "number", range: "0..1", defaultValue: "0", required: true,
title: "29. Switch functionality of S1 and S2. " +
"This parameter allows for switching the role of keys connected to S1 and S2 without changes in connection.\n" +
"Available settings:\n" +
"0 = standard mode,\n" +
"1 = S1 operates as S2, S2 operates as S1.\n" +
"Default value: 0."
paragraph = "GROUP 30 - Dimmer 2 operation - Advanced functionality"
input name: "param30", type: "number", range: "0..2", defaultValue: "2", required: true,
title: paragraph + "\n\n" +
"30. Load control mode. " +
"This parameter allows to set the desired load control mode. " +
"The de- vice automatically adjusts correct control mode, but the installer may force its change using this parameter. " +
"Forced auto-calibration will set this parameters value to 2.\n" +
"Available settings:\n" +
"0 = forced leading edge control,\n" +
"1 = forced trailing edge control,\n" +
"2 = control mode selected automatically (based on auto-calibration).\n" +
"Default value: 2."
input name: "param32", type: "number", range: "0..2", defaultValue: "2", required: true,
title: "32. On/Off mode. " +
"This mode is necessary while connecting non-dimmable light sources. " +
"Setting this parameter to 1 automatically ignores brightening/dimming time settings. " +
"Forced auto-calibration will set this parameters value to 2.\n" +
"Available settings:\n" +
"0 = on/off mode disabled (dimming is possible),\n" +
"1 = on/off mode enabled (dimming is not possible),\n" +
"2 = mode selected automatically.\n" +
"Default value: 2."
input name: "param34", type: "number", range: "0..2", defaultValue: "1", required: true,
title: "34. Soft-Start functionality. " +
"Time required to warm up the lament of halogen bulb.\n" +
"Available settings:\n" +
"0 = no soft-start,\n" +
"1 = short soft-start (0.1s),\n" +
"2 = long soft-start (0.5s).\n" +
"Default value: 1."
input name: "param35", type: "number", range: "0..4", defaultValue: "1", required: true,
title: "35. Auto-calibration after power on. " +
"This parameter determines the trigger of auto-calibration procedure, e.g. power on, load error, etc.\n" +
"Available settings:\n" +
"0 = No auto-calibration of the load after power on,\n" +
"1 = Auto-calibration performed after first power on,\n" +
"2 = Auto-calibration performed after each power on,\n" +
"3 = Auto-calibration performed after first power on or after each LOAD ERROR alarm (no load, load failure, burnt out bulb), if parameter 37 is set to 1 also after alarms: SURGE (Dimmer 2 output overvoltage) and OVERCURRENT (Dimmer 2 output overcurrent),\n" +
"4 = Auto-calibration performed after each power on or after each LOAD ERROR alarm (no load, load failure, burnt out bulb), if parameter 37 is set to 1 also after alarms: SURGE (Dimmer 2 output overvoltage) and OVERCURRENT (Dimmer 2 output overcurrent).\n" +
"Default value: 1."
input name: "param37", type: "number", range: "0..1", defaultValue: "1", required: true,
title: "37. Behaviour of the Dimmer 2 after OVERCURRENT or SURGE. " +
"Occuring of errors related to surge or overcurrent results in turning off the output to prevent possible malfunction. " +
"By default the device performs three attempts to turn on the load (useful in case of momentary, short failures of the power supply).\n" +
"Available settings:\n" +
"0 = device permanently disabled until re-ena- bling by command or external switch,\n" +
"1 = three attempts to turn on the load.\n" +
"Default value: 1."
input name: "param39", type: "number", range: "0..350", defaultValue: "250", required: true,
title: "39. Power limit - OVERLOAD. " +
"Reaching the defined value will result in turning off the load. " +
"Additional apparent power limit of 350VA is active by default.\n" +
"Available settings:\n0 - functionality disabled,\n1-350 - 1-350W.\n" +
"Default value: 250."
paragraph = "GROUP 40 - Dimmer 2 operation - Alarms"
input name: "param40", type: "number", range: "0..3", defaultValue: "3", required: true,
title: paragraph + "\n\n" +
"40. Response to General Purpose Alarm.\n" +
"Available settings:\n" +
"0 = No reaction,\n" +
"1 = Turn on the load,\n" +
"2 = Turn off the load,\n" +
"3 = Load blinking.\n" +
"Default value: 3."
input name: "param41", type: "number", range: "0..3", defaultValue: "2", required: true,
title: "41. Response to Water Flooding Alarm.\n" +
"Available settings:\n" +
"0 = No reaction,\n" +
"1 = Turn on the load,\n" +
"2 = Turn off the load,\n" +
"3 = Load blinking.\n" +
"Default value: 2."
input name: "param42", type: "number", range: "0..3", defaultValue: "3", required: true,
title: "42. Response to Smoke, CO or CO2 Alarm.\n" +
"Available settings:\n" +
"0 = No reaction,\n" +
"1 = Turn on the load,\n" +
"2 = Turn off the load,\n" +
"3 = Load blinking.\n" +
"Default value: 3."
input name: "param43", type: "number", range: "0..3", defaultValue: "1", required: true,
title: "43. Response to Temperature Alarm.\n" +
"Available settings:\n" +
"0 = No reaction,\n" +
"1 = Turn on the load,\n" +
"2 = Turn off the load,\n" +
"3 = Load blinking.\n" +
"Default value: 1."
input name: "param44", type: "number", range: "1..32767", defaultValue: "600", required: true,
title: "44. Time of alarm state.\n" +
"Available settings: 1-32767 (1-32767 seconds).\n" +
"Default value: 600."
paragraph = "Alarm settings - reports"
input name: "param45", type: "number", range: "0..1", defaultValue: "1", required: true,
title: paragraph + "\n\n" +
"45. OVERLOAD alarm report (load power consumption too high).\n" +
"Available settings:\n" +
"0 = No reaction,\n" +
"1 = Send an alarm frame.\n" +
"Default value: 1."
input name: "param46", type: "number", range: "0..1", defaultValue: "1", required: true,
title: "46. LOAD ERROR alarm report (no load, load failure, burnt out bulb).\n" +
"Available settings:\n" +
"0 = No reaction,\n" +
"1 = Send an alarm frame.\n" +
"Default value: 1."
input name: "param47", type: "number", range: "0..1", defaultValue: "1", required: true,
title: "47. OVERCURRENT alarm report (short circuit, burnt out bulb causing overcurrent).\n" +
"Available settings:\n" +
"0 = No reaction,\n" +
"1 = Send an alarm frame.\n" +
"Default value: 1."
input name: "param48", type: "number", range: "0..1", defaultValue: "1", required: true,
title: "48. SURGE alarm report (Dimmer 2 output overvoltage).\n" +
"Available settings:\n" +
"0 = No reaction,\n" +
"1 = Send an alarm frame.\n" +
"Default value: 1."
input name: "param49", type: "number", range: "0..1", defaultValue: "1", required: true,
title: "49. OVERHEAT (critical temperature) and VOLTAGE DROP (low voltage) alarm report.\n" +
"Available settings:\n" +
"0 = No reaction,\n" +
"1 = Send an alarm frame.\n" +
"Default value: 1."
paragraph = "GROUP 50 - Active power and energy reports"
input name: "param50", type: "number", range: "0..100", defaultValue: "10", required: true,
title: paragraph + "\n\n" +
"50. Active power reports. " +
"The parameter defines the power level change that will result in a new power report being sent. " +
"The value is a percentage of the previous report.\n" +
"Available settings:\n0 - power reports disabled,\n1-100 (1-100%) - power report threshold.\n" +
"Default value: 10."
input name: "param52", type: "number", range: "0..32767", defaultValue: "3600", required: true,
title: "52. Periodic active power and energy reports. " +
"Parameter 52 defines a time period between consecutive reports. Timer is reset and counted from zero after each report.\n" +
"Available settings:\n0 - periodic reports disabled,\n1-32767 (1-32767 seconds).\n" +
"Default value: 3600."
input name: "param53", type: "number", range: "0..255", defaultValue: "10", required: true,
title: "53. Energy reports. " +
"Energy level change which will result in sending a new energy report.\n" +
"Available settings:\n0 - energy reports disabled,\n1-255 (0.01-2.55 kWh) - report triggering threshold.\n" +
"Default value: 10."
input name: "param54", type: "number", range: "0..1", defaultValue: "0", required: true,
title: "54. Self-measurement. " +
"The Dimmer 2 may include active power and energy consumed by itself in reports sent to the main controller.\n" +
"Available settings:\n" +
"0 = Self-measurement inactive,\n" +
"1 = Self-measurement active.\n" +
"Default value: 0."
input name: "param58", type: "number", range: "0..2", defaultValue: "0", required: true,
title: "58. Method of calculating the active power. This parameter defines how to calculate active power. " +
"It is useful in a case of 2-wire connection with light sources other than resistive.\n" +
"Available settings:\n" +
"0 = measurement based on the standard algorithm,\n" +
"1 = approximation based on the calibration data,\n" +
"2 = approximation based on the control angle.\n" +
"Default value: 0."
input name: "param59", type: "number", range: "0..500", defaultValue: "0", required: true,
title: "59. Approximated power at the maximum brightness level. " +
"This parameter determines the approximate value of the power that will be reported by the device at its maximum brightness level.\n" +
"Available settings: 0-500 (0-500W) - power consumed by the load at the maximum brightness level.\n" +
"Default value: 0."
input name: "paramAssociationGroup1", type: "bool", defaultValue: true, required: true,
title: "The Dimmer 2 provides the association of five groups.\n\n" +
"1st Association Group „Lifeline”,\n" +
"Default value: true"
input name: "paramAssociationGroup2", type: "bool", defaultValue: true, required: true,
title: "2nd Association Group „On/Off (S1)”,\n" +
"Default value: true"
input name: "paramAssociationGroup3", type: "bool", defaultValue: false, required: true,
title: "3rd Association Group „Dimmer (S1)”,\n" +
"Default value: false"
input name: "paramAssociationGroup4", type: "bool", defaultValue: false, required: true,
title: "4th Association Group „On/Off (S2)”,\n" +
"Default value: false"
input name: "paramAssociationGroup5", type: "bool", defaultValue: false, required: true,
title: "5th Association Group „Dimmer (S2)”.\n" +
"Default value: false"
}
}
def parse(String description) {
log.trace(description)
log.debug("RAW command: $description")
def result = null
if (description != "updated") {
def cmd = zwave.parse(description.replace("98C1", "9881"), [0x20: 1, 0x26: 3, 0x32: 3, 0x25: 1, 0x98: 1, 0x70: 1, 0x85: 2, 0x9B: 1, 0x90: 1, 0x73: 1, 0x30: 1, 0x28: 1, 0x72: 1])
if (cmd) {
result = zwaveEvent(cmd)
}
}
log.debug "Parsed '${description}' to ${result.inspect()}"
return result
}
def zwaveEvent(physicalgraph.zwave.commands.sceneactivationv1.SceneActivationSet cmd) {
log.debug( "Scene ID: $cmd.sceneId")
log.debug( "Dimming Duration: $cmd.dimmingDuration")
sendEvent(name: "scene", value: "$cmd.sceneId", data: [switchType: "$settings.param20"], descriptionText: "Scene id $cmd.sceneId was activated", isStateChange: true)
log.debug( "Scene id $cmd.sceneId was activated" )
}
// Devices that support the Security command class can send messages in an encrypted form;
// they arrive wrapped in a SecurityMessageEncapsulation command and must be unencapsulated
def zwaveEvent(physicalgraph.zwave.commands.securityv1.SecurityMessageEncapsulation cmd) {
log.trace(cmd)
def encapsulatedCommand = cmd.encapsulatedCommand([0x20: 1, 0x26: 3, 0x32: 3, 0x25: 1, 0x98: 1, 0x70: 1, 0x85: 2, 0x9B: 1, 0x90: 1, 0x73: 1, 0x30: 1, 0x28: 1, 0x72: 1]) // can specify command class versions here like in zwave.parse
if (encapsulatedCommand) {
return zwaveEvent(encapsulatedCommand)
} else {
log.warn "Unable to extract encapsulated cmd from $cmd"
createEvent(descriptionText: cmd.toString())
}
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
log.trace(cmd)
dimmerEvents(cmd)
}
def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicSet cmd) {
log.trace(cmd)
//dimmerEvents(cmd)
}
def zwaveEvent(physicalgraph.zwave.commands.switchmultilevelv3.SwitchMultilevelReport cmd) {
log.trace(cmd)
dimmerEvents(cmd)
}
def zwaveEvent(physicalgraph.zwave.commands.switchbinaryv1.SwitchBinaryReport cmd)
{
log.trace(cmd)
dimmerEvents(cmd)
}
def dimmerEvents(physicalgraph.zwave.Command cmd) {
log.trace(cmd)
def result = []
def value = (cmd.value ? "on" : "off")
def switchEvent = createEvent(name: "switch", value: value, descriptionText: "$device.displayName was turned $value")
result << switchEvent
if (cmd.value) {
result << createEvent(name: "level", value: cmd.value, unit: "%")
}
if (switchEvent.isStateChange) {
result << response(["delay 3000", zwave.meterV2.meterGet(scale: 2).format()])
}
return result
}
def zwaveEvent(physicalgraph.zwave.commands.meterv3.MeterReport cmd) {
log.trace(cmd)
if (cmd.meterType == 1) {
if (cmd.scale == 0) {
return createEvent(name: "energy", value: cmd.scaledMeterValue, unit: "kWh")
} else if (cmd.scale == 1) {
return createEvent(name: "energy", value: cmd.scaledMeterValue, unit: "kVAh")
} else if (cmd.scale == 2) {
return createEvent(name: "power", value: Math.round(cmd.scaledMeterValue), unit: "W")
} else {
return createEvent(name: "electric", value: cmd.scaledMeterValue, unit: ["pulses", "V", "A", "R/Z", ""][cmd.scale - 3])
}
}
}
def zwaveEvent(physicalgraph.zwave.Command cmd) {
log.trace(cmd)
log.debug "No handler for $cmd"
// Handles all Z-Wave commands we aren't interested in
createEvent(descriptionText: cmd.toString(), isStateChange: false)
}
def on() {
log.trace("on")
secureSequence([
zwave.basicV1.basicSet(value: 0xFF),
zwave.switchMultilevelV1.switchMultilevelGet()
])
}
def off() {
log.trace("off")
secureSequence([
zwave.basicV1.basicSet(value: 0x00),
zwave.switchMultilevelV1.switchMultilevelGet()
])
}
def poll() {
log.trace("poll")
secureSequence([
zwave.meterV2.meterGet(scale: 0),
zwave.meterV2.meterGet(scale: 2)
])
}
def refresh() {
log.trace("trace")
secureSequence([
zwave.meterV2.meterGet(scale: 0),
zwave.meterV2.meterGet(scale: 2)
])
}
def reset() {
log.trace("reset")
return secureSequence([
zwave.switchMultilevelV1.switchMultilevelGet(),
zwave.meterV2.meterReset(),
zwave.meterV2.meterGet(scale: 0),
zwave.meterV2.meterGet(scale: 2)
])
}
def setLevel(level) {
log.trace("setlevel")
if(level > 99) level = 99
secureSequence([
zwave.basicV1.basicSet(value: level),
zwave.switchMultilevelV1.switchMultilevelGet()
], 5000)
}
def configureAfterSecure() {
log.debug "configureAfterSecure()"
def cmds = secureSequence([
zwave.configurationV1.configurationSet(parameterNumber: 1, size: 1, scaledConfigurationValue: param1.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 2, size: 1, scaledConfigurationValue: param2.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 3, size: 1, scaledConfigurationValue: param3.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 4, size: 2, scaledConfigurationValue: param4.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 5, size: 1, scaledConfigurationValue: param5.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 6, size: 2, scaledConfigurationValue: param6.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 7, size: 1, scaledConfigurationValue: param7.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 8, size: 2, scaledConfigurationValue: param8.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 9, size: 1, scaledConfigurationValue: param9.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 10, size: 2, scaledConfigurationValue: param10.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 11, size: 2, scaledConfigurationValue: param11.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 13, size: 1, scaledConfigurationValue: param13.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 15, size: 1, scaledConfigurationValue: param15.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 16, size: 2, scaledConfigurationValue: param16.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 19, size: 1, scaledConfigurationValue: param19.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 20, size: 1, scaledConfigurationValue: param20.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 21, size: 1, scaledConfigurationValue: param21.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 22, size: 1, scaledConfigurationValue: param22.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 23, size: 1, scaledConfigurationValue: param23.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 24, size: 1, scaledConfigurationValue: param24.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 25, size: 1, scaledConfigurationValue: param25.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 26, size: 1, scaledConfigurationValue: param26.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 27, size: 1, scaledConfigurationValue: param27.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 28, size: 1, scaledConfigurationValue: param28.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 29, size: 1, scaledConfigurationValue: param29.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 30, size: 1, scaledConfigurationValue: param30.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 32, size: 1, scaledConfigurationValue: param32.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 34, size: 1, scaledConfigurationValue: param34.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 35, size: 1, scaledConfigurationValue: param35.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 37, size: 1, scaledConfigurationValue: param37.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 39, size: 2, scaledConfigurationValue: param39.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 40, size: 1, scaledConfigurationValue: param40.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 41, size: 1, scaledConfigurationValue: param41.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 42, size: 1, scaledConfigurationValue: param42.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 43, size: 1, scaledConfigurationValue: param43.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 44, size: 2, scaledConfigurationValue: param44.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 45, size: 1, scaledConfigurationValue: param45.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 46, size: 1, scaledConfigurationValue: param46.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 47, size: 1, scaledConfigurationValue: param47.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 48, size: 1, scaledConfigurationValue: param48.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 49, size: 1, scaledConfigurationValue: param49.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 50, size: 1, scaledConfigurationValue: param50.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 52, size: 2, scaledConfigurationValue: param52.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 53, size: 2, scaledConfigurationValue: param53.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 54, size: 1, scaledConfigurationValue: param54.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 58, size: 1, scaledConfigurationValue: param58.toInteger()),
zwave.configurationV1.configurationSet(parameterNumber: 59, size: 2, scaledConfigurationValue: param59.toInteger())
])
// Register for Group 1
if(paramAssociationGroup1) {
cmds << secure(zwave.associationV2.associationSet(groupingIdentifier:1, nodeId: [zwaveHubNodeId]))
}
else {
cmds << secure(zwave.associationV2.associationRemove(groupingIdentifier:1, nodeId: [zwaveHubNodeId]))
}
// Register for Group 2
if(paramAssociationGroup2) {
cmds << secure(zwave.associationV2.associationSet(groupingIdentifier:2, nodeId: [zwaveHubNodeId]))
}
else {
cmds << secure(zwave.associationV2.associationRemove(groupingIdentifier:2, nodeId: [zwaveHubNodeId]))
}
// Register for Group 3
if(paramAssociationGroup3) {
cmds << secure(zwave.associationV2.associationSet(groupingIdentifier:3, nodeId: [zwaveHubNodeId]))
}
else {
cmds << secure(zwave.associationV2.associationRemove(groupingIdentifier:3, nodeId: [zwaveHubNodeId]))
}
// Register for Group 4
if(paramAssociationGroup4) {
cmds << secure(zwave.associationV2.associationSet(groupingIdentifier:4, nodeId: [zwaveHubNodeId]))
}
else {
cmds << secure(zwave.associationV2.associationRemove(groupingIdentifier:4, nodeId: [zwaveHubNodeId]))
}
// Register for Group 5
if(paramAssociationGroups5) {
cmds << secure(zwave.associationV2.associationSet(groupingIdentifier:5, nodeId: [zwaveHubNodeId]))
}
else {
cmds << secure(zwave.associationV2.associationRemove(groupingIdentifier:5, nodeId: [zwaveHubNodeId]))
}
cmds
}
def configure() {
// Wait until after the secure exchange for this
log.debug "configure()"
}
def updated() {
log.debug "updated()"
response(["delay 2000"] + configureAfterSecure() + refresh())
}
private secure(physicalgraph.zwave.Command cmd) {
log.trace(cmd)
zwave.securityV1.securityMessageEncapsulation().encapsulate(cmd).format()
}
private secureSequence(commands, delay=200) {
log.debug "$commands"
delayBetween(commands.collect{ secure(it) }, delay)
}

View File

@@ -1,7 +1,7 @@
/**
* GE Link Bulb
*
* Copyright 2014 SmartThings
* Copyright 2016 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
@@ -53,6 +53,8 @@ metadata {
capability "Polling"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,1000", outClusters: "0019", manufacturer: "GE_Appliances", model: "ZLL Light", deviceJoinName: "GE Link Bulb"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,1000", outClusters: "0019", manufacturer: "GE", model: "SoftWhite", deviceJoinName: "GE Link Soft White Bulb"
fingerprint profileId: "0104", inClusters: "0000,0003,0004,0005,0006,0008,1000", outClusters: "0019", manufacturer: "GE", model: "Daylight", deviceJoinName: "GE Link Daylight Bulb"
}
// UI tile definitions

View File

@@ -29,17 +29,14 @@ 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:"#00A0DC", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#C6C7CC", nextState:"turningOn"
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:"#C6C7CC", nextState:"turningOn"
attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel", range:"(0..100)"
}
tileAttribute ("device.level", key: "SECONDARY_CONTROL") {
attributeState "level", label: 'Level ${currentValue}%'
}
tileAttribute ("device.color", key: "COLOR_CONTROL") {
attributeState "color", action:"setAdjustedColor"
}

View File

@@ -38,9 +38,6 @@ metadata {
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel", range:"(0..100)"
}
tileAttribute ("device.level", key: "SECONDARY_CONTROL") {
attributeState "level", label: 'Level ${currentValue}%'
}
tileAttribute ("device.color", key: "COLOR_CONTROL") {
attributeState "color", action:"setAdjustedColor"
}

View File

@@ -25,17 +25,14 @@ 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:"#00A0DC", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#C6C7CC", nextState:"turningOn"
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:"#C6C7CC", nextState:"turningOn"
attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel", range:"(0..100)"
}
tileAttribute ("device.level", key: "SECONDARY_CONTROL") {
attributeState "level", label: 'Level ${currentValue}%'
}
}
controlTile("levelSliderControl", "device.level", "slider", height: 1, width: 2, inactiveLabel: false, range:"(0..100)") {

View File

@@ -1,4 +1,3 @@
#==============================================================================
# Copyright 2016 SmartThings
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -12,21 +11,12 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#==============================================================================
# Purpose: Mobile Presence i18n Translation File
#
# Filename: mobile-presence.src/i18n/messages.properties
#
# Change History:
# 1. 20160205 TW Initial release with informal Korean translation.
# 2. 20160224 TW Updated with formal Korean translation.
#==============================================================================
# Korean (ko)
# Device Preferences
'''Give your device a name'''.ko=기기 이름 바꾸기
'''Give your device a name'''.ko=기기 이름 설정
'''Set Device Image'''.ko=기기 이미지 설정
# Events / Notifications
'''{{ linkText }} has left'''.ko={{ linkText }}집을 나갔습니다.
'''{{ linkText }} has arrived'''.ko={{ linkText }}집에 도착했습니다.
'''{{ linkText }} has left'''.ko={{ linkText }} 외출
'''{{ linkText }} has arrived'''.ko={{ linkText }} 귀가
'''present'''.ko=집안
'''not present'''.ko=외출

View File

@@ -1,5 +1,4 @@
/*
===============================================================================
* Copyright 2016 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -13,14 +12,6 @@
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
===============================================================================
* Purpose: Mobile Presence DTH File
*
* Filename: mobile-presence.src/mobile-presence.groovy
*
* Change History:
* 1. 20160205 TW - Update/Edit to support i18n translations
===============================================================================
*/
metadata {

View File

@@ -24,6 +24,7 @@ metadata {
command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0500,0020", manufacturer: "NYCE", model: "3010", deviceJoinName: "NYCE Door Hinge Sensor"
fingerprint inClusters: "0000,0001,0003,0406,0500,0020", manufacturer: "NYCE", model: "3011", deviceJoinName: "NYCE Door/Window Sensor"
fingerprint inClusters: "0000,0001,0003,0500,0020", manufacturer: "NYCE", model: "3011", deviceJoinName: "NYCE Door/Window Sensor"
fingerprint inClusters: "0000,0001,0003,0406,0500,0020", manufacturer: "NYCE", model: "3014", deviceJoinName: "NYCE Tilt Sensor"

View File

@@ -1,4 +1,3 @@
#==============================================================================
# Copyright 2016 SmartThings
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -12,24 +11,16 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#==============================================================================
# Purpose: SmartPower Outlet i18n Translation File
#
# Filename: SmartPower-Outlet.src/i18n/messages.properties
#
# Change History:
# 1. 20160116 TW Initial release with informal Korean translation.
#==============================================================================
# Korean (ko)
# Device Preferences
'''Give your device a name'''.ko=기기 이름 바꾸기
'''Outlet'''.ko=플러그
'''Give your device a name'''.ko=기기 이름 설정
'''Outlet'''.ko= 스마트 플러그
# Events descriptionText
'''{{ device.displayName }} is On'''.ko={{ device.displayName }}켜졌습니다.
'''{{ device.displayName }} is Off'''.ko={{ device.displayName }}꺼졌습니다.
'''{{ device.displayName }} power is {{ value }} Watts'''.ko={{ device.displayName }} 전은 {{ value }}와트입니다
'''On'''.ko=켜짐
'''{{ device.displayName }} is On'''.ko={{ device.displayName }} 켜짐
'''{{ device.displayName }} is Off'''.ko={{ device.displayName }} 꺼짐
'''{{ device.displayName }} power is {{ value }} Watts'''.ko={{ device.displayName }} 전은 {{ value }}와트입니다.
'''On'''.ko= 켜짐
'''Off'''.ko=꺼짐
'''Turning On'''.ko=켜
'''Turning Off'''.ko=끄
'''Turning On'''.ko=켜는 중
'''Turning Off'''.ko=끄는 중
#==============================================================================

View File

@@ -1,5 +1,4 @@
/*
===============================================================================
* Copyright 2016 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -13,15 +12,8 @@
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
===============================================================================
* Purpose: SmartPower Outlet DTH File
*
* Filename: SmartPower-Outlet.src/SmartPower-Outlet.groovy
*
* Change History:
* 1. 20160117 TW - Update/Edit to support i18n translations
===============================================================================
*/
metadata {
// Automatically generated. Make future change here.
definition (name: "SmartPower Outlet", namespace: "smartthings", author: "SmartThings") {
@@ -31,6 +23,7 @@ metadata {
capability "Configuration"
capability "Refresh"
capability "Sensor"
capability "Health Check"
// indicates that device keeps track of heartbeat (in state.heartbeat)
attribute "heartbeat", "string"
@@ -136,6 +129,7 @@ def refresh() {
}
def configure() {
sendEvent(name: "checkInterval", value: 1200, displayed: false)
zigbee.onOffConfig() + powerConfig() + refresh()
}

View File

@@ -1,4 +1,3 @@
#==============================================================================
# Copyright 2016 SmartThings
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -12,14 +11,6 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#==============================================================================
# Purpose: SmartSense Moisture Sensor i18n Translation File
#
# Filename: SmartSense-Moisture-Sensor.src/i18n/messages.properties
#
# Change History:
# 1. 20160116 TW Initial release with formal Korean translation.
#==============================================================================
# Korean (ko)
# Device Preferences
'''Dry'''.ko=건조
@@ -31,14 +22,14 @@
'''This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.'''.ko=기준 온도를 원하는대로 몇 도 올리거나 내려서 설정할 수 있습니다.
'''Degrees'''.ko=온도
'''Adjust temperature by this many degrees'''.ko=몇 도씩 온도를 조절하십시오
'''Give your device a name'''.ko=기기 이름 바꾸기
'''Water Leak Sensor'''.ko=누수센서
'''Give your device a name'''.ko=기기 이름 설정
'''Water Leak Sensor'''.ko=누수감지 센서
'''${currentValue}% battery'''.ko=${currentValue}% 배터리
# Events descriptionText
'''{{ device.displayName }} is dry'''.ko={{ device.displayName }}가 건조
'''{{ device.displayName }} is wet'''.ko={{ device.displayName }}누수
'''{{ device.displayName }} was {{ value }}°C'''.ko={{ device.displayName }}이(가) {{ value }}°C였습니다
'''{{ device.displayName }} was {{ value }}°C'''.ko={{ device.displayName }}에서 {{ value }}°C 감지
'''{{ device.displayName }} was {{ value }}°F'''.ko={{ device.displayName }}이(가) {{ value }}°F였습니다
'''{{ device.displayName }} battery has too much power: (> 3.5) volts.'''.ko={{ device.displayName }} 배터리 전력이 너무 높습니다(3.5볼트 초과).
'''{{ device.displayName }} battery was {{ value }}%'''.ko={{ device.displayName }}남아있는 배터리 {{ value }}%입니다.
'''{{ device.displayName }} battery was {{ value }}%'''.ko={{ device.displayName }}의 남은 배터리 {{ value }}%
#==============================================================================

View File

@@ -1,5 +1,4 @@
/*
===============================================================================
* Copyright 2016 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -13,15 +12,6 @@
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
===============================================================================
* Purpose: SmartSense Moisture Sensor DTH File
*
* Filename: SmartSense-Moisture-Sensor.src/SmartSense-Moisture-Sensor.groovy
*
* Change History:
* 1. 20160116 TW - Update/Edit to support i18n translations
* 2. 20160125 TW = Incorporated new battery mapping from TM
===============================================================================
*/
metadata {
@@ -31,6 +21,7 @@ metadata {
capability "Refresh"
capability "Temperature Measurement"
capability "Water Sensor"
capability "Health Check"
command "enrollResponse"
@@ -320,6 +311,8 @@ def refresh() {
}
def configure() {
sendEvent(name: "checkInterval", value: 7200, displayed: false)
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."
def configCmds = [

View File

@@ -1,4 +1,3 @@
#==============================================================================
# Copyright 2016 SmartThings
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -12,15 +11,6 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#==============================================================================
# Purpose: SmartSense Motion Sensor i18n Translation File
#
# Filename: SmartSense-Motion-Sensor.src/i18n/messages.properties
#
# Change History:
# 1. 20160116 TW Initial release with formal Korean translation.
# 2. 20160224 TW Updated formal Korean translations from Mike Stoller.
#==============================================================================
# Korean (ko)
# Device Preferences
'''battery'''.ko=배터리
@@ -28,16 +18,16 @@
'''This feature allows you to correct any temperature variations by selecting an offset. Ex: If your sensor consistently reports a temp that's 5 degrees too warm, you'd enter '-5'. If 3 degrees too cold, enter '+3'.'''.ko=기준 온도를 원하는대로 몇 도 올리거나 내려서 설정할 수 있습니다.
'''Degrees'''.ko=온도
'''Adjust temperature by this many degrees'''.ko=몇 도씩 온도를 조절하십시오
'''Give your device a name'''.ko=기기 이름 바꾸기
'''Give your device a name'''.ko=기기 이름 설정
'''Motion Sensor'''.ko=모션 센서
'''motion'''.ko=동작 감지
'''motion'''.ko= 동작 감지
'''no motion'''.ko=동작 없음
'''${currentValue}% battery'''.ko=${currentValue}% 배터리
# Events descriptionText
'''{{ device.displayName }} detected motion'''.ko={{ device.displayName }} 움직임 감지하였습니다.
'''{{ device.displayName }} motion has stopped'''.ko={{ device.displayName }}움직임이 중단되었습니다
'''{{ device.displayName }} was {{ value }}°C'''.ko={{ device.displayName }}이(가){{ value }}°C였습니다.
'''{{ device.displayName }} detected motion'''.ko={{ device.displayName }}에서 움직임 감지되었습니다.
'''{{ device.displayName }} motion has stopped'''.ko={{ device.displayName }}에서 움직임이 중단되었습니다.
'''{{ device.displayName }} was {{ value }}°C'''.ko={{ device.displayName }}에서 {{ value }}°C 감지
'''{{ device.displayName }} was {{ value }}°F'''.ko={{ device.displayName }}이(가) {{ value }}°F였습니다
'''{{ device.displayName }} battery has too much power: (> 3.5) volts.'''.ko={{ device.displayName }} 배터리 전력이 너무 높습니다(3.5볼트 초과).
'''{{ device.displayName }} battery was {{ value }}%'''.ko={{ device.displayName }}남아있는 배터리 {{ value }}%입니다.
'''{{ device.displayName }} battery was {{ value }}%'''.ko={{ device.displayName }}의 남은 배터리 {{ value }}%
#==============================================================================

View File

@@ -1,5 +1,4 @@
/*
===============================================================================
* Copyright 2016 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -13,15 +12,6 @@
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
===============================================================================
* Purpose: SmartSense Motion Sensor DTH File
*
* Filename: SmartSense-Motion-Sensor.src/SmartSense-Motion-Sensor.groovy
*
* Change History:
* 1. 20160116 TW - Update/Edit to support i18n translations
* 2. 20160125 TW = Incorporated new battery mapping from TM
===============================================================================
*/
metadata {
@@ -31,6 +21,7 @@ metadata {
capability "Battery"
capability "Temperature Measurement"
capability "Refresh"
capability "Health Check"
command "enrollResponse"
@@ -332,6 +323,8 @@ def refresh() {
}
def configure() {
sendEvent(name: "checkInterval", value: 7200, displayed: false)
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."

View File

@@ -1,4 +1,3 @@
#==============================================================================
# Copyright 2016 SmartThings
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -12,14 +11,6 @@
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#==============================================================================
# Purpose: SmartSense Multi Sensor i18n Translation File
#
# Filename: SmartSense-Multi-Sensor.src/i18n/messages.properties
#
# Change History:
# 1. 20160117 TW Initial release with informal Korean translation.
#==============================================================================
# Korean (ko)
# Device Preferences
'''Yes'''.ko=
@@ -31,20 +22,20 @@
'''Adjust temperature by this many degrees'''.ko=몇 도씩 온도를 조절하십시오
'''Do you want to use this sensor on a garage door?'''.ko=차고 문의 센서 사용 설정하기
'''Tap to set'''.ko=눌러서 설정
'''Give your device a name'''.ko=기기 이름 바꾸기
'''Multipurpose Sensor'''.ko=멀티 센서
'''Give your device a name'''.ko=기기 이름 설정
'''Multipurpose Sensor'''.ko=문 및 창 센서
# Events descriptionText
'''{{ device.displayName }} was opened'''.ko={{ device.displayName }}열림 감지하였습니다.
'''{{ device.displayName }} was closed'''.ko={{ device.displayName }}닫혔습니다.
'''{{ device.displayName }} was active'''.ko={{ device.displayName }}활성화되었습니다.
'''{{ device.displayName }} was inactive'''.ko={{ device.displayName }}비활성화되었습니다.
'''{{ device.displayName }} was {{ value }}°C'''.ko={{ device.displayName }}이(가){{ value }}°C였습니다.
'''{{ device.displayName }} was opened'''.ko={{ device.displayName }}에서 열림 감지되었습니다.
'''{{ device.displayName }} was closed'''.ko={{ device.displayName }}에서 닫힘이 감지되었습니다.
'''{{ device.displayName }} was active'''.ko={{ device.displayName }} 활성화
'''{{ device.displayName }} was inactive'''.ko={{ device.displayName }} 비활성화
'''{{ device.displayName }} was {{ value }}°C'''.ko={{ device.displayName }}에서 {{ value }}°C 감지
'''{{ device.displayName }} was {{ value }}°F'''.ko={{ device.displayName }}이(가) {{ value }}°F였습니다
'''{{ device.displayName }} battery was {{ value }}%'''.ko={{ device.displayName }}남아있는 배터리 {{ value }}%입니다.
'''{{ device.displayName }} battery was {{ value }}%'''.ko={{ device.displayName }}의 남은 배터리 {{ value }}%
'''Updating device to garage sensor'''.ko=기기-차고 센서 업데이트 중
'''Updating device to open/close sensor'''.ko=기기-열림/닫힘 센서 업데이트 중
'''Inactive'''.ko=비활성
'''Active'''.ko=활성
'''Open'''.ko=열림
'''Inactive'''.ko=비활성 상태
'''Active'''.ko=활성 상태
'''Open'''.ko= 열림이 감지될 때
'''Closed'''.ko=닫힘
'''${currentValue}% battery'''.ko=${currentValue}% 배터리

View File

@@ -1,5 +1,4 @@
/*
===============================================================================
* Copyright 2016 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -13,15 +12,6 @@
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
===============================================================================
* Purpose: SmartSense Multi Sensor DTH File
*
* Filename: SmartSense-Multi-Sensor.src/SmartSense-Multi-Sensor.groovy
*
* Change History:
* 1. 20160117 TW - Update/Edit to support i18n translations
* 2. 20160125 TW = Incorporated new battery mapping from TM
===============================================================================
*/
metadata {
@@ -35,6 +25,7 @@ metadata {
capability "Acceleration Sensor"
capability "Refresh"
capability "Temperature Measurement"
capability "Health Check"
command "enrollResponse"
fingerprint inClusters: "0000,0001,0003,0402,0500,0020,0B05,FC02", outClusters: "0019", manufacturer: "CentraLite", model: "3320"
@@ -450,6 +441,8 @@ def refresh() {
}
def configure() {
sendEvent(name: "checkInterval", value: 7200, displayed: false)
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting"

View File

@@ -23,8 +23,9 @@
capability "Acceleration Sensor"
capability "Refresh"
capability "Temperature Measurement"
command "enrollResponse"
capability "Health Check"
command "enrollResponse"
}
simulator {
@@ -299,6 +300,7 @@ def getTemperature(value) {
}
def configure() {
sendEvent(name: "checkInterval", value: 7200, displayed: false)
String zigbeeEui = swapEndianHex(device.hub.zigbeeEui)
log.debug "Configuring Reporting, IAS CIE, and Bindings."

View File

@@ -20,6 +20,7 @@ metadata {
capability "Refresh"
capability "Temperature Measurement"
capability "Relative Humidity Measurement"
capability "Health Check"
fingerprint endpointId: "01", inClusters: "0001,0003,0020,0402,0B05,FC45", outClusters: "0019,0003"
}
@@ -251,6 +252,7 @@ def refresh()
}
def configure() {
sendEvent(name: "checkInterval", value: 7200, displayed: false)
log.debug "Configuring Reporting and Bindings."
def configCmds = [

View File

@@ -80,19 +80,31 @@ metadata {
state "default", label:''
}
main("standard1")
// multi-line text (explicit newlines)
standardTile("multiLine", "device.multiLine", width: 2, height: 2) {
state "default", label: '${currentValue}'
}
standardTile("multiLineWithIcon", "device.multiLine", width: 2, height: 2) {
state "default", label: '${currentValue}', icon: "st.switches.switch.off"
}
main("actionRings")
details([
"actionRings", "actionFlat", "noActionFlat",
"flatLabel", "flatIconLabel", "flatIcon",
"flatDefaultState", "flatImplicitDefaultState1", "flatImplicitDefaultState2",
"multiLine", "multiLineWithIcon"
])
}
}
def installed() {
sendEvent(name: "switch", value: "off")
sendEvent(name: "multiLine", value: "Line 1\nLine 2\nLine 3")
}
def parse(String description) {

View File

@@ -69,16 +69,25 @@ metadata {
]
}
valueTile("noValue", "device.nada", width: 2, height: 2) {
valueTile("noValue", "device.nada", width: 4, height: 2) {
state "default", label:'${currentValue}'
}
valueTile("multiLine", "device.multiLine", width: 3, height: 2) {
state "default", label: '${currentValue}'
}
valueTile("multiLineWithIcon", "device.multiLine", width: 3, height: 2) {
state "default", label: '${currentValue}', icon: "st.switches.switch.off"
}
main("text")
details([
"text", "longText", "integer",
"integerFloat", "pi", "floatAsText",
"bgColor", "bgColorRange", "bgColorRangeSingleItem",
"bgColorRangeConflict", "noValue"
"bgColorRangeConflict", "noValue",
"multiLine", "multiLineWithIcon"
])
}
}
@@ -90,6 +99,7 @@ def installed() {
sendEvent(name: "integerFloat", value: 47.0)
sendEvent(name: "pi", value: 3.14159)
sendEvent(name: "floatAsText", value: "3.14159")
sendEvent(name: "multiLine", value: "Line 1\nLine 2\nLine 3")
}
def parse(String description) {

View File

@@ -67,17 +67,50 @@ metadata {
attributeState "VALUE_DOWN", action: "levelDown"
}
}
multiAttributeTile(name:"lengthyTile", type:"generic", width:6, height:4) {
tileAttribute("device.lengthyText", key: "PRIMARY_CONTROL") {
attributeState "default", label:'The value of this tile is long and should wrap to two lines', backgroundColor:"#79b821"
}
tileAttribute("device.lengthyText", key: "SECONDARY_CONTROL") {
attributeState "default", label:'The value of this tile is long and should wrap to two lines', backgroundColor:"#79b821"
}
}
multiAttributeTile(name:"multilineTile", type:"generic", width:6, height:4) {
tileAttribute("device.multilineText", key: "PRIMARY_CONTROL") {
attributeState "default", label:'Line 1 YES\nLine 2 YES\nLine 3 NO', backgroundColor:"#79b821"
}
tileAttribute("device.multilineText", key: "SECONDARY_CONTROL") {
attributeState "default", label:'Line 1 YES\nLine 2 YES\nLine 3 NO', backgroundColor:"#79b821"
}
}
multiAttributeTile(name:"lengthyTileWithIcon", type:"generic", width:6, height:4) {
tileAttribute("device.lengthyText", key: "PRIMARY_CONTROL") {
attributeState "default", label:'The value of this tile is long and should wrap to two lines', backgroundColor:"#79b821", icon: "st.switches.switch.on"
}
tileAttribute("device.lengthyText", key: "SECONDARY_CONTROL") {
attributeState "default", label:'The value of this tile is long and should wrap to two lines', backgroundColor:"#79b821", icon: "st.switches.switch.on"
}
}
multiAttributeTile(name:"multilineTileWithIcon", type:"generic", width:6, height:4) {
tileAttribute("device.multilineText", key: "PRIMARY_CONTROL") {
attributeState "default", label:'Line 1 YES\nLine 2 YES\nLine 3 NO', backgroundColor:"#79b821", icon: "st.switches.switch.on"
}
tileAttribute("device.multilineText", key: "SECONDARY_CONTROL") {
attributeState "default", label:'Line 1 YES\nLine 2 YES\nLine 3 NO', backgroundColor:"#79b821", icon: "st.switches.switch.on"
}
}
main(["basicTile"])
details(["basicTile", "sliderTile", "valueTile"])
details(["basicTile", "sliderTile", "valueTile", "lengthyTile", "multilineTile", "lengthyTileWithIcon", "multilineTileWithIcon"])
}
}
def installed() {
sendEvent(name: "lengthyText", value: "The value of this tile is long and should wrap to two lines")
sendEvent(name: "multilineText", value: "Line 1 YES\nLine 2 YES\nLine 3 NO")
}
def parse() {
def parse(String description) {
// This is a simulated device. No incoming data to parse.
}

View File

@@ -164,7 +164,7 @@ metadata {
main("thermostatFull")
details([
"thermostatFull", "thermostatNoHumidity", "thermostatBasic"
"thermostatFull", "thermostatNoHumidity", "thermostatBasic",
"temperature","tempDown","tempUp",
"mode", "fanMode", "operatingState",
"heatingSetpoint", "heatDown", "heatUp",

View File

@@ -33,7 +33,7 @@ metadata {
state "power", label: '${currentValue} W'
}
htmlTile(name: "powerContent", attribute: "powerContent", type: "HTML", whitelist: "www.wattvision.com" , url: '${currentValue}', width: 3, height: 2)
htmlTile(name: "powerContent", attribute: "powerContent", type: "HTML", whitelist: ["www.wattvision.com"] , url: '${currentValue}', width: 3, height: 2)
standardTile("refresh", "device.power", inactiveLabel: false, decoration: "flat") {
state "default", label: '', action: "refresh.refresh", icon: "st.secondary.refresh"

View File

@@ -11,6 +11,9 @@
* for the specific language governing permissions and limitations under the License.
*
*/
//@Deprecated - Moved to zll-rgbw-bulb
/* Philips Hue (via Zigbee)
Capabilities:
@@ -22,10 +25,10 @@ Capabilities:
Sensor
Switch
Switch Level
Custom Commands:
setAdjustedColor
*/
metadata {
@@ -41,7 +44,7 @@ metadata {
command "setAdjustedColor"
fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,0300,1000", outClusters: "0019"
//fingerprint profileId: "C05E", inClusters: "0000,0003,0004,0005,0006,0008,0300,1000", outClusters: "0019"
}
// simulator metadata

View File

@@ -0,0 +1,101 @@
/**
* Copyright 2016 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
metadata {
definition (name: "ZLL Dimmer Bulb", namespace: "smartthings", author: "SmartThings") {
capability "Actuator"
capability "Configuration"
capability "Polling"
capability "Refresh"
capability "Switch"
capability "Switch Level"
fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000", outClusters: "0000,0019"
fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000", outClusters: "0000,0019", manufacturer: "CREE", model: "Connected A-19 60W Equivalent", deviceJoinName: "Cree Connected Bulb"
fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Classic A60 W clear", deviceJoinName: "OSRAM LIGHTIFY LED Smart Connected Light"
fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000, 0B04, FC0F", outClusters: "0019", manufacturer: "OSRAM", model: "Classic A60 W clear - LIGHTIFY", deviceJoinName: "OSRAM LIGHTIFY LED Smart Connected Light"
fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 1000", outClusters: "0019", manufacturer: "Philips", model: "LWB006", deviceJoinName: "Philips Hue White"
}
// simulator metadata
simulator {
// status messages
status "on": "on/off: 1"
status "off": "on/off: 0"
// reply messages
reply "zcl on-off on": "on/off: 1"
reply "zcl on-off off": "on/off: 0"
}
// UI tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", 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 "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel"
}
}
standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
main "switch"
details(["switch", "refresh"])
}
}
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
def resultMap = zigbee.getEvent(description)
if (resultMap) {
sendEvent(resultMap)
}
else {
log.debug "DID NOT PARSE MESSAGE for description : $description"
log.debug zigbee.parseDescriptionAsMap(description)
}
}
def off() {
zigbee.off() + ["delay 1500"] + zigbee.onOffRefresh()
}
def on() {
zigbee.on() + ["delay 1500"] + zigbee.onOffRefresh()
}
def setLevel(value) {
zigbee.setLevel(value) + ["delay 1500"] + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report
}
def refresh() {
zigbee.onOffRefresh() + zigbee.levelRefresh()
}
def poll() {
refresh()
}
def configure() {
log.debug "Configuring Reporting and Bindings."
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()
}

View File

@@ -0,0 +1,150 @@
/**
* Copyright 2016 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
metadata {
definition (name: "ZLL RGBW Bulb", namespace: "smartthings", author: "SmartThings") {
capability "Actuator"
capability "Color Control"
capability "Color Temperature"
capability "Configuration"
capability "Polling"
capability "Refresh"
capability "Switch"
capability "Switch Level"
fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300", outClusters: "0019"
fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 1000", outClusters: "0019"
fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 1000", outClusters: "0019", "manufacturer":"OSRAM", "model":"Classic A60 RGBW", deviceJoinName: "OSRAM LIGHTIFY LED Classic A60 RGBW"
}
// UI tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "off", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
attributeState "turningOn", label:'${name}', action:"switch.off", icon:"st.lights.philips.hue-single", backgroundColor:"#79b821", nextState:"turningOff"
attributeState "turningOff", label:'${name}', action:"switch.on", icon:"st.lights.philips.hue-single", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel"
}
tileAttribute ("device.color", key: "COLOR_CONTROL") {
attributeState "color", action:"color control.setColor"
}
}
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..6500)") {
state "colorTemperature", action:"color temperature.setColorTemperature"
}
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "colorTemperature", label: '${currentValue} K'
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
main(["switch"])
details(["switch", "colorTempSliderControl", "colorTemp", "refresh"])
}
}
//Globals
private getATTRIBUTE_HUE() { 0x0000 }
private getATTRIBUTE_SATURATION() { 0x0001 }
private getHUE_COMMAND() { 0x00 }
private getSATURATION_COMMAND() { 0x03 }
private getCOLOR_CONTROL_CLUSTER() { 0x0300 }
private getATTRIBUTE_COLOR_TEMPERATURE() { 0x0007 }
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
def finalResult = zigbee.getEvent(description)
if (finalResult) {
log.debug finalResult
sendEvent(finalResult)
}
else {
def zigbeeMap = zigbee.parseDescriptionAsMap(description)
log.trace "zigbeeMap : $zigbeeMap"
if (zigbeeMap?.clusterInt == COLOR_CONTROL_CLUSTER) {
if(zigbeeMap.attrInt == ATTRIBUTE_HUE){ //Hue Attribute
def hueValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 360)
sendEvent(name: "hue", value: hueValue, displayed:false)
}
else if(zigbeeMap.attrInt == ATTRIBUTE_SATURATION){ //Saturation Attribute
def saturationValue = Math.round(zigbee.convertHexToInt(zigbeeMap.value) / 255 * 100)
sendEvent(name: "saturation", value: saturationValue, displayed:false)
}
}
else {
log.info "DID NOT PARSE MESSAGE for description : $description"
}
}
}
def on() {
zigbee.on() + ["delay 1500"] + zigbee.onOffRefresh()
}
def off() {
zigbee.off() + ["delay 1500"] + zigbee.onOffRefresh()
}
def refresh() {
refreshAttributes() + configureAttributes()
}
def poll() {
refreshAttributes()
}
def configure() {
log.debug "Configuring Reporting and Bindings."
configureAttributes() + refreshAttributes()
}
def configureAttributes() {
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_HUE, 0x20, 1, 3600, 0x01) + zigbee.configureReporting(COLOR_CONTROL_CLUSTER, ATTRIBUTE_SATURATION, 0x20, 1, 3600, 0x01)
}
def refreshAttributes() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() + zigbee.readAttribute(0x0300, 0x00) + zigbee.readAttribute(0x0300, ATTRIBUTE_HUE) + zigbee.readAttribute(0x0300, ATTRIBUTE_SATURATION)
}
def setColorTemperature(value) {
zigbee.setColorTemperature(value) + ["delay 1500"] + zigbee.colorTemperatureRefresh()
}
def setLevel(value) {
zigbee.setLevel(value) + ["delay 1500"] + zigbee.levelRefresh() //adding refresh because of ZLL bulb not conforming to send-me-a-report
}
def setColor(value){
log.trace "setColor($value)"
zigbee.on() + setHue(value.hue) + ["delay 300"] + setSaturation(value.saturation) + ["delay 2000"] + refreshAttributes()
}
def setHue(value) {
def scaledHueValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2)
zigbee.command(COLOR_CONTROL_CLUSTER, HUE_COMMAND, scaledHueValue, "00", "0500") //payload-> hue value, direction (00-> shortest distance), transition time (1/10th second) (0500 in U16 reads 5)
}
def setSaturation(value) {
def scaledSatValue = zigbee.convertToHexString(Math.round(value * 0xfe / 100.0), 2)
zigbee.command(COLOR_CONTROL_CLUSTER, SATURATION_COMMAND, scaledSatValue, "0500") //payload-> sat value, transition time
}

View File

@@ -0,0 +1,124 @@
/**
* Copyright 2016 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*
*/
metadata {
definition (name: "ZLL White Color Temperature Bulb", namespace: "smartthings", author: "SmartThings") {
capability "Actuator"
capability "Color Temperature"
capability "Configuration"
capability "Polling"
capability "Refresh"
capability "Switch"
capability "Switch Level"
attribute "colorName", "string"
command "setGenericName"
fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 1000, 0B04, FC0F", outClusters: "0019", "manufacturer":"OSRAM", "model":"Classic A60 TW", deviceJoinName: "OSRAM LIGHTIFY LED Classic A60 Tunable White"
fingerprint profileId: "C05E", inClusters: "0000, 0003, 0004, 0005, 0006, 0008, 0300, 1000, FC0F", outClusters: "0019", "manufacturer":"OSRAM", "model":"PAR16 50 TW", deviceJoinName: "OSRAM LIGHTIFY LED PAR16 50 Tunable White"
}
// UI tile definitions
tiles(scale: 2) {
multiAttributeTile(name:"switch", type: "lighting", width: 6, height: 4, canChangeIcon: true){
tileAttribute ("device.switch", key: "PRIMARY_CONTROL") {
attributeState "on", label:'${name}', action:"switch.off", icon:"st.switches.light.on", backgroundColor:"#79b821", 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 "turningOff", label:'${name}', action:"switch.on", icon:"st.switches.light.off", backgroundColor:"#ffffff", nextState:"turningOn"
}
tileAttribute ("device.level", key: "SLIDER_CONTROL") {
attributeState "level", action:"switch level.setLevel"
}
tileAttribute ("colorName", key: "SECONDARY_CONTROL") {
attributeState "colorName", label:'${currentValue}'
}
}
standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
}
controlTile("colorTempSliderControl", "device.colorTemperature", "slider", width: 4, height: 2, inactiveLabel: false, range:"(2700..6500)") {
state "colorTemperature", action:"color temperature.setColorTemperature"
}
valueTile("colorTemp", "device.colorTemperature", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
state "colorTemperature", label: '${currentValue} K'
}
main(["switch"])
details(["switch", "colorTempSliderControl", "colorTemp", "refresh"])
}
}
// Parse incoming device messages to generate events
def parse(String description) {
log.debug "description is $description"
def event = zigbee.getEvent(description)
if (event) {
sendEvent(event)
}
else {
log.warn "DID NOT PARSE MESSAGE for description : $description"
log.debug zigbee.parseDescriptionAsMap(description)
}
}
def off() {
zigbee.off() + ["delay 1500"] + zigbee.onOffRefresh()
}
def on() {
zigbee.on() + ["delay 1500"] + zigbee.onOffRefresh()
}
def setLevel(value) {
zigbee.setLevel(value) + ["delay 1500"] + zigbee.levelRefresh()
}
def refresh() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh() + zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig()
}
def poll() {
zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
}
def configure() {
log.debug "Configuring Reporting and Bindings."
zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.colorTemperatureConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh() + zigbee.colorTemperatureRefresh()
}
def setColorTemperature(value) {
setGenericName(value)
zigbee.setColorTemperature(value) + ["delay 1500"] + zigbee.colorTemperatureRefresh()
}
//Naming based on the wiki article here: http://en.wikipedia.org/wiki/Color_temperature
def setGenericName(value){
if (value != null) {
def genericName = ""
if (value < 3300) {
genericName = "Soft White"
} else if (value < 4150) {
genericName = "Moonlight"
} else if (value <= 5000) {
genericName = "Cool White"
} else {
genericName = "Daylight"
}
sendEvent(name: "colorName", value: genericName)
}
}

View File

@@ -25,7 +25,10 @@ metadata {
fingerprint deviceId: "0x2001", inClusters: "0x30,0x80,0x84,0x85,0x86,0x72"
fingerprint deviceId: "0x07", inClusters: "0x30"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x98"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x86,0x72,0x98", outClusters: "0x5A,0x82"
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x80,0x71,0x85,0x70,0x72,0x86,0x30,0x31,0x84,0x59,0x73,0x5A,0x8F,0x98,0x7A", outClusters:"0x20" // Philio multi+
fingerprint deviceId: "0x0701", inClusters: "0x5E,0x72,0x5A,0x80,0x73,0x86,0x84,0x85,0x59,0x71,0x70,0x7A,0x98" // Vision door/window
}
// simulator metadata
@@ -240,7 +243,7 @@ def batteryGetCommand() {
def retypeBasedOnMSR() {
switch (state.MSR) {
case "0086-0002-002D":
log.debug("Changing device type to Z-Wave Water Sensor")
log.debug "Changing device type to Z-Wave Water Sensor"
setDeviceType("Z-Wave Water Sensor")
break
case "011F-0001-0001": // Schlage motion
@@ -249,9 +252,16 @@ def retypeBasedOnMSR() {
case "0060-0001-0002": // Everspring SP814
case "0060-0001-0003": // Everspring HSP02
case "011A-0601-0901": // Enerwave ZWN-BPC
log.debug("Changing device type to Z-Wave Motion Sensor")
log.debug "Changing device type to Z-Wave Motion Sensor"
setDeviceType("Z-Wave Motion Sensor")
break
case "013C-0002-000D": // Philio multi +
log.debug "Changing device type to 3-in-1 Multisensor Plus (SG)"
setDeviceType("3-in-1 Multisensor Plus (SG)")
break
case "0109-2001-0106": // Vision door/window
log.debug "Changing device type to Door / Window Sensor Plus (SG)"
setDeviceType("Door / Window Sensor Plus (SG)")
break
}
}

View File

@@ -0,0 +1,66 @@
/**
* Door Jammed Notification
*
* Copyright 2015 John Rucker
*
* 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.
*
*/
definition(
name: "Door Jammed Notification",
namespace: "JohnRucker",
author: "John.Rucker@Solar-current.com",
description: "Sends a SmartThings notification and text messages when your CoopBoss detects a door jam.",
category: "My Apps",
iconUrl: "http://coopboss.com/images/SmartThingsIcons/coopbossLogo.png",
iconX2Url: "http://coopboss.com/images/SmartThingsIcons/coopbossLogo2x.png",
iconX3Url: "http://coopboss.com/images/SmartThingsIcons/coopbossLogo3x.png")
preferences {
section("When the door state changes") {
paragraph "Send a SmartThings notification when the coop's door jammed and did not close."
input "doorSensor", "capability.doorControl", title: "Select CoopBoss", required: true, multiple: false
input("recipients", "contact", title: "Recipients", description: "Send notifications to") {
input "phone", "phone", title: "Phone number?", required: true}
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
subscribe(doorSensor, "doorState", coopDoorStateHandler)
}
def coopDoorStateHandler(evt) {
if (evt.value == "jammed"){
def msg = "WARNING ${doorSensor.displayName} door is jammed and did not close!"
log.debug "WARNING ${doorSensor.displayName} door is jammed and did not close, texting $phone"
if (location.contactBookEnabled) {
sendNotificationToContacts(msg, recipients)
}
else {
sendPush(msg)
if (phone) {
sendSms(phone, msg)
}
}
}
}

View File

@@ -0,0 +1,141 @@
/**
* CoopBoss Door Status to color
*
* Copyright 2015 John Rucker
*
* 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.
*
*/
definition(
name: "Door State to Color Light (Hue Bulb)",
namespace: "JohnRucker",
author: "John Rucker",
description: "Change the color of your Hue bulbs based on your coop's door status.",
category: "My Apps",
iconUrl: "http://coopboss.com/images/SmartThingsIcons/coopbossLogo.png",
iconX2Url: "http://coopboss.com/images/SmartThingsIcons/coopbossLogo2x.png",
iconX3Url: "http://coopboss.com/images/SmartThingsIcons/coopbossLogo3x.png")
preferences {
section("When the door opens/closese...") {
paragraph "Sets a Hue bulb or bulbs to a color based on your coop's door status:\r unknown = white\r open = blue\r opening = purple\r closed = green\r closing = pink\r jammed = red\r forced close = orange."
input "doorSensor", "capability.doorControl", title: "Select CoopBoss", required: true, multiple: false
input "bulbs", "capability.colorControl", title: "pick a bulb", required: true, multiple: true
}
}
def installed() {
log.debug "Installed with settings: ${settings}"
initialize()
}
def updated() {
log.debug "Updated with settings: ${settings}"
unsubscribe()
initialize()
}
def initialize() {
subscribe(doorSensor, "doorState", coopDoorStateHandler)
}
def coopDoorStateHandler(evt) {
log.debug "${evt.descriptionText}, $evt.value"
def color = "White"
def hueColor = 100
def saturation = 100
Map hClr = [:]
hClr.hex = "#FFFFFF"
switch(evt.value) {
case "open":
color = "Blue"
break;
case "opening":
color = "Purple"
break;
case "closed":
color = "Green"
break;
case "closing":
color = "Pink"
break;
case "jammed":
color = "Red"
break;
case "forced close":
color = "Orange"
break;
case "unknown":
color = "White"
break;
}
switch(color) {
case "White":
hueColor = 52
saturation = 19
break;
case "Daylight":
hueColor = 53
saturation = 91
break;
case "Soft White":
hueColor = 23
saturation = 56
break;
case "Warm White":
hueColor = 20
saturation = 80 //83
break;
case "Blue":
hueColor = 70
hClr.hex = "#0000FF"
break;
case "Green":
hueColor = 39
hClr.hex = "#00FF00"
break;
case "Yellow":
hueColor = 25
hClr.hex = "#FFFF00"
break;
case "Orange":
hueColor = 10
hClr.hex = "#FF6000"
break;
case "Purple":
hueColor = 75
hClr.hex = "#BF7FBF"
break;
case "Pink":
hueColor = 83
hClr.hex = "#FF5F5F"
break;
case "Red":
hueColor = 100
hClr.hex = "#FF0000"
break;
}
//bulbs*.on()
bulbs*.setHue(hueColor)
bulbs*.setSaturation(saturation)
bulbs*.setColor(hClr)
//bulbs.each{
//it.on() // Turn the bulb on when open (this method does not come directly from the colorControl capability)
//it.setLevel(100) // Make sure the light brightness is 100%
//it.setHue(hueColor)
//it.setSaturation(saturation)
//}
}

View File

@@ -0,0 +1,88 @@
/**
* Copyright 2015 SmartThings
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
* for the specific language governing permissions and limitations under the License.
*/
definition(
name: "Fibaro Dimmer Scenes",
namespace: "My Apps",
author: "Elnar Hajiyev",
description: "Smart app that allows to control switches with changes of Fibaro Dimmer Scenes.",
category: "Convenience",
iconUrl: "https://s3.amazonaws.com/smartapp-icons/Meta/light_outlet.png",
iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Meta/light_outlet@2x.png"
)
preferences {
section("Listen to scenes from this Fibaro Dimmer devices...") {
input "fibaroDevicesSet", "capability.switch", title: "Fibaro Dimmers?", multiple: true, required: true
}
section("When any of these scenes are activated...") {
input "scenesSet1", "enum", title: "Fibaro Dimmer scenes (set 1)?", multiple: true, required: false,
options: ["10","11","12","13", "14", "15", "16", "17", "18", "20", "21", "22", "23", "24", "25", "26"]
}
section("Turn on all of these switches") {
input "switchesSet1", "capability.switch", multiple: true, required: false
}
section("When any of these scenes are activated...") {
input "scenesSet2", "enum", title: "Fibaro Dimmer scenes (set 2)?", multiple: true, required: false,
options: ["10","11","12","13", "14", "15", "16", "17", "18", "20", "21", "22", "23", "24", "25", "26"]
}
section("Turn off all of these switches") {
input "switchesSet2", "capability.switch", multiple: true, required: false
}
section("When any of these scenes are activated...") {
input "scenesSet3", "enum", title: "Fibaro Dimmer scenes (set 3)?", multiple: true, required: false,
options: ["10","11","12","13", "14", "15", "16", "17", "18", "20", "21", "22", "23", "24", "25", "26"]
}
section("Toggle all of these switches") {
input "switchesSet3", "capability.switch", multiple: true, required: false
}
}
def installed()
{
subscribe(fibaroDevicesSet, "scene", sceneHandler, [filterEvents: false])
}
def updated()
{
unsubscribe()
subscribe(fibaroDevicesSet, "scene", sceneHandler, [filterEvents: false])
}
def sceneHandler(evt) {
log.debug evt.value
log.debug evt.data
if(scenesSet1 && scenesSet1.contains(evt.value)) {
switchesSet1.on()
}
else if(scenesSet2 && scenesSet2.contains(evt.value)) {
switchesSet2.off()
}
else if(scenesSet3 && scenesSet3.contains(evt.value)) {
toggle(switchesSet3)
}
}
def toggle(devices) {
log.debug "toggle: $devices = ${devices*.currentValue('switch')}"
if (devices*.currentValue('switch').contains('off')) {
devices.on()
}
else if (devices*.currentValue('switch').contains('on')) {
devices.off()
}
else {
devices.on()
}
}

View File

@@ -60,7 +60,7 @@ def bridgeDiscovery(params=[:])
app.updateSetting("selectedHue", "")
}
subscribe(location, null, locationHandler, [filterEvents:false])
ssdpSubscribe()
//bridge discovery request every 15 //25 seconds
if((bridgeRefreshCount % 5) == 0) {
@@ -152,6 +152,10 @@ private discoverBridges() {
sendHubCommand(new physicalgraph.device.HubAction("lan discovery urn:schemas-upnp-org:device:basic:1", physicalgraph.device.Protocol.LAN))
}
void ssdpSubscribe() {
subscribe(location, "ssdpTerm.urn:schemas-upnp-org:device:basic:1", ssdpBridgeHandler)
}
private sendDeveloperReq() {
def token = app.id
def host = getBridgeIP()
@@ -161,7 +165,7 @@ private sendDeveloperReq() {
headers: [
HOST: host
],
body: [devicetype: "$token-0"]], "${selectedHue}"))
body: [devicetype: "$token-0"]], "${selectedHue}", [callback: "usernameHandler"]))
}
private discoverHueBulbs() {
@@ -171,7 +175,7 @@ private discoverHueBulbs() {
path: "/api/${state.username}/lights",
headers: [
HOST: host
]], "${selectedHue}"))
]], "${selectedHue}", [callback: "lightsHandler"]))
}
private verifyHueBridge(String deviceNetworkId, String host) {
@@ -181,7 +185,7 @@ private verifyHueBridge(String deviceNetworkId, String host) {
path: "/description.xml",
headers: [
HOST: host
]], deviceNetworkId))
]], deviceNetworkId, [callback: "bridgeDescriptionHandler"]))
}
private verifyHueBridges() {
@@ -293,8 +297,9 @@ def bulbListHandler(hub, data = "") {
}
}
def bridge = null
if (selectedHue)
bridge = getChildDevice(selectedHue)
if (selectedHue) {
bridge = getChildDevice(selectedHue)
}
bridge.sendEvent(name: "bulbList", value: hub, data: bulbs, isStateChange: true, displayed: false)
msg = "${bulbs.size()} bulbs found. ${bulbs}"
return msg
@@ -327,8 +332,7 @@ private addChildBulb(dni, hueType, name, hub, update=false, device = null) {
if (deviceType) {
return addChildDevice("smartthings", deviceType, dni, hub, ["label": name])
}
else {
} else {
log.warn "Device type $hueType not supported"
return null
}
@@ -344,8 +348,10 @@ def addBulbs() {
newHueBulb = bulbs.find { (app.id + "/" + it.value.id) == dni }
if (newHueBulb != null) {
d = addChildBulb(dni, newHueBulb?.value?.type, newHueBulb?.value?.name, newHueBulb?.value?.hub)
log.debug "created ${d.displayName} with id $dni"
d.refresh()
if (d) {
log.debug "created ${d.displayName} with id $dni"
d.refresh()
}
} else {
log.debug "$dni in not longer paired to the Hue Bridge or ID changed"
}
@@ -353,7 +359,7 @@ def addBulbs() {
//backwards compatable
newHueBulb = bulbs.find { (app.id + "/" + it.id) == dni }
d = addChildBulb(dni, "Extended Color Light", newHueBulb?.value?.name, newHueBulb?.value?.hub)
d.refresh()
d?.refresh()
}
} else {
log.debug "found ${d.displayName} with id $dni already exists, type: '$d.typeName'"
@@ -382,8 +388,9 @@ def addBridge() {
def oldDNI = it.deviceNetworkId
log.debug "updating dni for device ${it} with $newDNI - previous DNI = ${it.deviceNetworkId}"
it.setDeviceNetworkId("${newDNI}")
if (oldDNI == selectedHue)
app.updateSetting("selectedHue", newDNI)
if (oldDNI == selectedHue) {
app.updateSetting("selectedHue", newDNI)
}
newbridge = false
}
}
@@ -412,6 +419,111 @@ def addBridge() {
}
}
def ssdpBridgeHandler(evt) {
def description = evt.description
log.trace "Location: $description"
def hub = evt?.hubId
def parsedEvent = parseLanMessage(description)
parsedEvent << ["hub":hub]
def bridges = getHueBridges()
log.trace bridges.toString()
if (!(bridges."${parsedEvent.ssdpUSN.toString()}")) {
//bridge does not exist
log.trace "Adding bridge ${parsedEvent.ssdpUSN}"
bridges << ["${parsedEvent.ssdpUSN.toString()}":parsedEvent]
} else {
// update the values
def ip = convertHexToIP(parsedEvent.networkAddress)
def port = convertHexToInt(parsedEvent.deviceAddress)
def host = ip + ":" + port
log.debug "Device ($parsedEvent.mac) was already found in state with ip = $host."
def dstate = bridges."${parsedEvent.ssdpUSN.toString()}"
def dni = "${parsedEvent.mac}"
def d = getChildDevice(dni)
def networkAddress = null
if (!d) {
childDevices.each {
if (it.getDeviceDataByName("mac")) {
def newDNI = "${it.getDeviceDataByName("mac")}"
if (newDNI != it.deviceNetworkId) {
def oldDNI = it.deviceNetworkId
log.debug "updating dni for device ${it} with $newDNI - previous DNI = ${it.deviceNetworkId}"
it.setDeviceNetworkId("${newDNI}")
if (oldDNI == selectedHue) {
app.updateSetting("selectedHue", newDNI)
}
doDeviceSync()
}
}
}
} else {
if (d.getDeviceDataByName("networkAddress")) {
networkAddress = d.getDeviceDataByName("networkAddress")
} else {
networkAddress = d.latestState('networkAddress').stringValue
}
log.trace "Host: $host - $networkAddress"
if (host != networkAddress) {
log.debug "Device's port or ip changed for device $d..."
dstate.ip = ip
dstate.port = port
dstate.name = "Philips hue ($ip)"
d.sendEvent(name:"networkAddress", value: host)
d.updateDataValue("networkAddress", host)
}
}
}
}
void bridgeDescriptionHandler(physicalgraph.device.HubResponse hubResponse) {
log.trace "description.xml response (application/xml)"
def body = hubResponse.xml
if (body?.device?.modelName?.text().startsWith("Philips hue bridge")) {
def bridges = getHueBridges()
def bridge = bridges.find {it?.key?.contains(body?.device?.UDN?.text())}
if (bridge) {
bridge.value << [name:body?.device?.friendlyName?.text(), serialNumber:body?.device?.serialNumber?.text(), verified: true]
} else {
log.error "/description.xml returned a bridge that didn't exist"
}
}
}
void lightsHandler(physicalgraph.device.HubResponse hubResponse) {
if (isValidSource(hubResponse.mac)) {
def body = hubResponse.json
if (!body?.state?.on) { //check if first time poll made it here by mistake
def bulbs = getHueBulbs()
log.debug "Adding bulbs to state!"
body.each { k, v ->
bulbs[k] = [id: k, name: v.name, type: v.type, modelid: v.modelid, hub: hubResponse.hubId]
}
}
}
}
void usernameHandler(physicalgraph.device.HubResponse hubResponse) {
if (isValidSource(hubResponse.mac)) {
def body = hubResponse.json
if (body.success != null) {
if (body.success[0] != null) {
if (body.success[0].username)
state.username = body.success[0].username
}
} else if (body.error != null) {
//TODO: handle retries...
log.error "ERROR: application/json ${body.error}"
}
}
}
/**
* @deprecated This has been replaced by the combination of {@link #ssdpBridgeHandler()}, {@link #bridgeDescriptionHandler()},
* {@link #lightsHandler()}, and {@link #usernameHandler()}. After a pending event subscription migration, it can be removed.
*/
@Deprecated
def locationHandler(evt) {
def description = evt.description
log.trace "Location: $description"
@@ -447,17 +559,19 @@ def locationHandler(evt) {
def oldDNI = it.deviceNetworkId
log.debug "updating dni for device ${it} with $newDNI - previous DNI = ${it.deviceNetworkId}"
it.setDeviceNetworkId("${newDNI}")
if (oldDNI == selectedHue)
app.updateSetting("selectedHue", newDNI)
if (oldDNI == selectedHue) {
app.updateSetting("selectedHue", newDNI)
}
doDeviceSync()
}
}
}
} else {
if (d.getDeviceDataByName("networkAddress"))
networkAddress = d.getDeviceDataByName("networkAddress")
else
networkAddress = d.latestState('networkAddress').stringValue
if (d.getDeviceDataByName("networkAddress")) {
networkAddress = d.getDeviceDataByName("networkAddress")
} else {
networkAddress = d.latestState('networkAddress').stringValue
}
log.trace "Host: $host - $networkAddress"
if(host != networkAddress) {
log.debug "Device's port or ip changed for device $d..."
@@ -490,8 +604,9 @@ def locationHandler(evt) {
def body = new groovy.json.JsonSlurper().parseText(parsedEvent.body)
if (body.success != null) {
if (body.success[0] != null) {
if (body.success[0].username)
if (body.success[0].username) {
state.username = body.success[0].username
}
}
} else if (body.error != null) {
//TODO: handle retries...
@@ -516,11 +631,7 @@ def doDeviceSync(){
log.trace "Doing Hue Device Sync!"
convertBulbListToMap()
poll()
try {
subscribe(location, null, locationHandler, [filterEvents:false])
} catch (all) {
log.trace "Subscription already exist"
}
ssdpSubscribe()
discoverBridges()
}
@@ -714,7 +825,7 @@ def setColor(childDevice, huesettings) {
value.bri = Math.min(Math.round(huesettings.level * 255 / 100), 255)
}
value.alert = huesettings.alert ? huesettings.alert : "none"
value.transition = huesettings.transition ? huesettings.transition : 4
value.transitiontime = huesettings.transitiontime ? huesettings.transitiontime : 4
// Make sure to turn off light if requested
if (huesettings.switch == "off")
@@ -747,15 +858,11 @@ private getId(childDevice) {
private poll() {
def host = getBridgeIP()
def uri = "/api/${state.username}/lights/"
try {
sendHubCommand(new physicalgraph.device.HubAction("""GET ${uri} HTTP/1.1
log.debug "GET: $host$uri"
sendHubCommand(new physicalgraph.device.HubAction("""GET ${uri} HTTP/1.1
HOST: ${host}
""", physicalgraph.device.Protocol.LAN, selectedHue))
} catch (all) {
log.warn "Parsing Body failed - trying again..."
doDeviceSync()
}
}
private put(path, body) {

View File

@@ -131,19 +131,69 @@ def update() {
def type = params.deviceType
def data = request.JSON
def devices = settings[type]
def device = settings[type]?.find { it.id == params.id }
def command = data.command
log.debug "[PROD] update, params: ${params}, request: ${data}, devices: ${devices*.id}"
if (command) {
def device = devices?.find { it.id == params.id }
if (!device) {
httpError(404, "Device not found")
} else {
device."$command"()
}
if (!device) {
httpError(404, "Device not found")
}
if (validateCommand(device, type, command)) {
device."$command"()
} else {
httpError(403, "Access denied. This command is not supported by current capability.")
}
}
/**
* Validating the command passed by the user based on capability.
* @return boolean
*/
def validateCommand(device, deviceType, command) {
def capabilityCommands = getDeviceCapabilityCommands(device.capabilities)
def currentDeviceCapability = getCapabilityName(deviceType)
if (capabilityCommands[currentDeviceCapability]) {
return command in capabilityCommands[currentDeviceCapability] ? true : false
} else {
// Handling other device types here, which don't accept commands
httpError(400, "Bad request.")
}
}
/**
* Need to get the attribute name to do the lookup. Only
* doing it for the device types which accept commands
* @return attribute name of the device type
*/
def getCapabilityName(type) {
switch(type) {
case "switches":
return "Switch"
case "alarms":
return "Alarm"
case "locks":
return "Lock"
default:
return type
}
}
/**
* Constructing the map over here of
* supported commands by device capability
* @return a map of device capability -> supported commands
*/
def getDeviceCapabilityCommands(deviceCapabilities) {
def map = [:]
deviceCapabilities.collect {
map[it.name] = it.commands.collect{ it.name.toString() }
}
return map
}
def show() {
def type = params.deviceType
def devices = settings[type]

View File

@@ -23,9 +23,9 @@
'''Minimum time between messages (optional, defaults to every message)'''.ko=메시지 전송 간격 설정
'''If outside the US please make sure to enter the proper country code'''.ko=미국 이외 국가에 거주한다면 국가 코드와 함께 입력하여 주세요.
'''Water Sensor Wet'''.ko=누수가 감지되었을 때
'''{{ triggerEvent.linkText }} has arrived at the {{ location.name }}'''.ko={{ triggerEvent.linkText }}님이 {{ location.name }}에 도착했습니다
'''{{ triggerEvent.linkText }} has arrived at {{ location.name }}'''.ko={{ triggerEvent.linkText }}님이 {{ location.name }}에 도착했습니다
'''{{ triggerEvent.linkText }} has left the {{ location.name }}'''.ko={{ triggerEvent.linkText }}님이 {{ location.name }}을(를) 떠났습니다
'''{{ triggerEvent.linkText }} has left {{ location.name }}'''.ko={{ triggerEvent.linkText }}님이 {{ location.name }}을(를) 떠났습니다
'''{{ triggerEvent.linkText }} has arrived at the {{ location.name }}'''.ko={{ location.name }}에 {{ triggerEvent.linkText }} 귀가
'''{{ triggerEvent.linkText }} has arrived at {{ location.name }}'''.ko={{ location.name }}에 {{ triggerEvent.linkText }} 귀가
'''{{ triggerEvent.linkText }} has left the {{ location.name }}'''.ko={{ location.name }}에서 {{ triggerEvent.linkText }} 외출
'''{{ triggerEvent.linkText }} has left {{ location.name }}'''.ko={{ location.name }}에서 {{ triggerEvent.linkText }} 외출
'''Assign a name'''.ko=이름 설정
'''Choose Modes'''.ko=상태 선택

View File

@@ -236,23 +236,22 @@ def addSwitches() {
d = getChildDevices()?.find {
it.deviceNetworkId == selectedSwitch.value.mac || it.device.getDataValue("mac") == selectedSwitch.value.mac
}
}
if (!d) {
log.debug "Creating WeMo Switch with dni: ${selectedSwitch.value.mac}"
d = addChildDevice("smartthings", "Wemo Switch", selectedSwitch.value.mac, selectedSwitch?.value.hub, [
"label": selectedSwitch?.value?.name ?: "Wemo Switch",
"data": [
"mac": selectedSwitch.value.mac,
"ip": selectedSwitch.value.ip,
"port": selectedSwitch.value.port
]
])
def ipvalue = convertHexToIP(selectedSwitch.value.ip)
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
} else {
log.debug "found ${d.displayName} with id $dni already exists"
if (!d) {
log.debug "Creating WeMo Switch with dni: ${selectedSwitch.value.mac}"
d = addChildDevice("smartthings", "Wemo Switch", selectedSwitch.value.mac, selectedSwitch?.value.hub, [
"label": selectedSwitch?.value?.name ?: "Wemo Switch",
"data": [
"mac": selectedSwitch.value.mac,
"ip": selectedSwitch.value.ip,
"port": selectedSwitch.value.port
]
])
def ipvalue = convertHexToIP(selectedSwitch.value.ip)
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
} else {
log.debug "found ${d.displayName} with id $dni already exists"
}
}
}
}
@@ -267,23 +266,22 @@ def addMotions() {
d = getChildDevices()?.find {
it.deviceNetworkId == selectedMotion.value.mac || it.device.getDataValue("mac") == selectedMotion.value.mac
}
}
if (!d) {
log.debug "Creating WeMo Motion with dni: ${selectedMotion.value.mac}"
d = addChildDevice("smartthings", "Wemo Motion", selectedMotion.value.mac, selectedMotion?.value.hub, [
"label": selectedMotion?.value?.name ?: "Wemo Motion",
"data": [
"mac": selectedMotion.value.mac,
"ip": selectedMotion.value.ip,
"port": selectedMotion.value.port
]
])
def ipvalue = convertHexToIP(selectedMotion.value.ip)
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
} else {
log.debug "found ${d.displayName} with id $dni already exists"
if (!d) {
log.debug "Creating WeMo Motion with dni: ${selectedMotion.value.mac}"
d = addChildDevice("smartthings", "Wemo Motion", selectedMotion.value.mac, selectedMotion?.value.hub, [
"label": selectedMotion?.value?.name ?: "Wemo Motion",
"data": [
"mac": selectedMotion.value.mac,
"ip": selectedMotion.value.ip,
"port": selectedMotion.value.port
]
])
def ipvalue = convertHexToIP(selectedMotion.value.ip)
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
log.debug "Created ${d.displayName} with id: ${d.id}, dni: ${d.deviceNetworkId}"
} else {
log.debug "found ${d.displayName} with id $dni already exists"
}
}
}
}
@@ -298,23 +296,22 @@ def addLightSwitches() {
d = getChildDevices()?.find {
it.deviceNetworkId == selectedLightSwitch.value.mac || it.device.getDataValue("mac") == selectedLightSwitch.value.mac
}
}
if (!d) {
log.debug "Creating WeMo Light Switch with dni: ${selectedLightSwitch.value.mac}"
d = addChildDevice("smartthings", "Wemo Light Switch", selectedLightSwitch.value.mac, selectedLightSwitch?.value.hub, [
"label": selectedLightSwitch?.value?.name ?: "Wemo Light Switch",
"data": [
"mac": selectedLightSwitch.value.mac,
"ip": selectedLightSwitch.value.ip,
"port": selectedLightSwitch.value.port
]
])
def ipvalue = convertHexToIP(selectedLightSwitch.value.ip)
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
log.debug "created ${d.displayName} with id $dni"
} else {
log.debug "found ${d.displayName} with id $dni already exists"
if (!d) {
log.debug "Creating WeMo Light Switch with dni: ${selectedLightSwitch.value.mac}"
d = addChildDevice("smartthings", "Wemo Light Switch", selectedLightSwitch.value.mac, selectedLightSwitch?.value.hub, [
"label": selectedLightSwitch?.value?.name ?: "Wemo Light Switch",
"data": [
"mac": selectedLightSwitch.value.mac,
"ip": selectedLightSwitch.value.ip,
"port": selectedLightSwitch.value.port
]
])
def ipvalue = convertHexToIP(selectedLightSwitch.value.ip)
d.sendEvent(name: "currentIP", value: ipvalue, descriptionText: "IP is ${ipvalue}")
log.debug "created ${d.displayName} with id $dni"
} else {
log.debug "found ${d.displayName} with id $dni already exists"
}
}
}
}