1
+ /**
2
+ * Copyright 2017 SmartThings
3
+ *
4
+ * Simulates a dimmer switch, including physical operation
5
+ *
6
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7
+ * in compliance with the License. You may obtain a copy of the License at:
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
12
+ * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
13
+ * for the specific language governing permissions and limitations under the License.
14
+ *
15
+ */
16
+ metadata {
17
+ definition (name : " Simulated Dimmer Switch" , namespace : " smartthings/testing" , author : " SmartThings" ) {
18
+ capability " Actuator"
19
+ capability " Sensor"
20
+
21
+ capability " Switch"
22
+ capability " Switch Level"
23
+ capability " Refresh"
24
+ capability " Configuration"
25
+
26
+ command " onPhysical"
27
+ command " offPhysical"
28
+ command " setLevelPhysical"
29
+ }
30
+
31
+ preferences {
32
+ }
33
+
34
+ tiles(scale : 2 ) {
35
+ multiAttributeTile(name :" switch" , type : " lighting" , width : 6 , height : 4 , canChangeIcon : true ){
36
+ tileAttribute (" device.switch" , key : " PRIMARY_CONTROL" ) {
37
+ attributeState " on" , label :' ${name}' , action :" switch.off" , icon :" st.Home.home30" , backgroundColor :" #00A0DC" , nextState :" turningOff"
38
+ attributeState " off" , label :' ${name}' , action :" switch.on" , icon :" st.Home.home30" , backgroundColor :" #FFFFFF" , nextState :" turningOn" , defaultState : true
39
+ attributeState " turningOn" , label :' Turning On' , action :" switch.off" , icon :" st.Home.home30" , backgroundColor :" #00A0DC" , nextState :" turningOn"
40
+ attributeState " turningOff" , label :' Turning Off' , action :" switch.on" , icon :" st.Home.home30" , backgroundColor :" #FFFFFF" , nextState :" turningOff"
41
+ }
42
+ tileAttribute (" device.level" , key : " SLIDER_CONTROL" ) {
43
+ attributeState " level" , action : " setLevel"
44
+ }
45
+ tileAttribute (" brightnessLabel" , key : " SECONDARY_CONTROL" ) {
46
+ attributeState " Brightness" , label : ' ${name}' , defaultState : true
47
+ }
48
+ }
49
+
50
+
51
+ valueTile(" physicalLabel" , " device.switch" , width : 2 , height : 2 , decoration : " flat" ) {
52
+ state " label" , label : " Simulate\n Physical\n Operations" , defaultState : true
53
+ }
54
+ standardTile(" physicalOn" , " device.switch" , width : 2 , height : 2 , decoration : " flat" ) {
55
+ state " default" , label : " Physical On" , action : " onPhysical" , icon : " st.Home.home30" , backgroundColor : " #ffffff"
56
+ }
57
+ standardTile(" physicalOff" , " device.switch" , width : 2 , height : 2 , decoration : " flat" ) {
58
+ state " default" , label : " Physical Off" , action : " offPhysical" , icon : " st.Home.home30" , backgroundColor : " #ffffff"
59
+ }
60
+
61
+ valueTile(" physicalLevelLabel" , " device.switch" , width : 2 , height : 1 , decoration : " flat" ) {
62
+ state " label" , label : " Physical Level" , defaultState : true
63
+ }
64
+ controlTile(" physicalLevelSlider" , " device.level" , " slider" , width : 4 , height : 1 , inactiveLabel : false , range : " (1..99)" ) {
65
+ state " physicalLevel" , action : " setLevelPhysical"
66
+ }
67
+
68
+ standardTile(" refresh" , " device.switch" , width : 1 , height : 1 , inactiveLabel : false , decoration : " flat" ) {
69
+ state " default" , label : " " , action :" refresh.refresh" , icon :" st.secondary.refresh"
70
+ }
71
+ valueTile(" reset" , " device.switch" , inactiveLabel : false , decoration : " flat" , width : 1 , height : 1 ) {
72
+ state " default" , label : " Reset" , action : " configure"
73
+ }
74
+
75
+ main([" switch" ])
76
+ details([" switch" , " physicalLabel" , " physicalOn" , " physicalOff" , " physicalLevelLabel" , " physicalLevelSlider" , " refresh" , " reset" ])
77
+
78
+ }
79
+ }
80
+
81
+ // parse events into attributes
82
+ def parse (String description ) {
83
+ log. trace " parse $description "
84
+ def parsedEvents
85
+ def pair = description?. split(" :" )
86
+ if (! pair || pair. length < 2 ) {
87
+ log. warn " parse() could not extract an event name and value from '$description '"
88
+ } else {
89
+ String name = pair[0 ]?. trim()
90
+ if (name) {
91
+ name = name. replaceAll(~/ \W / , " _" ). replaceAll(~/ _{2,}?/ , " _" )
92
+ }
93
+ parsedEvents = createEvent(name : name, value : pair[1 ]?. trim())
94
+ }
95
+ return parsedEvents
96
+ }
97
+
98
+ def installed () {
99
+ log. trace " Executing 'installed'"
100
+ initialize()
101
+ }
102
+
103
+ def updated () {
104
+ log. trace " Executing 'updated'"
105
+ initialize()
106
+ }
107
+
108
+ //
109
+ // command methods
110
+ //
111
+ def refresh () {
112
+ log. trace " Executing 'refresh'"
113
+ // ummm.... not much to do here without a physical device
114
+ }
115
+
116
+ def configure () {
117
+ log. trace " Executing 'configure'"
118
+ initialize()
119
+ }
120
+
121
+ def on () {
122
+ log. trace " Executing 'on'"
123
+ turnOn()
124
+ }
125
+
126
+ def off () {
127
+ log. trace " Executing 'off'"
128
+ turnOff()
129
+ }
130
+
131
+ def setLevel (value ) {
132
+ log. trace " Executing setLevel $value "
133
+ Map levelEventMap = buildSetLevelEvent(value)
134
+ if (levelEventMap. value == 0 ) {
135
+ turnOff()
136
+ // notice that we don't set the level to 0'
137
+ } else {
138
+ implicitOn()
139
+ sendEvent(levelEventMap)
140
+ }
141
+ }
142
+
143
+ def setLevel (value , duration ) {
144
+ log. trace " Executing setLevel $value (ignoring duration)"
145
+ setLevel(value)
146
+ }
147
+
148
+ private initialize () {
149
+ log. trace " Executing 'initialize'"
150
+ sendEvent(name : " switch" , value : " off" )
151
+ sendEvent(name : " level" , value : 100 )
152
+ }
153
+
154
+ private Map buildSetLevelEvent (value ) {
155
+ def intValue = value as Integer
156
+ def newLevel = Math . max(Math . min(intValue, 99 ), 0 )
157
+ Map eventMap = [name : " level" , value : newLevel, unit : " %" ]
158
+ return eventMap
159
+ }
160
+
161
+ /**
162
+ * Turns device on if it is not already on
163
+ */
164
+ private implicitOn () {
165
+ if (device. currentValue(" switch" ) != " on" ) {
166
+ turnOn()
167
+ }
168
+ }
169
+
170
+ /*
171
+ * no-frills turn-on, no log, no simulation
172
+ */
173
+ private turnOn () {
174
+ sendEvent(name : " switch" , value : " on" )
175
+ }
176
+
177
+ /**
178
+ * no-frills turn-off, no log, no simulation
179
+ */
180
+ private turnOff () {
181
+ sendEvent(name : " switch" , value : " off" )
182
+ }
183
+
184
+ // Generate pretend physical events
185
+ private onPhysical () {
186
+ log. trace " Executing 'onPhysical'"
187
+ sendEvent(name : " switch" , value : " on" , type : " physical" )
188
+ }
189
+
190
+ private offPhysical () {
191
+ log. trace " Executing 'offPhysical'"
192
+ sendEvent(name : " switch" , value : " off" , type : " physical" )
193
+ }
194
+
195
+ private setLevelPhysical (value ) {
196
+ log. trace " Executing 'setLevelPhysical'"
197
+ Map eventMap = buildSetLevelEvent(value)
198
+ if (eventMap. value == 0 ) eventMap. value = 1 // can't turn it off by physically setting level
199
+ eventMap. type = " physical"
200
+ sendEvent(eventMap)
201
+ }
0 commit comments