Some minor changes in events' format
authoramiraj <amiraj.95@uci.edu>
Mon, 29 Jul 2019 23:20:45 +0000 (16:20 -0700)
committeramiraj <amiraj.95@uci.edu>
Mon, 29 Jul 2019 23:20:45 +0000 (16:20 -0700)
17 files changed:
AllEvents [deleted file]
Extractor/App1/App1.groovy
Extractor/App1/extractedFunctionsApp1.groovy
Extractor/App1/extractedObjectsApp1.groovy
Extractor/App1/extractedObjectsConstructorApp1.groovy
Extractor/App2/App2.groovy
Extractor/App2/extractedFunctionsApp2.groovy
Extractor/App2/extractedObjectsApp2.groovy
Extractor/App2/extractedObjectsConstructorApp2.groovy
Extractor/extractorFile.groovy
SameFeatureDifferentDevices [new file with mode: 0644]
Switch/Switch.groovy
SwitchLevel/SwitchLevel.groovy
SwitchLevel/SwitchLevels.groovy
Variables and events for each device
eventSimulator/eventSimulator.groovy
main.groovy

diff --git a/AllEvents b/AllEvents
deleted file mode 100644 (file)
index f7a0eba..0000000
--- a/AllEvents
+++ /dev/null
@@ -1,206 +0,0 @@
-//
-alarmObject.setValue([name: "alarm", value: "both", deviceId: "alarmID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-alarmObject.setValue([name: "alarm", value: "siren", deviceId: "alarmID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-alarmObject.setValue([name: "alarm", value: "strobe", deviceId: "alarmID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-alarmObject.setValue([name: "alarm", value: "off", deviceId: "alarmID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-contactObject.setValue([name: "contact.closed", value: "closed", deviceId: "contactSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-contactObject.setValue([name: "contact.open", value: "open", deviceId: "contactSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-contactObject.setValue([name: "contact", value: "open", deviceId: "contactSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-contactObject.setValue([name: "contact", value: "close[d", deviceId: "contactSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-doorControlObject.setValue([name: "doorState", value: "closed", deviceId: "doorControlID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-doorControlObject.setValue([name: "doorState", value: "open", deviceId: "doorControlID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-locationObject.setValue([name: "Location", value: "away", deviceId: "locationID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-locationObject.setValue([name: "Location", value: "home", deviceId: "locationID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-locationObject.setValue([name: "Location", value: "night", deviceId: "locationID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-lockObject.setValue([name: "lock", value: "locked", deviceId: "lockID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-lockObject.setValue([name: "unlock", value: "unlocked ", deviceId: "lockID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-lockObject.setValue([name: "lock", value: "unlocked", deviceId: "lockID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-motionSensorObject.setValue([name: "motion", value: "active", deviceId: "motionSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-motionSensorObject.setValue([name: "motion", value: "inactive", deviceId: "motionSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-musicPlayerObject.setValue([name: "status", value: "playing", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-musicPlayerObject.setValue([name: "status", value: "stopped", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-musicPlayerObject.setValue([name: "status", value: "paused", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-musicPlayerObject.setValue([name: "level", value: "36"/*A number between 0 to 100 as a charge*/, deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-musicPlayerObject.setValue([name: "trackDescription", value: "someDescriptions", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-musicPlayerObject.setValue([name: "trackData", value: "someTrack", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-musicPlayerObject.setValue([name: "mute", value: "umuted", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-musicPlayerObject.setValue([name: "mute", value: "muted", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-presenceSensorObject.setValue([name: "presence", value: "present", deviceId: "presenceSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"presence":"1","dni":"mobile0"}'])
-presenceSensorObject.setValue([name: "presence", value: "not present", deviceId: "presenceSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"presence":"1","dni":"mobile0"}'])
-presenceSensorObject.setValue([name: "presence", value: "presence.present", deviceId: "presenceSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"presence":"1","dni":"mobile0"}'])
-
-smokeDetectorObject.setValue([name: "smoke", value: "clear", deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-smokeDetectorObject.setValue([name: "smoke", value: "detected", deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-smokeDetectorObject.setValue([name: "smoke", value: "tested", deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-smokeDetectorObject.setValue([name: "carbonMonoxide", value: "clear", deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-smokeDetectorObject.setValue([name: "carbonMonoxide", value: "detected", deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-smokeDetectorObject.setValue([name: "carbonMonoxide", value: "tested", deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-smokeDetectorObject.setValue([name: "battery", value: "5"/*A number between 0 to 100 as a charge*/, deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-thermostatObject.setValue([name: "thermostatMode", value: "auto", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatMode", value: "cool", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatMode", value: "emergencyHeat", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatMode", value: "heat", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatMode", value: "off", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "temperature", value: "55", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "heatingSetpoint", value: "40", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "coolingSetpoint", value: "60", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatSetpoint", value: "50", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatFanMode", value: "auto", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatFanMode", value: "fanCirculate", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatFanMode", value: "circulate", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatFanMode", value: "fanOn", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatFanMode", value: "on", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatOperatingState", value: "auto", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatOperatingState", value: "cool", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatOperatingState", value: "off", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatOperatingState", value: "emergencyHeat", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-thermostatObject.setValue([name: "thermostatOperatingState", value: "heat", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-switchObject.setValue([name: "switch", value: "off", deviceId: "switchID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-switchObject.setValue([name: "switch", value: "on", deviceId: "switchID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-appObject.setValue([name: "Touched", value: "touched", deviceId: "touchedSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-touchSensorObject.setValue([name: "nfcTouch", value: "touched", deviceId: "nfcSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-aeonKeyFobObject.setValue([name: "button", value: "pushed", deviceId: "aeonKeyFobID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-aeonKeyFobObject.setValue([name: "button", value: "held", deviceId: "aeonKeyFobID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-accelerationSensorObject.setValue([name: "acceleration", value: "active", deviceId: "accelerationSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-accelerationSensorObject.setValue([name: "acceleration", value: "inactive", deviceId: "accelerationSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-batteryObject.setValue([name: "battery", value: "50"/*number between 0 to 100 as a string*/, deviceId: "batteryID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-beaconSensorObject.setValue([name: "presence", value: "present", deviceId: "beaconeSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"presence":"1","dni":"mobile0"}'])
-beaconSensorObject.setValue([name: "presence", value: "not present", deviceId: "beaconSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"presence":"1","dni":"mobile0"}'])
-
-carbonMonoxideDetectorObject.setValue([name: "carbonMonoxide", value: "clear", deviceId: "carbonMonoxideDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-carbonMonoxideDetectorObject.setValue([name: "carbonMonoxide", value: "detected", deviceId: "carbonMonoxideDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-carbonMonoxideDetectorObject.setValue([name: "carbonMonoxide", value: "tested", deviceId: "carbonMonoxideDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-colorControlObject.setValue([name: "color", value: "red", deviceId: "colorControlID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-colorControlObject.setValue([name: "hue", value: "50", deviceId: "colorControlID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-colorControlObject.setValue([name: "saturation", value: "50", deviceId: "colorControlID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-energyMeterObject.setValue([name: "energy", value: "45"/*A number between 0 to 100 as a charge*/, deviceId: "energyMeterID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-illuminanceMeasurementObject.setValue([name: "illuminance", value: "70"/*A number between 0 to 100 as a charge*/, deviceId: "illuminanceMeasurementID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-powerMeterObject.setValue([name: "power", value: "70"/*A number between 0 to 100 as a charge*/, deviceId: "powerMeterID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-humidityMeasurementObject.setValue([name: "humidity", value: "70"/*A number between 0 to 100 as a charge*/, deviceId: "humidityMeasurementID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-switchObject.setValue([name: "switch", value: "off", deviceId: "relaySwitchID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-switchObject.setValue([name: "switch", value: "on", deviceId: "relaySwitchID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-sleepSensorObject.setValue([name: "sleeping", value: "sleeping", deviceId: "sleepSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-sleepSensorObject.setValue([name: "sleeping", value: "not sleeping", deviceId: "sleepSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-stepSensorObject.setValue([name: "goal", value: "100"/*A number*/, deviceId: "stepSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-stepSensorObject.setValue([name: "steps", value: "46"/*A number*/, deviceId: "stepSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-switchLevelObject.setValue([name: "level", value: "45"/*A number between 0 to 100*/, deviceId: "switchLevelID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-temperatureMeasurementObject.setValue([name: "temperature", value: "45"/*A number between 0 to 100*/, deviceId: "temperatureMeasurementID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-valveObject.setValue([name: "contact", value: "closed", deviceId: "valveID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-valveObject.setValue([name: "contact", value: "open", deviceId: "valveID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-
-waterSensorObject.setValue([name: "water", value: "dry", deviceId: "waterSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-waterSensorObject.setValue([name: "water", value: "wet", deviceId: "waterSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
index 49a97c3..94ec37c 100644 (file)
-/**
- *  groveStreams
- *
- *  Copyright 2014 Yves Racine
- *
- *  LinkedIn profile: ca.linkedin.com/pub/yves-racine-m-sc-a/0/406/4b/
- *
- *  Developer retains all right, title, copyright, and interest, including all copyright, patent rights, trade secret 
- *  in the Background technology. May be subject to consulting fees under the Agreement between the Developer and the Customer. 
- *  Developer grants a non exclusive perpetual license to use the Background technology in the Software developed for and delivered 
- *  to Customer under this Agreement. However, the Customer shall make no commercial use of the Background technology without
- *  Developer's written consent.
- *
- *  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. 
- *  Software Distribution is restricted and shall be done only with Developer's written approval.
- *
- *  Based on code from Jason Steele & Minollo
- *  Adapted to be compatible with MyEcobee and My Automatic devices which are available at my store:
- *          http://www.ecomatiqhomes.com/#!store/tc3yr 
- * 
- */
 definition(
-       name: "groveStreams",
-       namespace: "yracine",
-       author: "Yves Racine",
-       description: "Log to groveStreams and send data streams based on devices selection",
-       category: "My Apps",
-       iconUrl: "https://s3.amazonaws.com/smartapp-icons/Partner/ecobee.png",
-       iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Partner/ecobee@2x.png"
+    name: "Enhanced Auto Lock Door",
+    namespace: "Lock Auto Super Enhanced",
+    author: "Arnaud",
+    description: "Automatically locks a specific door after X minutes when closed  and unlocks it when open after X seconds.",
+    category: "Safety & Security",
+    iconUrl: "http://www.gharexpert.com/mid/4142010105208.jpg",
+    iconX2Url: "http://www.gharexpert.com/mid/4142010105208.jpg"
 )
 
-
-
-preferences {
-       section("About") {
-               paragraph "groveStreams, the smartapp that sends your device states to groveStreams for data correlation"
-               paragraph "Version 2.2.2" 
-               paragraph "If you like this smartapp, please support the developer via PayPal and click on the Paypal link below " 
-                       href url: "https://www.paypal.me/ecomatiqhomes",
-                               title:"Paypal donation..."
-               paragraph "Copyright©2014 Yves Racine"
-                       href url:"http://github.com/yracine/device-type.myecobee", style:"embedded", required:false, title:"More information..."  
-                               description: "http://github.com/yracine"
-       }
-       section("Log devices...") {
-               input "temperatures", "capability.temperatureMeasurement", title: "Temperatures", required: false, multiple: true
-               input "thermostats", "capability.thermostat", title: "Thermostats", required: false, multiple: true
-               //input "ecobees", "device.myEcobeeDevice", title: "Ecobees", required: false, multiple: true
-               input "automatic", "capability.presenceSensor", title: "Automatic Connected Device(s)", required: false, multiple: true
-               input "detectors", "capability.smokeDetector", title: "Smoke/CarbonMonoxide Detectors", required: false, multiple: true
-               input "humidities", "capability.relativeHumidityMeasurement", title: "Humidity sensors", required: false, multiple: true
-               input "waters", "capability.waterSensor", title: "Water sensors", required: false, multiple: true
-               input "illuminances", "capability.illuminanceMeasurement", title: "Illuminance sensor", required: false, multiple: true
-               input "locks", "capability.lock", title: "Locks", required: false, multiple: true
-               input "contacts", "capability.contactSensor", title: "Doors open/close", required: false, multiple: true
-               input "accelerations", "capability.accelerationSensor", title: "Accelerations", required: false, multiple: true
-               input "motions", "capability.motionSensor", title: "Motions", required: false, multiple: true
-               input "presence", "capability.presenceSensor", title: "Presence", required: false, multiple: true
-               input "switches", "capability.switch", title: "Switches", required: false, multiple: true
-               input "dimmerSwitches", "capability.switchLevel", title: "Dimmer Switches", required: false, multiple: true
-               input "batteries", "capability.battery", title: "Battery-powered devices", required: false, multiple: true
-               input "powers", "capability.powerMeter", title: "Power Meters", required: false, multiple: true
-               input "energys", "capability.energyMeter", title: "Energy Meters", required: false, multiple: true
-
-       }
-
-       section("GroveStreams Feed PUT API key...") {
-               input "channelKey", "text", title: "API key"
-       }
-       section("Sending data at which interval in minutes (default=5)?") {
-               input "givenInterval", "number", title: 'Send Data Interval', required: false
-       }
-}
-
-def installed() {
-       initialize()
-}
-
-def updated() {
-       unsubscribe()
-       unschedule()
-       initialize()
-}
-
-def initialize() {
-       subscribe(temperatures, "temperature", handleTemperatureEvent)
-       subscribe(humidities, "humidity", handleHumidityEvent)
-       subscribe(waters, "water", handleWaterEvent)
-       subscribe(waters, "water", handleWaterEvent)
-       subscribe(detectors, "smoke", handleSmokeEvent)
-       subscribe(detectors, "carbonMonoxide", handleCarbonMonoxideEvent)
-       subscribe(illuminances, "illuminance", handleIlluminanceEvent)
-       subscribe(contacts, "contact", handleContactEvent)
-       subscribe(locks, "lock", handleLockEvent)
-       subscribe(accelerations, "acceleration", handleAccelerationEvent)
-       subscribe(motions, "motion", handleMotionEvent)
-       subscribe(presence, "presence", handlePresenceEvent)
-       subscribe(switches, "switch", handleSwitchEvent)
-       subscribe(dimmerSwitches, "switch", handleSwitchEvent)
-       subscribe(dimmerSwitches, "level", handleSetLevelEvent)
-       subscribe(batteries, "battery", handleBatteryEvent)
-       subscribe(powers, "power", handlePowerEvent)
-       subscribe(energys, "energy", handleEnergyEvent)
-       subscribe(energys, "cost", handleCostEvent)
-       subscribe(thermostats, "heatingSetpoint", handleHeatingSetpointEvent)
-       subscribe(thermostats, "coolingSetpoint", handleCoolingSetpointEvent)
-       subscribe(thermostats, "thermostatMode", handleThermostatModeEvent)
-       subscribe(thermostats, "fanMode", handleFanModeEvent)
-       subscribe(thermostats, "thermostatOperatingState", handleThermostatOperatingStateEvent)
-       /*subscribe(ecobees, "dehumidifierMode", handleDehumidifierModeEvent)
-       subscribe(ecobees, "equipmentStatus", handleEquipmentStatusEvent)
-       subscribe(ecobees, "dehumidifierLevel", handleDehumidifierLevelEvent)
-       subscribe(ecobees, "humidifierMode", handleHumidifierModeEvent)
-       subscribe(ecobees, "humidifierLevel", handleHumidifierLevelEvent)
-       subscribe(ecobees, "fanMinOnTime", handleFanMinOnTimeEvent)
-       subscribe(ecobees, "ventilatorMode", handleVentilatorModeEvent)
-       subscribe(ecobees, "ventilatorMinOnTime", handleVentilatorMinOnTimeEvent)
-       subscribe(ecobees, "programScheduleName", handleProgramNameEvent)
-       subscribe(ecobees, "auxHeat1RuntimeDaily", handleDailyStats)
-       subscribe(ecobees, "auxHeat2RuntimeDaily", handleDailyStats)
-       subscribe(ecobees, "auxHeat3RuntimeDaily", handleDailyStats)
-       subscribe(ecobees, "compCool1RuntimeDaily", handleDailyStats)
-       subscribe(ecobees, "compCool2RuntimeDaily", handleDailyStats)
-       subscribe(ecobees, "fanRuntimeDaily", handleDailyStats)
-       subscribe(ecobees, "humidifierRuntimeDaily", handleDailyStats)
-       subscribe(ecobees, "dehumidifierRuntimeDaily", handleDailyStats)
-       subscribe(ecobees, "ventilatorRuntimeDaily", handleDailyStats)
-       subscribe(ecobees, "presence", handlePresenceEvent)
-       subscribe(ecobees, "compCool2RuntimeDaily", handleDailyStats)*/
-       subscribe(automatic, "yesterdayTripsAvgAverageKmpl",handleDailyStats)
-       subscribe(automatic, "yesterdayTripsAvgDistanceM",handleDailyStats)
-       subscribe(automatic, "yesterdayTripsAvgDurationS",handleDailyStats)
-       subscribe(automatic, "yesterdayTotalDistanceM",handleDailyStats)
-       subscribe(automatic, "yesterdayTripsAvgFuelVolumeL",handleDailyStats)
-       subscribe(automatic, "yesterdayTotalFuelVolumeL",handleDailyStats)
-       subscribe(automatic, "yesterdayTotalDurationS:",handleDailyStats)
-       subscribe(automatic, "yesterdayTotalNbTrips",handleDailyStats)
-       subscribe(automatic, "yesterdayTotalHardAccels",handleDailyStats)
-       subscribe(automatic, "yesterdayTotalHardBrakes:",handleDailyStats)
-       subscribe(automatic, "yesterdayTripsAvgScoreSpeeding",handleDailyStats)
-       subscribe(automatic, "yesterdayTripsAvgScoreEvents",handleDailyStats)
-       def queue = []
-       atomicState.queue=queue
-    
-       if (atomicState.queue==null) {
-               atomicState.queue = []
-       }    
-       atomicState?.poll = [ last: 0, rescheduled: now() ]
-
-       Integer delay  = givenInterval ?: 5 // By default, schedule processQueue every 5 min.
-       log.debug "initialize>scheduling processQueue every ${delay} minutes"
-
-       //Subscribe to different events (ex. sunrise and sunset events) to trigger rescheduling if needed
-       subscribe(location, "sunrise", rescheduleIfNeeded)
-       subscribe(location, "sunset", rescheduleIfNeeded)
-       subscribe(location, "mode", rescheduleIfNeeded)
-       subscribe(location, "sunriseTime", rescheduleIfNeeded)
-       subscribe(location, "sunsetTime", rescheduleIfNeeded)
-       subscribe(app, appTouch)
-
-       //rescheduleIfNeeded()   
-}
-
-def appTouch(evt) {
-       rescheduleIfNeeded(evt)
-       processQueue()
-       def queue = []
-       atomicState.queue=queue
-}
-
-
-def rescheduleIfNeeded(evt) {
-       if (evt) log.debug("rescheduleIfNeeded>$evt.name=$evt.value")
-       Integer delay  = givenInterval ?: 5 // By default, schedule processQueue every 5 min.
-       BigDecimal currentTime = now()    
-       BigDecimal lastPollTime = (currentTime - (atomicState?.poll["last"]?:0))  
-       if (lastPollTime != currentTime) {    
-               Double lastPollTimeInMinutes = (lastPollTime/60000).toDouble().round(1)      
-               log.info "rescheduleIfNeeded>last poll was  ${lastPollTimeInMinutes.toString()} minutes ago"
-       }
-       if (((atomicState?.poll["last"]?:0) + (delay * 60000) < currentTime) && canSchedule()) {
-               log.info "rescheduleIfNeeded>scheduling processQueue in ${delay} minutes.."
-               unschedule()  
-               schedule("14:00", processQueue)
-       }
-       // Update rescheduled state
-    
-       if (!evt) {
-               atomicState.poll["rescheduled"] = now()    
-       }        
-}    
-
-def handleTemperatureEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-
-def handleHumidityEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-
-def handleHeatingSetpointEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-def handleCoolingSetpointEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-
-def handleThermostatModeEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-def handleFanModeEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-def handleHumidifierModeEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-def handleHumidifierLevelEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-def handleDehumidifierModeEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-def handleDehumidifierLevelEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-def handleVentilatorModeEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-def handleFanMinOnTimeEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-def handleVentilatorMinOnTimeEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-
-def handleThermostatOperatingStateEvent(evt) {
-       queueValue(evt) {
-               it == "idle" ? 0 : (it == 'fan only') ? 1 : (it == 'heating') ? 2 : 3
-       }
-
-}
-def handleDailyStats(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-
-}
-def handleEquipmentStatusEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
+preferences{
+    section("Select the door lock:") {
+        input "lock1", "capability.lock", required: true
+    }
+    section("Select the door contact sensor:") {
+        input "contact", "capability.contactSensor", required: true
+    }   
+    section("Automatically lock the door when closed...") {
+        input "minutesLater", "number", title: "Delay (in minutes):", required: true
+    }
+    section("Automatically unlock the door when open...") {
+        input "secondsLater", "number", title: "Delay (in seconds):", required: true
+    }
+    section( "Notifications" ) {
+        input("recipients", "contact", title: "Send notifications to", required: false) {
+            input "phoneNumber", "phone", title: "Warn with text message (optional)", description: "Phone Number", required: false
+        }
+    }
+}
+
+def installed(){
+    initialize()
+}
+
+def updated(){
+    unsubscribe()
+    unschedule()
+    initialize()
+}
+
+def initialize(){
+    log.debug "Settings: ${settings}"
+    subscribe(lock1, "lock", doorHandler, [filterEvents: false])
+    subscribe(lock1, "unlock", doorHandler, [filterEvents: false])  
+    subscribe(contact, "contact.open", doorHandler)
+    subscribe(contact, "contact.closed", doorHandler)
+}
+
+def lockDoor(){
+    log.debug "Locking the door."
+    lock1.lock()
+    if(location.contactBookEnabled) {
+        if ( recipients ) {
+            log.debug ( "Sending Push Notification..." ) 
+            sendNotificationToContacts( "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!", recipients)
+        }
+    }
+    if (phoneNumber) {
+        log.debug("Sending text message...")
+        sendSms( phoneNumber, "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!")
+    }
+}
+
+def unlockDoor(){
+    log.debug "Unlocking the door."
+    lock1.unlock()
+    if(location.contactBookEnabled) {
+        if ( recipients ) {
+            log.debug ( "Sending Push Notification..." ) 
+            sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!", recipients)
+        }
+    }
+    if ( phoneNumber ) {
+        log.debug("Sending text message...")
+        sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!")
+    }
+}
+
+def doorHandler(evt){
+    if ((contact.latestValue("contact") == "open") && (evt.value == "locked")) { // If the door is open and a person locks the door then...  
+        //def delay = (secondsLater) // runIn uses seconds
+        runIn( secondsLater, unlockDoor )   // ...schedule (in minutes) to unlock...  We don't want the door to be closed while the lock is engaged. 
+    }
+    else if ((contact.latestValue("contact") == "open") && (evt.value == "unlocked")) { // If the door is open and a person unlocks it then...
+        unschedule( unlockDoor ) // ...we don't need to unlock it later.
+    }
+    else if ((contact.latestValue("contact") == "closed") && (evt.value == "locked")) { // If the door is closed and a person manually locks it then...
+        unschedule( lockDoor ) // ...we don't need to lock it later.
+    }   
+    else if ((contact.latestValue("contact") == "closed") && (evt.value == "unlocked")) { // If the door is closed and a person unlocks it then...
+       //def delay = (minutesLater * 60) // runIn uses seconds
+        runIn( (minutesLater * 60), lockDoor ) // ...schedule (in minutes) to lock.
+    }
+    else if ((lock1.latestValue("lock") == "unlocked") && (evt.value == "open")) { // If a person opens an unlocked door...
+        unschedule( lockDoor ) // ...we don't need to lock it later.
+    }
+    else if ((lock1.latestValue("lock") == "unlocked") && (evt.value == "closed")) { // If a person closes an unlocked door...
+        //def delay = (minutesLater * 60) // runIn uses seconds
+        runIn( (minutesLater * 60), lockDoor ) // ...schedule (in minutes) to lock.
+    }
+    else { //Opening or Closing door when locked (in case you have a handle lock)
+        log.debug "Unlocking the door."
+        lock1.unlock()
+        if(location.contactBookEnabled) {
+            if ( recipients ) {
+                log.debug ( "Sending Push Notification..." ) 
+                sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!", recipients)
+            }
+        }
+        if ( phoneNumber ) {
+            log.debug("Sending text message...")
+            sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!")
+        }
+    }
 }
-
-def handleProgramNameEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-
-def handleWaterEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-def handleSmokeEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-def handleCarbonMonoxideEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-
-def handleIlluminanceEvent(evt) {
-       log.debug ("handleIlluminanceEvent> $evt.name= $evt.value")
-       queueValue(evt) {
-               it.toString()
-       }
-}
-
-def handleLockEvent(evt) {
-       queueValue(evt) {
-               it == "locked" ? 1 : 0
-       }
-}
-
-def handleBatteryEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-
-def handleContactEvent(evt) {
-       queueValue(evt) {
-               it == "open" ? 1 : 0
-       }
-}
-
-def handleAccelerationEvent(evt) {
-       queueValue(evt) {
-               it == "active" ? 1 : 0
-       }
-}
-
-def handleMotionEvent(evt) {
-       queueValue(evt) {
-               it == "active" ? 1 : 0
-       }
-}
-
-def handlePresenceEvent(evt) {
-       queueValue(evt) {
-               it == "present" ? 1 : 0
-       }
-}
-
-def handleSwitchEvent(evt) {
-       queueValue(evt) {
-               it == "on" ? 1 : 0
-       }
-}
-
-def handleSetLevelEvent(evt) {
-       queueValue(evt) {
-               it.toString()
-       }
-}
-
-def handlePowerEvent(evt) {
-       if (evt.value) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-}
-
-def handleEnergyEvent(evt) {
-       if (evt.value) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-}
-def handleCostEvent(evt) {
-       if (evt.value) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-}
-
-private queueValue(evt, Closure convert) {
-       def MAX_QUEUE_SIZE=95000
-       def jsonPayload = [compId: evt.displayName, streamId: evt.name, data: convert(evt.value), time: now()]
-       def queue
-
-       queue = atomicState.queue
-       queue << jsonPayload
-       atomicState.queue = queue    
-       def queue_size = queue.toString().length()
-       def last_item_in_queue = queue[queue.size() -1]    
-       log.debug "queueValue>queue size in chars=${queue_size}, appending ${jsonPayload} to queue, last item in queue= $last_item_in_queue"
-       if (queue_size >  MAX_QUEUE_SIZE) {
-               processQueue()
-       }
-}
-
-def processQueue() {
-       Integer delay  = givenInterval ?: 5 // By default, schedule processQueue every 5 min.
-       atomicState?.poll["last"] = now()
-
-       if (((atomicState?.poll["rescheduled"]?:0) + (delay * 60000)) < now()) {
-               log.info "processQueue>scheduling rescheduleIfNeeded() in ${delay} minutes.."
-               schedule("0 0/${delay} * * * ?", rescheduleIfNeeded)
-               // Update rescheduled state
-               atomicState?.poll["rescheduled"] = now()
-       }
-
-       def queue = atomicState.queue
-    
-   
-       def url = "https://grovestreams.com/api/feed?api_key=${channelKey}"
-       log.debug "processQueue"
-       if (queue != []) {
-               log.debug "Events to be sent to groveStreams: ${queue}"
-
-               /*try {
-                       httpPutJson([uri: url, body: queue]) {response ->
-                               if (response.status != 200) {
-                                       log.debug "GroveStreams logging failed, status = ${response.status}"
-                               } else {
-                                       log.debug "GroveStreams accepted event(s)"
-                                       // reset the queue 
-                                       queue =[]                         
-                                       atomicState.queue = queue                     
-                               }
-                       }
-               } catch (groovyx.net.http.ResponseParseException e) {
-                       // ignore error 200, bogus exception
-                       if (e.statusCode != 200) {
-                               log.error "Grovestreams: ${e}"
-                       } else {
-                               log.debug "GroveStreams accepted event(s)"
-                       }
-                       // reset the queue 
-                       queue =[]                         
-                       atomicState.queue = queue                      
-            
-               } catch (e) {
-                       def errorInfo = "Error sending value: ${e}"
-                       log.error errorInfo
-                       // reset the queue 
-                       queue =[]                         
-                       atomicState.queue = queue                        
-               }*/
-       }
-
-}
-
index 3155b29..b7e30e6 100644 (file)
@@ -5,74 +5,8 @@ def updated = this.&updated
 //Global Object for functions in subscribe method!
 def initialize = this.&initialize
 //Global Object for functions in subscribe method!
-def appTouch = this.&appTouch
+def lockDoor = this.&lockDoor
 //Global Object for functions in subscribe method!
-def rescheduleIfNeeded = this.&rescheduleIfNeeded
+def unlockDoor = this.&unlockDoor
 //Global Object for functions in subscribe method!
-def handleTemperatureEvent = this.&handleTemperatureEvent
-//Global Object for functions in subscribe method!
-def handleHumidityEvent = this.&handleHumidityEvent
-//Global Object for functions in subscribe method!
-def handleHeatingSetpointEvent = this.&handleHeatingSetpointEvent
-//Global Object for functions in subscribe method!
-def handleCoolingSetpointEvent = this.&handleCoolingSetpointEvent
-//Global Object for functions in subscribe method!
-def handleThermostatModeEvent = this.&handleThermostatModeEvent
-//Global Object for functions in subscribe method!
-def handleFanModeEvent = this.&handleFanModeEvent
-//Global Object for functions in subscribe method!
-def handleHumidifierModeEvent = this.&handleHumidifierModeEvent
-//Global Object for functions in subscribe method!
-def handleHumidifierLevelEvent = this.&handleHumidifierLevelEvent
-//Global Object for functions in subscribe method!
-def handleDehumidifierModeEvent = this.&handleDehumidifierModeEvent
-//Global Object for functions in subscribe method!
-def handleDehumidifierLevelEvent = this.&handleDehumidifierLevelEvent
-//Global Object for functions in subscribe method!
-def handleVentilatorModeEvent = this.&handleVentilatorModeEvent
-//Global Object for functions in subscribe method!
-def handleFanMinOnTimeEvent = this.&handleFanMinOnTimeEvent
-//Global Object for functions in subscribe method!
-def handleVentilatorMinOnTimeEvent = this.&handleVentilatorMinOnTimeEvent
-//Global Object for functions in subscribe method!
-def handleThermostatOperatingStateEvent = this.&handleThermostatOperatingStateEvent
-//Global Object for functions in subscribe method!
-def handleDailyStats = this.&handleDailyStats
-//Global Object for functions in subscribe method!
-def handleEquipmentStatusEvent = this.&handleEquipmentStatusEvent
-//Global Object for functions in subscribe method!
-def handleProgramNameEvent = this.&handleProgramNameEvent
-//Global Object for functions in subscribe method!
-def handleWaterEvent = this.&handleWaterEvent
-//Global Object for functions in subscribe method!
-def handleSmokeEvent = this.&handleSmokeEvent
-//Global Object for functions in subscribe method!
-def handleCarbonMonoxideEvent = this.&handleCarbonMonoxideEvent
-//Global Object for functions in subscribe method!
-def handleIlluminanceEvent = this.&handleIlluminanceEvent
-//Global Object for functions in subscribe method!
-def handleLockEvent = this.&handleLockEvent
-//Global Object for functions in subscribe method!
-def handleBatteryEvent = this.&handleBatteryEvent
-//Global Object for functions in subscribe method!
-def handleContactEvent = this.&handleContactEvent
-//Global Object for functions in subscribe method!
-def handleAccelerationEvent = this.&handleAccelerationEvent
-//Global Object for functions in subscribe method!
-def handleMotionEvent = this.&handleMotionEvent
-//Global Object for functions in subscribe method!
-def handlePresenceEvent = this.&handlePresenceEvent
-//Global Object for functions in subscribe method!
-def handleSwitchEvent = this.&handleSwitchEvent
-//Global Object for functions in subscribe method!
-def handleSetLevelEvent = this.&handleSetLevelEvent
-//Global Object for functions in subscribe method!
-def handlePowerEvent = this.&handlePowerEvent
-//Global Object for functions in subscribe method!
-def handleEnergyEvent = this.&handleEnergyEvent
-//Global Object for functions in subscribe method!
-def handleCostEvent = this.&handleCostEvent
-//Global Object for functions in subscribe method!
-def queueValue = this.&queueValue
-//Global Object for functions in subscribe method!
-def processQueue = this.&processQueue
+def doorHandler = this.&doorHandler
index 83899d9..e4ce692 100644 (file)
@@ -1,38 +1,12 @@
-//Object for class temperature measurement!
-def temperatures
-//Object for class thermostat!
-def thermostats
-//Object for class presence sensor!
-def automatic
-//Object for class smoke detector!
-def detectors
-//Object for class humidity measurement!
-def humidities
-//Object for class water sensor!
-def waters
-//Object for class illuminance measurement!
-def illuminances
 //Object for class lock!
-def locks
+def lock1
 //Object for class contactSensor!
-def contacts
-//Object for class Acceleration Sensor!
-def accelerations
-//Object for class Motion Sensor!
-def motions
-//Object for class presence sensor!
-def presence
-//Object for class switch!
-def switches
-//Object for class switch level!
-def dimmerSwitches
-//Object for class Battery!
-def batteries
-//Object for class power meter!
-def powers
-//Object for class energy meter!
-def energys
-//Global variable for text!
-def channelKey = "This is just a text!"
+def contact
 //Global variable for number!
-def givenInterval = 75
+def minutesLater = 48
+//Global variable for number!
+def secondsLater = 55
+//Global variable for contact!
+def recipients = "AJ"
+//Global variable for phone!
+def phoneNumber = 9495379373
index 53906e5..29bfad5 100644 (file)
@@ -1,19 +1,4 @@
-temperatures = obj.temperatureMeasurementObject
-thermostats = obj.thermostatObject
-automatic = obj.presenceSensorObject
-detectors = obj.smokeDetectorObject
-humidities = obj.humidityMeasurementObject
-waters = obj.waterSensorObject
-illuminances = obj.illuminanceMeasurementObject
-locks = obj.lockObject
-contacts = obj.contactObject
-accelerations = obj.accelerationSensorObject
-motions = obj.motionSensorObject
-presence = obj.presenceSensorObject
-switches = obj.switchObject
-dimmerSwitches = obj.switchLevelObject
-batteries = obj.batteryObject
-powers = obj.powerMeterObject
-energys = obj.energyMeterObject
+lock1 = obj.lockObject
+contact = obj.contactObject
 //Global variable for settings!
-settings = [app:app, temperatures:temperatures, thermostats:thermostats, automatic:automatic, detectors:detectors, humidities:humidities, waters:waters, illuminances:illuminances, locks:locks, contacts:contacts, accelerations:accelerations, motions:motions, presence:presence, switches:switches, dimmerSwitches:dimmerSwitches, batteries:batteries, powers:powers, energys:energys, channelKey:channelKey, givenInterval:givenInterval]
+settings = [app:app, lock1:lock1, contact:contact, minutesLater:minutesLater, secondsLater:secondsLater, recipients:recipients, phoneNumber:phoneNumber]
index 86096f4..61b6434 100644 (file)
@@ -1,7 +1,7 @@
 /**
- *  Notify If Left Unlocked
+ *  Beacon Control
  *
- *  Copyright 2014 George Sudarkoff
+ *  Copyright 2014 Physical Graph Corporation
  *
  *  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:
  *  for the specific language governing permissions and limitations under the License.
  *
  */
-
 definition(
-    name: "Notify If Left Unlocked",
-    namespace: "com.sudarkoff",
-    author: "George Sudarkoff",
-    description: "Send a push or SMS notification (and lock, if it's closed) if a door is left unlocked for a period of time.",
-    category: "Safety & Security",
-    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
-    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
-
+       name: "Beacon Control",
+       category: "SmartThings Internal",
+       namespace: "smartthings",
+       author: "SmartThings",
+       description: "Execute a Hello, Home phrase, turn on or off some lights, and/or lock or unlock your door when you enter or leave a monitored region",
+       iconUrl: "https://s3.amazonaws.com/smartapp-icons/MiscHacking/mindcontrol.png",
+       iconX2Url: "https://s3.amazonaws.com/smartapp-icons/MiscHacking/mindcontrol@2x.png"
+)
 
 preferences {
-    section("If this lock...") {
-        input "aLock", "capability.lock", multiple: false, required: true
-        input "openSensor", "capability.contactSensor", title: "Open/close sensor (optional)", multiple: false, required: false
-    }
-    section("Left unlocked for...") {
-        input "duration", "number", title: "How many minutes?", required: true
-    }
-    section("Notify me...") {
-        input "pushNotification", "bool", title: "Push notification"
-        input "phoneNumber", "phone", title: "Phone number (optional)", required: false
-        input "lockIfClosed", "bool", title: "Lock the door if it's closed?"
-    }
-}
-
-def installed()
-{
-    initialize()
-}
-
-def updated()
-{
-    unsubscribe()
-    initialize()
-}
-
-def initialize()
-{
-    log.trace "Initializing with: ${settings}"
-    subscribe(aLock, "lock", lockHandler)
-}
-
-def lockHandler(evt)
-{
-    log.trace "${evt.name} is ${evt.value}."
-    if (evt.value == "locked") {
-        log.debug "Canceling lock check because the door is locked..."
-        unschedule(notifyUnlocked)
-    }
-    else {
-        log.debug "Starting the countdown for ${duration} minutes..."
-        state.retries = 0
-        runIn(duration * 60, notifyUnlocked)
-    }
-}
-
-def notifyUnlocked()
-{
-    // if no open/close sensor specified, assume the door is closed
-    def open = openSensor?.latestValue("contact") ?: "closed"
-
-    def message = "${aLock.displayName} is left unlocked and ${open} for more than ${duration} minutes."
-    log.trace "Sending the notification: ${message}."
-    sendMessage(message)
-
-    if (lockIfClosed) {
-        if (open == "closed") {
-            log.trace "And locking the door."
-            sendMessage("Locking the ${aLock.displayName} as prescribed.")
-            aLock.lock()
-        }
-        else {
-            if (state.retries++ < 3) {
-                log.trace "Door is open, can't lock. Rescheduling the check."
-                sendMessage("Can't lock the ${aLock.displayName} because the door is open. Will try again in ${duration} minutes.")
-                runIn(duration * 60, notifyUnlocked)
+       page(name: "timeIntervalInput", title: "Only during a certain time") {
+               section {
+                       input "starting", "time", title: "Starting", required: false
+                       input "ending", "time", title: "Ending", required: false
+               }
+       }
+       
+       page(name: "mainPage")
+}
+
+def mainPage() {
+       dynamicPage(name: "mainPage", install: true, uninstall: true) {
+
+               section("Where do you want to watch?") {
+                       input name: "beacons", type: "capability.beacon", title: "Select your beacon(s)", 
+                               multiple: true, required: true
+               }
+
+               section("Who do you want to watch for?") {
+                       input name: "phones", type: "device.mobilePresence", title: "Select your phone(s)", 
+                               multiple: true, required: true
+               }
+
+               section("What do you want to do on arrival?") {
+                       input name: "arrivalPhrase", type: "enum", title: "Execute a phrase", 
+                               options: listPhrases(), required: false
+                       input "arrivalOnSwitches", "capability.switch", title: "Turn on some switches", 
+                               multiple: true, required: false
+                       input "arrivalOffSwitches", "capability.switch", title: "Turn off some switches", 
+                               multiple: true, required: false
+                       input "arrivalLocks", "capability.lock", title: "Unlock the door",
+                               multiple: true, required: false
+               }
+
+               section("What do you want to do on departure?") {
+                       input name: "departPhrase", type: "enum", title: "Execute a phrase", 
+                               options: listPhrases(), required: false
+                       input "departOnSwitches", "capability.switch", title: "Turn on some switches", 
+                               multiple: true, required: false
+                       input "departOffSwitches", "capability.switch", title: "Turn off some switches", 
+                               multiple: true, required: false
+                       input "departLocks", "capability.lock", title: "Lock the door",
+                               multiple: true, required: false
+               }
+
+               section("Do you want to be notified?") {
+                       input "pushNotification", "bool", title: "Send a push notification"
+                       input "phone", "phone", title: "Send a text message", description: "Tap to enter phone number", 
+                               required: false
+               }
+
+               section {
+                       label title: "Give your automation a name", description: "e.g. Goodnight Home, Wake Up"
+               }
+
+               def timeLabel = timeIntervalLabel()
+               section(title: "More options", hidden: hideOptionsSection(), hideable: true) {
+                       href "timeIntervalInput", title: "Only during a certain time", 
+                               description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : "incomplete"
+
+                       input "days", "enum", title: "Only on certain days of the week", multiple: true, required: false,
+                               options: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
+
+                       input "modes", "mode", title: "Only when mode is", multiple: true, required: false
+               }
+       }
+}
+
+// Lifecycle management
+def installed() {
+       log.debug "<beacon-control> Installed with settings: ${settings}"
+       initialize()
+}
+
+def updated() {
+       log.debug "<beacon-control> Updated with settings: ${settings}"
+       unsubscribe()
+       initialize()
+}
+
+def initialize() {
+       subscribe(beacons, "presence", beaconHandler)
+}
+
+// Event handlers
+def beaconHandler(evt) {
+       log.debug "<beacon-control> beaconHandler: $evt"
+
+       if (allOk) {
+               def data = new groovy.json.JsonSlurper().parseText(evt.data)
+                // removed logging of device names. can be added back for debugging
+               //log.debug "<beacon-control> data: $data - phones: " + phones*.deviceNetworkId
+
+               def beaconName = getBeaconName(evt)
+                // removed logging of device names. can be added back for debugging
+               //log.debug "<beacon-control> beaconName: $beaconName"
+
+               def phoneName = getPhoneName(data)
+                // removed logging of device names. can be added back for debugging
+               //log.debug "<beacon-control> phoneName: $phoneName"
+               if (phoneName != null) {
+            def action = data.presence == "1" ? "arrived" : "left"
+            def msg = "$phoneName has $action ${action == 'arrived' ? 'at ' : ''}the $beaconName"
+
+            if (action == "arrived") {
+                msg = arriveActions(msg)
+            }
+            else if (action == "left") {
+                msg = departActions(msg)
             }
-            else {
-                log.trace "The door is still open after ${state.retries} retries, giving up."
-                sendMessage("Unable to lock the ${aLock.displayName} after ${state.retries} retries, giving up.")
+            log.debug "<beacon-control> msg: $msg"
+
+            if (pushNotification || phone) {
+                def options = [
+                    method: (pushNotification && phone) ? "both" : (pushNotification ? "push" : "sms"),
+                    phone: phone
+                ]
+                sendNotification(msg, options)
             }
         }
-    }
+       }
 }
 
-def sendMessage(msg) {
-    if (pushNotification) {
-        sendPush(msg)
-    }
-    if (phoneNumber) {
-        sendSMS(phoneNumber, msg)
-    }
+// Helpers
+private arriveActions(msg) {
+       if (arrivalPhrase || arrivalOnSwitches || arrivalOffSwitches || arrivalLocks) msg += ", so"
+       
+       if (arrivalPhrase) {
+               log.debug "<beacon-control> executing: $arrivalPhrase"
+               executePhrase(arrivalPhrase)
+               msg += " ${prefix('executed')} $arrivalPhrase."
+       }
+       if (arrivalOnSwitches) {
+               log.debug "<beacon-control> turning on: $arrivalOnSwitches"
+               arrivalOnSwitches.on()
+               msg += " ${prefix('turned')} ${list(arrivalOnSwitches)} on."
+       }
+       if (arrivalOffSwitches) {
+               log.debug "<beacon-control> turning off: $arrivalOffSwitches"
+               arrivalOffSwitches.off()
+               msg += " ${prefix('turned')} ${list(arrivalOffSwitches)} off."
+       }
+       if (arrivalLocks) {
+               log.debug "<beacon-control> unlocking: $arrivalLocks"
+               arrivalLocks.unlock()
+               msg += " ${prefix('unlocked')} ${list(arrivalLocks)}."
+       }
+       msg
 }
 
+private departActions(msg) {
+       if (departPhrase || departOnSwitches || departOffSwitches || departLocks) msg += ", so"
+       
+       if (departPhrase) {
+               log.debug "<beacon-control> executing: $departPhrase"
+               executePhrase(departPhrase)
+               msg += " ${prefix('executed')} $departPhrase."
+       }
+       if (departOnSwitches) {
+               log.debug "<beacon-control> turning on: $departOnSwitches"
+               departOnSwitches.on()
+               msg += " ${prefix('turned')} ${list(departOnSwitches)} on."
+       }
+       if (departOffSwitches) {
+               log.debug "<beacon-control> turning off: $departOffSwitches"
+               departOffSwitches.off()
+               msg += " ${prefix('turned')} ${list(departOffSwitches)} off."
+       }
+       if (departLocks) {
+               log.debug "<beacon-control> unlocking: $departLocks"
+               departLocks.lock()
+               msg += " ${prefix('locked')} ${list(departLocks)}."
+       }
+       msg
+}
+
+private prefix(word) {
+       def result
+       def index = settings.prefixIndex == null ? 0 : settings.prefixIndex + 1
+       switch (index) {
+               case 0:
+                       result = "I $word"
+                       break
+               case 1:
+                       result = "I also $word"
+                       break
+               case 2:
+                       result = "And I $word"
+                       break
+               default:
+                       result = "And $word"
+                       break
+       }
+
+       settings.prefixIndex = index
+       log.trace "prefix($word'): $result"
+       result
+}
+
+private listPhrases() {
+       location.helloHome.getPhrases().label
+}
+
+private executePhrase(phraseName) {
+       if (phraseName) {
+               location.helloHome.execute(phraseName)
+               log.debug "<beacon-control> executed phrase: $phraseName"
+       }
+}
+
+private getBeaconName(evt) {
+       def beaconName = beacons.find { b -> b.id == evt.deviceId }
+       return beaconName
+}
+
+private getPhoneName(data) {    
+       def phoneName = phones.find { phone ->
+               // Work around DNI bug in data
+               def pParts = phone.deviceNetworkId.split('\\|')
+               def dParts = data.dni.split('\\|')
+        pParts[0] == dParts[0]
+       }
+       return phoneName
+}
+
+private hideOptionsSection() {
+       (starting || ending || days || modes) ? false : true
+}
+
+private getAllOk() {
+       modeOk && daysOk && timeOk
+}
+
+private getModeOk() {
+       def result = !modes || modes.contains(location.mode)
+       log.trace "<beacon-control> modeOk = $result"
+       result
+}
+
+private getDaysOk() {
+       def result = true
+       if (days) {
+               def df = new java.text.SimpleDateFormat("EEEE")
+               if (location.timeZone) {
+                       df.setTimeZone(location.timeZone)
+               }
+               else {
+                       df.setTimeZone(TimeZone.getTimeZone("America/New_York"))
+               }
+               def day = df.format(new Date())
+               result = days.contains(day)
+       }
+       log.trace "<beacon-control> daysOk = $result"
+       result
+}
+
+private getTimeOk() {
+       def result = true
+       if (starting && ending) {
+               def currTime = now()
+               def start = timeToday(starting, location?.timeZone).time
+               def stop = timeToday(ending, location?.timeZone).time
+               result = start < stop ? currTime >= start && currTime <= stop : currTime <= stop || currTime >= start
+       }
+       log.trace "<beacon-control> timeOk = $result"
+       result
+}
+
+private hhmm(time, fmt = "h:mm a") {
+       def t = timeToday(time, location.timeZone)
+       def f = new java.text.SimpleDateFormat(fmt)
+       f.setTimeZone(location.timeZone ?: timeZone(time))
+       f.format(t)
+}
+
+private timeIntervalLabel() {
+       (starting && ending) ? hhmm(starting) + "-" + hhmm(ending, "h:mm a z") : ""
+}
+
+private list(Object names) {
+       return names[0]
+}
index c59c464..8430b82 100644 (file)
@@ -1,12 +1,40 @@
 //Global Object for functions in subscribe method!
+def mainPage = this.&mainPage
+//Global Object for functions in subscribe method!
 def installed = this.&installed
 //Global Object for functions in subscribe method!
 def updated = this.&updated
 //Global Object for functions in subscribe method!
 def initialize = this.&initialize
 //Global Object for functions in subscribe method!
-def lockHandler = this.&lockHandler
+def beaconHandler = this.&beaconHandler
+//Global Object for functions in subscribe method!
+def arriveActions = this.&arriveActions
+//Global Object for functions in subscribe method!
+def departActions = this.&departActions
+//Global Object for functions in subscribe method!
+def prefix = this.&prefix
+//Global Object for functions in subscribe method!
+def listPhrases = this.&listPhrases
+//Global Object for functions in subscribe method!
+def executePhrase = this.&executePhrase
+//Global Object for functions in subscribe method!
+def getBeaconName = this.&getBeaconName
+//Global Object for functions in subscribe method!
+def getPhoneName = this.&getPhoneName
+//Global Object for functions in subscribe method!
+def hideOptionsSection = this.&hideOptionsSection
+//Global Object for functions in subscribe method!
+def getAllOk = this.&getAllOk
+//Global Object for functions in subscribe method!
+def getModeOk = this.&getModeOk
+//Global Object for functions in subscribe method!
+def getDaysOk = this.&getDaysOk
+//Global Object for functions in subscribe method!
+def getTimeOk = this.&getTimeOk
+//Global Object for functions in subscribe method!
+def hhmm = this.&hhmm
 //Global Object for functions in subscribe method!
-def notifyUnlocked = this.&notifyUnlocked
+def timeIntervalLabel = this.&timeIntervalLabel
 //Global Object for functions in subscribe method!
-def sendMessage = this.&sendMessage
+def list = this.&list
index 09638b3..7444a10 100644 (file)
@@ -1,12 +1,32 @@
+//Global variable for time!
+def starting = "15:00"
+//Global variable for time!
+def ending = "15:00"
+//Object for class beacon sensor!
+def beacons
+//Object for class mobile presence!
+def phones
+//Global variable for enum!
+def arrivalPhrase = "Good Night!"
+//Object for class switch!
+def arrivalOnSwitches
+//Object for class switch!
+def arrivalOffSwitches
 //Object for class lock!
-def aLock
-//Object for class contactSensor!
-def openSensor
-//Global variable for number!
-def duration = 47
+def arrivalLocks
+//Global variable for enum!
+def departPhrase = "Good Night!"
+//Object for class switch!
+def departOnSwitches
+//Object for class switch!
+def departOffSwitches
+//Object for class lock!
+def departLocks
 //Global variable for boolean!
 def pushNotification = "0"
 //Global variable for phone!
-def phoneNumber = 9495379373
-//Global variable for boolean!
-def lockIfClosed = "1"
+def phone = 9495379373
+//Global variable for enum!
+def days = "Monday"
+//Global variable for mode!
+def modes = "away"
index cc84ca8..e10e014 100644 (file)
@@ -1,4 +1,10 @@
-aLock = obj.lockObject
-openSensor = obj.contactObject
+beacons = obj.beaconSensorObject
+phones = obj.mobilePresenceObject
+arrivalOnSwitches = obj.switchObject
+arrivalOffSwitches = obj.switchObject
+arrivalLocks = obj.lockObject
+departOnSwitches = obj.switchObject
+departOffSwitches = obj.switchObject
+departLocks = obj.lockObject
 //Global variable for settings!
-settings = [app:app, aLock:aLock, openSensor:openSensor, duration:duration, pushNotification:pushNotification, phoneNumber:phoneNumber, lockIfClosed:lockIfClosed]
+settings = [app:app, starting:starting, ending:ending, beacons:beacons, phones:phones, arrivalPhrase:arrivalPhrase, arrivalOnSwitches:arrivalOnSwitches, arrivalOffSwitches:arrivalOffSwitches, arrivalLocks:arrivalLocks, departPhrase:departPhrase, departOnSwitches:departOnSwitches, departOffSwitches:departOffSwitches, departLocks:departLocks, pushNotification:pushNotification, phone:phone, days:days, modes:modes]
index 5e4d0e3..3696113 100644 (file)
@@ -1612,9 +1612,9 @@ def mappings(Closure inputData) {
 
 
 /**
- *  Notify If Left Unlocked
+ *  Beacon Control
  *
- *  Copyright 2014 George Sudarkoff
+ *  Copyright 2014 Physical Graph Corporation
  *
  *  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:
@@ -1626,98 +1626,296 @@ def mappings(Closure inputData) {
  *  for the specific language governing permissions and limitations under the License.
  *
  */
-
 definition(
-    name: "Notify If Left Unlocked",
-    namespace: "com.sudarkoff",
-    author: "George Sudarkoff",
-    description: "Send a push or SMS notification (and lock, if it's closed) if a door is left unlocked for a period of time.",
-    category: "Safety & Security",
-    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
-    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience@2x.png")
-
+       name: "Beacon Control",
+       category: "SmartThings Internal",
+       namespace: "smartthings",
+       author: "SmartThings",
+       description: "Execute a Hello, Home phrase, turn on or off some lights, and/or lock or unlock your door when you enter or leave a monitored region",
+       iconUrl: "https://s3.amazonaws.com/smartapp-icons/MiscHacking/mindcontrol.png",
+       iconX2Url: "https://s3.amazonaws.com/smartapp-icons/MiscHacking/mindcontrol@2x.png"
+)
 
 preferences {
-    section("If this lock...") {
-        input "aLock", "capability.lock", multiple: false, required: true
-        input "openSensor", "capability.contactSensor", title: "Open/close sensor (optional)", multiple: false, required: false
-    }
-    section("Left unlocked for...") {
-        input "duration", "number", title: "How many minutes?", required: true
-    }
-    section("Notify me...") {
-        input "pushNotification", "bool", title: "Push notification"
-        input "phoneNumber", "phone", title: "Phone number (optional)", required: false
-        input "lockIfClosed", "bool", title: "Lock the door if it's closed?"
-    }
+       page(name: "timeIntervalInput", title: "Only during a certain time") {
+               section {
+                       input "starting", "time", title: "Starting", required: false
+                       input "ending", "time", title: "Ending", required: false
+               }
+       }
+       
+       page(name: "mainPage")
 }
 
-def installed()
-{
-    initialize()
+def mainPage() {
+       dynamicPage(name: "mainPage", install: true, uninstall: true) {
+
+               section("Where do you want to watch?") {
+                       input name: "beacons", type: "capability.beacon", title: "Select your beacon(s)", 
+                               multiple: true, required: true
+               }
+
+               section("Who do you want to watch for?") {
+                       input name: "phones", type: "device.mobilePresence", title: "Select your phone(s)", 
+                               multiple: true, required: true
+               }
+
+               section("What do you want to do on arrival?") {
+                       input name: "arrivalPhrase", type: "enum", title: "Execute a phrase", 
+                               options: listPhrases(), required: false
+                       input "arrivalOnSwitches", "capability.switch", title: "Turn on some switches", 
+                               multiple: true, required: false
+                       input "arrivalOffSwitches", "capability.switch", title: "Turn off some switches", 
+                               multiple: true, required: false
+                       input "arrivalLocks", "capability.lock", title: "Unlock the door",
+                               multiple: true, required: false
+               }
+
+               section("What do you want to do on departure?") {
+                       input name: "departPhrase", type: "enum", title: "Execute a phrase", 
+                               options: listPhrases(), required: false
+                       input "departOnSwitches", "capability.switch", title: "Turn on some switches", 
+                               multiple: true, required: false
+                       input "departOffSwitches", "capability.switch", title: "Turn off some switches", 
+                               multiple: true, required: false
+                       input "departLocks", "capability.lock", title: "Lock the door",
+                               multiple: true, required: false
+               }
+
+               section("Do you want to be notified?") {
+                       input "pushNotification", "bool", title: "Send a push notification"
+                       input "phone", "phone", title: "Send a text message", description: "Tap to enter phone number", 
+                               required: false
+               }
+
+               section {
+                       label title: "Give your automation a name", description: "e.g. Goodnight Home, Wake Up"
+               }
+
+               def timeLabel = timeIntervalLabel()
+               section(title: "More options", hidden: hideOptionsSection(), hideable: true) {
+                       href "timeIntervalInput", title: "Only during a certain time", 
+                               description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : "incomplete"
+
+                       input "days", "enum", title: "Only on certain days of the week", multiple: true, required: false,
+                               options: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
+
+                       input "modes", "mode", title: "Only when mode is", multiple: true, required: false
+               }
+       }
 }
 
-def updated()
-{
-    unsubscribe()
-    initialize()
+// Lifecycle management
+def installed() {
+       log.debug "<beacon-control> Installed with settings: ${settings}"
+       initialize()
 }
 
-def initialize()
-{
-    log.trace "Initializing with: ${settings}"
-    subscribe(aLock, "lock", lockHandler)
+def updated() {
+       log.debug "<beacon-control> Updated with settings: ${settings}"
+       unsubscribe()
+       initialize()
 }
 
-def lockHandler(evt)
-{
-    log.trace "${evt.name} is ${evt.value}."
-    if (evt.value == "locked") {
-        log.debug "Canceling lock check because the door is locked..."
-        unschedule(notifyUnlocked)
-    }
-    else {
-        log.debug "Starting the countdown for ${duration} minutes..."
-        state.retries = 0
-        runIn(duration * 60, notifyUnlocked)
-    }
+def initialize() {
+       subscribe(beacons, "presence", beaconHandler)
 }
 
-def notifyUnlocked()
-{
-    // if no open/close sensor specified, assume the door is closed
-    def open = openSensor?.latestValue("contact") ?: "closed"
+// Event handlers
+def beaconHandler(evt) {
+       log.debug "<beacon-control> beaconHandler: $evt"
 
-    def message = "${aLock.displayName} is left unlocked and ${open} for more than ${duration} minutes."
-    log.trace "Sending the notification: ${message}."
-    sendMessage(message)
+       if (allOk) {
+               def data = new groovy.json.JsonSlurper().parseText(evt.data)
+                // removed logging of device names. can be added back for debugging
+               //log.debug "<beacon-control> data: $data - phones: " + phones*.deviceNetworkId
 
-    if (lockIfClosed) {
-        if (open == "closed") {
-            log.trace "And locking the door."
-            sendMessage("Locking the ${aLock.displayName} as prescribed.")
-            aLock.lock()
-        }
-        else {
-            if (state.retries++ < 3) {
-                log.trace "Door is open, can't lock. Rescheduling the check."
-                sendMessage("Can't lock the ${aLock.displayName} because the door is open. Will try again in ${duration} minutes.")
-                runIn(duration * 60, notifyUnlocked)
+               def beaconName = getBeaconName(evt)
+                // removed logging of device names. can be added back for debugging
+               //log.debug "<beacon-control> beaconName: $beaconName"
+
+               def phoneName = getPhoneName(data)
+                // removed logging of device names. can be added back for debugging
+               //log.debug "<beacon-control> phoneName: $phoneName"
+               if (phoneName != null) {
+            def action = data.presence == "1" ? "arrived" : "left"
+            def msg = "$phoneName has $action ${action == 'arrived' ? 'at ' : ''}the $beaconName"
+
+            if (action == "arrived") {
+                msg = arriveActions(msg)
             }
-            else {
-                log.trace "The door is still open after ${state.retries} retries, giving up."
-                sendMessage("Unable to lock the ${aLock.displayName} after ${state.retries} retries, giving up.")
+            else if (action == "left") {
+                msg = departActions(msg)
+            }
+            log.debug "<beacon-control> msg: $msg"
+
+            if (pushNotification || phone) {
+                def options = [
+                    method: (pushNotification && phone) ? "both" : (pushNotification ? "push" : "sms"),
+                    phone: phone
+                ]
+                sendNotification(msg, options)
             }
         }
-    }
+       }
+}
+
+// Helpers
+private arriveActions(msg) {
+       if (arrivalPhrase || arrivalOnSwitches || arrivalOffSwitches || arrivalLocks) msg += ", so"
+       
+       if (arrivalPhrase) {
+               log.debug "<beacon-control> executing: $arrivalPhrase"
+               executePhrase(arrivalPhrase)
+               msg += " ${prefix('executed')} $arrivalPhrase."
+       }
+       if (arrivalOnSwitches) {
+               log.debug "<beacon-control> turning on: $arrivalOnSwitches"
+               arrivalOnSwitches.on()
+               msg += " ${prefix('turned')} ${list(arrivalOnSwitches)} on."
+       }
+       if (arrivalOffSwitches) {
+               log.debug "<beacon-control> turning off: $arrivalOffSwitches"
+               arrivalOffSwitches.off()
+               msg += " ${prefix('turned')} ${list(arrivalOffSwitches)} off."
+       }
+       if (arrivalLocks) {
+               log.debug "<beacon-control> unlocking: $arrivalLocks"
+               arrivalLocks.unlock()
+               msg += " ${prefix('unlocked')} ${list(arrivalLocks)}."
+       }
+       msg
+}
+
+private departActions(msg) {
+       if (departPhrase || departOnSwitches || departOffSwitches || departLocks) msg += ", so"
+       
+       if (departPhrase) {
+               log.debug "<beacon-control> executing: $departPhrase"
+               executePhrase(departPhrase)
+               msg += " ${prefix('executed')} $departPhrase."
+       }
+       if (departOnSwitches) {
+               log.debug "<beacon-control> turning on: $departOnSwitches"
+               departOnSwitches.on()
+               msg += " ${prefix('turned')} ${list(departOnSwitches)} on."
+       }
+       if (departOffSwitches) {
+               log.debug "<beacon-control> turning off: $departOffSwitches"
+               departOffSwitches.off()
+               msg += " ${prefix('turned')} ${list(departOffSwitches)} off."
+       }
+       if (departLocks) {
+               log.debug "<beacon-control> unlocking: $departLocks"
+               departLocks.lock()
+               msg += " ${prefix('locked')} ${list(departLocks)}."
+       }
+       msg
+}
+
+private prefix(word) {
+       def result
+       def index = settings.prefixIndex == null ? 0 : settings.prefixIndex + 1
+       switch (index) {
+               case 0:
+                       result = "I $word"
+                       break
+               case 1:
+                       result = "I also $word"
+                       break
+               case 2:
+                       result = "And I $word"
+                       break
+               default:
+                       result = "And $word"
+                       break
+       }
+
+       settings.prefixIndex = index
+       log.trace "prefix($word'): $result"
+       result
 }
 
-def sendMessage(msg) {
-    if (pushNotification) {
-        sendPush(msg)
-    }
-    if (phoneNumber) {
-        sendSMS(phoneNumber, msg)
-    }
+private listPhrases() {
+       location.helloHome.getPhrases().label
 }
 
+private executePhrase(phraseName) {
+       if (phraseName) {
+               location.helloHome.execute(phraseName)
+               log.debug "<beacon-control> executed phrase: $phraseName"
+       }
+}
+
+private getBeaconName(evt) {
+       def beaconName = beacons.find { b -> b.id == evt.deviceId }
+       return beaconName
+}
+
+private getPhoneName(data) {    
+       def phoneName = phones.find { phone ->
+               // Work around DNI bug in data
+               def pParts = phone.deviceNetworkId.split('\\|')
+               def dParts = data.dni.split('\\|')
+        pParts[0] == dParts[0]
+       }
+       return phoneName
+}
+
+private hideOptionsSection() {
+       (starting || ending || days || modes) ? false : true
+}
+
+private getAllOk() {
+       modeOk && daysOk && timeOk
+}
+
+private getModeOk() {
+       def result = !modes || modes.contains(location.mode)
+       log.trace "<beacon-control> modeOk = $result"
+       result
+}
+
+private getDaysOk() {
+       def result = true
+       if (days) {
+               def df = new java.text.SimpleDateFormat("EEEE")
+               if (location.timeZone) {
+                       df.setTimeZone(location.timeZone)
+               }
+               else {
+                       df.setTimeZone(TimeZone.getTimeZone("America/New_York"))
+               }
+               def day = df.format(new Date())
+               result = days.contains(day)
+       }
+       log.trace "<beacon-control> daysOk = $result"
+       result
+}
+
+private getTimeOk() {
+       def result = true
+       if (starting && ending) {
+               def currTime = now()
+               def start = timeToday(starting, location?.timeZone).time
+               def stop = timeToday(ending, location?.timeZone).time
+               result = start < stop ? currTime >= start && currTime <= stop : currTime <= stop || currTime >= start
+       }
+       log.trace "<beacon-control> timeOk = $result"
+       result
+}
+
+private hhmm(time, fmt = "h:mm a") {
+       def t = timeToday(time, location.timeZone)
+       def f = new java.text.SimpleDateFormat(fmt)
+       f.setTimeZone(location.timeZone ?: timeZone(time))
+       f.format(t)
+}
+
+private timeIntervalLabel() {
+       (starting && ending) ? hhmm(starting) + "-" + hhmm(ending, "h:mm a z") : ""
+}
+
+private list(Object names) {
+       return names[0]
+}
diff --git a/SameFeatureDifferentDevices b/SameFeatureDifferentDevices
new file mode 100644 (file)
index 0000000..9734620
--- /dev/null
@@ -0,0 +1,46 @@
+///////////
+name of event:
+"battery"
+used in:
+'Battery class' + 'Smoke detector class'
+///////////
+name of event:
+"presence"
+used in:
+'Beacon sensor class' + 'Presence sensor class'
+///////////
+name of event:
+"carbonMonoxide"
+used in:
+'Carbon monoxide class' + 'Smoke detector class'
+///////////
+name of event:
+"contact"
+used in:
+'Contact sensor class' + 'Valve class'
+///////////
+name of event:
+"level"
+used in:
+'Switch level class' + 'Music player class'
+///////////
+name of event:
+"on"
+used in:
+'Switch class' + 'Relay switch class'
+///////////
+name of event:
+"off"
+used in:
+'Switch class' + 'Relay switch class'
+///////////
+name of event:
+"temperature"
+used in:
+'Temperature measurement class' + 'Thermostat class'
+///////////
+name of event:
+"switch"
+used in:
+'Switches class' + 'Switch level class' + 'Relay switch class'
+
index d01d27b..b924d21 100644 (file)
@@ -28,8 +28,12 @@ public class Switch {
 
        //By Apps
        def setLevel(int level) {
-               println("the switch with id:$id is setted to level $level!")
-               this.currentLevel = level
+               if (this.currentLevel != level) {
+                       println("the switch with id:$id is setted to level $level!")
+                       this.currentLevel = level
+                       sendEvent([name: "level", value: "40", deviceId: this.id, descriptionText: "",
+                           displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+               }
        }
 
        def on() {
index a09a450..4b7acbf 100644 (file)
@@ -6,13 +6,16 @@ public class SwitchLevel {
        private String id
        private String label
        private String displayName
+       private String switchState
+       private String currentSwitch
        private int level
        private int rate
+       private String switchLatestValue
        def sendEvent   
        def timers
        
 
-       SwitchLevel(Closure sendEvent, String id, String label, String displayName, int level) {
+       SwitchLevel(Closure sendEvent, String id, String label, String displayName, int level, String switchState, String switchLatestValue) {
                this.sendEvent = sendEvent
                this.timers = new SimulatedTimer()
                this.id = id
@@ -20,6 +23,9 @@ public class SwitchLevel {
                this.displayName = displayName
                this.level = level
                this.rate = level
+               this.switchState = switchState
+               this.currentSwitch = switchState
+               this.switchLatestValue = switchLatestValue
        }
 
        //By Apps
@@ -33,6 +39,54 @@ public class SwitchLevel {
                }
        }
 
+       def on() {
+               if (this.switchState != "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: '{"info": "info"}'])
+               }
+       }
+
+       def on(LinkedHashMap metaData) {
+               if (this.switchState != "on") {
+                       def task = timers.runAfter(metaData["delay"]) {
+                               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: '{"info": "info"}'])
+                       }
+               }
+       }
+
+       def off() {
+               if (this.switchState != "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: '{"info": "info"}'])
+               }
+       }
+
+       def off(LinkedHashMap metaData) {
+               if (this.switchState != "off") {
+                       def task = timers.runAfter(metaData["delay"]) {
+                               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: '{"info": "info"}'])
+                       }
+               }
+       }
+
        //By Model Checker
        def setValue(String value) {
                println("the switch with id:$id is setted to level $value!")
index 9e6e8a9..35c4ad9 100644 (file)
@@ -14,6 +14,9 @@ public class SwitchLevels {
        private String displayName = "switchLevel0"
        private int level = 50
        private int rate = 50
+       private String switchState = "off"
+       private String currentSwitch = "off"
+       private String switchLatestValue = "off"
 
        SwitchLevels(Closure sendEvent, int deviceNumbers) {
                this.sendEvent = sendEvent
@@ -21,7 +24,7 @@ public class SwitchLevels {
                this.deviceNumbers = deviceNumbers
                this.switchLevels = []
 
-               switchLevels.add(new SwitchLevel(sendEvent, id, label, displayName, this.level))
+               switchLevels.add(new SwitchLevel(sendEvent, id, label, displayName, this.level, this.switchState, this.switchLatestValue))
        }
 
        //Methods for closures
@@ -50,6 +53,38 @@ public class SwitchLevels {
                }
        }
 
+       def on() {
+               switchLevels[0].on()
+               switchLatestValue = switchState
+               switchState = "on"
+               currentSwitch = "on"
+       }
+
+       def on(LinkedHashMap metaData) {
+               def task = timers.runAfter(metaData["delay"]) {
+                       switchLevels[0].on()
+                       switchLatestValue = switchState
+                       switchState = "on"
+                       currentSwitch = "on"
+               }
+       }
+
+       def off() {
+               switchLevels[0].off()
+               switchLatestValue = switchState
+               switchState = "off"
+               currentSwitch = "off"
+       }
+
+       def off(LinkedHashMap metaData) {
+               def task = timers.runAfter(metaData["delay"]) {
+                       switchLevels[0].off()
+                       switchLatestValue = switchState
+                       switchState = "off"
+                       currentSwitch = "off"
+               }
+       }
+
        //By Model Checker
        def setValue(LinkedHashMap eventDataMap) {
                if (eventDataMap["value"] != switchLevels[0].level) {
index 0c049cc..7933983 100644 (file)
@@ -3,13 +3,13 @@
 String currentAlarm or String alarm
 /*events*/
 alarmObject.setValue([name: "alarm", value: "both", deviceId: "alarmID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 alarmObject.setValue([name: "alarm", value: "siren", deviceId: "alarmID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 alarmObject.setValue([name: "alarm", value: "strobe", deviceId: "alarmID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 alarmObject.setValue([name: "alarm", value: "off", deviceId: "alarmID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /*events*/
 //
 -------------------------------------------------------------------------------
@@ -20,9 +20,13 @@ String currentContact or String contactState
 /*events*/
 /////
 contactObject.setValue([name: "contact.closed", value: "closed", deviceId: "contactSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 contactObject.setValue([name: "contact.open", value: "open", deviceId: "contactSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+contactObject.setValue([name: "contact", value: "open", deviceId: "contactSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+contactObject.setValue([name: "contact", value: "closed", deviceId: "contactSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -33,9 +37,9 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 String doorState
 /*events*/
 doorControlObject.setValue([name: "doorState", value: "closed", deviceId: "doorControlID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 doorControlObject.setValue([name: "doorState", value: "open", deviceId: "doorControlID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -46,11 +50,17 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 String location.mode
 /*events*/
 locationObject.setValue([name: "Location", value: "away", deviceId: "locationID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 locationObject.setValue([name: "Location", value: "home", deviceId: "locationID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 locationObject.setValue([name: "Location", value: "night", deviceId: "locationID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+locationObject.setValue([name: "mode", value: "away", deviceId: "locationID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+locationObject.setValue([name: "mode", value: "home", deviceId: "locationID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+locationObject.setValue([name: "mode", value: "night", deviceId: "locationID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /*events*/
 //
 -------------------------------------------------------------------------------
@@ -60,9 +70,11 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 String currentLock or String lockState
 /*events*/
 lockObject.setValue([name: "lock", value: "locked", deviceId: "lockID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 lockObject.setValue([name: "unlock", value: "unlocked ", deviceId: "lockID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+lockObject.setValue([name: "lock", value: "unlocked", deviceId: "lockID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -73,9 +85,9 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 String currentMotion or String motion
 /*events*/
 motionSensorObject.setValue([name: "motion", value: "active", deviceId: "motionSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 motionSensorObject.setValue([name: "motion", value: "inactive", deviceId: "motionSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -90,21 +102,21 @@ String trackData
 String mute
 /*events*/
 musicPlayerObject.setValue([name: "status", value: "playing", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 musicPlayerObject.setValue([name: "status", value: "stopped", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 musicPlayerObject.setValue([name: "status", value: "paused", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 musicPlayerObject.setValue([name: "level", value: "36"/*A number between 0 to 100 as a charge*/, deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 musicPlayerObject.setValue([name: "trackDescription", value: "someDescriptions", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 musicPlayerObject.setValue([name: "trackData", value: "someTrack", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
-musicPlayerObject.setValue([name: "mute", value: "umuted", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+musicPlayerObject.setValue([name: "mute", value: "unmuted", deviceId: "musicPlayerID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 musicPlayerObject.setValue([name: "mute", value: "muted", deviceId: "musicPlayerID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /*events*/
 //
 -------------------------------------------------------------------------------
@@ -114,9 +126,11 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 String currentPresence or String presenceState
 /*events*/
 presenceSensorObject.setValue([name: "presence", value: "present", deviceId: "presenceSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"presence":"1","dni":"mobile0"}'])
 presenceSensorObject.setValue([name: "presence", value: "not present", deviceId: "presenceSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"presence":"0","dni":"mobile0"}'])
+presenceSensorObject.setValue([name: "presence.present", value: "present", deviceId: "presenceSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"presence":"1","dni":"mobile0"}'])
 /////
 /*events*/
 //
@@ -127,19 +141,19 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 String currentSmokeValue or String smoke
 /*events*/
 smokeDetectorObject.setValue([name: "smoke", value: "clear", deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 smokeDetectorObject.setValue([name: "smoke", value: "detected", deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 smokeDetectorObject.setValue([name: "smoke", value: "tested", deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 smokeDetectorObject.setValue([name: "carbonMonoxide", value: "clear", deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 smokeDetectorObject.setValue([name: "carbonMonoxide", value: "detected", deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 smokeDetectorObject.setValue([name: "carbonMonoxide", value: "tested", deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 smokeDetectorObject.setValue([name: "battery", value: "5"/*A number between 0 to 100 as a charge*/, deviceId: "smokeDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -155,43 +169,57 @@ String thermostatFanMode //fan mode
 String thermostatMode or currentThermostatMode //mode
 /*events*/
 thermostatObject.setValue([name: "thermostatMode", value: "auto", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 thermostatObject.setValue([name: "thermostatMode", value: "cool", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 thermostatObject.setValue([name: "thermostatMode", value: "emergencyHeat", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 thermostatObject.setValue([name: "thermostatMode", value: "heat", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 thermostatObject.setValue([name: "thermostatMode", value: "off", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 thermostatObject.setValue([name: "temperature", value: "55", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 thermostatObject.setValue([name: "heatingSetpoint", value: "40", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 thermostatObject.setValue([name: "coolingSetpoint", value: "60", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 thermostatObject.setValue([name: "thermostatSetpoint", value: "50", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 thermostatObject.setValue([name: "thermostatFanMode", value: "auto", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 thermostatObject.setValue([name: "thermostatFanMode", value: "fanCirculate", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 thermostatObject.setValue([name: "thermostatFanMode", value: "circulate", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 thermostatObject.setValue([name: "thermostatFanMode", value: "fanOn", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 thermostatObject.setValue([name: "thermostatFanMode", value: "on", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
-thermostatObject.setValue([name: "thermostatOperatingState", value: "auto", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
-thermostatObject.setValue([name: "thermostatOperatingState", value: "cool", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
-thermostatObject.setValue([name: "thermostatOperatingState", value: "off", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
-thermostatObject.setValue([name: "thermostatOperatingState", value: "emergencyHeat", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
-thermostatObject.setValue([name: "thermostatOperatingState", value: "heat", deviceId: "thermostatID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+thermostatObject.setValue([name: "fanMode", value: "auto", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+thermostatObject.setValue([name: "fanMode", value: "fanCirculate", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+thermostatObject.setValue([name: "fanMode", value: "circulate", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+thermostatObject.setValue([name: "fanMode", value: "fanOn", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+thermostatObject.setValue([name: "fanMode", value: "on", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+thermostatObject.setValue([name: "thermostatOperatingState", value: "cooling", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+thermostatObject.setValue([name: "thermostatOperatingState", value: "fan only", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+thermostatObject.setValue([name: "thermostatOperatingState", value: "heating", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+thermostatObject.setValue([name: "thermostatOperatingState", value: "idle", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+thermostatObject.setValue([name: "thermostatOperatingState", value: "pending cool", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+thermostatObject.setValue([name: "thermostatOperatingState", value: "pending heat", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+thermostatObject.setValue([name: "thermostatOperatingState", value: "vent economizer", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -202,9 +230,9 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 String currentSwitch or switchState
 /*events*/
 switchObject.setValue([name: "switch", value: "off", deviceId: "switchID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 switchObject.setValue([name: "switch", value: "on", deviceId: "switchID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -214,7 +242,7 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 //For appTouch:
 /*events*/
 appObject.setValue([name: "Touched", value: "touched", deviceId: "touchedSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -224,7 +252,7 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 //For nfcTouch:
 /*events*/
 touchSensorObject.setValue([name: "nfcTouch", value: "touched", deviceId: "nfcSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -234,9 +262,9 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 //For aeonKeyFob push button:
 /*events*/
 aeonKeyFobObject.setValue([name: "button", value: "pushed", deviceId: "aeonKeyFobID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 aeonKeyFobObject.setValue([name: "button", value: "held", deviceId: "aeonKeyFobID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /////
 /*events*/
@@ -248,9 +276,9 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 String currentAcceleration or String acceleration
 /*events*/
 accelerationSensorObject.setValue([name: "acceleration", value: "active", deviceId: "accelerationSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 accelerationSensorObject.setValue([name: "acceleration", value: "inactive", deviceId: "accelerationSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -261,7 +289,7 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 int currentBattery or int battery
 /*events*/
 batteryObject.setValue([name: "battery", value: "50"/*number between 0 to 100 as a string*/, deviceId: "batteryID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /*events*/
 //
 -------------------------------------------------------------------------------
@@ -270,10 +298,10 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 //For beacon sensor:
 String currentPresence or String presence
 /*events*/
-beaconSensorObject.setValue([name: "beacon", value: "present", deviceId: "beaconeSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
-beaconSensorObject.setValue([name: "beacon", value: "not present", deviceId: "beaconSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+beaconSensorObject.setValue([name: "presence", value: "present", deviceId: "beaconeSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"presence":"1","dni":"mobile0"}'])
+beaconSensorObject.setValue([name: "presence", value: "not present", deviceId: "beaconSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"presence":"0","dni":"mobile0"}'])
 /////
 /*events*/
 //
@@ -284,11 +312,11 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 String currentCarbonMonoxideValue or String carbonMonoxide
 /*events*/
 carbonMonoxideDetectorObject.setValue([name: "carbonMonoxide", value: "clear", deviceId: "carbonMonoxideDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 carbonMonoxideDetectorObject.setValue([name: "carbonMonoxide", value: "detected", deviceId: "carbonMonoxideDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 carbonMonoxideDetectorObject.setValue([name: "carbonMonoxide", value: "tested", deviceId: "carbonMonoxideDetectorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /*events*/
 //
 -------------------------------------------------------------------------------
@@ -300,11 +328,11 @@ int hue
 int saturation
 /*events*/
 colorControlObject.setValue([name: "color", value: "red", deviceId: "colorControlID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 colorControlObject.setValue([name: "hue", value: "50", deviceId: "colorControlID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 colorControlObject.setValue([name: "saturation", value: "50", deviceId: "colorControlID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /*events*/
 //
 -------------------------------------------------------------------------------
@@ -314,7 +342,7 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 int energy or int currentEnergy
 /*events*/
 energyMeterObject.setValue([name: "energy", value: "45"/*A number between 0 to 100 as a charge*/, deviceId: "energyMeterID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /*events*/
 //
 -------------------------------------------------------------------------------
@@ -324,7 +352,7 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 int illuminance or int currentIlluminance
 /*events*/
 illuminanceMeasurementObject.setValue([name: "illuminance", value: "70"/*A number between 0 to 100 as a charge*/, deviceId: "illuminanceMeasurementID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /*events*/
 //
 -------------------------------------------------------------------------------
@@ -334,7 +362,7 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 int power or int currentPower
 /*events*/
 powerMeterObject.setValue([name: "power", value: "70"/*A number between 0 to 100 as a charge*/, deviceId: "powerMeterID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /*events*/
 //
 -------------------------------------------------------------------------------
@@ -344,7 +372,7 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 int humidity or int currentHumidity
 /*events*/
 humidityMeasurementObject.setValue([name: "humidity", value: "70"/*A number between 0 to 100 as a charge*/, deviceId: "humidityMeasurementID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /*events*/
 //
 -------------------------------------------------------------------------------
@@ -353,10 +381,10 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 //For relay switches:
 String currentSwitch or switchState
 /*events*/
-switchObject.setValue([name: "switch", value: "off", deviceId: "relaySwitchID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
-switchObject.setValue([name: "switch", value: "on", deviceId: "relaySwitchID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+relaySwitchObject.setValue([name: "switch", value: "off", deviceId: "relaySwitchID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+relaySwitchObject.setValue([name: "switch", value: "on", deviceId: "relaySwitchID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -367,9 +395,9 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 String sleeping
 /*events*/
 sleepSensorObject.setValue([name: "sleeping", value: "sleeping", deviceId: "sleepSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 sleepSensorObject.setValue([name: "sleeping", value: "not sleeping", deviceId: "sleepSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -381,9 +409,9 @@ int goal
 int steps
 /*events*/
 stepSensorObject.setValue([name: "goal", value: "100"/*A number*/, deviceId: "stepSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 stepSensorObject.setValue([name: "steps", value: "46"/*A number*/, deviceId: "stepSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -394,7 +422,11 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 int level or int rate
 /*events*/
 switchLevelObject.setValue([name: "level", value: "45"/*A number between 0 to 100*/, deviceId: "switchLevelID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+switchLevelObject.setValue([name: "switch", value: "on", deviceId: "switchLevelID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
+switchLevelObject.setValue([name: "switch", value: "off", deviceId: "switchLevelID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -405,7 +437,7 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 int temperature
 /*events*/
 temperatureMeasurementObject.setValue([name: "temperature", value: "45"/*A number between 0 to 100*/, deviceId: "temperatureMeasurementID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -416,9 +448,9 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 String valve
 /*events*/
 valveObject.setValue([name: "contact", value: "closed", deviceId: "valveID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 valveObject.setValue([name: "contact", value: "open", deviceId: "valveID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
@@ -429,9 +461,9 @@ displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "inf
 String water
 /*events*/
 waterSensorObject.setValue([name: "water", value: "dry", deviceId: "waterSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 waterSensorObject.setValue([name: "water", value: "wet", deviceId: "waterSensorID0", descriptionText: "",
-displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
 /////
 /*events*/
 //
index b0cd6dc..82cbd6a 100644 (file)
@@ -1,67 +1,23 @@
 while(true) {
-       def eventNumber = Verify.getInt(0,53)
+       def eventNumber = Verify.getInt(0,4)
        switch(eventNumber) {
                case 0:
+                       lockObject.setValue([name: "lock", value: "locked", deviceId: "lockID0", descriptionText: "",
+                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
                        break
                case 1:
+                       lockObject.setValue([name: "unlock", value: "unlocked ", deviceId: "lockID0", descriptionText: "",
+                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
                        break
                case 2:
+                       contactObject.setValue([name: "contact.open", value: "open", deviceId: "contactSensorID0", descriptionText: "",
+                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
                        break
                case 3:
-                       def event = Verify.getInt(0,2)
-                       if (event == 0) {
-                                       smokeDetectorObject.setValue([name: "smoke", value: "clear", deviceId: "smokeDetectorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else if (event == 1) {
-                                       smokeDetectorObject.setValue([name: "smoke", value: "detected", deviceId: "smokeDetectorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       smokeDetectorObject.setValue([name: "smoke", value: "tested", deviceId: "smokeDetectorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 4:
-                       def event = Verify.getInt(0,2)
-                       if (event == 0) {
-                                       smokeDetectorObject.setValue([name: "carbonMonoxide", value: "clear", deviceId: "smokeDetectorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else if (event == 1) {
-                                       smokeDetectorObject.setValue([name: "carbonMonoxide", value: "detected", deviceId: "smokeDetectorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       smokeDetectorObject.setValue([name: "carbonMonoxide", value: "tested", deviceId: "smokeDetectorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 5:
-                       break
-               case 6:
-                       break
-               case 7:
-                       lockObject.setValue([name: "lock", value: "locked", deviceId: "lockID0", descriptionText: "",
+                       contactObject.setValue([name: "contact.closed", value: "closed", deviceId: "contactSensorID0", descriptionText: "",
                                        displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
                        break
-               case 8:
-                       def event = Verify.getInt(0,1)
-                       if (event == 0) {
-                                       accelerationSensorObject.setValue([name: "acceleration", value: "active", deviceId: "accelerationSensorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       accelerationSensorObject.setValue([name: "acceleration", value: "inactive", deviceId: "accelerationSensorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 9:
-                       def event = Verify.getInt(0,1)
-                       if (event == 0) {
-                                       motionSensorObject.setValue([name: "motion", value: "active", deviceId: "motionSensorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       motionSensorObject.setValue([name: "motion", value: "inactive", deviceId: "motionSensorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 10:
+               case 4:
                        def event = Verify.getInt(0,1)
                        if (event == 0) {
                                        presenceSensorObject.setValue([name: "presence", value: "present", deviceId: "presenceSensorID0", descriptionText: "",
@@ -71,131 +27,5 @@ while(true) {
                                                        displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"presence":"0","dni":"mobile0"}'])
                        }
                        break
-               case 11:
-                       def event = Verify.getInt(0,1)
-                       if (event == 0) {
-                                       switchObject.setValue([name: "switch", value: "on", deviceId: "switchID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       switchObject.setValue([name: "switch", value: "off", deviceId: "switchID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 12:
-                       break
-               case 13:
-                       smokeDetectorObject.setValue([name: "battery", value: "5", deviceId: "smokeDetectorID0", descriptionText: "",
-                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       break
-               case 14:
-                       break
-               case 15:
-                       break
-               case 16:
-                       break
-               case 17:
-                       break
-               case 18:
-                       break
-               case 19:
-                       def event = Verify.getInt(0,4)
-                       if (event == 0) {
-                                       thermostatObject.setValue([name: "thermostatMode", value: "auto", deviceId: "thermostatID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else if (event == 1) {
-                                       thermostatObject.setValue([name: "thermostatMode", value: "cool", deviceId: "thermostatID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else if (event == 2) {
-                                       thermostatObject.setValue([name: "thermostatMode", value: "emergencyHeat", deviceId: "thermostatID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else if (event == 3) {
-                                       thermostatObject.setValue([name: "thermostatMode", value: "heat", deviceId: "thermostatID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       thermostatObject.setValue([name: "thermostatMode", value: "off", deviceId: "thermostatID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 20:
-                       break
-               case 21:
-                       break
-               case 22:
-                       break
-               case 23:
-                       break
-               case 24:
-                       break
-               case 25:
-                       break
-               case 26:
-                       break
-               case 27:
-                       break
-               case 28:
-                       break
-               case 29:
-                       break
-               case 30:
-                       break
-               case 31:
-                       break
-               case 32:
-                       break
-               case 33:
-                       break
-               case 34:
-                       break
-               case 35:
-                       break
-               case 36:
-                       break
-               case 37:
-                       break
-               case 38:
-                       break
-               case 39:
-                       break
-               case 40:
-                       break
-               case 41:
-                       break
-               case 42:
-                       break
-               case 43:
-                       break
-               case 44:
-                       break
-               case 45:
-                       break
-               case 46:
-                       break
-               case 47:
-                       break
-               case 48:
-                       break
-               case 49:
-                       break
-               case 50:
-                       break
-               case 51:
-                       break
-               case 52:
-                       def event = Verify.getInt(0,2)
-                       if (event == 0) {
-                                       locationObject.setValue([name: "Location", value: "home", deviceId: "locationID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else if (event == 1) {
-                                       locationObject.setValue([name: "Location", value: "away", deviceId: "locationID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       locationObject.setValue([name: "Location", value: "night", deviceId: "locationID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 53:
-                       appObject.setValue([name: "Touched", value: "touched", deviceId: "touchedSensorID0", descriptionText: "",
-                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       break
        }
 }
index 6ef1bda..bccee10 100644 (file)
@@ -188,44 +188,18 @@ class App1 {
        def atomicState
 
        //Extracted objects for App1
-       //Object for class temperature measurement!
-       def temperatures
-       //Object for class thermostat!
-       def thermostats
-       //Object for class presence sensor!
-       def automatic
-       //Object for class smoke detector!
-       def detectors
-       //Object for class humidity measurement!
-       def humidities
-       //Object for class water sensor!
-       def waters
-       //Object for class illuminance measurement!
-       def illuminances
        //Object for class lock!
-       def locks
+       def lock1
        //Object for class contactSensor!
-       def contacts
-       //Object for class Acceleration Sensor!
-       def accelerations
-       //Object for class Motion Sensor!
-       def motions
-       //Object for class presence sensor!
-       def presence
-       //Object for class switch!
-       def switches
-       //Object for class switch level!
-       def dimmerSwitches
-       //Object for class Battery!
-       def batteries
-       //Object for class power meter!
-       def powers
-       //Object for class energy meter!
-       def energys
-       //Global variable for text!
-       def channelKey = "This is just a text!"
+       def contact
+       //Global variable for number!
+       def minutesLater = 48
        //Global variable for number!
-       def givenInterval = 75
+       def secondsLater = 55
+       //Global variable for contact!
+       def recipients = "AJ"
+       //Global variable for phone!
+       def phoneNumber = 9495379373
 
        //Extracted objects for functions for App1
        //Global Object for functions in subscribe method!
@@ -235,102 +209,21 @@ class App1 {
        //Global Object for functions in subscribe method!
        def initialize = this.&initialize
        //Global Object for functions in subscribe method!
-       def appTouch = this.&appTouch
-       //Global Object for functions in subscribe method!
-       def rescheduleIfNeeded = this.&rescheduleIfNeeded
-       //Global Object for functions in subscribe method!
-       def handleTemperatureEvent = this.&handleTemperatureEvent
-       //Global Object for functions in subscribe method!
-       def handleHumidityEvent = this.&handleHumidityEvent
-       //Global Object for functions in subscribe method!
-       def handleHeatingSetpointEvent = this.&handleHeatingSetpointEvent
-       //Global Object for functions in subscribe method!
-       def handleCoolingSetpointEvent = this.&handleCoolingSetpointEvent
-       //Global Object for functions in subscribe method!
-       def handleThermostatModeEvent = this.&handleThermostatModeEvent
-       //Global Object for functions in subscribe method!
-       def handleFanModeEvent = this.&handleFanModeEvent
-       //Global Object for functions in subscribe method!
-       def handleHumidifierModeEvent = this.&handleHumidifierModeEvent
-       //Global Object for functions in subscribe method!
-       def handleHumidifierLevelEvent = this.&handleHumidifierLevelEvent
-       //Global Object for functions in subscribe method!
-       def handleDehumidifierModeEvent = this.&handleDehumidifierModeEvent
-       //Global Object for functions in subscribe method!
-       def handleDehumidifierLevelEvent = this.&handleDehumidifierLevelEvent
-       //Global Object for functions in subscribe method!
-       def handleVentilatorModeEvent = this.&handleVentilatorModeEvent
-       //Global Object for functions in subscribe method!
-       def handleFanMinOnTimeEvent = this.&handleFanMinOnTimeEvent
-       //Global Object for functions in subscribe method!
-       def handleVentilatorMinOnTimeEvent = this.&handleVentilatorMinOnTimeEvent
-       //Global Object for functions in subscribe method!
-       def handleThermostatOperatingStateEvent = this.&handleThermostatOperatingStateEvent
-       //Global Object for functions in subscribe method!
-       def handleDailyStats = this.&handleDailyStats
-       //Global Object for functions in subscribe method!
-       def handleEquipmentStatusEvent = this.&handleEquipmentStatusEvent
-       //Global Object for functions in subscribe method!
-       def handleProgramNameEvent = this.&handleProgramNameEvent
+       def lockDoor = this.&lockDoor
        //Global Object for functions in subscribe method!
-       def handleWaterEvent = this.&handleWaterEvent
+       def unlockDoor = this.&unlockDoor
        //Global Object for functions in subscribe method!
-       def handleSmokeEvent = this.&handleSmokeEvent
-       //Global Object for functions in subscribe method!
-       def handleCarbonMonoxideEvent = this.&handleCarbonMonoxideEvent
-       //Global Object for functions in subscribe method!
-       def handleIlluminanceEvent = this.&handleIlluminanceEvent
-       //Global Object for functions in subscribe method!
-       def handleLockEvent = this.&handleLockEvent
-       //Global Object for functions in subscribe method!
-       def handleBatteryEvent = this.&handleBatteryEvent
-       //Global Object for functions in subscribe method!
-       def handleContactEvent = this.&handleContactEvent
-       //Global Object for functions in subscribe method!
-       def handleAccelerationEvent = this.&handleAccelerationEvent
-       //Global Object for functions in subscribe method!
-       def handleMotionEvent = this.&handleMotionEvent
-       //Global Object for functions in subscribe method!
-       def handlePresenceEvent = this.&handlePresenceEvent
-       //Global Object for functions in subscribe method!
-       def handleSwitchEvent = this.&handleSwitchEvent
-       //Global Object for functions in subscribe method!
-       def handleSetLevelEvent = this.&handleSetLevelEvent
-       //Global Object for functions in subscribe method!
-       def handlePowerEvent = this.&handlePowerEvent
-       //Global Object for functions in subscribe method!
-       def handleEnergyEvent = this.&handleEnergyEvent
-       //Global Object for functions in subscribe method!
-       def handleCostEvent = this.&handleCostEvent
-       //Global Object for functions in subscribe method!
-       def queueValue = this.&queueValue
-       //Global Object for functions in subscribe method!
-       def processQueue = this.&processQueue
+       def doorHandler = this.&doorHandler
 
        App1(Object obj) {
                reference = obj
                location = obj.locationObject
                app = obj.appObject
                atomicState = obj.atomicState
-               temperatures = obj.temperatureMeasurementObject
-               thermostats = obj.thermostatObject
-               automatic = obj.presenceSensorObject
-               detectors = obj.smokeDetectorObject
-               humidities = obj.humidityMeasurementObject
-               waters = obj.waterSensorObject
-               illuminances = obj.illuminanceMeasurementObject
-               locks = obj.lockObject
-               contacts = obj.contactObject
-               accelerations = obj.accelerationSensorObject
-               motions = obj.motionSensorObject
-               presence = obj.presenceSensorObject
-               switches = obj.switchObject
-               dimmerSwitches = obj.switchLevelObject
-               batteries = obj.batteryObject
-               powers = obj.powerMeterObject
-               energys = obj.energyMeterObject
+               lock1 = obj.lockObject
+               contact = obj.contactObject
                //Global variable for settings!
-               settings = [app:app, temperatures:temperatures, thermostats:thermostats, automatic:automatic, detectors:detectors, humidities:humidities, waters:waters, illuminances:illuminances, locks:locks, contacts:contacts, accelerations:accelerations, motions:motions, presence:presence, switches:switches, dimmerSwitches:dimmerSwitches, batteries:batteries, powers:powers, energys:energys, channelKey:channelKey, givenInterval:givenInterval]
+               settings = [app:app, lock1:lock1, contact:contact, minutesLater:minutesLater, secondsLater:secondsLater, recipients:recipients, phoneNumber:phoneNumber]
        }
        //Global variables for each app
        //Global variable for state[mode]
@@ -543,379 +436,91 @@ class App1 {
                return true
        }
 
-       def installed() {
-               initialize()
-       }
-       
-       def updated() {
-               unsubscribe()
-               unschedule()
-               initialize()
-       }
-       
-       def initialize() {
-               subscribe(temperatures, "temperature", handleTemperatureEvent)
-               subscribe(humidities, "humidity", handleHumidityEvent)
-               subscribe(waters, "water", handleWaterEvent)
-               subscribe(waters, "water", handleWaterEvent)
-               subscribe(detectors, "smoke", handleSmokeEvent)
-               subscribe(detectors, "carbonMonoxide", handleCarbonMonoxideEvent)
-               subscribe(illuminances, "illuminance", handleIlluminanceEvent)
-               subscribe(contacts, "contact", handleContactEvent)
-               subscribe(locks, "lock", handleLockEvent)
-               subscribe(accelerations, "acceleration", handleAccelerationEvent)
-               subscribe(motions, "motion", handleMotionEvent)
-               subscribe(presence, "presence", handlePresenceEvent)
-               subscribe(switches, "switch", handleSwitchEvent)
-               subscribe(dimmerSwitches, "switch", handleSwitchEvent)
-               subscribe(dimmerSwitches, "level", handleSetLevelEvent)
-               subscribe(batteries, "battery", handleBatteryEvent)
-               subscribe(powers, "power", handlePowerEvent)
-               subscribe(energys, "energy", handleEnergyEvent)
-               subscribe(energys, "cost", handleCostEvent)
-               subscribe(thermostats, "heatingSetpoint", handleHeatingSetpointEvent)
-               subscribe(thermostats, "coolingSetpoint", handleCoolingSetpointEvent)
-               subscribe(thermostats, "thermostatMode", handleThermostatModeEvent)
-               subscribe(thermostats, "fanMode", handleFanModeEvent)
-               subscribe(thermostats, "thermostatOperatingState", handleThermostatOperatingStateEvent)
-               /*subscribe(ecobees, "dehumidifierMode", handleDehumidifierModeEvent)
-               subscribe(ecobees, "equipmentStatus", handleEquipmentStatusEvent)
-               subscribe(ecobees, "dehumidifierLevel", handleDehumidifierLevelEvent)
-               subscribe(ecobees, "humidifierMode", handleHumidifierModeEvent)
-               subscribe(ecobees, "humidifierLevel", handleHumidifierLevelEvent)
-               subscribe(ecobees, "fanMinOnTime", handleFanMinOnTimeEvent)
-               subscribe(ecobees, "ventilatorMode", handleVentilatorModeEvent)
-               subscribe(ecobees, "ventilatorMinOnTime", handleVentilatorMinOnTimeEvent)
-               subscribe(ecobees, "programScheduleName", handleProgramNameEvent)
-               subscribe(ecobees, "auxHeat1RuntimeDaily", handleDailyStats)
-               subscribe(ecobees, "auxHeat2RuntimeDaily", handleDailyStats)
-               subscribe(ecobees, "auxHeat3RuntimeDaily", handleDailyStats)
-               subscribe(ecobees, "compCool1RuntimeDaily", handleDailyStats)
-               subscribe(ecobees, "compCool2RuntimeDaily", handleDailyStats)
-               subscribe(ecobees, "fanRuntimeDaily", handleDailyStats)
-               subscribe(ecobees, "humidifierRuntimeDaily", handleDailyStats)
-               subscribe(ecobees, "dehumidifierRuntimeDaily", handleDailyStats)
-               subscribe(ecobees, "ventilatorRuntimeDaily", handleDailyStats)
-               subscribe(ecobees, "presence", handlePresenceEvent)
-               subscribe(ecobees, "compCool2RuntimeDaily", handleDailyStats)*/
-               subscribe(automatic, "yesterdayTripsAvgAverageKmpl",handleDailyStats)
-               subscribe(automatic, "yesterdayTripsAvgDistanceM",handleDailyStats)
-               subscribe(automatic, "yesterdayTripsAvgDurationS",handleDailyStats)
-               subscribe(automatic, "yesterdayTotalDistanceM",handleDailyStats)
-               subscribe(automatic, "yesterdayTripsAvgFuelVolumeL",handleDailyStats)
-               subscribe(automatic, "yesterdayTotalFuelVolumeL",handleDailyStats)
-               subscribe(automatic, "yesterdayTotalDurationS:",handleDailyStats)
-               subscribe(automatic, "yesterdayTotalNbTrips",handleDailyStats)
-               subscribe(automatic, "yesterdayTotalHardAccels",handleDailyStats)
-               subscribe(automatic, "yesterdayTotalHardBrakes:",handleDailyStats)
-               subscribe(automatic, "yesterdayTripsAvgScoreSpeeding",handleDailyStats)
-               subscribe(automatic, "yesterdayTripsAvgScoreEvents",handleDailyStats)
-               def queue = []
-               atomicState.queue=queue
-           
-               if (atomicState.queue==null) {
-                       atomicState.queue = []
-               }    
-               atomicState?.poll = [ last: 0, rescheduled: now() ]
-       
-               Integer delay  = givenInterval ?: 5 // By default, schedule processQueue every 5 min.
-               log.debug "initialize>scheduling processQueue every ${delay} minutes"
-       
-               //Subscribe to different events (ex. sunrise and sunset events) to trigger rescheduling if needed
-               subscribe(location, "sunrise", rescheduleIfNeeded)
-               subscribe(location, "sunset", rescheduleIfNeeded)
-               subscribe(location, "mode", rescheduleIfNeeded)
-               subscribe(location, "sunriseTime", rescheduleIfNeeded)
-               subscribe(location, "sunsetTime", rescheduleIfNeeded)
-               subscribe(app, appTouch)
-       
-               //rescheduleIfNeeded()   
-       }
-       
-       def appTouch(evt) {
-               rescheduleIfNeeded(evt)
-               processQueue()
-               def queue = []
-               atomicState.queue=queue
-       }
-       
-       
-       def rescheduleIfNeeded(evt) {
-               if (evt) log.debug("rescheduleIfNeeded>$evt.name=$evt.value")
-               Integer delay  = givenInterval ?: 5 // By default, schedule processQueue every 5 min.
-               BigDecimal currentTime = now()    
-               BigDecimal lastPollTime = (currentTime - (atomicState?.poll["last"]?:0))  
-               if (lastPollTime != currentTime) {    
-                       Double lastPollTimeInMinutes = (lastPollTime/60000).toDouble().round(1)      
-                       log.info "rescheduleIfNeeded>last poll was  ${lastPollTimeInMinutes.toString()} minutes ago"
-               }
-               if (((atomicState?.poll["last"]?:0) + (delay * 60000) < currentTime) && canSchedule()) {
-                       log.info "rescheduleIfNeeded>scheduling processQueue in ${delay} minutes.."
-                       unschedule()  
-                       schedule("14:00", processQueue)
-               }
-               // Update rescheduled state
-           
-               if (!evt) {
-                       atomicState.poll["rescheduled"] = now()    
-               }        
-       }    
-       
-       def handleTemperatureEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       
-       def handleHumidityEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       
-       def handleHeatingSetpointEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       def handleCoolingSetpointEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       
-       def handleThermostatModeEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       def handleFanModeEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       def handleHumidifierModeEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       def handleHumidifierLevelEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       def handleDehumidifierModeEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       def handleDehumidifierLevelEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       def handleVentilatorModeEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       def handleFanMinOnTimeEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       def handleVentilatorMinOnTimeEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       
-       def handleThermostatOperatingStateEvent(evt) {
-               queueValue(evt) {
-                       it == "idle" ? 0 : (it == 'fan only') ? 1 : (it == 'heating') ? 2 : 3
-               }
-       
-       }
-       def handleDailyStats(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       
-       }
-       def handleEquipmentStatusEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       
-       def handleProgramNameEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       
-       def handleWaterEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       def handleSmokeEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       def handleCarbonMonoxideEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       
-       def handleIlluminanceEvent(evt) {
-               log.debug ("handleIlluminanceEvent> $evt.name= $evt.value")
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       
-       def handleLockEvent(evt) {
-               queueValue(evt) {
-                       it == "locked" ? 1 : 0
-               }
-       }
-       
-       def handleBatteryEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
-       }
-       
-       def handleContactEvent(evt) {
-               queueValue(evt) {
-                       it == "open" ? 1 : 0
-               }
-       }
-       
-       def handleAccelerationEvent(evt) {
-               queueValue(evt) {
-                       it == "active" ? 1 : 0
-               }
-       }
-       
-       def handleMotionEvent(evt) {
-               queueValue(evt) {
-                       it == "active" ? 1 : 0
-               }
-       }
-       
-       def handlePresenceEvent(evt) {
-               queueValue(evt) {
-                       it == "present" ? 1 : 0
-               }
-       }
-       
-       def handleSwitchEvent(evt) {
-               queueValue(evt) {
-                       it == "on" ? 1 : 0
-               }
+       def installed(){
+           initialize()
        }
        
-       def handleSetLevelEvent(evt) {
-               queueValue(evt) {
-                       it.toString()
-               }
+       def updated(){
+           unsubscribe()
+           unschedule()
+           initialize()
        }
        
-       def handlePowerEvent(evt) {
-               if (evt.value) {
-                       queueValue(evt) {
-                               it.toString()
-                       }
-               }
+       def initialize(){
+           log.debug "Settings: ${settings}"
+           subscribe(lock1, "lock", doorHandler, [filterEvents: false])
+           subscribe(lock1, "unlock", doorHandler, [filterEvents: false])  
+           subscribe(contact, "contact.open", doorHandler)
+           subscribe(contact, "contact.closed", doorHandler)
        }
        
-       def handleEnergyEvent(evt) {
-               if (evt.value) {
-                       queueValue(evt) {
-                               it.toString()
-                       }
-               }
-       }
-       def handleCostEvent(evt) {
-               if (evt.value) {
-                       queueValue(evt) {
-                               it.toString()
-                       }
-               }
+       def lockDoor(){
+           log.debug "Locking the door."
+           lock1.lock()
+           if(location.contactBookEnabled) {
+               if ( recipients ) {
+                   log.debug ( "Sending Push Notification..." ) 
+                   sendNotificationToContacts( "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!", recipients)
+               }
+           }
+           if (phoneNumber) {
+               log.debug("Sending text message...")
+               sendSms( phoneNumber, "${lock1} locked after ${contact} was closed for ${minutesLater} minutes!")
+           }
        }
        
-       private queueValue(evt, Closure convert) {
-               def MAX_QUEUE_SIZE=95000
-               def jsonPayload = [compId: evt.displayName, streamId: evt.name, data: convert(evt.value), time: now()]
-               def queue
-       
-               queue = atomicState.queue
-               queue << jsonPayload
-               atomicState.queue = queue    
-               def queue_size = queue.toString().length()
-               def last_item_in_queue = queue[queue.size() -1]    
-               log.debug "queueValue>queue size in chars=${queue_size}, appending ${jsonPayload} to queue, last item in queue= $last_item_in_queue"
-               if (queue_size >  MAX_QUEUE_SIZE) {
-                       processQueue()
-               }
+       def unlockDoor(){
+           log.debug "Unlocking the door."
+           lock1.unlock()
+           if(location.contactBookEnabled) {
+               if ( recipients ) {
+                   log.debug ( "Sending Push Notification..." ) 
+                   sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!", recipients)
+               }
+           }
+           if ( phoneNumber ) {
+               log.debug("Sending text message...")
+               sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened for ${secondsLater} seconds!")
+           }
        }
        
-       def processQueue() {
-               Integer delay  = givenInterval ?: 5 // By default, schedule processQueue every 5 min.
-               atomicState?.poll["last"] = now()
-       
-               if (((atomicState?.poll["rescheduled"]?:0) + (delay * 60000)) < now()) {
-                       log.info "processQueue>scheduling rescheduleIfNeeded() in ${delay} minutes.."
-                       schedule("0 0/${delay} * * * ?", rescheduleIfNeeded)
-                       // Update rescheduled state
-                       atomicState?.poll["rescheduled"] = now()
-               }
-       
-               def queue = atomicState.queue
-           
-          
-               def url = "https://grovestreams.com/api/feed?api_key=${channelKey}"
-               log.debug "processQueue"
-               if (queue != []) {
-                       log.debug "Events to be sent to groveStreams: ${queue}"
-       
-                       /*try {
-                               httpPutJson([uri: url, body: queue]) {response ->
-                                       if (response.status != 200) {
-                                               log.debug "GroveStreams logging failed, status = ${response.status}"
-                                       } else {
-                                               log.debug "GroveStreams accepted event(s)"
-                                               // reset the queue 
-                                               queue =[]                         
-                                               atomicState.queue = queue                     
-                                       }
-                               }
-                       } catch (groovyx.net.http.ResponseParseException e) {
-                               // ignore error 200, bogus exception
-                               if (e.statusCode != 200) {
-                                       log.error "Grovestreams: ${e}"
-                               } else {
-                                       log.debug "GroveStreams accepted event(s)"
-                               }
-                               // reset the queue 
-                               queue =[]                         
-                               atomicState.queue = queue                      
-                   
-                       } catch (e) {
-                               def errorInfo = "Error sending value: ${e}"
-                               log.error errorInfo
-                               // reset the queue 
-                               queue =[]                         
-                               atomicState.queue = queue                        
-                       }*/
-               }
-       
+       def doorHandler(evt){
+           if ((contact.latestValue("contact") == "open") && (evt.value == "locked")) { // If the door is open and a person locks the door then...  
+               //def delay = (secondsLater) // runIn uses seconds
+               runIn( secondsLater, unlockDoor )   // ...schedule (in minutes) to unlock...  We don't want the door to be closed while the lock is engaged. 
+           }
+           else if ((contact.latestValue("contact") == "open") && (evt.value == "unlocked")) { // If the door is open and a person unlocks it then...
+               unschedule( unlockDoor ) // ...we don't need to unlock it later.
+           }
+           else if ((contact.latestValue("contact") == "closed") && (evt.value == "locked")) { // If the door is closed and a person manually locks it then...
+               unschedule( lockDoor ) // ...we don't need to lock it later.
+           }   
+           else if ((contact.latestValue("contact") == "closed") && (evt.value == "unlocked")) { // If the door is closed and a person unlocks it then...
+              //def delay = (minutesLater * 60) // runIn uses seconds
+               runIn( (minutesLater * 60), lockDoor ) // ...schedule (in minutes) to lock.
+           }
+           else if ((lock1.latestValue("lock") == "unlocked") && (evt.value == "open")) { // If a person opens an unlocked door...
+               unschedule( lockDoor ) // ...we don't need to lock it later.
+           }
+           else if ((lock1.latestValue("lock") == "unlocked") && (evt.value == "closed")) { // If a person closes an unlocked door...
+               //def delay = (minutesLater * 60) // runIn uses seconds
+               runIn( (minutesLater * 60), lockDoor ) // ...schedule (in minutes) to lock.
+           }
+           else { //Opening or Closing door when locked (in case you have a handle lock)
+               log.debug "Unlocking the door."
+               lock1.unlock()
+               if(location.contactBookEnabled) {
+                   if ( recipients ) {
+                       log.debug ( "Sending Push Notification..." ) 
+                       sendNotificationToContacts( "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!", recipients)
+                   }
+               }
+               if ( phoneNumber ) {
+                   log.debug("Sending text message...")
+                   sendSms( phoneNumber, "${lock1} unlocked after ${contact} was opened or closed when ${lock1} was locked!")
+               }
+           }
        }
-       
 }
 
 
@@ -927,42 +532,96 @@ class App2 {
        def atomicState
 
        //Extracted objects for App2
+       //Global variable for time!
+       def starting = "15:00"
+       //Global variable for time!
+       def ending = "15:00"
+       //Object for class beacon sensor!
+       def beacons
+       //Object for class mobile presence!
+       def phones
+       //Global variable for enum!
+       def arrivalPhrase = "Good Night!"
+       //Object for class switch!
+       def arrivalOnSwitches
+       //Object for class switch!
+       def arrivalOffSwitches
        //Object for class lock!
-       def aLock
-       //Object for class contactSensor!
-       def openSensor
-       //Global variable for number!
-       def duration = 47
+       def arrivalLocks
+       //Global variable for enum!
+       def departPhrase = "Good Night!"
+       //Object for class switch!
+       def departOnSwitches
+       //Object for class switch!
+       def departOffSwitches
+       //Object for class lock!
+       def departLocks
        //Global variable for boolean!
        def pushNotification = "0"
        //Global variable for phone!
-       def phoneNumber = 9495379373
-       //Global variable for boolean!
-       def lockIfClosed = "1"
+       def phone = 9495379373
+       //Global variable for enum!
+       def days = "Monday"
+       //Global variable for mode!
+       def modes = "away"
 
        //Extracted objects for functions for App2
        //Global Object for functions in subscribe method!
+       def mainPage = this.&mainPage
+       //Global Object for functions in subscribe method!
        def installed = this.&installed
        //Global Object for functions in subscribe method!
        def updated = this.&updated
        //Global Object for functions in subscribe method!
        def initialize = this.&initialize
        //Global Object for functions in subscribe method!
-       def lockHandler = this.&lockHandler
+       def beaconHandler = this.&beaconHandler
+       //Global Object for functions in subscribe method!
+       def arriveActions = this.&arriveActions
+       //Global Object for functions in subscribe method!
+       def departActions = this.&departActions
+       //Global Object for functions in subscribe method!
+       def prefix = this.&prefix
        //Global Object for functions in subscribe method!
-       def notifyUnlocked = this.&notifyUnlocked
+       def listPhrases = this.&listPhrases
        //Global Object for functions in subscribe method!
-       def sendMessage = this.&sendMessage
+       def executePhrase = this.&executePhrase
+       //Global Object for functions in subscribe method!
+       def getBeaconName = this.&getBeaconName
+       //Global Object for functions in subscribe method!
+       def getPhoneName = this.&getPhoneName
+       //Global Object for functions in subscribe method!
+       def hideOptionsSection = this.&hideOptionsSection
+       //Global Object for functions in subscribe method!
+       def getAllOk = this.&getAllOk
+       //Global Object for functions in subscribe method!
+       def getModeOk = this.&getModeOk
+       //Global Object for functions in subscribe method!
+       def getDaysOk = this.&getDaysOk
+       //Global Object for functions in subscribe method!
+       def getTimeOk = this.&getTimeOk
+       //Global Object for functions in subscribe method!
+       def hhmm = this.&hhmm
+       //Global Object for functions in subscribe method!
+       def timeIntervalLabel = this.&timeIntervalLabel
+       //Global Object for functions in subscribe method!
+       def list = this.&list
 
        App2(Object obj) {
                reference = obj
                location = obj.locationObject
                app = obj.appObject
                atomicState = obj.atomicState
-               aLock = obj.lockObject
-               openSensor = obj.contactObject
+               beacons = obj.beaconSensorObject
+               phones = obj.mobilePresenceObject
+               arrivalOnSwitches = obj.switchObject
+               arrivalOffSwitches = obj.switchObject
+               arrivalLocks = obj.lockObject
+               departOnSwitches = obj.switchObject
+               departOffSwitches = obj.switchObject
+               departLocks = obj.lockObject
                //Global variable for settings!
-               settings = [app:app, aLock:aLock, openSensor:openSensor, duration:duration, pushNotification:pushNotification, phoneNumber:phoneNumber, lockIfClosed:lockIfClosed]
+               settings = [app:app, starting:starting, ending:ending, beacons:beacons, phones:phones, arrivalPhrase:arrivalPhrase, arrivalOnSwitches:arrivalOnSwitches, arrivalOffSwitches:arrivalOffSwitches, arrivalLocks:arrivalLocks, departPhrase:departPhrase, departOnSwitches:departOnSwitches, departOffSwitches:departOffSwitches, departLocks:departLocks, pushNotification:pushNotification, phone:phone, days:days, modes:modes]
        }
        //Global variables for each app
        //Global variable for state[mode]
@@ -1175,75 +834,278 @@ class App2 {
                return true
        }
 
-       def installed()
-       {
-           initialize()
+       def mainPage() {
+               dynamicPage(name: "mainPage", install: true, uninstall: true) {
+       
+                       section("Where do you want to watch?") {
+                               input name: "beacons", type: "capability.beacon", title: "Select your beacon(s)", 
+                                       multiple: true, required: true
+                       }
+       
+                       section("Who do you want to watch for?") {
+                               input name: "phones", type: "device.mobilePresence", title: "Select your phone(s)", 
+                                       multiple: true, required: true
+                       }
+       
+                       section("What do you want to do on arrival?") {
+                               input name: "arrivalPhrase", type: "enum", title: "Execute a phrase", 
+                                       options: listPhrases(), required: false
+                               input "arrivalOnSwitches", "capability.switch", title: "Turn on some switches", 
+                                       multiple: true, required: false
+                               input "arrivalOffSwitches", "capability.switch", title: "Turn off some switches", 
+                                       multiple: true, required: false
+                               input "arrivalLocks", "capability.lock", title: "Unlock the door",
+                                       multiple: true, required: false
+                       }
+       
+                       section("What do you want to do on departure?") {
+                               input name: "departPhrase", type: "enum", title: "Execute a phrase", 
+                                       options: listPhrases(), required: false
+                               input "departOnSwitches", "capability.switch", title: "Turn on some switches", 
+                                       multiple: true, required: false
+                               input "departOffSwitches", "capability.switch", title: "Turn off some switches", 
+                                       multiple: true, required: false
+                               input "departLocks", "capability.lock", title: "Lock the door",
+                                       multiple: true, required: false
+                       }
+       
+                       section("Do you want to be notified?") {
+                               input "pushNotification", "bool", title: "Send a push notification"
+                               input "phone", "phone", title: "Send a text message", description: "Tap to enter phone number", 
+                                       required: false
+                       }
+       
+                       section {
+                               label title: "Give your automation a name", description: "e.g. Goodnight Home, Wake Up"
+                       }
+       
+                       def timeLabel = timeIntervalLabel()
+                       section(title: "More options", hidden: hideOptionsSection(), hideable: true) {
+                               href "timeIntervalInput", title: "Only during a certain time", 
+                                       description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : "incomplete"
+       
+                               input "days", "enum", title: "Only on certain days of the week", multiple: true, required: false,
+                                       options: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
+       
+                               input "modes", "mode", title: "Only when mode is", multiple: true, required: false
+                       }
+               }
        }
        
-       def updated()
-       {
-           unsubscribe()
-           initialize()
+       // Lifecycle management
+       def installed() {
+               log.debug "<beacon-control> Installed with settings: ${settings}"
+               initialize()
        }
        
-       def initialize()
-       {
-           log.trace "Initializing with: ${settings}"
-           subscribe(aLock, "lock", lockHandler)
+       def updated() {
+               log.debug "<beacon-control> Updated with settings: ${settings}"
+               unsubscribe()
+               initialize()
        }
        
-       def lockHandler(evt)
-       {
-           log.trace "${evt.name} is ${evt.value}."
-           if (evt.value == "locked") {
-               log.debug "Canceling lock check because the door is locked..."
-               unschedule(notifyUnlocked)
-           }
-           else {
-               log.debug "Starting the countdown for ${duration} minutes..."
-               state.retries = 0
-               runIn(duration * 60, notifyUnlocked)
-           }
+       def initialize() {
+               subscribe(beacons, "presence", beaconHandler)
        }
        
-       def notifyUnlocked()
-       {
-           // if no open/close sensor specified, assume the door is closed
-           def open = openSensor?.latestValue("contact") ?: "closed"
+       // Event handlers
+       def beaconHandler(evt) {
+               log.debug "<beacon-control> beaconHandler: $evt"
        
-           def message = "${aLock.displayName} is left unlocked and ${open} for more than ${duration} minutes."
-           log.trace "Sending the notification: ${message}."
-           sendMessage(message)
+               if (allOk) {
+                       def data = new groovy.json.JsonSlurper().parseText(evt.data)
+                       // removed logging of device names. can be added back for debugging
+                       //log.debug "<beacon-control> data: $data - phones: " + phones*.deviceNetworkId
        
-           if (lockIfClosed) {
-               if (open == "closed") {
-                   log.trace "And locking the door."
-                   sendMessage("Locking the ${aLock.displayName} as prescribed.")
-                   aLock.lock()
-               }
-               else {
-                   if (state.retries++ < 3) {
-                       log.trace "Door is open, can't lock. Rescheduling the check."
-                       sendMessage("Can't lock the ${aLock.displayName} because the door is open. Will try again in ${duration} minutes.")
-                       runIn(duration * 60, notifyUnlocked)
+                       def beaconName = getBeaconName(evt)
+                       // removed logging of device names. can be added back for debugging
+                       //log.debug "<beacon-control> beaconName: $beaconName"
+       
+                       def phoneName = getPhoneName(data)
+                       // removed logging of device names. can be added back for debugging
+                       //log.debug "<beacon-control> phoneName: $phoneName"
+                       if (phoneName != null) {
+                   def action = data.presence == "1" ? "arrived" : "left"
+                   def msg = "$phoneName has $action ${action == 'arrived' ? 'at ' : ''}the $beaconName"
+       
+                   if (action == "arrived") {
+                       msg = arriveActions(msg)
                    }
-                   else {
-                       log.trace "The door is still open after ${state.retries} retries, giving up."
-                       sendMessage("Unable to lock the ${aLock.displayName} after ${state.retries} retries, giving up.")
+                   else if (action == "left") {
+                       msg = departActions(msg)
+                   }
+                   log.debug "<beacon-control> msg: $msg"
+       
+                   if (pushNotification || phone) {
+                       def options = [
+                           method: (pushNotification && phone) ? "both" : (pushNotification ? "push" : "sms"),
+                           phone: phone
+                       ]
+                       sendNotification(msg, options)
                    }
                }
-           }
+               }
        }
        
-       def sendMessage(msg) {
-           if (pushNotification) {
-               sendPush(msg)
-           }
-           if (phoneNumber) {
-               sendSMS(phoneNumber, msg)
-           }
+       // Helpers
+       private arriveActions(msg) {
+               if (arrivalPhrase || arrivalOnSwitches || arrivalOffSwitches || arrivalLocks) msg += ", so"
+               
+               if (arrivalPhrase) {
+                       log.debug "<beacon-control> executing: $arrivalPhrase"
+                       executePhrase(arrivalPhrase)
+                       msg += " ${prefix('executed')} $arrivalPhrase."
+               }
+               if (arrivalOnSwitches) {
+                       log.debug "<beacon-control> turning on: $arrivalOnSwitches"
+                       arrivalOnSwitches.on()
+                       msg += " ${prefix('turned')} ${list(arrivalOnSwitches)} on."
+               }
+               if (arrivalOffSwitches) {
+                       log.debug "<beacon-control> turning off: $arrivalOffSwitches"
+                       arrivalOffSwitches.off()
+                       msg += " ${prefix('turned')} ${list(arrivalOffSwitches)} off."
+               }
+               if (arrivalLocks) {
+                       log.debug "<beacon-control> unlocking: $arrivalLocks"
+                       arrivalLocks.unlock()
+                       msg += " ${prefix('unlocked')} ${list(arrivalLocks)}."
+               }
+               msg
+       }
+       
+       private departActions(msg) {
+               if (departPhrase || departOnSwitches || departOffSwitches || departLocks) msg += ", so"
+               
+               if (departPhrase) {
+                       log.debug "<beacon-control> executing: $departPhrase"
+                       executePhrase(departPhrase)
+                       msg += " ${prefix('executed')} $departPhrase."
+               }
+               if (departOnSwitches) {
+                       log.debug "<beacon-control> turning on: $departOnSwitches"
+                       departOnSwitches.on()
+                       msg += " ${prefix('turned')} ${list(departOnSwitches)} on."
+               }
+               if (departOffSwitches) {
+                       log.debug "<beacon-control> turning off: $departOffSwitches"
+                       departOffSwitches.off()
+                       msg += " ${prefix('turned')} ${list(departOffSwitches)} off."
+               }
+               if (departLocks) {
+                       log.debug "<beacon-control> unlocking: $departLocks"
+                       departLocks.lock()
+                       msg += " ${prefix('locked')} ${list(departLocks)}."
+               }
+               msg
+       }
+       
+       private prefix(word) {
+               def result
+               def index = settings.prefixIndex == null ? 0 : settings.prefixIndex + 1
+               switch (index) {
+                       case 0:
+                               result = "I $word"
+                               break
+                       case 1:
+                               result = "I also $word"
+                               break
+                       case 2:
+                               result = "And I $word"
+                               break
+                       default:
+                               result = "And $word"
+                               break
+               }
+       
+               settings.prefixIndex = index
+               log.trace "prefix($word'): $result"
+               result
+       }
+       
+       private listPhrases() {
+               location.helloHome.getPhrases().label
+       }
+       
+       private executePhrase(phraseName) {
+               if (phraseName) {
+                       location.helloHome.execute(phraseName)
+                       log.debug "<beacon-control> executed phrase: $phraseName"
+               }
+       }
+       
+       private getBeaconName(evt) {
+               def beaconName = beacons.find { b -> b.id == evt.deviceId }
+               return beaconName
+       }
+       
+       private getPhoneName(data) {    
+               def phoneName = phones.find { phone ->
+                       // Work around DNI bug in data
+                       def pParts = phone.deviceNetworkId.split('\\|')
+                       def dParts = data.dni.split('\\|')
+               pParts[0] == dParts[0]
+               }
+               return phoneName
+       }
+       
+       private hideOptionsSection() {
+               (starting || ending || days || modes) ? false : true
+       }
+       
+       private getAllOk() {
+               modeOk && daysOk && timeOk
+       }
+       
+       private getModeOk() {
+               def result = !modes || modes.contains(location.mode)
+               log.trace "<beacon-control> modeOk = $result"
+               result
+       }
+       
+       private getDaysOk() {
+               def result = true
+               if (days) {
+                       def df = new java.text.SimpleDateFormat("EEEE")
+                       if (location.timeZone) {
+                               df.setTimeZone(location.timeZone)
+                       }
+                       else {
+                               df.setTimeZone(TimeZone.getTimeZone("America/New_York"))
+                       }
+                       def day = df.format(new Date())
+                       result = days.contains(day)
+               }
+               log.trace "<beacon-control> daysOk = $result"
+               result
+       }
+       
+       private getTimeOk() {
+               def result = true
+               if (starting && ending) {
+                       def currTime = now()
+                       def start = timeToday(starting, location?.timeZone).time
+                       def stop = timeToday(ending, location?.timeZone).time
+                       result = start < stop ? currTime >= start && currTime <= stop : currTime <= stop || currTime >= start
+               }
+               log.trace "<beacon-control> timeOk = $result"
+               result
+       }
+       
+       private hhmm(time, fmt = "h:mm a") {
+               def t = timeToday(time, location.timeZone)
+               def f = new java.text.SimpleDateFormat(fmt)
+               f.setTimeZone(location.timeZone ?: timeZone(time))
+               f.format(t)
        }
        
+       private timeIntervalLabel() {
+               (starting && ending) ? hhmm(starting) + "-" + hhmm(ending, "h:mm a z") : ""
+       }
+       
+       private list(Object names) {
+               return names[0]
+       }
 }
 
 @Field def app1
@@ -1267,69 +1129,25 @@ if (installOrder) {
 }
 
 while(true) {
-       def eventNumber = Verify.getInt(0,53)
+       def eventNumber = Verify.getInt(0,4)
        switch(eventNumber) {
                case 0:
+                       lockObject.setValue([name: "lock", value: "locked", deviceId: "lockID0", descriptionText: "",
+                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
                        break
                case 1:
+                       lockObject.setValue([name: "unlock", value: "unlocked ", deviceId: "lockID0", descriptionText: "",
+                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
                        break
                case 2:
+                       contactObject.setValue([name: "contact.open", value: "open", deviceId: "contactSensorID0", descriptionText: "",
+                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
                        break
                case 3:
-                       def event = Verify.getInt(0,2)
-                       if (event == 0) {
-                                       smokeDetectorObject.setValue([name: "smoke", value: "clear", deviceId: "smokeDetectorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else if (event == 1) {
-                                       smokeDetectorObject.setValue([name: "smoke", value: "detected", deviceId: "smokeDetectorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       smokeDetectorObject.setValue([name: "smoke", value: "tested", deviceId: "smokeDetectorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 4:
-                       def event = Verify.getInt(0,2)
-                       if (event == 0) {
-                                       smokeDetectorObject.setValue([name: "carbonMonoxide", value: "clear", deviceId: "smokeDetectorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else if (event == 1) {
-                                       smokeDetectorObject.setValue([name: "carbonMonoxide", value: "detected", deviceId: "smokeDetectorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       smokeDetectorObject.setValue([name: "carbonMonoxide", value: "tested", deviceId: "smokeDetectorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 5:
-                       break
-               case 6:
-                       break
-               case 7:
-                       lockObject.setValue([name: "lock", value: "locked", deviceId: "lockID0", descriptionText: "",
+                       contactObject.setValue([name: "contact.closed", value: "closed", deviceId: "contactSensorID0", descriptionText: "",
                                        displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
                        break
-               case 8:
-                       def event = Verify.getInt(0,1)
-                       if (event == 0) {
-                                       accelerationSensorObject.setValue([name: "acceleration", value: "active", deviceId: "accelerationSensorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       accelerationSensorObject.setValue([name: "acceleration", value: "inactive", deviceId: "accelerationSensorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 9:
-                       def event = Verify.getInt(0,1)
-                       if (event == 0) {
-                                       motionSensorObject.setValue([name: "motion", value: "active", deviceId: "motionSensorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       motionSensorObject.setValue([name: "motion", value: "inactive", deviceId: "motionSensorID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 10:
+               case 4:
                        def event = Verify.getInt(0,1)
                        if (event == 0) {
                                        presenceSensorObject.setValue([name: "presence", value: "present", deviceId: "presenceSensorID0", descriptionText: "",
@@ -1339,131 +1157,5 @@ while(true) {
                                                        displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"presence":"0","dni":"mobile0"}'])
                        }
                        break
-               case 11:
-                       def event = Verify.getInt(0,1)
-                       if (event == 0) {
-                                       switchObject.setValue([name: "switch", value: "on", deviceId: "switchID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       switchObject.setValue([name: "switch", value: "off", deviceId: "switchID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 12:
-                       break
-               case 13:
-                       smokeDetectorObject.setValue([name: "battery", value: "5", deviceId: "smokeDetectorID0", descriptionText: "",
-                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       break
-               case 14:
-                       break
-               case 15:
-                       break
-               case 16:
-                       break
-               case 17:
-                       break
-               case 18:
-                       break
-               case 19:
-                       def event = Verify.getInt(0,4)
-                       if (event == 0) {
-                                       thermostatObject.setValue([name: "thermostatMode", value: "auto", deviceId: "thermostatID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else if (event == 1) {
-                                       thermostatObject.setValue([name: "thermostatMode", value: "cool", deviceId: "thermostatID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else if (event == 2) {
-                                       thermostatObject.setValue([name: "thermostatMode", value: "emergencyHeat", deviceId: "thermostatID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else if (event == 3) {
-                                       thermostatObject.setValue([name: "thermostatMode", value: "heat", deviceId: "thermostatID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       thermostatObject.setValue([name: "thermostatMode", value: "off", deviceId: "thermostatID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 20:
-                       break
-               case 21:
-                       break
-               case 22:
-                       break
-               case 23:
-                       break
-               case 24:
-                       break
-               case 25:
-                       break
-               case 26:
-                       break
-               case 27:
-                       break
-               case 28:
-                       break
-               case 29:
-                       break
-               case 30:
-                       break
-               case 31:
-                       break
-               case 32:
-                       break
-               case 33:
-                       break
-               case 34:
-                       break
-               case 35:
-                       break
-               case 36:
-                       break
-               case 37:
-                       break
-               case 38:
-                       break
-               case 39:
-                       break
-               case 40:
-                       break
-               case 41:
-                       break
-               case 42:
-                       break
-               case 43:
-                       break
-               case 44:
-                       break
-               case 45:
-                       break
-               case 46:
-                       break
-               case 47:
-                       break
-               case 48:
-                       break
-               case 49:
-                       break
-               case 50:
-                       break
-               case 51:
-                       break
-               case 52:
-                       def event = Verify.getInt(0,2)
-                       if (event == 0) {
-                                       locationObject.setValue([name: "Location", value: "home", deviceId: "locationID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else if (event == 1) {
-                                       locationObject.setValue([name: "Location", value: "away", deviceId: "locationID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       } else {
-                                       locationObject.setValue([name: "Location", value: "night", deviceId: "locationID0", descriptionText: "",
-                                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       }
-                       break
-               case 53:
-                       appObject.setValue([name: "Touched", value: "touched", deviceId: "touchedSensorID0", descriptionText: "",
-                                       displayed: true, linkText: "", isStateChange: false, unit: "", data: '{"info": "info"}'])
-                       break
        }
 }