From: amiraj Date: Mon, 29 Jul 2019 23:20:45 +0000 (-0700) Subject: Some minor changes in events' format X-Git-Url: http://plrg.eecs.uci.edu/git/?p=smartthings-infrastructure.git;a=commitdiff_plain;h=a97167cd66b70c9fa13d31ed411036713f386498 Some minor changes in events' format --- diff --git a/AllEvents b/AllEvents deleted file mode 100644 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"}']) diff --git a/Extractor/App1/App1.groovy b/Extractor/App1/App1.groovy index 49a97c3..94ec37c 100644 --- a/Extractor/App1/App1.groovy +++ b/Extractor/App1/App1.groovy @@ -1,448 +1,115 @@ -/** - * 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 - }*/ - } - -} - diff --git a/Extractor/App1/extractedFunctionsApp1.groovy b/Extractor/App1/extractedFunctionsApp1.groovy index 3155b29..b7e30e6 100644 --- a/Extractor/App1/extractedFunctionsApp1.groovy +++ b/Extractor/App1/extractedFunctionsApp1.groovy @@ -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 diff --git a/Extractor/App1/extractedObjectsApp1.groovy b/Extractor/App1/extractedObjectsApp1.groovy index 83899d9..e4ce692 100644 --- a/Extractor/App1/extractedObjectsApp1.groovy +++ b/Extractor/App1/extractedObjectsApp1.groovy @@ -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 diff --git a/Extractor/App1/extractedObjectsConstructorApp1.groovy b/Extractor/App1/extractedObjectsConstructorApp1.groovy index 53906e5..29bfad5 100644 --- a/Extractor/App1/extractedObjectsConstructorApp1.groovy +++ b/Extractor/App1/extractedObjectsConstructorApp1.groovy @@ -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] diff --git a/Extractor/App2/App2.groovy b/Extractor/App2/App2.groovy index 86096f4..61b6434 100644 --- a/Extractor/App2/App2.groovy +++ b/Extractor/App2/App2.groovy @@ -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: @@ -13,98 +13,296 @@ * 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 " Installed with settings: ${settings}" + initialize() +} + +def updated() { + log.debug " Updated with settings: ${settings}" + unsubscribe() + initialize() +} + +def initialize() { + subscribe(beacons, "presence", beaconHandler) +} + +// Event handlers +def beaconHandler(evt) { + log.debug " 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 " data: $data - phones: " + phones*.deviceNetworkId + + def beaconName = getBeaconName(evt) + // removed logging of device names. can be added back for debugging + //log.debug " beaconName: $beaconName" + + def phoneName = getPhoneName(data) + // removed logging of device names. can be added back for debugging + //log.debug " 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 " 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 " executing: $arrivalPhrase" + executePhrase(arrivalPhrase) + msg += " ${prefix('executed')} $arrivalPhrase." + } + if (arrivalOnSwitches) { + log.debug " turning on: $arrivalOnSwitches" + arrivalOnSwitches.on() + msg += " ${prefix('turned')} ${list(arrivalOnSwitches)} on." + } + if (arrivalOffSwitches) { + log.debug " turning off: $arrivalOffSwitches" + arrivalOffSwitches.off() + msg += " ${prefix('turned')} ${list(arrivalOffSwitches)} off." + } + if (arrivalLocks) { + log.debug " unlocking: $arrivalLocks" + arrivalLocks.unlock() + msg += " ${prefix('unlocked')} ${list(arrivalLocks)}." + } + msg } +private departActions(msg) { + if (departPhrase || departOnSwitches || departOffSwitches || departLocks) msg += ", so" + + if (departPhrase) { + log.debug " executing: $departPhrase" + executePhrase(departPhrase) + msg += " ${prefix('executed')} $departPhrase." + } + if (departOnSwitches) { + log.debug " turning on: $departOnSwitches" + departOnSwitches.on() + msg += " ${prefix('turned')} ${list(departOnSwitches)} on." + } + if (departOffSwitches) { + log.debug " turning off: $departOffSwitches" + departOffSwitches.off() + msg += " ${prefix('turned')} ${list(departOffSwitches)} off." + } + if (departLocks) { + log.debug " 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 " 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 " 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 " 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 " 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/Extractor/App2/extractedFunctionsApp2.groovy b/Extractor/App2/extractedFunctionsApp2.groovy index c59c464..8430b82 100644 --- a/Extractor/App2/extractedFunctionsApp2.groovy +++ b/Extractor/App2/extractedFunctionsApp2.groovy @@ -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.¬ifyUnlocked +def timeIntervalLabel = this.&timeIntervalLabel //Global Object for functions in subscribe method! -def sendMessage = this.&sendMessage +def list = this.&list diff --git a/Extractor/App2/extractedObjectsApp2.groovy b/Extractor/App2/extractedObjectsApp2.groovy index 09638b3..7444a10 100644 --- a/Extractor/App2/extractedObjectsApp2.groovy +++ b/Extractor/App2/extractedObjectsApp2.groovy @@ -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" diff --git a/Extractor/App2/extractedObjectsConstructorApp2.groovy b/Extractor/App2/extractedObjectsConstructorApp2.groovy index cc84ca8..e10e014 100644 --- a/Extractor/App2/extractedObjectsConstructorApp2.groovy +++ b/Extractor/App2/extractedObjectsConstructorApp2.groovy @@ -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] diff --git a/Extractor/extractorFile.groovy b/Extractor/extractorFile.groovy index 5e4d0e3..3696113 100644 --- a/Extractor/extractorFile.groovy +++ b/Extractor/extractorFile.groovy @@ -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 " Installed with settings: ${settings}" + initialize() } -def initialize() -{ - log.trace "Initializing with: ${settings}" - subscribe(aLock, "lock", lockHandler) +def updated() { + log.debug " 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 " 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 " 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 " beaconName: $beaconName" + + def phoneName = getPhoneName(data) + // removed logging of device names. can be added back for debugging + //log.debug " 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 " 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 " executing: $arrivalPhrase" + executePhrase(arrivalPhrase) + msg += " ${prefix('executed')} $arrivalPhrase." + } + if (arrivalOnSwitches) { + log.debug " turning on: $arrivalOnSwitches" + arrivalOnSwitches.on() + msg += " ${prefix('turned')} ${list(arrivalOnSwitches)} on." + } + if (arrivalOffSwitches) { + log.debug " turning off: $arrivalOffSwitches" + arrivalOffSwitches.off() + msg += " ${prefix('turned')} ${list(arrivalOffSwitches)} off." + } + if (arrivalLocks) { + log.debug " unlocking: $arrivalLocks" + arrivalLocks.unlock() + msg += " ${prefix('unlocked')} ${list(arrivalLocks)}." + } + msg +} + +private departActions(msg) { + if (departPhrase || departOnSwitches || departOffSwitches || departLocks) msg += ", so" + + if (departPhrase) { + log.debug " executing: $departPhrase" + executePhrase(departPhrase) + msg += " ${prefix('executed')} $departPhrase." + } + if (departOnSwitches) { + log.debug " turning on: $departOnSwitches" + departOnSwitches.on() + msg += " ${prefix('turned')} ${list(departOnSwitches)} on." + } + if (departOffSwitches) { + log.debug " turning off: $departOffSwitches" + departOffSwitches.off() + msg += " ${prefix('turned')} ${list(departOffSwitches)} off." + } + if (departLocks) { + log.debug " 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 " 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 " 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 " 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 " 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 index 0000000..9734620 --- /dev/null +++ b/SameFeatureDifferentDevices @@ -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' + diff --git a/Switch/Switch.groovy b/Switch/Switch.groovy index d01d27b..b924d21 100644 --- a/Switch/Switch.groovy +++ b/Switch/Switch.groovy @@ -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() { diff --git a/SwitchLevel/SwitchLevel.groovy b/SwitchLevel/SwitchLevel.groovy index a09a450..4b7acbf 100644 --- a/SwitchLevel/SwitchLevel.groovy +++ b/SwitchLevel/SwitchLevel.groovy @@ -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!") diff --git a/SwitchLevel/SwitchLevels.groovy b/SwitchLevel/SwitchLevels.groovy index 9e6e8a9..35c4ad9 100644 --- a/SwitchLevel/SwitchLevels.groovy +++ b/SwitchLevel/SwitchLevels.groovy @@ -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) { diff --git a/Variables and events for each device b/Variables and events for each device index 0c049cc..7933983 100644 --- a/Variables and events for each device +++ b/Variables and events for each device @@ -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*/ // diff --git a/eventSimulator/eventSimulator.groovy b/eventSimulator/eventSimulator.groovy index b0cd6dc..82cbd6a 100644 --- a/eventSimulator/eventSimulator.groovy +++ b/eventSimulator/eventSimulator.groovy @@ -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 } } diff --git a/main.groovy b/main.groovy index 6ef1bda..bccee10 100644 --- a/main.groovy +++ b/main.groovy @@ -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.¬ifyUnlocked + 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 " Installed with settings: ${settings}" + initialize() } - def initialize() - { - log.trace "Initializing with: ${settings}" - subscribe(aLock, "lock", lockHandler) + def updated() { + log.debug " 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 " 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 " 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 " beaconName: $beaconName" + + def phoneName = getPhoneName(data) + // removed logging of device names. can be added back for debugging + //log.debug " 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 " 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 " executing: $arrivalPhrase" + executePhrase(arrivalPhrase) + msg += " ${prefix('executed')} $arrivalPhrase." + } + if (arrivalOnSwitches) { + log.debug " turning on: $arrivalOnSwitches" + arrivalOnSwitches.on() + msg += " ${prefix('turned')} ${list(arrivalOnSwitches)} on." + } + if (arrivalOffSwitches) { + log.debug " turning off: $arrivalOffSwitches" + arrivalOffSwitches.off() + msg += " ${prefix('turned')} ${list(arrivalOffSwitches)} off." + } + if (arrivalLocks) { + log.debug " unlocking: $arrivalLocks" + arrivalLocks.unlock() + msg += " ${prefix('unlocked')} ${list(arrivalLocks)}." + } + msg + } + + private departActions(msg) { + if (departPhrase || departOnSwitches || departOffSwitches || departLocks) msg += ", so" + + if (departPhrase) { + log.debug " executing: $departPhrase" + executePhrase(departPhrase) + msg += " ${prefix('executed')} $departPhrase." + } + if (departOnSwitches) { + log.debug " turning on: $departOnSwitches" + departOnSwitches.on() + msg += " ${prefix('turned')} ${list(departOnSwitches)} on." + } + if (departOffSwitches) { + log.debug " turning off: $departOffSwitches" + departOffSwitches.off() + msg += " ${prefix('turned')} ${list(departOffSwitches)} off." + } + if (departLocks) { + log.debug " 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 " 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 " 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 " 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 " 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 } }