// //import libraries import groovy.transform.Field //import classes public class Switches { int deviceNumbers List switches def sendEvent //If we have only one device private int id = 40 private String label = "switch" private String displayName = "switch" private String switchState = "off" private String currentSwitch = "off" private int currentLevel = 50 private String switchLatestValue = "off" Switches(Closure sendEvent, int deviceNumbers) { this.sendEvent = sendEvent this.deviceNumbers = deviceNumbers this.switches = [] for (int i = 0;i < deviceNumbers;i++) { switches.add(new Switch(sendEvent, i+40, label+i.toString(), displayName+i.toString(), this.switchState, this.currentSwitch, this.currentLevel, this.switchLatestValue)) } } //Methods for closures def count(Closure Input) { switches.count(Input) } def size() { switches.size() } def each(Closure Input) { switches.each(Input) } //By Apps def setLevel(int level) { switches*.setLevel(level) } def on() { switches*.on() } def on(LinkedHashMap metaData) { switches*.on() } def off() { switches*.off() } def off(LinkedHashMap metaData) { switches*.off() } //By Model Checker def setValue(LinkedHashMap eventDataMap) { switches[eventDataMap["deviceId"]].setValue(eventDataMap["value"]) if (deviceNumbers == 1) this.switchState = switches[eventDataMap["deviceId"]].switchState this.switchLatestValue = switches[eventDataMap["deviceId"]].switchLatestValue sendEvent(eventDataMap) } def currentValue(String deviceFeature) { if (deviceNumbers == 1) switches[0].currentValue(deviceFeature) else switches*.currentValue(deviceFeature) } def latestValue(String deviceFeature) { if (deviceNumbers == 1) switches[0].latestValue(deviceFeature) else switches*.latestValue(deviceFeature) } def getAt(int ix) { switches[ix] } } public class Switch { private int id private String label private String displayName private String switchState private String currentSwitch private int currentLevel private String switchLatestValue def sendEvent Switch(Closure sendEvent, int id, String label, String displayName, String switchState, String currentSwitch, int currentLevel, String switchLatestValue) { this.sendEvent = sendEvent this.currentSwitch = currentSwitch this.currentLevel = currentLevel this.id = id this.label = label this.displayName = displayName this.switchState = switchState this.switchLatestValue = switchLatestValue } //By Apps def setLevel(int level) { println("the switch with id:$id is setted to level $level!") this.currentLevel = level } def on() { println("the switch with id:$id is on!") this.switchLatestValue = this.switchState this.switchState = "on" this.currentSwitch = "on" sendEvent([name: "switch", value: "on", deviceId: this.id, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) } def on(LinkedHashMap metaData) { println("the switch with id:$id is on!") this.switchLatestValue = this.switchState this.switchState = "on" this.currentSwitch = "on" sendEvent([name: "switch", value: "on", deviceId: this.id, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) } def off() { println("the switch with id:$id is off!") this.switchLatestValue = this.switchState this.switchState = "off" this.currentSwitch = "off" sendEvent([name: "switch", value: "off", deviceId: this.id, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) } def off(LinkedHashMap metaData) { println("the switch with id:$id is off!") this.switchLatestValue = this.switchState this.switchState = "off" this.currentSwitch = "off" sendEvent([name: "switch", value: "off", deviceId: this.id, descriptionText: "", displayed: true, linkText: "", isStateChange: false, unit: "", data: []]) } //By Model Checker def setValue(String value) { println("the switch with id:$id is $value!") this.switchLatestValue = this.switchState this.switchState = value this.currentSwitch = value } def currentValue(String deviceFeature) { if (deviceFeature == "switch") { return switchState } } def latestValue(String deviceFeature) { if (deviceFeature == "switch") { return switchLatestValue } } } @Field def switchObject //input "","" def input(String name, String type) { switch(type) { case "capability.lock": break case "capability.alarm": break case "capability.battery": break case "capability.beacon": break case "capability.carbonMonoxideDetector": break case "capability.colorControl": break case "capability.contactSensor": break case "capability.doorControl": break case "capability.energyMeter": break case "capability.illuminanceMeasurement": break case "capability.accelerationSensor": break case "capability.motionSensor": break case "capability.musicPlayer": break case "capability.powerMeter": break case "capability.presenceSensor": break case "capability.relativeHumidityMeasurement": break case "capability.relaySwitch": break case "capability.sleepSensor": break case "capability.smokeDetector": break case "capability.stepSensor": break case "capability.switch": break case "capability.switchLevel": break case "capability.temperatureMeasurement": break case "capability.thermostat": break case "capability.valve": break case "capability.waterSensor": break case "capability.touchSensor": break case "capability.imageCapture": break case "device.mobilePresence": break case "device.aeonKeyFob": break case "mode": break case "decimal": break case "text": break case "number": break case "time": break case "enum": break case "bool": break case "phone": break case "contact": break default: break } } //input "","",linkedHashMap def input(LinkedHashMap metaData, String name, String type) { switch(type) { case "capability.lock": break case "capability.alarm": break case "capability.battery": break case "capability.beacon": break case "capability.carbonMonoxideDetector": break case "capability.colorControl": break case "capability.contactSensor": break case "capability.doorControl": break case "capability.energyMeter": break case "capability.illuminanceMeasurement": break case "capability.accelerationSensor": break case "capability.motionSensor": break case "capability.musicPlayer": break case "capability.powerMeter": break case "capability.presenceSensor": break case "capability.relativeHumidityMeasurement": break case "capability.relaySwitch": break case "capability.sleepSensor": break case "capability.smokeDetector": break case "capability.stepSensor": break case "capability.switch": break case "capability.switchLevel": break case "capability.temperatureMeasurement": break case "capability.thermostat": break case "capability.valve": break case "capability.waterSensor": break case "capability.touchSensor": break case "capability.imageCapture": break case "device.mobilePresence": break case "device.aeonKeyFob": break case "mode": break case "decimal": break case "text": break case "number": break case "time": break case "enum": break case "bool": break case "phone": break case "contact": break default: break } } //input linkedHashMap def input(LinkedHashMap metaData) { switch(metaData['type']) { case "capability.lock": break case "capability.alarm": break case "capability.battery": break case "capability.beacon": break case "capability.carbonMonoxideDetector": break case "capability.colorControl": break case "capability.contactSensor": break case "capability.doorControl": break case "capability.energyMeter": break case "capability.illuminanceMeasurement": break case "capability.accelerationSensor": break case "capability.motionSensor": break case "capability.musicPlayer": break case "capability.powerMeter": break case "capability.presenceSensor": break case "capability.relativeHumidityMeasurement": break case "capability.relaySwitch": break case "capability.sleepSensor": break case "capability.smokeDetector": break case "capability.stepSensor": break case "capability.switch": break case "capability.switchLevel": break case "capability.temperatureMeasurement": break case "capability.thermostat": break case "capability.valve": break case "capability.waterSensor": break case "capability.touchSensor": break case "capability.imageCapture": break case "device.mobilePresence": break case "device.aeonKeyFob": break case "mode": break case "decimal": break case "text": break case "number": break case "time": break case "enum": break case "bool": break case "phone": break case "contact": break default: break } } def definition(LinkedHashMap metaData) { println("///Just some information///") } def preferences(Closure inputData) { find(inputData) //Run the closure to extract pages/sections/inputMethods } def page(LinkedHashMap metaData, Closure inputData) { if (metaData.containsKey('name')) println(metaData['name']) if (metaData.containsKey('title')) println(metaData['title']) find(inputData) //Run the closure to extract sections/inputMethods } def page(LinkedHashMap metaData) { def nameOfFunction = metaData['name'] "$nameOfFunction"() //Call the page } def dynamicPage(LinkedHashMap metaData, Closure inputData) { if (metaData.containsKey('name')) println(metaData['name']) if (metaData.containsKey('title')) println(metaData['title']) //find(inputData) //Run the closure to extract sections/inputMethods } def section(String title, Closure inputData) { println(title) find(inputData) //Run the closure to extract inputMethods switchObject = "switch1" this[switchObject] = new Switches({}, 1) switch1.on() } //////////////// definition( name: "NFC Tag Toggle", namespace: "smartthings", author: "SmartThings", description: "Allows toggling of a switch, lock, or garage door based on an NFC Tag touch event", category: "SmartThings Internal", iconUrl: "https://s3.amazonaws.com/smartapp-icons/Developers/nfc-tag-executor.png", iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Developers/nfc-tag-executor@2x.png", iconX3Url: "https://s3.amazonaws.com/smartapp-icons/Developers/nfc-tag-executor@2x.png") preferences { page(name: "pageOne", title: "Device selection", uninstall: true, nextPage: "pageTwo") { section("Select an NFC tag") { input "tag", "capability.touchSensor", title: "NFC Tag" } section("Select devices to control") { input "switch1", "capability.switch", title: "Light or switch", required: false, multiple: true input "lock", "capability.lock", title: "Lock", required: false, multiple: true input "garageDoor", "capability.doorControl", title: "Garage door controller", required: false, multiple: true } } page(name: "pageTwo", title: "Master devices", install: true, uninstall: true) } switch1.on() def pageTwo() { dynamicPage(name: "pageTwo") { section("If set, the state of these devices will be toggled each time the tag is touched, " + "e.g. a light that's on will be turned off and one that's off will be turned on, " + "other devices of the same type will be set to the same state as their master device. " + "If no master is designated then the majority of devices of the same type will be used " + "to determine whether to turn on or off the devices.") { if (switch1 || masterSwitch) { input "masterSwitch", "enum", title: "Master switch", options: switch1.collect{[(it.id): it.displayName]}, required: false } if (lock || masterLock) { input "masterLock", "enum", title: "Master lock", options: lock.collect{[(it.id): it.displayName]}, required: false } if (garageDoor || masterDoor) { input "masterDoor", "enum", title: "Master door", options: garageDoor.collect{[(it.id): it.displayName]}, required: false } } section([mobileOnly:true]) { label title: "Assign a name", required: false mode title: "Set for specific mode(s)", required: false } } } def installed() { log.debug "Installed with settings: ${settings}" initialize() } def updated() { log.debug "Updated with settings: ${settings}" unsubscribe() initialize() } def initialize() { subscribe tag, "nfcTouch", touchHandler subscribe app, touchHandler } private currentStatus(devices, master, attribute) { log.trace "currentStatus($devices, $master, $attribute)" def result = null if (master) { result = devices.find{it.id == master}?.currentValue(attribute) } else { def map = [:] devices.each { def value = it.currentValue(attribute) map[value] = (map[value] ?: 0) + 1 log.trace "$it.displayName: $value" } log.trace map result = map.collect{it}.sort{it.value}[-1].key } log.debug "$attribute = $result" result } def touchHandler(evt) { log.trace "touchHandler($evt.descriptionText)" if (switch1) { def status = currentStatus(switch1, masterSwitch, "switch") switch1.each { if (status == "on") { it.off() } else { it.on() } } } if (lock) { def status = currentStatus(lock, masterLock, "lock") lock.each { if (status == "locked") { lock.unlock() } else { lock.lock() } } } if (garageDoor) { def status = currentStatus(garageDoor, masterDoor, "status") garageDoor.each { if (status == "open") { it.close() } else { it.open() } } } }