Commit #8: New version of extractor with running the preferences method make things...
[smartthings-infrastructure.git] / Test / Test.groovy
1 //
2 //import libraries
3 import groovy.transform.Field
4
5 //import classes
6 public class Switches {
7         int deviceNumbers       
8         List switches
9         def sendEvent
10
11         //If we have only one device
12         private int id = 40
13         private String label = "switch"
14         private String displayName = "switch"
15         private String switchState = "off"
16         private String currentSwitch = "off"
17         private int currentLevel = 50
18         private String switchLatestValue = "off"
19
20         Switches(Closure sendEvent, int deviceNumbers) {
21                 this.sendEvent = sendEvent
22                 this.deviceNumbers = deviceNumbers
23                 this.switches = []
24                 for (int i = 0;i < deviceNumbers;i++) {
25                         switches.add(new Switch(sendEvent, i+40, label+i.toString(), displayName+i.toString(), this.switchState, this.currentSwitch, this.currentLevel, this.switchLatestValue))
26                 }
27         }
28
29         //Methods for closures
30         def count(Closure Input) {
31                 switches.count(Input)
32         }
33         def size() {
34                 switches.size()
35         }
36         def each(Closure Input) {
37                 switches.each(Input)
38         }
39
40         //By Apps
41         def setLevel(int level) {
42                 switches*.setLevel(level)
43         }
44
45         def on() {
46                 switches*.on()
47         }
48
49         def on(LinkedHashMap metaData) {
50                 switches*.on()
51         }
52
53         def off() {
54                 switches*.off()
55         }
56
57         def off(LinkedHashMap metaData) {
58                 switches*.off()
59         }
60
61         //By Model Checker
62         def setValue(LinkedHashMap eventDataMap) {
63                 switches[eventDataMap["deviceId"]].setValue(eventDataMap["value"])
64                 if (deviceNumbers == 1)
65                         this.switchState = switches[eventDataMap["deviceId"]].switchState
66                         this.switchLatestValue = switches[eventDataMap["deviceId"]].switchLatestValue
67                 sendEvent(eventDataMap)
68         }
69
70
71         def currentValue(String deviceFeature) {
72                 if (deviceNumbers == 1)
73                         switches[0].currentValue(deviceFeature)
74                 else
75                         switches*.currentValue(deviceFeature)
76         }
77
78         def latestValue(String deviceFeature) {
79                 if (deviceNumbers == 1)
80                         switches[0].latestValue(deviceFeature)
81                 else
82                         switches*.latestValue(deviceFeature)
83         }
84
85         def getAt(int ix) {
86                 switches[ix]
87         }
88 }
89 public class Switch {
90         private int id
91         private String label
92         private String displayName
93         private String switchState
94         private String currentSwitch
95         private int currentLevel
96         private String switchLatestValue
97         def sendEvent   
98         
99
100         Switch(Closure sendEvent, int id, String label, String displayName, String switchState, String currentSwitch, int currentLevel, String switchLatestValue) {
101                 this.sendEvent = sendEvent
102                 this.currentSwitch = currentSwitch
103                 this.currentLevel = currentLevel
104                 this.id = id
105                 this.label = label
106                 this.displayName = displayName
107                 this.switchState = switchState
108                 this.switchLatestValue = switchLatestValue
109         }
110
111         //By Apps
112         def setLevel(int level) {
113                 println("the switch with id:$id is setted to level $level!")
114                 this.currentLevel = level
115         }
116
117         def on() {
118                 println("the switch with id:$id is on!")
119                 this.switchLatestValue = this.switchState
120                 this.switchState = "on"
121                 this.currentSwitch = "on"
122                 sendEvent([name: "switch", value: "on", deviceId: this.id, descriptionText: "",
123                     displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
124         }
125
126         def on(LinkedHashMap metaData) {
127                 println("the switch with id:$id is on!")
128                 this.switchLatestValue = this.switchState
129                 this.switchState = "on"
130                 this.currentSwitch = "on"
131                 sendEvent([name: "switch", value: "on", deviceId: this.id, descriptionText: "",
132                            displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
133         }
134
135         def off() {
136                 println("the switch with id:$id is off!")
137                 this.switchLatestValue = this.switchState
138                 this.switchState = "off"
139                 this.currentSwitch = "off"
140                 sendEvent([name: "switch", value: "off", deviceId: this.id, descriptionText: "",
141                     displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
142         }
143
144         def off(LinkedHashMap metaData) {
145                 println("the switch with id:$id is off!")
146                 this.switchLatestValue = this.switchState
147                 this.switchState = "off"
148                 this.currentSwitch = "off"
149                 sendEvent([name: "switch", value: "off", deviceId: this.id, descriptionText: "",
150                            displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
151         }
152
153         //By Model Checker
154         def setValue(String value) {
155                 println("the switch with id:$id is $value!")
156                 this.switchLatestValue = this.switchState
157                 this.switchState = value
158                 this.currentSwitch = value
159         }
160         
161         def currentValue(String deviceFeature) {
162                 if (deviceFeature == "switch") {
163                         return switchState
164                 }
165         }
166
167         def latestValue(String deviceFeature) {
168                 if (deviceFeature == "switch") {
169                         return switchLatestValue
170                 }
171         }
172 }
173
174 @Field def switchObject
175
176 //input "",""
177 def input(String name, String type) {
178         switch(type) {
179                 case "capability.lock":
180                         break
181                 case "capability.alarm":
182                         break
183                 case "capability.battery":
184                         break
185                 case "capability.beacon":
186                         break
187                 case "capability.carbonMonoxideDetector":
188                         break
189                 case "capability.colorControl":
190                         break
191                 case "capability.contactSensor":
192                         break
193                 case "capability.doorControl":
194                         break
195                 case "capability.energyMeter":
196                         break
197                 case "capability.illuminanceMeasurement":
198                         break
199                 case "capability.accelerationSensor":
200                         break
201                 case "capability.motionSensor":
202                         break
203                 case "capability.musicPlayer":
204                         break
205                 case "capability.powerMeter":
206                         break
207                 case "capability.presenceSensor":
208                         break
209                 case "capability.relativeHumidityMeasurement":
210                         break
211                 case "capability.relaySwitch":
212                         break
213                 case "capability.sleepSensor":
214                         break
215                 case "capability.smokeDetector":
216                         break
217                 case "capability.stepSensor":
218                         break
219                 case "capability.switch":
220                         break
221                 case "capability.switchLevel":
222                         break
223                 case "capability.temperatureMeasurement":
224                         break   
225                 case "capability.thermostat":
226                         break
227                 case "capability.valve":
228                         break
229                 case "capability.waterSensor":
230                         break
231                 case "capability.touchSensor":
232                         break
233                 case "capability.imageCapture":
234                         break
235                 case "device.mobilePresence":
236                         break
237                 case "device.aeonKeyFob":
238                         break
239                 case "mode":
240                         break
241                 case "decimal":
242                         break
243                 case "text":
244                         break
245                 case "number":
246                         break
247                 case "time":
248                         break
249                 case "enum":
250                         break
251                 case "bool":
252                         break
253                 case "phone":
254                         break
255                 case "contact":
256                         break
257                 default:
258                         break
259         }       
260 }
261
262 //input "","",linkedHashMap
263 def input(LinkedHashMap metaData, String name, String type) {
264         switch(type) {
265                 case "capability.lock":
266                         break
267                 case "capability.alarm":
268                         break
269                 case "capability.battery":
270                         break
271                 case "capability.beacon":
272                         break
273                 case "capability.carbonMonoxideDetector":
274                         break
275                 case "capability.colorControl":
276                         break
277                 case "capability.contactSensor":
278                         break
279                 case "capability.doorControl":
280                         break
281                 case "capability.energyMeter":
282                         break
283                 case "capability.illuminanceMeasurement":
284                         break
285                 case "capability.accelerationSensor":
286                         break
287                 case "capability.motionSensor":
288                         break
289                 case "capability.musicPlayer":
290                         break
291                 case "capability.powerMeter":
292                         break
293                 case "capability.presenceSensor":
294                         break
295                 case "capability.relativeHumidityMeasurement":
296                         break
297                 case "capability.relaySwitch":
298                         break
299                 case "capability.sleepSensor":
300                         break
301                 case "capability.smokeDetector":
302                         break
303                 case "capability.stepSensor":
304                         break
305                 case "capability.switch":
306                         break
307                 case "capability.switchLevel":
308                         break
309                 case "capability.temperatureMeasurement":
310                         break   
311                 case "capability.thermostat":
312                         break
313                 case "capability.valve":
314                         break
315                 case "capability.waterSensor":
316                         break
317                 case "capability.touchSensor":
318                         break
319                 case "capability.imageCapture":
320                         break
321                 case "device.mobilePresence":
322                         break
323                 case "device.aeonKeyFob":
324                         break
325                 case "mode":
326                         break
327                 case "decimal":
328                         break
329                 case "text":
330                         break
331                 case "number":
332                         break
333                 case "time":
334                         break
335                 case "enum":
336                         break
337                 case "bool":
338                         break
339                 case "phone":
340                         break
341                 case "contact":
342                         break
343                 default:
344                         break
345         }
346 }
347 //input linkedHashMap
348 def input(LinkedHashMap metaData) {
349         switch(metaData['type']) {
350                 case "capability.lock":
351                         break
352                 case "capability.alarm":
353                         break
354                 case "capability.battery":
355                         break
356                 case "capability.beacon":
357                         break
358                 case "capability.carbonMonoxideDetector":
359                         break
360                 case "capability.colorControl":
361                         break
362                 case "capability.contactSensor":
363                         break
364                 case "capability.doorControl":
365                         break
366                 case "capability.energyMeter":
367                         break
368                 case "capability.illuminanceMeasurement":
369                         break
370                 case "capability.accelerationSensor":
371                         break
372                 case "capability.motionSensor":
373                         break
374                 case "capability.musicPlayer":
375                         break
376                 case "capability.powerMeter":
377                         break
378                 case "capability.presenceSensor":
379                         break
380                 case "capability.relativeHumidityMeasurement":
381                         break
382                 case "capability.relaySwitch":
383                         break
384                 case "capability.sleepSensor":
385                         break
386                 case "capability.smokeDetector":
387                         break
388                 case "capability.stepSensor":
389                         break
390                 case "capability.switch":
391                         break
392                 case "capability.switchLevel":
393                         break
394                 case "capability.temperatureMeasurement":
395                         break   
396                 case "capability.thermostat":
397                         break
398                 case "capability.valve":
399                         break
400                 case "capability.waterSensor":
401                         break
402                 case "capability.touchSensor":
403                         break
404                 case "capability.imageCapture":
405                         break
406                 case "device.mobilePresence":
407                         break
408                 case "device.aeonKeyFob":
409                         break
410                 case "mode":
411                         break
412                 case "decimal":
413                         break
414                 case "text":
415                         break
416                 case "number":
417                         break
418                 case "time":
419                         break
420                 case "enum":
421                         break
422                 case "bool":
423                         break
424                 case "phone":
425                         break
426                 case "contact":
427                         break
428                 default:
429                         break
430         }       
431 }
432
433 def definition(LinkedHashMap metaData) {
434         println("///Just some information///")
435 }
436
437 def preferences(Closure inputData) {
438         find(inputData) //Run the closure to extract pages/sections/inputMethods
439 }
440
441 def page(LinkedHashMap metaData, Closure inputData) {
442         if (metaData.containsKey('name'))
443                 println(metaData['name'])
444         if (metaData.containsKey('title'))
445                 println(metaData['title'])
446
447         find(inputData) //Run the closure to extract sections/inputMethods
448 }
449
450 def page(LinkedHashMap metaData) {
451         def nameOfFunction = metaData['name']
452         "$nameOfFunction"() //Call the page
453         
454 }
455
456 def dynamicPage(LinkedHashMap metaData, Closure inputData) {
457         if (metaData.containsKey('name'))
458                 println(metaData['name'])
459         if (metaData.containsKey('title'))
460                 println(metaData['title'])
461
462         //find(inputData) //Run the closure to extract sections/inputMethods
463 }
464
465 def section(String title, Closure inputData) {
466         println(title)
467         find(inputData) //Run the closure to extract inputMethods
468         switchObject = "switch1"
469         this[switchObject] = new Switches({}, 1)
470         switch1.on()
471 }
472
473
474 ////////////////
475 definition(
476     name: "NFC Tag Toggle",
477     namespace: "smartthings",
478     author: "SmartThings",
479     description: "Allows toggling of a switch, lock, or garage door based on an NFC Tag touch event",
480     category: "SmartThings Internal",
481     iconUrl: "https://s3.amazonaws.com/smartapp-icons/Developers/nfc-tag-executor.png",
482     iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Developers/nfc-tag-executor@2x.png",
483     iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Developers/nfc-tag-executor@2x.png")
484
485
486 preferences {
487     page(name: "pageOne", title: "Device selection", uninstall: true, nextPage: "pageTwo") {
488         section("Select an NFC tag") {
489             input "tag", "capability.touchSensor", title: "NFC Tag"
490         }
491         section("Select devices to control") {
492             input "switch1", "capability.switch", title: "Light or switch", required: false, multiple: true
493             input "lock", "capability.lock", title: "Lock", required: false, multiple: true
494             input "garageDoor", "capability.doorControl", title: "Garage door controller", required: false, multiple: true
495         }
496     }
497     
498     page(name: "pageTwo", title: "Master devices", install: true, uninstall: true)
499 }
500
501 switch1.on()
502
503 def pageTwo() {
504         dynamicPage(name: "pageTwo") {
505         section("If set, the state of these devices will be toggled each time the tag is touched, " + 
506                 "e.g. a light that's on will be turned off and one that's off will be turned on, " +
507                 "other devices of the same type will be set to the same state as their master device. " +
508                 "If no master is designated then the majority of devices of the same type will be used " +
509                 "to determine whether to turn on or off the devices.") {
510             
511             if (switch1 || masterSwitch) {
512                 input "masterSwitch", "enum", title: "Master switch", options: switch1.collect{[(it.id): it.displayName]}, required: false
513             }
514             if (lock || masterLock) {
515                 input "masterLock", "enum", title: "Master lock", options: lock.collect{[(it.id): it.displayName]}, required: false
516             }
517             if (garageDoor || masterDoor) {
518                 input "masterDoor", "enum", title: "Master door", options: garageDoor.collect{[(it.id): it.displayName]}, required: false
519             }            
520                 }
521                 section([mobileOnly:true]) {
522                         label title: "Assign a name", required: false
523                         mode title: "Set for specific mode(s)", required: false
524                 }        
525     }
526 }
527
528 def installed() {
529         log.debug "Installed with settings: ${settings}"
530         initialize()
531 }
532
533 def updated() {
534         log.debug "Updated with settings: ${settings}"
535         unsubscribe()
536         initialize()
537 }
538
539 def initialize() {
540         subscribe tag, "nfcTouch", touchHandler
541         subscribe app, touchHandler
542 }
543
544 private currentStatus(devices, master, attribute) {
545         log.trace "currentStatus($devices, $master, $attribute)"
546         def result = null
547         if (master) {
548         result = devices.find{it.id == master}?.currentValue(attribute)
549     }
550     else {
551         def map = [:]
552         devices.each {
553                 def value = it.currentValue(attribute)
554             map[value] = (map[value] ?: 0) + 1
555             log.trace "$it.displayName: $value"
556         }
557         log.trace map
558         result = map.collect{it}.sort{it.value}[-1].key
559     }
560     log.debug "$attribute = $result"
561     result
562 }
563
564 def touchHandler(evt) {
565         log.trace "touchHandler($evt.descriptionText)"
566     if (switch1) {
567         def status = currentStatus(switch1, masterSwitch, "switch")
568         switch1.each {
569             if (status == "on") {
570                 it.off()
571             }
572             else {
573                 it.on()
574             }
575         }
576     }
577     
578     if (lock) {
579         def status = currentStatus(lock, masterLock, "lock")
580         lock.each {
581             if (status == "locked") {
582                 lock.unlock()
583             }
584             else {
585                 lock.lock()
586             }
587         }
588     }
589     
590     if (garageDoor) {
591         def status = currentStatus(garageDoor, masterDoor, "status")
592         garageDoor.each {
593                 if (status == "open") {
594                 it.close()
595             }
596             else {
597                 it.open()
598             }
599         }
600     }
601 }
602