Commit #9: More classes + Extractor with Rahmadi's editions + Fixing some bugs
authoramiraj <amiraj.95@uci.edu>
Tue, 23 Jul 2019 22:52:12 +0000 (15:52 -0700)
committeramiraj <amiraj.95@uci.edu>
Tue, 23 Jul 2019 22:52:12 +0000 (15:52 -0700)
41 files changed:
Alarm/Alarm.groovy [new file with mode: 0644]
Alarm/Alarms.groovy [new file with mode: 0644]
ContactSensor/ContactSensor.groovy
ContactSensor/ContactSensors.groovy
DoorControl/DoorControls.groovy
Event/Event.groovy
Extractor/App1/App1.groovy
Extractor/App1/extractedFunctionsApp1.groovy
Extractor/App1/extractedObjectsApp1.groovy
Extractor/App1/extractedObjectsConstructorApp1.groovy
Extractor/App2/App2.groovy
Extractor/App2/extractedFunctionsApp2.groovy
Extractor/App2/extractedObjectsApp2.groovy
Extractor/Extractor.groovy
Extractor/ExtractorScript.py
Extractor/extractorFile.groovy
GlobalVariables/GlobalVariablesBothApps.groovy
GlobalVariables/GlobalVariablesEachApp.groovy
ImageCapture/ImageCapture.groovy [new file with mode: 0644]
ImageCapture/ImageCaptures.groovy [new file with mode: 0644]
Location/LocationVar.groovy
Lock/Locks.groovy
Methods/getSunriseAndSunset.groovy [new file with mode: 0644]
Methods/getTemperatureScale.groovy [new file with mode: 0644]
Methods/runIn.groovy
Methods/schedule.groovy
Methods/sendSms.groovy
MotionSensor/MotionSensor.groovy [new file with mode: 0644]
MotionSensor/MotionSensors.groovy [new file with mode: 0644]
MusicPlayer/MusicPlayers.groovy
PresenceSensor/PresenceSensors.groovy
Runner.py
SmokeDetector/SmokeDetector.groovy [new file with mode: 0644]
SmokeDetector/SmokeDetectors.groovy [new file with mode: 0644]
SpeechSynthesis/SpeechSynthesis.groovy [new file with mode: 0644]
SpeechSynthesis/SpeechSynthesises.groovy [new file with mode: 0644]
Switch/Switches.groovy
Thermostat/Thermostat.groovy
Thermostat/Thermostats.groovy
Variables and events for each device [new file with mode: 0644]
main.groovy

diff --git a/Alarm/Alarm.groovy b/Alarm/Alarm.groovy
new file mode 100644 (file)
index 0000000..00f4169
--- /dev/null
@@ -0,0 +1,79 @@
+//Create a class for alarm device
+package Alarm
+import Timer.SimulatedTimer
+
+public class Alarm {
+       private String id
+       private String label
+       private String displayName
+       private String alarm
+       private String currentAlarm
+       private String alarmLatestValue
+       def sendEvent   
+       def timers
+       
+
+       Alarm(Closure sendEvent, String id, String label, String displayName, String alarm, String currentAlarm, String alarmLatestValue) {
+               this.sendEvent = sendEvent
+               this.timers = new SimulatedTimer()
+               this.id = id
+               this.label = label
+               this.displayName = displayName
+               this.alarm = alarm
+               this.currentAlarm = currentAlarm
+               this.alarmLatestValue = alarmLatestValue
+       }
+
+       //By Apps
+       def both() {
+               println("the alarm with id:$id is changed to both!")
+               this.alarmLatestValue = this.alarm
+               this.alarm = "both"
+               this.currentAlarm = "both"
+               sendEvent([name: "alarm", value: "both", deviceId: this.id, descriptionText: "",
+                   displayed: true, linkText: "", isStateChange: false, unit: "", data: [value: "both"]])
+       }
+
+       def on() {
+               both()
+       }
+
+       def off() {
+               println("the alarm with id:$id is changed to off!")
+               this.alarmLatestValue = this.alarm
+               this.alarm = "off"
+               this.currentAlarm = "off"
+               sendEvent([name: "alarm", value: "off", deviceId: this.id, descriptionText: "",
+                   displayed: true, linkText: "", isStateChange: false, unit: "", data: [value: "off"]])
+       }
+
+       def siren() {
+               println("the alarm with id:$id is changed to siren!")
+               this.alarmLatestValue = this.alarm
+               this.alarm = "siren"
+               this.currentAlarm = "siren"
+               sendEvent([name: "alarm", value: "siren", deviceId: this.id, descriptionText: "",
+                   displayed: true, linkText: "", isStateChange: false, unit: "", data: [value: "siren"]])
+       }
+
+       def strobe() {
+               println("the alarm with id:$id is changed to strobe!")
+               this.alarmLatestValue = this.alarm
+               this.alarm = "strobe"
+               this.currentAlarm = "strobe"
+               sendEvent([name: "alarm", value: "strobe", deviceId: this.id, descriptionText: "",
+                   displayed: true, linkText: "", isStateChange: false, unit: "", data: [value: "strobe"]])
+       }
+
+       def currentValue(String deviceFeature) {
+               if (deviceFeature == "alarm") {
+                       return currentAlarm
+               }
+       }
+
+       def latestValue(String deviceFeature) {
+               if (deviceFeature == "alarm") {
+                       return alarmLatestValue
+               }
+       }
+}
diff --git a/Alarm/Alarms.groovy b/Alarm/Alarms.groovy
new file mode 100644 (file)
index 0000000..9be6569
--- /dev/null
@@ -0,0 +1,89 @@
+//Create a class for alarm device
+package Alarm
+import Timer.SimulatedTimer
+
+public class Alarms {
+       int deviceNumbers       
+       List alarms
+       def timers
+       def sendEvent
+
+       //If we have only one device
+       private String id = "alarmID0"
+       private String label = "alarm0"
+       private String displayName = "alarm0"
+       private String alarm = "off"
+       private String currentAlarm = "off"
+       private String alarmLatestValue = "off"
+
+       Alarms(Closure sendEvent, int deviceNumbers) {
+               this.sendEvent = sendEvent
+               this.timers = new SimulatedTimer()
+               this.deviceNumbers = deviceNumbers
+               this.alarms = []
+
+               alarms.add(new Alarm(sendEvent, id, label, displayName, this.alarm, this.currentAlarm, this.alarmLatestValue))
+       }
+
+       //Methods for closures
+       def count(Closure Input) {
+               alarms.count(Input)
+       }
+       def size() {
+               alarms.size()
+       }
+       def each(Closure Input) {
+               alarms.each(Input)
+       }
+       def find(Closure Input) {
+               alarms.find(Input)
+       }
+       def collect(Closure Input) {
+               alarms.collect(Input)
+       }
+
+       //By Apps
+       def both() {
+               alarms[0].both()
+               alarmLatestValue = alarm
+               alarm = "both"
+               currentAlarm = "both"
+       }
+
+       def off() {
+               alarms[0].off()
+               alarmLatestValue = alarm
+               alarm = "off"
+               currentAlarm = "off"
+       }
+
+       def on() {
+               both()
+       }
+
+       def siren() {
+               alarms[0].siren()
+               alarmLatestValue = alarm
+               alarm = "siren"
+               currentAlarm = "siren"
+       }
+
+       def strobe() {
+               alarms[0].strobe()
+               alarmLatestValue = alarm
+               alarm = "strobe"
+               currentAlarm = "strobe"
+       }
+
+       def currentValue(String deviceFeature) {
+               alarms[0].currentValue(deviceFeature)
+       }
+
+       def latestValue(String deviceFeature) {
+               alarms[0].latestValue(deviceFeature)
+       }
+
+       def getAt(int ix) {
+               alarms[ix]
+       }
+}
index 05e961d..d13993a 100644 (file)
@@ -7,20 +7,36 @@ public class ContactSensor {
        private String label
        private String displayName
        private String contactState
+       private String currentContact   
        private String latestValue
+       private String alarmState
+       
 
-       ContactSensor(String id, String label, String displayName, String contactState, String latestValue) {
+       ContactSensor(String id, String label, String displayName, String contactState, String currentContact, String alarmState, String latestValue) {
                this.id = id
                this.label = label
                this.displayName = displayName
                this.contactState = contactState
+               this.currentContact = currentContact
                this.latestValue = latestValue
+               this.alarmState = alarmState
        }
 
        def setValue(String value) {
                this.latestValue = contactState
                println("the contact sensor with id:$id is triggered to $value!")
                this.contactState = value
+               this.currentContact = value
+       }
+       
+       def on() {
+               println("the contact sensor with id:$id is armed!")
+               this.alarmState = "armed"
+       }
+
+       def off() {
+               println("the contact sensor with id:$id is not armed!")
+               this.alarmState = "not armed"
        }
        
        def currentValue(String deviceFeature) {
index 10c4aa6..1de8c76 100644 (file)
@@ -12,7 +12,9 @@ public class ContactSensors {
        private String label = "contactSensor0"
        private String displayName = "contactSensor0"
        private String contactState = "closed"
+       private String currentContact = "closed"
        private String latestValue = "closed"
+       private String alarmState = "armed"
 
                
        ContactSensors(Closure sendEvent, int deviceNumbers) {
@@ -20,7 +22,7 @@ public class ContactSensors {
                this.deviceNumbers = deviceNumbers
                this.contacts = []
 
-               contacts.add(new ContactSensor(id, label, displayName, this.contactState, this.latestValue))
+               contacts.add(new ContactSensor(id, label, displayName, this.contactState, this.currentContact, this.alarmState, this.latestValue))
        }
 
        //Methods for closures
@@ -42,10 +44,23 @@ public class ContactSensors {
 
        //By Model Checker
        def setValue(LinkedHashMap eventDataMap) {
-               contacts[0].setValue(eventDataMap["value"])
-               this.latestValue = contacts[0].latestValue
-               this.contactState = contacts[0].contactState
-               sendEvent(eventDataMap)
+               if (eventDataMap["value"] != contacts[0].contactState) {
+                       contacts[0].setValue(eventDataMap["value"])
+                       this.latestValue = contacts[0].latestValue
+                       this.contactState = contacts[0].contactState
+                       this.currentContact = contacts[0].contactState
+                       sendEvent(eventDataMap)
+               }
+       }
+
+       def on() {
+               contacts[0].on()
+               this.alarmState = "armed"
+       }
+
+       def off() {
+               contacts[0].off()
+               this.alarmState = "not armed"
        }
 
        def currentValue(String deviceFeature) {
index 19cc18b..9210899 100644 (file)
@@ -64,9 +64,11 @@ public class DoorControls {
 
        //By Model Checker
        def setValue(LinkedHashMap eventDataMap) {
-               doorControls[0].setValue(eventDataMap["value"])
-               this.doorState = doorControls[0].doorState
-               sendEvent(eventDataMap)
+               if (eventDataMap["value"] != doorControls[0].doorState) {
+                       doorControls[0].setValue(eventDataMap["value"])
+                       this.doorState = doorControls[0].doorState
+                       sendEvent(eventDataMap)
+               }
        }
 
 
index b05425a..8c1d1c9 100644 (file)
@@ -12,6 +12,7 @@ public class Event {
        private boolean isStateChange
        private String unit
        private LinkedHashMap data
+       private int integerValue
        
        Event(String value, String name, String deviceId, String descriptionText, boolean displayed, String linkText, String displayName, boolean isStateChange, String unit, LinkedHashMap data) {
                this.deviceId = deviceId
@@ -24,5 +25,7 @@ public class Event {
                this.unit = unit
                this.data = data
                this.displayed = displayed
+               if (name == "battery")
+                       this.integerValue = value.toInteger()
        }
 }
index 0d4c97e..718d69e 100644 (file)
-
 /**
- *  Auto Lock Door
+ *  Copyright 2015 SmartThings
+ *
+ *  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:
  *
- *  Author: Chris Sader (@csader)
- *  Collaborators: @chrisb
- *  Date: 2013-08-21
- *  URL: http://www.github.com/smartthings-users/smartapp.auto-lock-door
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
- * Copyright (C) 2013 Chris Sader.
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this
- * software and associated documentation files (the "Software"), to deal in the Software
- * without restriction, including without limitation the rights to use, copy, modify,
- * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to the following
- * conditions: The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
+ *  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. See the License
+ *  for the specific language governing permissions and limitations under the License.
  *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
- * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
- * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *  Make it So
+ *
+ *  Author: SmartThings
+ *  Date: 2013-03-06
  */
+definition(
+    name: "Make It So",
+    namespace: "smartthings",
+    author: "SmartThings",
+    description: "Saves the states of a specified set switches and thermostat setpoints and restores them at each mode change. To use 1) Set the mode, 2) Change switches and setpoint to where you want them for that mode, and 3) Install or update the app. Changing to that mode or touching the app will set the devices to the saved state.",
+    category: "Convenience",
+    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Meta/light_thermo-switch.png",
+    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Meta/light_thermo-switch@2x.png"
+)
 
-preferences
-{
-    section("When a door unlocks...") {
-        input "lock1", "capability.lock"
-    }
-    section("Lock it how many minutes later?") {
-        input "minutesLater", "number", title: "When?"
-    }
-    section("Lock it only when this door is closed") {
-        input "openSensor", "capability.contactSensor", title: "Where?"
-    }
+preferences {
+       section("Switches") {
+               input "switches", "capability.switch", multiple: true, required: false
+       }
+       section("Thermostats") {
+               input "thermostats", "capability.thermostat", multiple: true, required: false
+       }
+       section("Locks") {
+               input "locks", "capability.lock", multiple: true, required: false
+       }
 }
 
-def installed()
-{
-    log.debug "Auto Lock Door installed. (URL: http://www.github.com/smartthings-users/smartapp.auto-lock-door)"
-    initialize()
+def installed() {
+       subscribe(location, changedLocationMode)
+       subscribe(app, appTouch)
+       saveState()
 }
 
-def updated()
-{
-    unsubscribe()
-    unschedule()
-    log.debug "Auto Lock Door updated."
-    initialize()
+def updated() {
+       unsubscribe()
+       subscribe(location, changedLocationMode)
+       subscribe(app, appTouch)
+       saveState()
 }
 
-def initialize()
+def appTouch(evt)
 {
-    log.debug "Settings: ${settings}"
-    subscribe(lock1, "lock", doorHandler)
-    subscribe(openSensor, "contact.closed", doorClosed)
-    subscribe(openSensor, "contact.open", doorOpen)
+       restoreState(currentMode)
 }
 
-def lockDoor()
+def changedLocationMode(evt)
 {
-    log.debug "Locking Door if Closed"
-    if((openSensor.latestValue("contact") == "closed")){
-       log.debug "Door Closed"
-       lock1.lock()
-    } else {
-       if ((openSensor.latestValue("contact") == "open")) {
-        def delay = minutesLater * 60
-        log.debug "Door open will try again in $minutesLater minutes"
-        runIn( delay, lockDoor )
-        }
-    }
+       restoreState(evt.value)
 }
 
-def doorOpen(evt) {
-    log.debug "Door open reset previous lock task..."
-    unschedule( lockDoor )
-    def delay = minutesLater * 60
-    runIn( delay, lockDoor )
-}
+private restoreState(mode)
+{
+       log.info "restoring state for mode '$mode'"
+       def map = state[mode] ?: [:]
+       switches?.each {
+               def value = map[it.id]
+               if (value?.switch == "on") {
+                       def level = value.level
+                       if (level) {
+                               log.debug "setting $it.label level to $level"
+                               it.setLevel(level)
+                       }
+                       else {
+                               log.debug "turning $it.label on"
+                               it.on()
+                       }
+               }
+               else if (value?.switch == "off") {
+                       log.debug "turning $it.label off"
+                       it.off()
+               }
+       }
 
-def doorClosed(evt) {
-    log.debug "Door Closed"
+       thermostats?.each {
+               def value = map[it.id]
+               if (value?.coolingSetpoint) {
+                       log.debug "coolingSetpoint = $value.coolingSetpoint"
+                       it.setCoolingSetpoint(value.coolingSetpoint)
+               }
+               if (value?.heatingSetpoint) {
+                       log.debug "heatingSetpoint = $value.heatingSetpoint"
+                       it.setHeatingSetpoint(value.heatingSetpoint)
+               }
+       }
+
+       locks?.each {
+               def value = map[it.id]
+               if (value) {
+                       if (value?.locked) {
+                               it.lock()
+                       }
+                       else {
+                               it.unlock()
+                       }
+               }
+       }
 }
 
-def doorHandler(evt)
+
+private saveState()
 {
-    log.debug "Door ${openSensor.latestValue}"
-    log.debug "Lock ${evt.name} is ${evt.value}."
+       def mode = currentMode
+       def map = state[mode] ?: [:]
+
+       switches?.each {
+               map[it.id] = [switch: it.currentSwitch, level: it.currentLevel]
+       }
+
+       thermostats?.each {
+               map[it.id] = [coolingSetpoint: it.currentCoolingSetpoint, heatingSetpoint: it.currentHeatingSetpoint]
+       }
 
-    if (evt.value == "locked") {                  // If the human locks the door then...
-        log.debug "Cancelling previous lock task..."
-        unschedule( lockDoor )                  // ...we don't need to lock it later.
-    }
-    else {                                      // If the door is unlocked then...
-        def delay = minutesLater * 60          // runIn uses seconds
-        log.debug "Re-arming lock in ${minutesLater} minutes (${delay}s)."
-        runIn( delay, lockDoor )                // ...schedule to lock in x minutes.
-    }
+       locks?.each {
+               map[it.id] = [locked: it.currentLock == "locked"]
+       }
+
+       state[mode] = map
+       log.debug "saved state for mode ${mode}: ${state[mode]}"
+       log.debug "state: $state"
+}
+
+private getCurrentMode()
+{
+       location.mode ?: "_none_"
 }
index a892f94..577b4dc 100644 (file)
@@ -3,12 +3,12 @@ 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
+def appTouch = this.&appTouch
 //Global Object for functions in subscribe method!
-def lockDoor = this.&lockDoor
+def changedLocationMode = this.&changedLocationMode
 //Global Object for functions in subscribe method!
-def doorOpen = this.&doorOpen
+def restoreState = this.&restoreState
 //Global Object for functions in subscribe method!
-def doorClosed = this.&doorClosed
+def saveState = this.&saveState
 //Global Object for functions in subscribe method!
-def doorHandler = this.&doorHandler
+def getCurrentMode = this.&getCurrentMode
index 4ab787d..0680408 100644 (file)
@@ -1,6 +1,6 @@
+//Object for class switch!
+def switches
+//Object for class thermostat!
+def thermostats
 //Object for class lock!
-def lock1
-//Global variable for number!
-def minutesLater = 1
-//Object for class contactSensor!
-def openSensor
+def locks
index 554fba3..ebcafcc 100644 (file)
@@ -1,4 +1,5 @@
-lock1 = obj.lockObject
-openSensor = obj.contactObject
+switches = obj.switchObject
+thermostats = obj.thermostatObject
+locks = obj.lockObject
 //Global variable for settings!
-settings = [app:app, lock1:lock1, minutesLater:minutesLater, openSensor:openSensor]
+settings = [app:app, switches:switches, thermostats:thermostats, locks:locks]
index ce2ea22..497be41 100644 (file)
@@ -1,4 +1,19 @@
-////////////////
+/**
+ *  NFC Tag Toggle
+ *
+ *  Copyright 2014 SmartThings
+ *
+ *  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:
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  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. See the License
+ *  for the specific language governing permissions and limitations under the License.
+ *
+ */
 definition(
     name: "NFC Tag Toggle",
     namespace: "smartthings",
@@ -21,18 +36,18 @@ preferences {
             input "garageDoor", "capability.doorControl", title: "Garage door controller", required: false, multiple: true
         }
     }
-
+    
     page(name: "pageTwo", title: "Master devices", install: true, uninstall: true)
 }
 
 def pageTwo() {
        dynamicPage(name: "pageTwo") {
-       section("If set, the state of these devices will be toggled each time the tag is touched, " +
+       section("If set, the state of these devices will be toggled each time the tag is touched, " + 
                 "e.g. a light that's on will be turned off and one that's off will be turned on, " +
                 "other devices of the same type will be set to the same state as their master device. " +
                 "If no master is designated then the majority of devices of the same type will be used " +
                 "to determine whether to turn on or off the devices.") {
-
+            
             if (switch1 || masterSwitch) {
                 input "masterSwitch", "enum", title: "Master switch", options: switch1.collect{[(it.id): it.displayName]}, required: false
             }
@@ -41,12 +56,12 @@ def pageTwo() {
             }
             if (garageDoor || masterDoor) {
                 input "masterDoor", "enum", title: "Master door", options: garageDoor.collect{[(it.id): it.displayName]}, required: false
-            }
+            }            
                }
                section([mobileOnly:true]) {
                        label title: "Assign a name", required: false
                        mode title: "Set for specific mode(s)", required: false
-               }
+               }        
     }
 }
 
@@ -101,7 +116,7 @@ def touchHandler(evt) {
             }
         }
     }
-
+    
     if (lock) {
        def status = currentStatus(lock, masterLock, "lock")
         lock.each {
@@ -113,7 +128,7 @@ def touchHandler(evt) {
             }
         }
     }
-
+    
     if (garageDoor) {
         def status = currentStatus(garageDoor, masterDoor, "status")
        garageDoor.each {
index 9efae44..058c880 100644 (file)
@@ -7,6 +7,4 @@ def updated = this.&updated
 //Global Object for functions in subscribe method!
 def initialize = this.&initialize
 //Global Object for functions in subscribe method!
-def currentStatus = this.&currentStatus
-//Global Object for functions in subscribe method!
 def touchHandler = this.&touchHandler
index ff33ee0..781ac82 100644 (file)
@@ -7,8 +7,8 @@ def lock
 //Object for class door control!
 def garageDoor
 //Global variable for enum!
-def masterSwitch = "switchID0"
+def masterSwitch = "Yes"
 //Global variable for enum!
-def masterLock = "lockID0"
+def masterLock = "Yes"
 //Global variable for enum!
-def masterDoor = "DoorControlID0"
+def masterDoor = "No"
index 2c2affe..65dcafa 100644 (file)
@@ -26,6 +26,16 @@ import AeonKeyFob.AeonKeyFob
 import AeonKeyFob.AeonKeyFobs
 import MusicPlayer.MusicPlayer
 import MusicPlayer.MusicPlayers
+import MotionSensor.MotionSensor
+import MotionSensor.MotionSensors
+import ImageCapture.ImageCapture
+import ImageCapture.ImageCaptures
+import SmokeDetector.SmokeDetector
+import SmokeDetector.SmokeDetectors
+import Alarm.Alarm
+import Alarm.Alarms
+import SpeechSynthesis.SpeechSynthesis
+import SpeechSynthesis.SpeechSynthesises
 import Timer.SimulatedTimer
 
 //GlobalVariables
@@ -36,6 +46,8 @@ import Timer.SimulatedTimer
 @Field def state = [home:[],away:[],night:[]]
 //Create a global logger object for methods
 @Field def log = new Logger()
+//Create a global variable for optional property
+@Field def optional = false //by default for now
 
 
 //Global variables for files
@@ -104,6 +116,31 @@ if (App == "App1") {
 @Field def aeonKeyFobObject0
 @Field def aeonKeyFobObject1
 @Field def aeonKeyFobObject2
+//Global Object for class motion sensor!
+@Field motionSensorObjects = 0
+@Field def motionSensorObject0
+@Field def motionSensorObject1
+@Field def motionSensorObject2
+//Global Object for class image capture!
+@Field imageCaptureObjects = 0
+@Field def imageCaptureObject0
+@Field def imageCaptureObject1
+@Field def imageCaptureObject2
+//Global Object for class smoke detector!
+@Field smokeDetectorObjects = 0
+@Field def smokeDetectorObject0
+@Field def smokeDetectorObject1
+@Field def smokeDetectorObject2
+//Global Object for class alarm!
+@Field alarmObjects = 0
+@Field def alarmObject0
+@Field def alarmObject1
+@Field def alarmObject2
+//Global Object for class alarm!
+@Field speechSynthesisObjects = 0
+@Field def speechSynthesisObject0
+@Field def speechSynthesisObject1
+@Field def speechSynthesisObject2
 
 
 //Global variables
@@ -123,6 +160,14 @@ if (App == "App1") {
 @Field number3
 @Field number4
 @Field number5
+//For decimal
+@Field decimalVariables = 0
+@Field decimal0
+@Field decimal1
+@Field decimal2
+@Field decimal3
+@Field decimal4
+@Field decimal5
 //For time
 @Field timeVariables = 0
 @Field time0
@@ -155,7 +200,22 @@ if (App == "App1") {
 @Field contact3
 @Field contact4
 @Field contact5
-
+//For text
+@Field textVariables = 0
+@Field textVariable0
+@Field textVariable1
+@Field textVariable2
+@Field textVariable3
+@Field textVariable4
+@Field textVariable5
+//For boolean
+@Field boolVariables = 0
+@Field boolVariable0
+@Field boolVariable1
+@Field boolVariable2
+@Field boolVariable3
+@Field boolVariable4
+@Field boolVariable5
 
 
 /////Input Methods/////
@@ -174,6 +234,14 @@ def input(LinkedHashMap metaData, String name, String type) {
        input(metaData)
 }
 
+//input "", "", linkedHashMap, Closure
+def input(LinkedHashMap metaData, String name, String type, Closure Input) {
+       metaData.put('name',name)
+       metaData.put('type',type)
+       input(metaData)
+       find(Input)
+}
+
 //input linkedHashMap
 def input(LinkedHashMap metaData) {
        if (metaData.containsKey('title')) {
@@ -210,6 +278,30 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "capability.alarm":
+                       if (alarmObjects == 0) {
+                               alarmObject0 = metaData['name']
+                               this[alarmObject0] = new Alarms({}, 1)
+                       } else if (alarmObjects == 1) {
+                               alarmObject1 = metaData['name']
+                               this[alarmObject1] = new Alarms({}, 1)
+                       } else if (alarmObjects == 2) {
+                               alarmObject2 = metaData['name']
+                               this[alarmObject2] = new Alarms({}, 1)
+                       }
+
+                       alarmObjects=alarmObjects+1
+
+                       settings.put(metaData['name'], metaData['name']) 
+
+                       if (App == "App1") {
+                               extractedObjectsApp1.append("//Object for class alarm!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp1.append(metaData['name']+" = obj.alarmObject\n")         
+                       } else {
+                               extractedObjectsApp2.append("//Object for class alarm!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp2.append(metaData['name']+" = obj.alarmObject\n")
+                       }
                        break
                case "capability.battery":
                        break
@@ -278,6 +370,30 @@ def input(LinkedHashMap metaData) {
                case "capability.accelerationSensor":
                        break
                case "capability.motionSensor":
+                       if (motionSensorObjects == 0) {
+                               motionSensorObject0 = metaData['name']
+                               this[motionSensorObject0] = new MotionSensors({}, 1)
+                       } else if (motionSensorObjects == 1) {
+                               motionSensorObject1 = metaData['name']
+                               this[motionSensorObject1] = new MotionSensors({}, 1)
+                       } else if (motionSensorObjects == 2) {
+                               motionSensorObject2 = metaData['name']
+                               this[motionSensorObject2] = new MotionSensors({}, 1)
+                       }
+
+                       motionSensorObjects=motionSensorObjects+1
+
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {
+                               extractedObjectsApp1.append("//Object for class Motion Sensor!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp1.append(metaData['name']+" = obj.motionSensorObject\n")          
+                       } else {
+                               extractedObjectsApp2.append("//Object for class Motion Sensor!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp2.append(metaData['name']+" = obj.motionSensorObject\n")
+                       }
                        break
                case "capability.musicPlayer":
                        if (musicPlayerObjects == 0) {
@@ -340,6 +456,30 @@ def input(LinkedHashMap metaData) {
                case "capability.sleepSensor":
                        break
                case "capability.smokeDetector":
+                       if (smokeDetectorObjects == 0) {
+                               smokeDetectorObject0 = metaData['name']
+                               this[smokeDetectorObject0] = new SmokeDetectors({}, 1)
+                       } else if (smokeDetectorObjects == 1) {
+                               smokeDetectorObject1 = metaData['name']
+                               this[smokeDetectorObject1] = new SmokeDetectors({}, 1)
+                       } else if (smokeDetectorObjects == 2) {
+                               smokeDetectorObject2 = metaData['name']
+                               this[smokeDetectorObject2] = new SmokeDetectors({}, 1)
+                       }
+
+                       smokeDetectorObjects=smokeDetectorObjects+1
+                       
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {
+                               extractedObjectsApp1.append("//Object for class smoke detector!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp1.append(metaData['name']+" = obj.smokeDetectorObject\n")         
+                       } else {
+                               extractedObjectsApp2.append("//Object for class smoke detector!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp2.append(metaData['name']+" = obj.smokeDetectorObject\n")
+                       }
                        break
                case "capability.stepSensor":
                        break
@@ -401,6 +541,32 @@ def input(LinkedHashMap metaData) {
                        break
                case "capability.valve":
                        break
+               case "capability.speechSynthesis":
+                       if (speechSynthesisObjects == 0) {
+                               speechSynthesisObject0 = metaData['name']
+                               this[speechSynthesisObject0] = new SpeechSynthesises({}, 1)
+                       } else if (speechSynthesisObjects == 1) {
+                               speechSynthesisObject1 = metaData['name']
+                               this[speechSynthesisObject1] = new SpeechSynthesises({}, 1)
+                       } else if (speechSynthesisObjects == 2) {
+                               speechSynthesisObject2 = metaData['name']
+                               this[speechSynthesisObject2] = new SpeechSynthesises({}, 1)
+                       }
+
+                       speechSynthesisObjects=speechSynthesisObjects+1
+
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {
+                               extractedObjectsApp1.append("//Object for class speech synthesis!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp1.append(metaData['name']+" = obj.speechSynthesisObject\n")               
+                       } else {
+                               extractedObjectsApp2.append("//Object for class speech synthesis!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp2.append(metaData['name']+" = obj.speechSynthesisObject\n")
+                       }
+                       break
                case "capability.waterSensor":
                        break
                case "capability.touchSensor":
@@ -430,6 +596,30 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "capability.imageCapture":
+                       if (imageCaptureObjects == 0) {
+                               imageCaptureObject0 = metaData['name']
+                               this[imageCaptureObject0] = new ImageCaptures({}, 1)
+                       } else if (imageCaptureObjects == 1) {
+                               imageCaptureObject1 = metaData['name']
+                               this[imageCaptureObject1] = new ImageCaptures({}, 1)
+                       } else if (imageCaptureObjects == 2) {
+                               imageCaptureObject2 = metaData['name']
+                               this[imageCaptureObject2] = new ImageCaptures({}, 1)
+                       }
+
+                       imageCaptureObjects=imageCaptureObjects+1
+
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {
+                               extractedObjectsApp1.append("//Object for class Image Capture!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp1.append(metaData['name']+" = obj.imageCaptureObject\n")          
+                       } else {
+                               extractedObjectsApp2.append("//Object for class Image Capture!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp2.append(metaData['name']+" = obj.imageCaptureObject\n")
+                       }
                        break
                case "device.mobilePresence":
                        break
@@ -460,7 +650,9 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "mode":
-                       def userInput = System.console().readLine 'Enter the mode:'
+                       def randomVariable = Math.abs(new Random().nextInt() % 3)
+                       def modes = ["away", "home", "night"]
+                       def userInput = modes[randomVariable]
 
                        if (modeVariables == 0) {
                                mode0 = metaData['name']
@@ -495,11 +687,77 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "decimal":
+                       def userInput = Math.abs(new Random().nextInt() % 60) + 40
+                       
+                       if (decimalVariables == 0) {
+                               decimal0 = metaData['name']
+                               this[decimal0] = userInput
+                       } else if (decimalVariables == 1) {
+                               decimal1 = metaData['name']
+                               this[decimal1] = userInput
+                       } else if (decimalVariables == 2) {
+                               decimal2 = metaData['name']
+                               this[decimal2] = userInput
+                       } else if (decimalVariables == 3) {
+                               decimal3 = metaData['name']
+                               this[decimal3] = userInput
+                       } else if (decimalVariables == 4) {
+                               decimal4 = metaData['name']
+                               this[decimal4] = userInput
+                       } else if (decimalVariables == 5) {
+                               decimal5 = metaData['name']
+                               this[decimal5] = userInput
+                       }
+
+                       decimalVariables=decimalVariables+1
+
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {                    
+                               extractedObjectsApp1.append("//Global variable for decimal number!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+" = "+userInput+"\n")
+                       } else {
+                               extractedObjectsApp2.append("//Global variable for decimal number!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+" = "+userInput+"\n")
+                       }
                        break
                case "text":
+                       def userInput = "This is just a text!"
+       
+                       if (textVariables == 0) {
+                               text0 = metaData['name']
+                               this[text0] = userInput
+                       } else if (textVariables == 1) {
+                               text1 = metaData['name']
+                               this[text1] = userInput
+                       } else if (textVariables == 2) {
+                               text2 = metaData['name']
+                               this[text2] = userInput
+                       } else if (textVariables == 3) {
+                               text3 = metaData['name']
+                               this[text3] = userInput
+                       } else if (textVariables == 4) {
+                               text4 = metaData['name']
+                               this[text4] = userInput
+                       } else if (textVariables == 5) {
+                               text5 = metaData['name']
+                               this[text5] = userInput
+                       }
+
+                       textVariables=textVariables+1
+
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {                    
+                               extractedObjectsApp1.append("//Global variable for text!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+" = \""+userInput+"\"\n")
+                       } else {
+                               extractedObjectsApp2.append("//Global variable for text!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+" = \""+userInput+"\"\n")
+                       }
                        break
                case "number":
-                       def userInput = System.console().readLine 'Enter the number:'
+                       def userInput = Math.abs(new Random().nextInt() % 60) + 40
                        
                        if (numberVariables == 0) {
                                number0 = metaData['name']
@@ -534,7 +792,7 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "time":
-                       def userInput = System.console().readLine 'Enter the time:'
+                       def userInput = "15:00"
                        
                        if (timeVariables == 0) {
                                time0 = metaData['name']
@@ -569,7 +827,9 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "enum":
-                       def userInput = System.console().readLine 'Enter the enum:'
+                       def randomVariable = Math.abs(new Random().nextInt() % 2)
+                       def modes = ["Yes", "No"]
+                       def userInput = modes[randomVariable]
        
                        if (enumVariables == 0) {
                                enum0 = metaData['name']
@@ -604,9 +864,42 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "bool":
+                       def userInput = Math.abs(new Random().nextInt() % 2)
+       
+                       if (boolVariables == 0) {
+                               bool0 = metaData['name']
+                               this[bool0] = userInput
+                       } else if (boolVariables == 1) {
+                               bool1 = metaData['name']
+                               this[bool1] = userInput
+                       } else if (boolVariables == 2) {
+                               bool2 = metaData['name']
+                               this[bool2] = userInput
+                       } else if (boolVariables == 3) {
+                               bool3 = metaData['name']
+                               this[bool3] = userInput
+                       } else if (boolVariables == 4) {
+                               bool4 = metaData['name']
+                               this[bool4] = userInput
+                       } else if (boolVariables == 5) {
+                               bool5 = metaData['name']
+                               this[bool5] = userInput
+                       }
+
+                       boolVariables=boolVariables+1
+
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {                    
+                               extractedObjectsApp1.append("//Global variable for boolean!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+" = \""+userInput+"\"\n")
+                       } else {
+                               extractedObjectsApp2.append("//Global variable for boolean!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+" = \""+userInput+"\"\n")
+                       }
                        break
                case "phone":
-                       def userInput = System.console().readLine 'Enter the phone:'
+                       def userInput = 9495379373
 
                        if (phoneVariables == 0) {
                                phone0 = metaData['name']
@@ -641,7 +934,7 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "contact":
-                       def userInput = System.console().readLine 'Enter the metaData['name'] of the contact:'
+                       def userInput = "AJ"
        
                        if (contactVariables == 0) {
                                contact0 = metaData['name']
@@ -701,6 +994,10 @@ def mode(LinkedHashMap metaData) {
 
        println("//IGNORE--ForMobileUse//")
 }
+
+def href(LinkedHashMap metaData) {
+       println("//IGNORE--some data//")
+}
 /////Input Methods/////
 
 
@@ -743,6 +1040,10 @@ def dynamicPage(LinkedHashMap metaData, Closure inputData) {
        find(inputData) //Run the closure to extract sections/inputMethods
 }
 
+def paragraph(String paragraphText) {
+       println(paragraphText)
+}
+
 def section(String title, Closure inputData) {
        println(title)
        find(inputData) //Run the closure to extract inputMethods
index 1588235..38124be 100644 (file)
@@ -1,6 +1,9 @@
 import os
 readyToReturn = 0
 ToReturn = ""
+eventMap = []
+app1Capabilities = []
+app2Capabilities = []
 
 def GetToken(f):
        global readyToReturn
@@ -33,12 +36,15 @@ def GetToken(f):
                        return "EOF"
 
 def ExtractFunctions(F, appName):
+       global eventMap
        Temp = GetToken(F)
        while (Temp != "EOF"):
                if (Temp == "def" or Temp == "private"):
                        Temp = GetToken(F)
+                       if (Temp == "def" or Temp == "private"):
+                               Temp = GetToken(F)
                        NameofFunc = Temp
-                       if (GetToken(F) != "="): #We have a function to create object for
+                       if (GetToken(F) == "("): #We have a function to create object for
                                if (appName == "App1"):
                                        extractedFunctionsApp1.write("//Global Object for functions in subscribe method!\n")    
                                        extractedFunctionsApp1.write("def %s = this.&" % NameofFunc)
@@ -47,7 +53,162 @@ def ExtractFunctions(F, appName):
                                        extractedFunctionsApp2.write("//Global Object for functions in subscribe method!\n")    
                                        extractedFunctionsApp2.write("def %s = this.&" % NameofFunc)
                                        extractedFunctionsApp2.write("%s\n" % NameofFunc)
+               #Check subscribed events
+               if (Temp == "subscribe"):
+                       counter = 0
+                       while (counter < 5 and Temp != "\""):
+                               Temp = GetToken(F)
+                               counter = counter + 1
+                       Temp = GetToken(F)
+                       #If counter >= 5 that means it is not found, so it must be appTouch
+                       if (counter >= 5):
+                               Temp = "Touched"
+                       if Temp not in eventMap:
+                               eventMap.append(Temp)
+
+               #Check and analyze capabilities for physical interaction
+               AnalyzeCapabilities(Temp, appName)
+
                Temp = GetToken(F)
+
+       #Warn if there is a potential for physical interaction
+       AnalyzePhysicalInteraction(app1Capabilities, app2Capabilities)
+       AnalyzePhysicalInteraction(app2Capabilities, app1Capabilities)
+
+
+def AnalyzeCapabilities(Temp, appName):
+                       #Illuminance related
+       if (Temp == "capability.switch" or
+                       Temp == "capability.switchLevel" or
+                       Temp == "capability.illuminanceMeasurement" or
+                       #Motion related
+                       Temp == "capability.motionSensor" or
+                       #Water related
+                       Temp == "capability.valve" or
+                       Temp == "capability.waterSensor" or
+                       #Sound related
+                       Temp == "capability.musicPlayer" or
+                       Temp == "capability.alarm" or
+                       Temp == "capability.speechSynthesis" or
+                       Temp == "capability.soundSensor"):
+               if (appName == "App1"):
+                       app1Capabilities.append(Temp)
+               else:
+                       app2Capabilities.append(Temp)
+                       
+def AnalyzePhysicalInteraction(app1Capab, app2Capab):
+       #Light
+       if ("capability.illuminanceMeasurement" in app1Capab) and ("capability.switch" in app2Capab or 
+                       "capability.switchLevel" in app2Capab):
+               print ("\nWARNING: Potential PHYSICAL CONFLICT (light) detected between App1 and App2!\n")
+       #Motion
+       if ("capability.motionSensor" in app1Capab):
+               print ("\nWARNING: Potential PHYSICAL CONFLICT (motion) detected between App1 and App2!\n")             
+       #Water
+       if ("capability.waterSensor" in app1Capab) and ("capability.valve" in app2Capab or 
+                       "capability.switch" in app2Capab):
+               print ("\nWARNING: Potential PHYSICAL CONFLICT (water) detected between App1 and App2!\n")
+       #Sound
+       if ("capability.soundSensor" in app1Capab) and ("capability.musicPlayer" in app2Capab or 
+                       "capability.alarm" in app2Capab or "capability.speechSynthesis" in app2Capab):
+               print ("\nWARNING: Potential PHYSICAL CONFLICT (sound) detected between App1 and App2!\n")
+
+def ExtractEvents(extractedEvents):
+       global eventMap
+       extractedEvents.write("Random random = new Random(42)\n")
+       extractedEvents.write("counter = 1000\n")
+       extractedEvents.write("while(counter > 0) {\n")
+       extractedEvents.write("\tdef eventNumber = random.nextInt(%d)\n" % (len(eventMap) - 1))
+       extractedEvents.write("\tswitch(eventNumber) {\n")
+       eventCounter = 0;
+       for i in range(len(eventMap)):
+               extractedEvents.write("\t\tcase %d:\n" % eventCounter)
+               if eventMap[i] == "lock":
+                       event = open("eventSimulator/lockEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+               elif eventMap[i] == "unlock":
+                       event = open("eventSimulator/unlockEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+               elif eventMap[i] == "contact.open":
+                       event = open("eventSimulator/contactOpenEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+               elif eventMap[i] == "contact.closed":
+                       event = open("eventSimulator/contactClosedEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+               elif eventMap[i] == "switch.on":
+                       event = open("eventSimulator/switchOnEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+               elif eventMap[i] == "switch.off":
+                       event = open("eventSimulator/switchOffEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+               elif eventMap[i] == "nfcTouch":
+                       event = open("eventSimulator/nfcTouchEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+               elif eventMap[i] == "Touched":
+                       event = open("eventSimulator/appTouchEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+               elif eventMap[i] == "button":
+                       #Write two events subsequently
+                       event = open("eventSimulator/buttonPushedEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+                       extractedEvents.write("\t\t\tbreak\n")
+                       eventCounter = eventCounter + 1
+                       extractedEvents.write("\t\tcase %d:\n" % eventCounter)
+                       event = open("eventSimulator/buttonHeldEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+               elif eventMap[i] == "presence":
+                       #Write two events subsequently
+                       event = open("eventSimulator/presencePresentEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+                       extractedEvents.write("\t\t\tbreak\n")
+                       eventCounter = eventCounter + 1
+                       extractedEvents.write("\t\tcase %d:\n" % eventCounter)
+                       event = open("eventSimulator/presenceLeftEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+               elif eventMap[i] == "doorState":
+                       #Write two events subsequently
+                       event = open("eventSimulator/doorOpenEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+                       extractedEvents.write("\t\t\tbreak\n")
+                       eventCounter = eventCounter + 1
+                       extractedEvents.write("\t\tcase %d:\n" % eventCounter)
+                       event = open("eventSimulator/doorClosedEvent.groovy", "r")
+                       for line in event:
+                               extractedEvents.write(line)
+                       event.close()
+               eventCounter = eventCounter + 1
+
+               ###TODO: Add more events later
+               extractedEvents.write("\n\t\t\tbreak\n")
+       extractedEvents.write("\t}\n")
+       extractedEvents.write("\tcounter--\n")
+       extractedEvents.write("}\n")
                
 
 
index e59706c..5900547 100644 (file)
@@ -29,6 +29,16 @@ import AeonKeyFob.AeonKeyFob
 import AeonKeyFob.AeonKeyFobs
 import MusicPlayer.MusicPlayer
 import MusicPlayer.MusicPlayers
+import MotionSensor.MotionSensor
+import MotionSensor.MotionSensors
+import ImageCapture.ImageCapture
+import ImageCapture.ImageCaptures
+import SmokeDetector.SmokeDetector
+import SmokeDetector.SmokeDetectors
+import Alarm.Alarm
+import Alarm.Alarms
+import SpeechSynthesis.SpeechSynthesis
+import SpeechSynthesis.SpeechSynthesises
 import Timer.SimulatedTimer
 
 //GlobalVariables
@@ -39,6 +49,8 @@ import Timer.SimulatedTimer
 @Field def state = [home:[],away:[],night:[]]
 //Create a global logger object for methods
 @Field def log = new Logger()
+//Create a global variable for optional property
+@Field def optional = false //by default for now
 
 
 //Global variables for files
@@ -107,6 +119,31 @@ if (App == "App1") {
 @Field def aeonKeyFobObject0
 @Field def aeonKeyFobObject1
 @Field def aeonKeyFobObject2
+//Global Object for class motion sensor!
+@Field motionSensorObjects = 0
+@Field def motionSensorObject0
+@Field def motionSensorObject1
+@Field def motionSensorObject2
+//Global Object for class image capture!
+@Field imageCaptureObjects = 0
+@Field def imageCaptureObject0
+@Field def imageCaptureObject1
+@Field def imageCaptureObject2
+//Global Object for class smoke detector!
+@Field smokeDetectorObjects = 0
+@Field def smokeDetectorObject0
+@Field def smokeDetectorObject1
+@Field def smokeDetectorObject2
+//Global Object for class alarm!
+@Field alarmObjects = 0
+@Field def alarmObject0
+@Field def alarmObject1
+@Field def alarmObject2
+//Global Object for class alarm!
+@Field speechSynthesisObjects = 0
+@Field def speechSynthesisObject0
+@Field def speechSynthesisObject1
+@Field def speechSynthesisObject2
 
 
 //Global variables
@@ -126,6 +163,14 @@ if (App == "App1") {
 @Field number3
 @Field number4
 @Field number5
+//For decimal
+@Field decimalVariables = 0
+@Field decimal0
+@Field decimal1
+@Field decimal2
+@Field decimal3
+@Field decimal4
+@Field decimal5
 //For time
 @Field timeVariables = 0
 @Field time0
@@ -158,7 +203,22 @@ if (App == "App1") {
 @Field contact3
 @Field contact4
 @Field contact5
-
+//For text
+@Field textVariables = 0
+@Field textVariable0
+@Field textVariable1
+@Field textVariable2
+@Field textVariable3
+@Field textVariable4
+@Field textVariable5
+//For boolean
+@Field boolVariables = 0
+@Field boolVariable0
+@Field boolVariable1
+@Field boolVariable2
+@Field boolVariable3
+@Field boolVariable4
+@Field boolVariable5
 
 
 /////Input Methods/////
@@ -177,6 +237,14 @@ def input(LinkedHashMap metaData, String name, String type) {
        input(metaData)
 }
 
+//input "", "", linkedHashMap, Closure
+def input(LinkedHashMap metaData, String name, String type, Closure Input) {
+       metaData.put('name',name)
+       metaData.put('type',type)
+       input(metaData)
+       find(Input)
+}
+
 //input linkedHashMap
 def input(LinkedHashMap metaData) {
        if (metaData.containsKey('title')) {
@@ -213,6 +281,30 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "capability.alarm":
+                       if (alarmObjects == 0) {
+                               alarmObject0 = metaData['name']
+                               this[alarmObject0] = new Alarms({}, 1)
+                       } else if (alarmObjects == 1) {
+                               alarmObject1 = metaData['name']
+                               this[alarmObject1] = new Alarms({}, 1)
+                       } else if (alarmObjects == 2) {
+                               alarmObject2 = metaData['name']
+                               this[alarmObject2] = new Alarms({}, 1)
+                       }
+
+                       alarmObjects=alarmObjects+1
+
+                       settings.put(metaData['name'], metaData['name']) 
+
+                       if (App == "App1") {
+                               extractedObjectsApp1.append("//Object for class alarm!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp1.append(metaData['name']+" = obj.alarmObject\n")         
+                       } else {
+                               extractedObjectsApp2.append("//Object for class alarm!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp2.append(metaData['name']+" = obj.alarmObject\n")
+                       }
                        break
                case "capability.battery":
                        break
@@ -281,6 +373,30 @@ def input(LinkedHashMap metaData) {
                case "capability.accelerationSensor":
                        break
                case "capability.motionSensor":
+                       if (motionSensorObjects == 0) {
+                               motionSensorObject0 = metaData['name']
+                               this[motionSensorObject0] = new MotionSensors({}, 1)
+                       } else if (motionSensorObjects == 1) {
+                               motionSensorObject1 = metaData['name']
+                               this[motionSensorObject1] = new MotionSensors({}, 1)
+                       } else if (motionSensorObjects == 2) {
+                               motionSensorObject2 = metaData['name']
+                               this[motionSensorObject2] = new MotionSensors({}, 1)
+                       }
+
+                       motionSensorObjects=motionSensorObjects+1
+
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {
+                               extractedObjectsApp1.append("//Object for class Motion Sensor!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp1.append(metaData['name']+" = obj.motionSensorObject\n")          
+                       } else {
+                               extractedObjectsApp2.append("//Object for class Motion Sensor!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp2.append(metaData['name']+" = obj.motionSensorObject\n")
+                       }
                        break
                case "capability.musicPlayer":
                        if (musicPlayerObjects == 0) {
@@ -343,6 +459,30 @@ def input(LinkedHashMap metaData) {
                case "capability.sleepSensor":
                        break
                case "capability.smokeDetector":
+                       if (smokeDetectorObjects == 0) {
+                               smokeDetectorObject0 = metaData['name']
+                               this[smokeDetectorObject0] = new SmokeDetectors({}, 1)
+                       } else if (smokeDetectorObjects == 1) {
+                               smokeDetectorObject1 = metaData['name']
+                               this[smokeDetectorObject1] = new SmokeDetectors({}, 1)
+                       } else if (smokeDetectorObjects == 2) {
+                               smokeDetectorObject2 = metaData['name']
+                               this[smokeDetectorObject2] = new SmokeDetectors({}, 1)
+                       }
+
+                       smokeDetectorObjects=smokeDetectorObjects+1
+                       
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {
+                               extractedObjectsApp1.append("//Object for class smoke detector!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp1.append(metaData['name']+" = obj.smokeDetectorObject\n")         
+                       } else {
+                               extractedObjectsApp2.append("//Object for class smoke detector!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp2.append(metaData['name']+" = obj.smokeDetectorObject\n")
+                       }
                        break
                case "capability.stepSensor":
                        break
@@ -404,6 +544,32 @@ def input(LinkedHashMap metaData) {
                        break
                case "capability.valve":
                        break
+               case "capability.speechSynthesis":
+                       if (speechSynthesisObjects == 0) {
+                               speechSynthesisObject0 = metaData['name']
+                               this[speechSynthesisObject0] = new SpeechSynthesises({}, 1)
+                       } else if (speechSynthesisObjects == 1) {
+                               speechSynthesisObject1 = metaData['name']
+                               this[speechSynthesisObject1] = new SpeechSynthesises({}, 1)
+                       } else if (speechSynthesisObjects == 2) {
+                               speechSynthesisObject2 = metaData['name']
+                               this[speechSynthesisObject2] = new SpeechSynthesises({}, 1)
+                       }
+
+                       speechSynthesisObjects=speechSynthesisObjects+1
+
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {
+                               extractedObjectsApp1.append("//Object for class speech synthesis!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp1.append(metaData['name']+" = obj.speechSynthesisObject\n")               
+                       } else {
+                               extractedObjectsApp2.append("//Object for class speech synthesis!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp2.append(metaData['name']+" = obj.speechSynthesisObject\n")
+                       }
+                       break
                case "capability.waterSensor":
                        break
                case "capability.touchSensor":
@@ -433,6 +599,30 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "capability.imageCapture":
+                       if (imageCaptureObjects == 0) {
+                               imageCaptureObject0 = metaData['name']
+                               this[imageCaptureObject0] = new ImageCaptures({}, 1)
+                       } else if (imageCaptureObjects == 1) {
+                               imageCaptureObject1 = metaData['name']
+                               this[imageCaptureObject1] = new ImageCaptures({}, 1)
+                       } else if (imageCaptureObjects == 2) {
+                               imageCaptureObject2 = metaData['name']
+                               this[imageCaptureObject2] = new ImageCaptures({}, 1)
+                       }
+
+                       imageCaptureObjects=imageCaptureObjects+1
+
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {
+                               extractedObjectsApp1.append("//Object for class Image Capture!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp1.append(metaData['name']+" = obj.imageCaptureObject\n")          
+                       } else {
+                               extractedObjectsApp2.append("//Object for class Image Capture!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+"\n")
+                               extractedObjectsConstructorApp2.append(metaData['name']+" = obj.imageCaptureObject\n")
+                       }
                        break
                case "device.mobilePresence":
                        break
@@ -463,7 +653,9 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "mode":
-                       def userInput = System.console().readLine 'Enter the mode:'
+                       def randomVariable = Math.abs(new Random().nextInt() % 3)
+                       def modes = ["away", "home", "night"]
+                       def userInput = modes[randomVariable]
 
                        if (modeVariables == 0) {
                                mode0 = metaData['name']
@@ -498,11 +690,77 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "decimal":
+                       def userInput = Math.abs(new Random().nextInt() % 60) + 40
+                       
+                       if (decimalVariables == 0) {
+                               decimal0 = metaData['name']
+                               this[decimal0] = userInput
+                       } else if (decimalVariables == 1) {
+                               decimal1 = metaData['name']
+                               this[decimal1] = userInput
+                       } else if (decimalVariables == 2) {
+                               decimal2 = metaData['name']
+                               this[decimal2] = userInput
+                       } else if (decimalVariables == 3) {
+                               decimal3 = metaData['name']
+                               this[decimal3] = userInput
+                       } else if (decimalVariables == 4) {
+                               decimal4 = metaData['name']
+                               this[decimal4] = userInput
+                       } else if (decimalVariables == 5) {
+                               decimal5 = metaData['name']
+                               this[decimal5] = userInput
+                       }
+
+                       decimalVariables=decimalVariables+1
+
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {                    
+                               extractedObjectsApp1.append("//Global variable for decimal number!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+" = "+userInput+"\n")
+                       } else {
+                               extractedObjectsApp2.append("//Global variable for decimal number!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+" = "+userInput+"\n")
+                       }
                        break
                case "text":
+                       def userInput = "This is just a text!"
+       
+                       if (textVariables == 0) {
+                               text0 = metaData['name']
+                               this[text0] = userInput
+                       } else if (textVariables == 1) {
+                               text1 = metaData['name']
+                               this[text1] = userInput
+                       } else if (textVariables == 2) {
+                               text2 = metaData['name']
+                               this[text2] = userInput
+                       } else if (textVariables == 3) {
+                               text3 = metaData['name']
+                               this[text3] = userInput
+                       } else if (textVariables == 4) {
+                               text4 = metaData['name']
+                               this[text4] = userInput
+                       } else if (textVariables == 5) {
+                               text5 = metaData['name']
+                               this[text5] = userInput
+                       }
+
+                       textVariables=textVariables+1
+
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {                    
+                               extractedObjectsApp1.append("//Global variable for text!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+" = \""+userInput+"\"\n")
+                       } else {
+                               extractedObjectsApp2.append("//Global variable for text!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+" = \""+userInput+"\"\n")
+                       }
                        break
                case "number":
-                       def userInput = System.console().readLine 'Enter the number:'
+                       def userInput = Math.abs(new Random().nextInt() % 60) + 40
                        
                        if (numberVariables == 0) {
                                number0 = metaData['name']
@@ -537,7 +795,7 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "time":
-                       def userInput = System.console().readLine 'Enter the time:'
+                       def userInput = "15:00"
                        
                        if (timeVariables == 0) {
                                time0 = metaData['name']
@@ -572,7 +830,9 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "enum":
-                       def userInput = System.console().readLine 'Enter the enum:'
+                       def randomVariable = Math.abs(new Random().nextInt() % 2)
+                       def modes = ["Yes", "No"]
+                       def userInput = modes[randomVariable]
        
                        if (enumVariables == 0) {
                                enum0 = metaData['name']
@@ -607,9 +867,42 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "bool":
+                       def userInput = Math.abs(new Random().nextInt() % 2)
+       
+                       if (boolVariables == 0) {
+                               bool0 = metaData['name']
+                               this[bool0] = userInput
+                       } else if (boolVariables == 1) {
+                               bool1 = metaData['name']
+                               this[bool1] = userInput
+                       } else if (boolVariables == 2) {
+                               bool2 = metaData['name']
+                               this[bool2] = userInput
+                       } else if (boolVariables == 3) {
+                               bool3 = metaData['name']
+                               this[bool3] = userInput
+                       } else if (boolVariables == 4) {
+                               bool4 = metaData['name']
+                               this[bool4] = userInput
+                       } else if (boolVariables == 5) {
+                               bool5 = metaData['name']
+                               this[bool5] = userInput
+                       }
+
+                       boolVariables=boolVariables+1
+
+                       settings.put(metaData['name'], metaData['name'])
+
+                       if (App == "App1") {                    
+                               extractedObjectsApp1.append("//Global variable for boolean!\n")
+                               extractedObjectsApp1.append("def "+metaData['name']+" = \""+userInput+"\"\n")
+                       } else {
+                               extractedObjectsApp2.append("//Global variable for boolean!\n")
+                               extractedObjectsApp2.append("def "+metaData['name']+" = \""+userInput+"\"\n")
+                       }
                        break
                case "phone":
-                       def userInput = System.console().readLine 'Enter the phone:'
+                       def userInput = 9495379373
 
                        if (phoneVariables == 0) {
                                phone0 = metaData['name']
@@ -644,7 +937,7 @@ def input(LinkedHashMap metaData) {
                        }
                        break
                case "contact":
-                       def userInput = System.console().readLine 'Enter the metaData['name'] of the contact:'
+                       def userInput = "AJ"
        
                        if (contactVariables == 0) {
                                contact0 = metaData['name']
@@ -704,6 +997,10 @@ def mode(LinkedHashMap metaData) {
 
        println("//IGNORE--ForMobileUse//")
 }
+
+def href(LinkedHashMap metaData) {
+       println("//IGNORE--some data//")
+}
 /////Input Methods/////
 
 
@@ -746,6 +1043,10 @@ def dynamicPage(LinkedHashMap metaData, Closure inputData) {
        find(inputData) //Run the closure to extract sections/inputMethods
 }
 
+def paragraph(String paragraphText) {
+       println(paragraphText)
+}
+
 def section(String title, Closure inputData) {
        println(title)
        find(inputData) //Run the closure to extract inputMethods
@@ -762,7 +1063,22 @@ def section(LinkedHashMap metaData, Closure inputData) {
 
 
 
-////////////////
+/**
+ *  NFC Tag Toggle
+ *
+ *  Copyright 2014 SmartThings
+ *
+ *  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:
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  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. See the License
+ *  for the specific language governing permissions and limitations under the License.
+ *
+ */
 definition(
     name: "NFC Tag Toggle",
     namespace: "smartthings",
@@ -785,18 +1101,18 @@ preferences {
             input "garageDoor", "capability.doorControl", title: "Garage door controller", required: false, multiple: true
         }
     }
-
+    
     page(name: "pageTwo", title: "Master devices", install: true, uninstall: true)
 }
 
 def pageTwo() {
        dynamicPage(name: "pageTwo") {
-       section("If set, the state of these devices will be toggled each time the tag is touched, " +
+       section("If set, the state of these devices will be toggled each time the tag is touched, " + 
                 "e.g. a light that's on will be turned off and one that's off will be turned on, " +
                 "other devices of the same type will be set to the same state as their master device. " +
                 "If no master is designated then the majority of devices of the same type will be used " +
                 "to determine whether to turn on or off the devices.") {
-
+            
             if (switch1 || masterSwitch) {
                 input "masterSwitch", "enum", title: "Master switch", options: switch1.collect{[(it.id): it.displayName]}, required: false
             }
@@ -805,12 +1121,12 @@ def pageTwo() {
             }
             if (garageDoor || masterDoor) {
                 input "masterDoor", "enum", title: "Master door", options: garageDoor.collect{[(it.id): it.displayName]}, required: false
-            }
+            }            
                }
                section([mobileOnly:true]) {
                        label title: "Assign a name", required: false
                        mode title: "Set for specific mode(s)", required: false
-               }
+               }        
     }
 }
 
@@ -865,7 +1181,7 @@ def touchHandler(evt) {
             }
         }
     }
-
+    
     if (lock) {
        def status = currentStatus(lock, masterLock, "lock")
         lock.each {
@@ -877,7 +1193,7 @@ def touchHandler(evt) {
             }
         }
     }
-
+    
     if (garageDoor) {
         def status = currentStatus(garageDoor, masterDoor, "status")
        garageDoor.each {
index 8810742..2110f72 100644 (file)
@@ -3,7 +3,7 @@
                        eventHandler(eventDataMap)
                        }
 //Object for location
-@Field def locationObject = new LocationVar()
+@Field def locationObject = new LocationVar(sendEvent)
 //Object for touch to call function
 @Field def appObject = new Touched(sendEvent, 0)
 //Create a global list for events
 @Field def aeonKeyFobObject = new AeonKeyFobs(sendEvent, 1)
 //Global Object for class music player!
 @Field def musicPlayerObject = new MusicPlayers(sendEvent, 1)
+//Global Object for class motion sensor!
+@Field def motionSensorObject = new MotionSensors(sendEvent, 1)
+//Global Object for class image capture!
+@Field def imageCaptureObject = new ImageCaptures(sendEvent, 1)
+//Global Object for class smoke detector!
+@Field def smokeDetectorObject = new SmokeDetectors(sendEvent, 1)
+//Global Object for class alarm!
+@Field def alarmObject = new Alarms(sendEvent, 1)
+//Global Object for class speech synthesis!
+@Field def speechSynthesisObject = new SpeechSynthesises(sendEvent, 1)
index ce8308c..0e1de0b 100644 (file)
@@ -14,3 +14,5 @@ def timersFuncList = []
 def timersList = []
 //Create a global variable for settings
 def settings
+//Zip code
+def zipCode = 92617
diff --git a/ImageCapture/ImageCapture.groovy b/ImageCapture/ImageCapture.groovy
new file mode 100644 (file)
index 0000000..5d9f945
--- /dev/null
@@ -0,0 +1,33 @@
+//Create a class for image capture sensor
+package ImageCapture
+import Timer.SimulatedTimer
+
+public class ImageCapture {
+       private String id
+       private String label
+       private String displayName
+       private String image
+       private String alarmState
+
+       ImageCapture(String id, String label, String displayName, String image, String alarmState) {
+               this.id = id
+               this.label = label
+               this.displayName = displayName
+               this.image = image
+               this.alarmState = alarmState
+       }
+       
+       def alarmOn() {
+               println("The camera with id:$id is armed!")
+               this.alarmState = "armed"
+       }
+
+       def alarmOff() {
+               println("The camera with id:$id is not armed!")
+               this.alarmState = "not armed"
+       }
+
+       def take() {
+               println("The camera with id:$id is taken a picture!")
+       }
+}
diff --git a/ImageCapture/ImageCaptures.groovy b/ImageCapture/ImageCaptures.groovy
new file mode 100644 (file)
index 0000000..2a63a3e
--- /dev/null
@@ -0,0 +1,60 @@
+//Create a class for image capture sensor
+package ImageCapture
+import Timer.SimulatedTimer
+
+public class ImageCaptures {
+       private int deviceNumbers
+       private List imageCaptureSensors
+       def sendEvent
+
+       //For one device(We cannot have obj.id)-> We should have obj[0].id
+       private String id = "motionSensorID0"
+       private String label = "motionSensor0"
+       private String displayName = "motionSensor0"
+       private String image = "imageData"
+       private String alarmState = "armed"
+
+               
+       ImageCaptures(Closure sendEvent, int deviceNumbers) {
+               this.sendEvent = sendEvent              
+               this.deviceNumbers = deviceNumbers
+               this.imageCaptureSensors = []
+
+               imageCaptureSensors.add(new ImageCapture(id, label, displayName, this.image, this.alarmState))
+       }
+
+
+       //Methods for closures
+       def count(Closure Input) {
+               imageCaptureSensors.count(Input)
+       }
+       def size() {
+               imageCaptureSensors.size()
+       }
+       def each(Closure Input) {
+               imageCaptureSensors.each(Input)
+       }
+       def find(Closure Input) {
+               imageCaptureSensors.find(Input)
+       }
+       def collect(Closure Input) {
+               imageCaptureSensors.collect(Input)
+       }
+
+       def alarmOn() {
+               imageCaptureSensors[0].alarmOn()
+               this.alarmState = "armed"
+       }
+
+       def alarmOff() {
+               imageCaptureSensors[0].alarmOff()
+               this.alarmState = "not armed"
+       }
+
+       def take() {
+               imageCaptureSensors[0].take()
+       }
+       def getAt(int ix) {
+               imageCaptureSensors[ix]
+       }
+}
index 43c88cd..b2016e8 100644 (file)
@@ -7,15 +7,25 @@ class LocationVar {
        private String mode
        private List contacts
        private List phoneNumbers
+       def sendEvent
     
        private Phrase helloHome
 
-       LocationVar() {
+       LocationVar(Closure sendEvent) {
                this.modes = [[name: "home"],[name: "away"],[name: "night"]]
                this.mode = "home"
                this.helloHome = new Phrase()
                this.contactBookEnabled = 1
                this.contacts = ['AJ']
                this.phoneNumbers = [9495379373]
+               this.sendEvent = sendEvent
        }
+
+       //By Model Checker
+       def setValue(LinkedHashMap eventDataMap) {
+               def sentMode = eventDataMap['value']
+               println("The location is changed to $sentMode!")
+               this.mode = sentMode
+               sendEvent(eventDataMap)
+       }
 }
index 6214b84..f792c6c 100644 (file)
@@ -28,22 +28,34 @@ public class Locks{
        //By Apps
        def lock() {
                locks[0].lock()
+               lockLatestValue = lockState
+               lockState = "locked"
+               currentLock = "locked"
        }
 
        def lock(LinkedHashMap metaData) {
                def task = timers.runAfter(metaData["delay"]) {
                        locks[0].lock()
+                       lockLatestValue = lockState
+                       lockState = "locked"
+                       currentLock = "locked"
                }
        }
 
        def unlock() {
                locks[0].unlock()
+               lockLatestValue = lockState
+               lockState = "unlocked"
+               currentLock = "unlocked"
        }
 
 
        def unlock(LinkedHashMap metaData) {
                def task = timers.runAfter(metaData["delay"]) {
                        locks[0].unlock()
+                       lockLatestValue = lockState
+                       lockState = "unlocked"
+                       currentLock = "unlocked"
                }
        }
 
@@ -66,11 +78,13 @@ public class Locks{
 
        //By Model Checker
        def setValue(LinkedHashMap eventDataMap) {
-               locks[0].setValue(eventDataMap["value"])
-               this.lockState = locks[0].lockState
-               this.currentLock = locks[0].lockState
-               this.lockLatestValue = locks[0].lockLatestValue
-               sendEvent(eventDataMap)
+               if (eventDataMap["value"] != locks[0].lockState) {
+                       locks[0].setValue(eventDataMap["value"])
+                       this.lockState = locks[0].lockState
+                       this.currentLock = locks[0].lockState
+                       this.lockLatestValue = locks[0].lockLatestValue
+                       sendEvent(eventDataMap)
+               }
        }
 
        def currentValue(String deviceFeature) {
diff --git a/Methods/getSunriseAndSunset.groovy b/Methods/getSunriseAndSunset.groovy
new file mode 100644 (file)
index 0000000..59f4418
--- /dev/null
@@ -0,0 +1,5 @@
+/////////////////////////////////////////////////////////////////////
+def getSunriseAndSunset(LinkedHashMap metaData) {
+       def sunRiseSetInfo = [sunrise:[time:1563800160000],sunset:[time:1563850740000]]
+       return sunRiseSetInfo
+}
diff --git a/Methods/getTemperatureScale.groovy b/Methods/getTemperatureScale.groovy
new file mode 100644 (file)
index 0000000..8fb2560
--- /dev/null
@@ -0,0 +1,5 @@
+/////////////////////////////////////////////////////////////////////
+def getTemperatureScale() {
+       return 'C' //Celsius for now
+}
+
index 178e16d..6e4bea3 100644 (file)
@@ -3,10 +3,26 @@
 def runIn(int seconds, Closure functionToCall) {
        if (timersFuncList.contains(functionToCall)) {
                timersList[timersFuncList.indexOf(functionToCall)].cancel()
-               def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall)
+               def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds*0, functionToCall)
        } else {
                timersFuncList.add(functionToCall)
                timersList.add(new SimulatedTimer())
-               def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall)
+               def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds*0, functionToCall)
+       }
+}
+
+def runIn(int seconds, Closure functionToCall, LinkedHashMap metaData) {
+       runIn(seconds, functionToCall)
+}
+
+def runIn(int seconds, String nameOfFunction, LinkedHashMap metaData) {
+       runIn(seconds, nameOfFunction)
+}
+
+def runIn(int seconds, String nameOfFunction) {
+       timersFuncList.add(nameOfFunction)
+       timersList.add(new SimulatedTimer())
+       def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(seconds*1000*0) {
+               "$nameOfFunction"()
        }
 }
index be935b8..3981f54 100644 (file)
@@ -18,7 +18,7 @@ def schedule(String time, String nameOfFunction) {
 
        timersFuncList.add(nameOfFunction)
        timersList.add(new SimulatedTimer())
-       def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000) {
+       def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000*0) {
                "$nameOfFunction"()
        }
 }
@@ -41,10 +41,10 @@ def schedule(String time, Closure nameOfFunction) {
 
        if (timersFuncList.contains(nameOfFunction)) {
                timersList[timersFuncList.indexOf(nameOfFunction)].cancel()
-               def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction)
+               def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds*0, nameOfFunction)
        } else {
                timersFuncList.add(nameOfFunction)
                timersList.add(new SimulatedTimer())
-               def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction)
+               def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds*0, nameOfFunction)
        }
 }
index 2d71fa9..8f0936c 100644 (file)
@@ -3,3 +3,7 @@
 def sendSms(long phoneNumber, String text) {
        println("Sending \""+text+"\" to "+phoneNumber.toString())
 }
+
+def sendSMS(long phoneNumber, String text) {
+       println("Sending \""+text+"\" to "+phoneNumber.toString())
+}
diff --git a/MotionSensor/MotionSensor.groovy b/MotionSensor/MotionSensor.groovy
new file mode 100644 (file)
index 0000000..825fe33
--- /dev/null
@@ -0,0 +1,55 @@
+//Create a class for presence sensor
+package MotionSensor
+import Timer.SimulatedTimer
+
+public class MotionSensor {
+       private String id
+       private String label
+       private String displayName
+       private String motion
+       private String currentMotion
+       private String motionLatestValue
+       private List states = []
+       private List timeOfStates = []
+
+       MotionSensor(String id, String label, String displayName, String motion, String motionLatestValue) {
+               this.id = id
+               this.label = label
+               this.displayName = displayName
+               this.motion = motion
+               this.currentMotion = motion
+               this.motionLatestValue = motionLatestValue
+       }
+
+       def setValue(String value) {
+               this.motionLatestValue = motion
+               println("the motion sensor with id:$id is triggered to $value!")
+               this.motion = value
+               this.currentMotion = value
+               this.states.add(value)
+               this.timeOfStates.add(System.currentTimeMillis())
+       }
+
+       def statesSince(String info, Date dateObj) {
+               def List happenedStates = []
+               def sinceThen = dateObj.time
+               for (int i = 0;i < timeOfStates.size();i++) {
+                       if (timeOfStates[i]>=sinceThen)
+                               happenedStates.add(states[i])
+               }
+               return happenedStates
+       }
+
+       
+       def currentValue(String deviceFeature) {
+               if (deviceFeature == "motion") {
+                       return motion
+               }
+       }
+
+       def latestValue(String deviceFeature) {
+               if (deviceFeature == "motion") {
+                       return motionLatestValue
+               }
+       }
+}
diff --git a/MotionSensor/MotionSensors.groovy b/MotionSensor/MotionSensors.groovy
new file mode 100644 (file)
index 0000000..863903c
--- /dev/null
@@ -0,0 +1,71 @@
+//Create a class for presence sensor
+package MotionSensor
+import Timer.SimulatedTimer
+
+public class MotionSensors {
+       private int deviceNumbers
+       private List motionSensors
+       def sendEvent
+
+       //For one device(We cannot have obj.id)-> We should have obj[0].id
+       private String id = "motionSensorID0"
+       private String label = "motionSensor0"
+       private String displayName = "motionSensor0"
+       private String motion = "inactive"
+       private String currentMotion = "inactive"
+       private String motionLatestValue = "inactive"
+
+               
+       MotionSensors(Closure sendEvent, int deviceNumbers) {
+               this.sendEvent = sendEvent              
+               this.deviceNumbers = deviceNumbers
+               this.motionSensors = []
+
+               motionSensors.add(new MotionSensor(id, label, displayName, this.motion, this.motionLatestValue))
+       }
+
+       //By Model Checker
+       def setValue(LinkedHashMap eventDataMap) {
+               if (eventDataMap["value"] != motionSensors[0].motion) {
+                       motionSensors[0].setValue(eventDataMap["value"])
+                       this.motionLatestValue = motionSensors[0].motionLatestValue
+                       this.motion = motionSensors[0].motion
+                       this.currentMotion = motionSensors[0].motion
+                       sendEvent(eventDataMap)
+               }
+       }
+
+       //Methods for closures
+       def count(Closure Input) {
+               motionSensors.count(Input)
+       }
+       def size() {
+               motionSensors.size()
+       }
+       def each(Closure Input) {
+               motionSensors.each(Input)
+       }
+       def find(Closure Input) {
+               motionSensors.find(Input)
+       }
+       def collect(Closure Input) {
+               motionSensors.collect(Input)
+       }
+
+
+       def currentValue(String deviceFeature) {
+               motionSensors[0].currentValue(deviceFeature)//It is called if we have only one device
+       }
+
+       def latestValue(String deviceFeature) {
+               motionSensors[0].latestValue(deviceFeature)//It is called if we have only one device
+       }
+
+       def statesSince(String info, Date dateObj) {
+               return motionSensors[0].statesSince(info, dateObj)
+       }
+
+       def getAt(int ix) {
+               motionSensors[ix]
+       }
+}
index 9968595..9cf8f69 100644 (file)
@@ -48,36 +48,50 @@ public class MusicPlayers {
        //methods
        def mute() {
                musicPlayers[0].mute()
+               this.mute = "muted"
        }
        def nextTrack() {
                musicPlayers[0].nextTrack()
+               this.status = "playing"
+               this.trackNumber = musicPlayers[0].trackNumber
        }
        def pause() {
                musicPlayers[0].pause()
+               this.status = "paused"
        }
        def play() {
                musicPlayers[0].play()
+               this.status = "playing"
        }
        def playTrack(String trackToPlay) {
                musicPlayers[0].playTrack(trackToPlay)
+               this.status = "playing"
+               this.trackNumber = musicPlayers[0].trackNumber
        }
        def previousTrack() {
                musicPlayers[0].previousTrack()
+               this.status = "playing"
+               this.trackNumber = musicPlayers[0].trackNumber
        }
        def restoreTrack(String trackToRestore) {
                musicPlayers[0].restoreTrack(trackToRestore)
        }
        def resumeTrack(String trackToResume) {
                musicPlayers[0].resumeTrack(trackToResume)
+               this.status = "playing"
        }
        def setLevel(int level) {
                musicPlayers[0].setLevel(level)
+               this.level = level
        }
        def setTrack(String trackToSet) {
                musicPlayers[0].setTrack(trackToSet)
+               this.status = "playing"
+               this.trackNumber = musicPlayers[0].trackNumber
        }
        def stop() {
                musicPlayers[0].stop()
+               this.status = "stopped"
        }
 
        def currentValue(String deviceFeature) {
index cc5c820..8fb9161 100644 (file)
@@ -26,12 +26,13 @@ public class PresenceSensors {
 
        //By Model Checker
        def setValue(LinkedHashMap eventDataMap) {
-               presenceSensors[0].setValue(eventDataMap["value"])
-               if (deviceNumbers == 1)
+               if (eventDataMap["value"] != presenceSensors[0].presenceState) {
+                       presenceSensors[0].setValue(eventDataMap["value"])
                        this.presenceLatestValue = presenceSensors[0].presenceLatestValue
                        this.presenceState = presenceSensors[0].presenceState
                        this.currentPresence = presenceSensors[0].presenceState
-               sendEvent(eventDataMap)
+                       sendEvent(eventDataMap)
+               }
        }
 
        //Methods for closures
index 33b3b56..d3d7c16 100644 (file)
--- a/Runner.py
+++ b/Runner.py
@@ -22,6 +22,8 @@ sendPush = open("Methods/"+"sendPush.groovy", "r")
 eventHandler = open("Methods/"+"eventHandler.groovy", "r")
 schedule = open("Methods/"+"schedule.groovy", "r")
 now = open("Methods/"+"now.groovy", "r")
+getTemperatureScale = open("Methods/"+"getTemperatureScale.groovy", "r")
+getSunriseAndSunset = open("Methods/"+"getSunriseAndSunset.groovy", "r")
 App1 = open("Extractor/"+"App1/App1.groovy", "r")
 extractedObjectsApp1 = open("Extractor/"+"App1/extractedObjectsApp1.groovy", "r")
 extractedObjectsConstructorApp1 = open("Extractor/"+"App1/extractedObjectsConstructorApp1.groovy", "r")
@@ -56,6 +58,16 @@ Out.write("import AeonKeyFob.AeonKeyFob\n")
 Out.write("import AeonKeyFob.AeonKeyFobs\n")
 Out.write("import MusicPlayer.MusicPlayer\n")
 Out.write("import MusicPlayer.MusicPlayers\n")
+Out.write("import MotionSensor.MotionSensor\n")
+Out.write("import MotionSensor.MotionSensors\n")
+Out.write("import ImageCapture.ImageCapture\n")
+Out.write("import ImageCapture.ImageCaptures\n")
+Out.write("import SmokeDetector.SmokeDetector\n")
+Out.write("import SmokeDetector.SmokeDetectors\n")
+Out.write("import Alarm.Alarm\n")
+Out.write("import Alarm.Alarms\n")
+Out.write("import SpeechSynthesis.SpeechSynthesis\n")
+Out.write("import SpeechSynthesis.SpeechSynthesises\n")
 Out.write("import Event.Event\n")
 Out.write("import Timer.SimulatedTimer\n")
 Out.write("\n")
@@ -111,6 +123,10 @@ for line in schedule:
        Out.write("\t"+line)
 for line in now:
        Out.write("\t"+line)
+for line in getTemperatureScale:
+       Out.write("\t"+line)
+for line in getSunriseAndSunset:
+       Out.write("\t"+line)
 Out.write("\n")
 Start = 0
 for line in App1:
@@ -133,6 +149,9 @@ sendNotificationToContacts = open("Methods/"+"sendNotificationToContacts.groovy"
 sendSms = open("Methods/"+"sendSms.groovy", "r")
 eventHandler = open("Methods/"+"eventHandler.groovy", "r")
 schedule = open("Methods/"+"schedule.groovy", "r")
+now = open("Methods/"+"now.groovy", "r")
+getTemperatureScale = open("Methods/"+"getTemperatureScale.groovy", "r")
+getSunriseAndSunset = open("Methods/"+"getSunriseAndSunset.groovy", "r")
 App2 = open("Extractor/"+"App2/App2.groovy", "r")
 extractedObjectsApp2 = open("Extractor/"+"App2/extractedObjectsApp2.groovy", "r")
 extractedObjectsConstructorApp2 = open("Extractor/"+"App2/extractedObjectsConstructorApp2.groovy", "r")
@@ -182,6 +201,10 @@ for line in schedule:
        Out.write("\t"+line)
 for line in now:
        Out.write("\t"+line)
+for line in getTemperatureScale:
+       Out.write("\t"+line)
+for line in getSunriseAndSunset:
+       Out.write("\t"+line)
 Out.write("\n")
 Start = 0
 for line in App2:
diff --git a/SmokeDetector/SmokeDetector.groovy b/SmokeDetector/SmokeDetector.groovy
new file mode 100644 (file)
index 0000000..3182cc3
--- /dev/null
@@ -0,0 +1,41 @@
+//Create a class for smoke detector
+package SmokeDetector
+import Timer.SimulatedTimer
+
+public class SmokeDetector {
+       private String id
+       private String label
+       private String displayName
+       private String smoke
+       private String currentSmokeValue
+       private String smokeLatestValue
+
+       SmokeDetector(String id, String label, String displayName, String smoke, String smokeLatestValue) {
+               this.id = id
+               this.label = label
+               this.displayName = displayName
+               this.smoke = smoke
+               this.currentSmokeValue = smoke
+               this.smokeLatestValue = smokeLatestValue
+       }
+
+       def setValue(String value) {
+               this.smokeLatestValue = smoke
+               println("the smoke detector with id:$id is triggered to $value!")
+               this.smoke = value
+               this.currentSmokeValue = value
+       }
+
+       
+       def currentValue(String deviceFeature) {
+               if (deviceFeature == "smoke") {
+                       return currentSmokeValue
+               }
+       }
+
+       def latestValue(String deviceFeature) {
+               if (deviceFeature == "smoke") {
+                       return smokeLatestValue
+               }
+       }
+}
diff --git a/SmokeDetector/SmokeDetectors.groovy b/SmokeDetector/SmokeDetectors.groovy
new file mode 100644 (file)
index 0000000..95bcb3c
--- /dev/null
@@ -0,0 +1,67 @@
+//Create a class for smoke detector
+package SmokeDetector
+import Timer.SimulatedTimer
+
+public class SmokeDetectors {
+       private int deviceNumbers
+       private List smokeDetectors
+       def sendEvent
+
+       //For one device(We cannot have obj.id)-> We should have obj[0].id
+       private String id = "smokeDetectorID0"
+       private String label = "smokeDetector0"
+       private String displayName = "smokeDetector0"
+       private String smoke = "clear"
+       private String currentSmokeValue = "clear"
+       private String smokeLatestValue = "clear"
+
+               
+       SmokeDetectors(Closure sendEvent, int deviceNumbers) {
+               this.sendEvent = sendEvent              
+               this.deviceNumbers = deviceNumbers
+               this.smokeDetectors = []
+
+               smokeDetectors.add(new SmokeDetector(id, label, displayName, this.currentSmokeValue, this.smokeLatestValue))
+       }
+
+       //By Model Checker
+       def setValue(LinkedHashMap eventDataMap) {
+               if (eventDataMap["value"] != smokeDetectors[0].currentSmokeValue) {
+                       smokeDetectors[0].setValue(eventDataMap["value"])
+                       this.smokeLatestValue = smokeDetectors[0].smokeLatestValue
+                       this.smoke = smokeDetectors[0].currentSmokeValue
+                       this.currentSmokeValue = smokeDetectors[0].currentSmokeValue
+                       sendEvent(eventDataMap)
+               }
+       }
+
+       //Methods for closures
+       def count(Closure Input) {
+               smokeDetectors.count(Input)
+       }
+       def size() {
+               smokeDetectors.size()
+       }
+       def each(Closure Input) {
+               smokeDetectors.each(Input)
+       }
+       def find(Closure Input) {
+               smokeDetectors.find(Input)
+       }
+       def collect(Closure Input) {
+               smokeDetectors.collect(Input)
+       }
+
+
+       def currentValue(String deviceFeature) {
+               smokeDetectors[0].currentValue(deviceFeature)//It is called if we have only one device
+       }
+
+       def latestValue(String deviceFeature) {
+               smokeDetectors[0].latestValue(deviceFeature)//It is called if we have only one device
+       }
+
+       def getAt(int ix) {
+               smokeDetectors[ix]
+       }
+}
diff --git a/SpeechSynthesis/SpeechSynthesis.groovy b/SpeechSynthesis/SpeechSynthesis.groovy
new file mode 100644 (file)
index 0000000..a13e7f7
--- /dev/null
@@ -0,0 +1,27 @@
+//Create a class for speech synthesis
+package SpeechSynthesis
+import Timer.SimulatedTimer
+
+public class SpeechSynthesis {
+       private String id
+       private String label
+       private String displayName
+       private int level
+
+
+       SpeechSynthesis(String id, String label, String displayName, int level) {
+               this.id = id
+               this.label = label
+               this.displayName = displayName
+               this.level = level
+       }
+
+       def setLevel(int level) {
+               println("The level of speech synthesis with id:$id is changed to $level")
+               this.level = level
+       }
+
+       def speak(String message) {
+               println("Speech synthesis with id:$id, SPEAKING:\"$message\"!")
+       }
+}
diff --git a/SpeechSynthesis/SpeechSynthesises.groovy b/SpeechSynthesis/SpeechSynthesises.groovy
new file mode 100644 (file)
index 0000000..033db31
--- /dev/null
@@ -0,0 +1,54 @@
+//Create a class for speech synthesis
+package SpeechSynthesis
+import Timer.SimulatedTimer
+
+public class SpeechSynthesises {
+       private int deviceNumbers
+       private List speechSynthesises
+       def sendEvent
+
+       //For one device(We cannot have obj.id)-> We should have obj[0].id
+       private String id = "speechSynthesisID0"
+       private String label = "speechSynthesis0"
+       private String displayName = "speechSynthesis0"
+       private int level = 50
+
+               
+       SpeechSynthesises(Closure sendEvent, int deviceNumbers) {
+               this.sendEvent = sendEvent              
+               this.deviceNumbers = deviceNumbers
+               this.speechSynthesises = []
+
+               speechSynthesises.add(new SpeechSynthesis(id, label, displayName, this.level))
+       }
+
+       //Methods for closures
+       def count(Closure Input) {
+               speechSynthesises.count(Input)
+       }
+       def size() {
+               speechSynthesises.size()
+       }
+       def each(Closure Input) {
+               speechSynthesises.each(Input)
+       }
+       def find(Closure Input) {
+               speechSynthesises.find(Input)
+       }
+       def collect(Closure Input) {
+               speechSynthesises.collect(Input)
+       }
+
+       def setLevel(int level) {
+               speechSynthesises[0].setLevel(level)
+               this.level = level
+       }
+
+       def speak(String message) {
+               speechSynthesises[0].speak(message)
+       }
+
+       def getAt(int ix) {
+               speechSynthesises[ix]
+       }
+}
index cf8c068..9007388 100644 (file)
@@ -46,34 +46,49 @@ public class Switches {
        //By Apps
        def setLevel(int level) {
                switches[0].setLevel(level)
+               currentLevel = level
        }
 
        def on() {
                switches[0].on()
+               switchLatestValue = switchState
+               switchState = "on"
+               currentSwitch = "on"
        }
 
        def on(LinkedHashMap metaData) {
                def task = timers.runAfter(metaData["delay"]) {
                        switches[0].on()
+                       switchLatestValue = switchState
+                       switchState = "on"
+                       currentSwitch = "on"
                }
        }
 
        def off() {
                switches[0].off()
+               switchLatestValue = switchState
+               switchState = "off"
+               currentSwitch = "off"
        }
 
        def off(LinkedHashMap metaData) {
                def task = timers.runAfter(metaData["delay"]) {
                        switches[0].off()
+                       switchLatestValue = switchState
+                       switchState = "off"
+                       currentSwitch = "off"
                }
        }
 
        //By Model Checker
        def setValue(LinkedHashMap eventDataMap) {
-               switches[0].setValue(eventDataMap["value"])
-               this.switchState = switches[0].switchState
-               this.switchLatestValue = switches[0].switchLatestValue
-               sendEvent(eventDataMap)
+               if (eventDataMap["value"] != switches[0].switchState) {
+                       switches[0].setValue(eventDataMap["value"])
+                       this.switchState = switches[0].switchState
+                       this.switchLatestValue = switches[0].switchLatestValue
+                       sendEvent(eventDataMap)
+               }
        }
 
 
index 8bd5e9f..720ba82 100644 (file)
@@ -20,13 +20,16 @@ public class Thermostat {
        private String thermostatOperatingState
        private String thermostatFanMode
        private String thermostatMode
+       private String currentThermostatMode
+       private String climateName
        def sendEvent
        def timers
 
 
        Thermostat(Closure sendEvent, String id, String label, String displayName, int temperature, int currentCoolingSetpoint, int currentHeatingSetpoint, int coolingSetpoint, 
                    int thermostatSetpoint, int heatingSetpoint, List coolingSetpointRange, List thermostatSetpointRange, List heatingSetpointRange, 
-                   List supportedThermostatFanModes, List supportedThermostatModes, String thermostatOperatingState, String thermostatFanMode, String thermostatMode) {
+                   List supportedThermostatFanModes, List supportedThermostatModes, String thermostatOperatingState, String thermostatFanMode, String thermostatMode,
+                  String climateName) {
                this.id = id
                this.label = label
                this.sendEvent = sendEvent
@@ -44,6 +47,8 @@ public class Thermostat {
                this.thermostatOperatingState = thermostatOperatingState
                this.thermostatFanMode = thermostatFanMode
                this.thermostatMode = thermostatMode
+               this.currentThermostatMode = thermostatMode
+               this.climateName = climateName
        }
 
 
@@ -71,15 +76,53 @@ public class Thermostat {
 
        def setThermostatMode(String thermostatMode) {
                this.thermostatMode = thermostatMode
+               this.currentThermostatMode = currentThermostatMode
                println("Mode of the thermostat with id:$id is changed to $thermostatMode!")
        }
 
+       def cool() {
+               this.thermostatMode = "cool"
+               this.currentThermostatMode = "cool"
+               println("Mode of the thermostat with id:$id is changed to cool!")
+       }
+
+       def heat() {
+               this.thermostatMode = "heat"
+               this.currentThermostatMode = "heat"
+               println("Mode of the thermostat with id:$id is changed to heat!")
+       }
+
+       def auto() {
+               this.thermostatMode = "auto"
+               this.currentThermostatMode = "auto"
+               println("Mode of the thermostat with id:$id is changed to auto!")
+       }
+
+       def off() {
+               this.thermostatMode = "off"
+               this.currentThermostatMode = "off"
+               println("Mode of the thermostat with id:$id is changed to off!")
+       }
+
+       def setClimate(String info, String givenClimateName) {
+               this.climateName = givenClimateName
+               println("Climate name of the thermostat with id:$id is changed to $givenClimateName!")
+       }
+
+       def setHold(String info1, int coolingSetpoint, int heatingSetpoint, String info2, String info3) {
+               this.coolingSetpoint = coolingSetpoint
+               this.currentCoolingSetpoint = currentCoolingSetpoint
+               println("Cooling set point for the thermostat with id:$id is changed to $coolingSetpoint!")
+               this.heatingSetpoint = heatingSetpoint
+               this.currentHeatingSetpoint = currentHeatingSetpoint
+               println("Heating set point for the thermostat with id:$id is changed to $heatingSetpoint!")
+       }
 
        //By Model Checker
-       /*def setValue(String value) {
-               println("the door with id:$id is $value!")
-               this.lockLatestValue = this.lockState
-               this.lockState = value
-               this.currentLock = value
-       }*/
+       def setValue(String value) {
+               println("the thermostat with id:$id is $value!")
+               this.thermostatMode = value
+               this.currentThermostatMode = value
+       }
+
 }
index 78386ab..9945066 100644 (file)
@@ -26,6 +26,8 @@ public class Thermostats{
        private String thermostatOperatingState = "cooling"
        private String thermostatFanMode = "auto"
        private String thermostatMode = "auto"
+       private String currentThermostatMode = "auto"
+       private String climateName = ""
 
        Thermostats(Closure sendEvent, int deviceNumbers) {
                this.sendEvent = sendEvent
@@ -36,7 +38,7 @@ public class Thermostats{
                thermostats.add(new Thermostat(sendEvent, id, label, displayName, this.temperature, this.currentCoolingSetpoint, 
                                                this.currentHeatingSetpoint, this.coolingSetpoint, this.thermostatSetpoint, this.heatingSetpoint, this.coolingSetpointRange,
                                                this.thermostatSetpointRange, this.heatingSetpointRange, this.supportedThermostatFanModes, this.supportedThermostatModes,
-                                               this.thermostatOperatingState, this.thermostatFanMode,  this.thermostatMode))
+                                               this.thermostatOperatingState, this.thermostatFanMode,  this.thermostatMode, this.climateName))
        }
 
        //Methods for closures
@@ -59,10 +61,14 @@ public class Thermostats{
        //By Apps
        def setCoolingSetpoint(int coolingSetpoint) {
                thermostats[0].setCoolingSetpoint(coolingSetpoint)
+               this.currentCoolingSetpoint = coolingSetpoint
+               this.coolingSetpoint = coolingSetpoint
        }
 
        def setHeatingSetpoint(int heatingSetpoint) {
                thermostats[0].setHeatingSetpoint(heatingSetpoint)
+               this.currentHeatingSetpoint = heatingSetpoint
+               this.heatingSetpoint = heatingSetpoint
        }
 
        def setSchedule() {
@@ -71,15 +77,64 @@ public class Thermostats{
 
        def setThermostatFanMode(String thermostatFanMode) {
                thermostats[0].setThermostatFanMode(thermostatFanMode)
+               this.thermostatFanMode = thermostatFanMode
        }
 
        def setThermostatMode(String thermostatMode) {
                thermostats[0].setThermostatMode(thermostatMode)
+               this.thermostatMode = thermostatMode
+               this.currentThermostatMode = currentThermostatMode
        }
 
+       def cool() {
+               thermostats[0].cool()
+               this.thermostatMode = "cool"
+               this.currentThermostatMode = "cool"
+       }
+
+       def heat() {
+               thermostats[0].heat()
+               this.thermostatMode = "heat"
+               this.currentThermostatMode = "heat"
+       }
+
+       def auto() {
+               thermostats[0].auto()
+               this.thermostatMode = "auto"
+               this.currentThermostatMode = "auto"
+       }
+
+       def off() {
+               thermostats[0].off()
+               this.thermostatMode = "off"
+               this.currentThermostatMode = "off"
+       }
+
+       def setClimate(String info, String givenClimateName) {
+               thermostats[0].setClimate(info, givenClimateName)
+               this.climateName = givenClimateName
+       }
+
+       def setHold(String info1, int coolingSetpoint, int heatingSetpoint, String info2, String info3) {
+               thermostats[0].setHold(info1, coolingSetpoint, heatingSetpoint, info2, info3)
+               this.currentCoolingSetpoint = coolingSetpoint
+               this.coolingSetpoint = coolingSetpoint
+               this.currentHeatingSetpoint = heatingSetpoint
+               this.heatingSetpoint = heatingSetpoint
+       }
+
+       //By Model Checker
+       def setValue(LinkedHashMap eventDataMap) {
+               if (eventDataMap["value"] != thermostats[0].thermostatMode) {
+                       thermostats[0].setValue(eventDataMap["value"])
+                       this.thermostatMode = thermostats[0].thermostatMode
+                       this.currentThermostatMode = thermostats[0].currentThermostatMode
+                       sendEvent(eventDataMap)
+               }
+       }
 
        def getAt(int ix) {
-               locks[ix]
+               thermostats[ix]
        }
 }
 
diff --git a/Variables and events for each device b/Variables and events for each device
new file mode 100644 (file)
index 0000000..d1fc80e
--- /dev/null
@@ -0,0 +1,238 @@
+//
+//For Alarms:
+String currentAlarm or String alarm
+/*events*/
+//No events based on this device
+/*events*/
+//
+-------------------------------------------------------------------------------
+
+
+//For Contact Sensor:
+String currentContact or String contactState
+/*events*/
+/////
+contact closed event:
+contactObject.setValue([name: "contact.closed", value: "closed", deviceId: "contactSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+contact open event:
+contactObject.setValue([name: "contact.open", value: "open", deviceId: "contactSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+/*events*/
+//
+-------------------------------------------------------------------------------
+
+
+//For DoorControl:
+String doorState
+/*events*/
+door closed event using doorControl:
+doorControlObject.setValue([name: "doorState", value: "closed", deviceId: "doorControlID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+door open event using doorControl:
+doorControlObject.setValue([name: "doorState", value: "open", deviceId: "doorControlID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+/*events*/
+//
+-------------------------------------------------------------------------------
+
+
+//For Location:
+String location.mode
+/*events*/
+location changes event:
+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"]])
+/*events*/
+//
+-------------------------------------------------------------------------------
+
+
+//For Locks:
+String currentLock or String lockState
+/*events*/
+lock event:
+lockObject.setValue([name: "lock", value: "locked", deviceId: "lockID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+unlock event:
+lockObject.setValue([name: "unlock", value: "unlocked ", deviceId: "lockID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+/*events*/
+//
+-------------------------------------------------------------------------------
+
+
+//For MotionSensors:
+String currentMotion or String motion
+/*events*/
+Motion sensor event: motion detected:
+doorControlObject.setValue([name: "motion", value: "active", deviceId: "motionSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+Motion sensor event: motion not detected:
+doorControlObject.setValue([name: "motion", value: "inactive", deviceId: "motionSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+/*events*/
+//
+-------------------------------------------------------------------------------
+
+
+//For MusicPlayer:
+String status
+/*events*/
+//No events based on this device
+/*events*/
+//
+-------------------------------------------------------------------------------
+
+
+//For PresenceSensor:
+String currentPresence or String presenceState
+/*events*/
+presence sensor, present event:
+presenceSensorObject.setValue([name: "presence", value: "present", deviceId: "presenceSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+presence sensor, left event:
+presenceSensorObject.setValue([name: "presence", value: "not present", deviceId: "presenceSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+/*events*/
+//
+-------------------------------------------------------------------------------
+
+
+//For SmokeDetector:
+String currentSmokeValue or String smoke
+/*events*/
+smoke is clear event:
+smokeDetectorObject.setValue([name: "smoke", value: "clear", deviceId: "smokeDetectorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+smoke is detected event:
+smokeDetectorObject.setValue([name: "smoke", value: "detected", deviceId: "smokeDetectorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+smoke is tested event:
+smokeDetectorObject.setValue([name: "smoke", value: "tested", deviceId: "smokeDetectorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+carbonMonoxide is clear event:
+smokeDetectorObject.setValue([name: "carbonMonoxide", value: "clear", deviceId: "smokeDetectorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+carbonMonoxide is detected event:
+smokeDetectorObject.setValue([name: "carbonMonoxide", value: "detected", deviceId: "smokeDetectorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+carbonMonoxide is tested event:
+smokeDetectorObject.setValue([name: "carbonMonoxide", value: "tested", deviceId: "smokeDetectorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+battery charge value event:
+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"]])
+/////
+battery charge value event:
+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"]])
+/////
+/*events*/
+//
+-------------------------------------------------------------------------------
+
+
+//For Thermostats:(we have different features in each line)
+String heatingSetpoint or currentHeatingSetpoint //heating set point
+String thermostatSetpoint //normal set point
+String coolingSetpoint or currentCoolingSetpoint //cooling set point
+String thermostatOperatingState //operating state
+String thermostatFanMode //fan mode
+String thermostatMode or currentThermostatMode //mode
+/*events*/
+thermostad mode change event: to auto
+thermostatObject.setValue([name: "thermostatMode", value: "auto", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+thermostad mode change event: to cool
+thermostatObject.setValue([name: "thermostatMode", value: "cool", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+thermostad mode change event: to emergencyHeat
+thermostatObject.setValue([name: "thermostatMode", value: "emergencyHeat", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+thermostad mode change event: to heat
+thermostatObject.setValue([name: "thermostatMode", value: "heat", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+thermostad mode change event: to off
+thermostatObject.setValue([name: "thermostatMode", value: "off", deviceId: "thermostatID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+/*events*/
+//
+-------------------------------------------------------------------------------
+
+
+//For Switches:
+String currentSwitch or switchState
+/*events*/
+switch changes to off:
+switchObject.setValue([name: "switch", value: "off", deviceId: "switchID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+switch changes to on:
+switchObject.setValue([name: "switch", value: "on", deviceId: "switchID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+/*events*/
+//
+-------------------------------------------------------------------------------
+
+
+//For appTouch:
+/*events*/
+appObject.setValue([name: "Touched", value: "touched", deviceId: "touchedSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+/*events*/
+//
+-------------------------------------------------------------------------------
+
+
+//For nfcTouch:
+/*events*/
+Nfc touched event:
+appObject.setValue([name: "nfcTouch", value: "touched", deviceId: "nfcSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+/*events*/
+//
+-------------------------------------------------------------------------------
+
+
+//For aeonKeyFob push button:
+/*events*/
+button pushed event:
+aeonKeyFobObject.setValue([name: "button", value: "pushed", deviceId: "aeonKeyFobID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+button held event:
+aeonKeyFobObject.setValue([name: "button", value: "held", deviceId: "aeonKeyFobID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+/////
+/////
+/*events*/
+//
index 5460511..1d6af3c 100644 (file)
@@ -24,11 +24,19 @@ import AeonKeyFob.AeonKeyFob
 import AeonKeyFob.AeonKeyFobs
 import MusicPlayer.MusicPlayer
 import MusicPlayer.MusicPlayers
+import MotionSensor.MotionSensor
+import MotionSensor.MotionSensors
+import ImageCapture.ImageCapture
+import ImageCapture.ImageCaptures
+import SmokeDetector.SmokeDetector
+import SmokeDetector.SmokeDetectors
+import Alarm.Alarm
+import Alarm.Alarms
+import SpeechSynthesis.SpeechSynthesis
+import SpeechSynthesis.SpeechSynthesises
 import Event.Event
 import Timer.SimulatedTimer
 
-import gov.nasa.jpf.vm.Verify
-
 //Global eventHandler
 /////////////////////////////////////////////////////////////////////
 def eventHandler(LinkedHashMap eventDataMap) {
@@ -65,7 +73,7 @@ def eventHandler(LinkedHashMap eventDataMap) {
                        eventHandler(eventDataMap)
                        }
 //Object for location
-@Field def locationObject = new LocationVar()
+@Field def locationObject = new LocationVar(sendEvent)
 //Object for touch to call function
 @Field def appObject = new Touched(sendEvent, 0)
 //Create a global list for events
@@ -88,6 +96,16 @@ def eventHandler(LinkedHashMap eventDataMap) {
 @Field def aeonKeyFobObject = new AeonKeyFobs(sendEvent, 1)
 //Global Object for class music player!
 @Field def musicPlayerObject = new MusicPlayers(sendEvent, 1)
+//Global Object for class motion sensor!
+@Field def motionSensorObject = new MotionSensors(sendEvent, 1)
+//Global Object for class image capture!
+@Field def imageCaptureObject = new ImageCaptures(sendEvent, 1)
+//Global Object for class smoke detector!
+@Field def smokeDetectorObject = new SmokeDetectors(sendEvent, 1)
+//Global Object for class alarm!
+@Field def alarmObject = new Alarms(sendEvent, 1)
+//Global Object for class speech synthesis!
+@Field def speechSynthesisObject = new SpeechSynthesises(sendEvent, 1)
 
 //Application #1
 class App1 {
@@ -96,12 +114,12 @@ class App1 {
        def app
 
        //Extracted objects for App1
+       //Object for class switch!
+       def switches
+       //Object for class thermostat!
+       def thermostats
        //Object for class lock!
-       def lock1
-       //Global variable for number!
-       def minutesLater = 1
-       //Object for class contactSensor!
-       def openSensor
+       def locks
 
        //Extracted objects for functions for App1
        //Global Object for functions in subscribe method!
@@ -109,24 +127,25 @@ class App1 {
        //Global Object for functions in subscribe method!
        def updated = this.&updated
        //Global Object for functions in subscribe method!
-       def initialize = this.&initialize
+       def appTouch = this.&appTouch
        //Global Object for functions in subscribe method!
-       def lockDoor = this.&lockDoor
+       def changedLocationMode = this.&changedLocationMode
        //Global Object for functions in subscribe method!
-       def doorOpen = this.&doorOpen
+       def restoreState = this.&restoreState
        //Global Object for functions in subscribe method!
-       def doorClosed = this.&doorClosed
+       def saveState = this.&saveState
        //Global Object for functions in subscribe method!
-       def doorHandler = this.&doorHandler
+       def getCurrentMode = this.&getCurrentMode
 
        App1(Object obj) {
                reference = obj
                location = obj.locationObject
                app = obj.appObject
-               lock1 = obj.lockObject
-               openSensor = obj.contactObject
+               switches = obj.switchObject
+               thermostats = obj.thermostatObject
+               locks = obj.lockObject
                //Global variable for settings!
-               settings = [app:app, lock1:lock1, minutesLater:minutesLater, openSensor:openSensor]
+               settings = [app:app, switches:switches, thermostats:thermostats, locks:locks]
        }
        //Global variables for each app
        //Global variable for state[mode]
@@ -145,6 +164,8 @@ class App1 {
        def timersList = []
        //Create a global variable for settings
        def settings
+       //Zip code
+       def zipCode = 92617
 
        //Methods
        /////////////////////////////////////////////////////////////////////
@@ -182,11 +203,27 @@ class App1 {
        def runIn(int seconds, Closure functionToCall) {
                if (timersFuncList.contains(functionToCall)) {
                        timersList[timersFuncList.indexOf(functionToCall)].cancel()
-                       def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall)
+                       def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds*0, functionToCall)
                } else {
                        timersFuncList.add(functionToCall)
                        timersList.add(new SimulatedTimer())
-                       def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall)
+                       def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds*0, functionToCall)
+               }
+       }
+       
+       def runIn(int seconds, Closure functionToCall, LinkedHashMap metaData) {
+               runIn(seconds, functionToCall)
+       }
+       
+       def runIn(int seconds, String nameOfFunction, LinkedHashMap metaData) {
+               runIn(seconds, nameOfFunction)
+       }
+       
+       def runIn(int seconds, String nameOfFunction) {
+               timersFuncList.add(nameOfFunction)
+               timersList.add(new SimulatedTimer())
+               def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(seconds*1000*0) {
+                       "$nameOfFunction"()
                }
        }
        /////////////////////////////////////////////////////////////////////
@@ -223,6 +260,10 @@ class App1 {
        def sendSms(long phoneNumber, String text) {
                println("Sending \""+text+"\" to "+phoneNumber.toString())
        }
+       
+       def sendSMS(long phoneNumber, String text) {
+               println("Sending \""+text+"\" to "+phoneNumber.toString())
+       }
        /////////////////////////////////////////////////////////////////////
        ////sendPush(text)
        def sendPush(String text) {
@@ -248,7 +289,7 @@ class App1 {
        
                timersFuncList.add(nameOfFunction)
                timersList.add(new SimulatedTimer())
-               def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000) {
+               def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000*0) {
                        "$nameOfFunction"()
                }
        }
@@ -271,80 +312,125 @@ class App1 {
        
                if (timersFuncList.contains(nameOfFunction)) {
                        timersList[timersFuncList.indexOf(nameOfFunction)].cancel()
-                       def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction)
+                       def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds*0, nameOfFunction)
                } else {
                        timersFuncList.add(nameOfFunction)
                        timersList.add(new SimulatedTimer())
-                       def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction)
+                       def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds*0, nameOfFunction)
                }
        }
        /////////////////////////////////////////////////////////////////////
        def now() {
                return System.currentTimeMillis()
        }
+       /////////////////////////////////////////////////////////////////////
+       def getTemperatureScale() {
+               return 'C' //Celsius for now
+       }
+       
+       /////////////////////////////////////////////////////////////////////
+       def getSunriseAndSunset(LinkedHashMap metaData) {
+               def sunRiseSetInfo = [sunrise:[time:1563800160000],sunset:[time:1563850740000]]
+               return sunRiseSetInfo
+       }
 
-       def installed()
-       {
-           log.debug "Auto Lock Door installed. (URL: http://www.github.com/smartthings-users/smartapp.auto-lock-door)"
-           initialize()
+       def installed() {
+               subscribe(location, changedLocationMode)
+               subscribe(app, appTouch)
+               saveState()
        }
        
-       def updated()
-       {
-           unsubscribe()
-           unschedule()
-           log.debug "Auto Lock Door updated."
-           initialize()
+       def updated() {
+               unsubscribe()
+               subscribe(location, changedLocationMode)
+               subscribe(app, appTouch)
+               saveState()
        }
        
-       def initialize()
+       def appTouch(evt)
        {
-           log.debug "Settings: ${settings}"
-           subscribe(lock1, "lock", doorHandler)
-           subscribe(openSensor, "contact.closed", doorClosed)
-           subscribe(openSensor, "contact.open", doorOpen)
+               restoreState(currentMode)
        }
        
-       def lockDoor()
+       def changedLocationMode(evt)
        {
-           log.debug "Locking Door if Closed"
-           if((openSensor.latestValue("contact") == "closed")){
-               log.debug "Door Closed"
-               lock1.lock()
-           } else {
-               if ((openSensor.latestValue("contact") == "open")) {
-               def delay = minutesLater * 60
-               log.debug "Door open will try again in $minutesLater minutes"
-               runIn( delay, lockDoor )
-               }
-           }
+               restoreState(evt.value)
        }
        
-       def doorOpen(evt) {
-           log.debug "Door open reset previous lock task..."
-           unschedule( lockDoor )
-           def delay = minutesLater * 60
-           runIn( delay, lockDoor )
-       }
+       private restoreState(mode)
+       {
+               log.info "restoring state for mode '$mode'"
+               def map = state[mode] ?: [:]
+               switches?.each {
+                       def value = map[it.id]
+                       if (value?.switch == "on") {
+                               def level = value.level
+                               if (level) {
+                                       log.debug "setting $it.label level to $level"
+                                       it.setLevel(level)
+                               }
+                               else {
+                                       log.debug "turning $it.label on"
+                                       it.on()
+                               }
+                       }
+                       else if (value?.switch == "off") {
+                               log.debug "turning $it.label off"
+                               it.off()
+                       }
+               }
+       
+               thermostats?.each {
+                       def value = map[it.id]
+                       if (value?.coolingSetpoint) {
+                               log.debug "coolingSetpoint = $value.coolingSetpoint"
+                               it.setCoolingSetpoint(value.coolingSetpoint)
+                       }
+                       if (value?.heatingSetpoint) {
+                               log.debug "heatingSetpoint = $value.heatingSetpoint"
+                               it.setHeatingSetpoint(value.heatingSetpoint)
+                       }
+               }
        
-       def doorClosed(evt) {
-           log.debug "Door Closed"
+               locks?.each {
+                       def value = map[it.id]
+                       if (value) {
+                               if (value?.locked) {
+                                       it.lock()
+                               }
+                               else {
+                                       it.unlock()
+                               }
+                       }
+               }
        }
        
-       def doorHandler(evt)
+       
+       private saveState()
        {
-           log.debug "Door ${openSensor.latestValue}"
-           log.debug "Lock ${evt.name} is ${evt.value}."
+               def mode = currentMode
+               def map = state[mode] ?: [:]
        
-           if (evt.value == "locked") {                  // If the human locks the door then...
-               log.debug "Cancelling previous lock task..."
-               unschedule( lockDoor )                  // ...we don't need to lock it later.
-           }
-           else {                                      // If the door is unlocked then...
-               def delay = minutesLater * 60          // runIn uses seconds
-               log.debug "Re-arming lock in ${minutesLater} minutes (${delay}s)."
-               runIn( delay, lockDoor )                // ...schedule to lock in x minutes.
-           }
+               switches?.each {
+                       map[it.id] = [switch: it.currentSwitch, level: it.currentLevel]
+               }
+       
+               thermostats?.each {
+                       map[it.id] = [coolingSetpoint: it.currentCoolingSetpoint, heatingSetpoint: it.currentHeatingSetpoint]
+               }
+       
+               locks?.each {
+                       map[it.id] = [locked: it.currentLock == "locked"]
+               }
+       
+               state[mode] = map
+               log.debug "saved state for mode ${mode}: ${state[mode]}"
+               log.debug "state: $state"
+       }
+       
+       private getCurrentMode()
+       {
+               location.mode ?: "_none_"
        }
 }
 
@@ -365,11 +451,11 @@ class App2 {
        //Object for class door control!
        def garageDoor
        //Global variable for enum!
-       def masterSwitch = "switchID0"
+       def masterSwitch = "Yes"
        //Global variable for enum!
-       def masterLock = "lockID0"
+       def masterLock = "Yes"
        //Global variable for enum!
-       def masterDoor = "DoorControlID0"
+       def masterDoor = "No"
 
        //Extracted objects for functions for App2
        //Global Object for functions in subscribe method!
@@ -381,8 +467,6 @@ class App2 {
        //Global Object for functions in subscribe method!
        def initialize = this.&initialize
        //Global Object for functions in subscribe method!
-       def currentStatus = this.&currentStatus
-       //Global Object for functions in subscribe method!
        def touchHandler = this.&touchHandler
 
        App2(Object obj) {
@@ -413,6 +497,8 @@ class App2 {
        def timersList = []
        //Create a global variable for settings
        def settings
+       //Zip code
+       def zipCode = 92617
 
        //Methods
        /////////////////////////////////////////////////////////////////////
@@ -450,11 +536,27 @@ class App2 {
        def runIn(int seconds, Closure functionToCall) {
                if (timersFuncList.contains(functionToCall)) {
                        timersList[timersFuncList.indexOf(functionToCall)].cancel()
-                       def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall)
+                       def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds*0, functionToCall)
                } else {
                        timersFuncList.add(functionToCall)
                        timersList.add(new SimulatedTimer())
-                       def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds, functionToCall)
+                       def task = timersList[timersFuncList.indexOf(functionToCall)].runAfter(1000*seconds*0, functionToCall)
+               }
+       }
+       
+       def runIn(int seconds, Closure functionToCall, LinkedHashMap metaData) {
+               runIn(seconds, functionToCall)
+       }
+       
+       def runIn(int seconds, String nameOfFunction, LinkedHashMap metaData) {
+               runIn(seconds, nameOfFunction)
+       }
+       
+       def runIn(int seconds, String nameOfFunction) {
+               timersFuncList.add(nameOfFunction)
+               timersList.add(new SimulatedTimer())
+               def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(seconds*1000*0) {
+                       "$nameOfFunction"()
                }
        }
        /////////////////////////////////////////////////////////////////////
@@ -491,6 +593,10 @@ class App2 {
        def sendSms(long phoneNumber, String text) {
                println("Sending \""+text+"\" to "+phoneNumber.toString())
        }
+       
+       def sendSMS(long phoneNumber, String text) {
+               println("Sending \""+text+"\" to "+phoneNumber.toString())
+       }
        /////////////////////////////////////////////////////////////////////
        ////schedule(time, nameOfFunction as String)
        def schedule(String time, String nameOfFunction) {
@@ -511,7 +617,7 @@ class App2 {
        
                timersFuncList.add(nameOfFunction)
                timersList.add(new SimulatedTimer())
-               def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000) {
+               def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*1000*0) {
                        "$nameOfFunction"()
                }
        }
@@ -534,22 +640,36 @@ class App2 {
        
                if (timersFuncList.contains(nameOfFunction)) {
                        timersList[timersFuncList.indexOf(nameOfFunction)].cancel()
-                       def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction)
+                       def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds*0, nameOfFunction)
                } else {
                        timersFuncList.add(nameOfFunction)
                        timersList.add(new SimulatedTimer())
-                       def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds, nameOfFunction)
+                       def task = timersList[timersFuncList.indexOf(nameOfFunction)].runAfter(delay*seconds*0, nameOfFunction)
                }
        }
+       /////////////////////////////////////////////////////////////////////
+       def now() {
+               return System.currentTimeMillis()
+       }
+       /////////////////////////////////////////////////////////////////////
+       def getTemperatureScale() {
+               return 'C' //Celsius for now
+       }
+       
+       /////////////////////////////////////////////////////////////////////
+       def getSunriseAndSunset(LinkedHashMap metaData) {
+               def sunRiseSetInfo = [sunrise:[time:1563800160000],sunset:[time:1563850740000]]
+               return sunRiseSetInfo
+       }
 
        def pageTwo() {
                dynamicPage(name: "pageTwo") {
-               section("If set, the state of these devices will be toggled each time the tag is touched, " +
+               section("If set, the state of these devices will be toggled each time the tag is touched, " + 
                        "e.g. a light that's on will be turned off and one that's off will be turned on, " +
                        "other devices of the same type will be set to the same state as their master device. " +
                        "If no master is designated then the majority of devices of the same type will be used " +
                        "to determine whether to turn on or off the devices.") {
-       
+                   
                    if (switch1 || masterSwitch) {
                        input "masterSwitch", "enum", title: "Master switch", options: switch1.collect{[(it.id): it.displayName]}, required: false
                    }
@@ -558,12 +678,12 @@ class App2 {
                    }
                    if (garageDoor || masterDoor) {
                        input "masterDoor", "enum", title: "Master door", options: garageDoor.collect{[(it.id): it.displayName]}, required: false
-                   }
+                   }            
                        }
                        section([mobileOnly:true]) {
                                label title: "Assign a name", required: false
                                mode title: "Set for specific mode(s)", required: false
-                       }
+                       }        
            }
        }
        
@@ -618,7 +738,7 @@ class App2 {
                    }
                }
            }
-       
+           
            if (lock) {
                def status = currentStatus(lock, masterLock, "lock")
                lock.each {
@@ -630,7 +750,7 @@ class App2 {
                    }
                }
            }
-       
+           
            if (garageDoor) {
                def status = currentStatus(garageDoor, masterDoor, "status")
                garageDoor.each {
@@ -650,48 +770,13 @@ class App2 {
 app1.installed()
 app2.installed()
 
-def events = [1,2,3,4,5,6,7]
-def list = events.permutations()
-int count = Verify.getInt(0,list.size()-1)
-println "COUNT: " + count
-
-list[count].each {
-  switch(it) {
-    case 1:
-      appObject.setValue([name: "Touched", value: "Touched", deviceId: 0, descriptionText: "",
-                                          displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
-      println "1"
-      break
-    case 2:
-      lockObject.setValue([name: "lock0", value: "locked", deviceId: 0, descriptionText: "",
-                                          displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
-      println "   2"
-                       break
-    case 3:
-      lockObject.setValue([name: "lock0", value: "unlocked", deviceId: 0, descriptionText: "",
-                                          displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
-      println "      3"
-      break
-    case 4:
-      contactObject.setValue([name: "contact0", value: "open", deviceId: 0, descriptionText: "",
-                                          displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
-      println "         4"
-      break
-    case 5:
-      contactObject.setValue([name: "contact0", value: "closed", deviceId: 0, descriptionText: "",
-                                          displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
-      println "            5"
-      break
-    case 6:
-      switchObject.setValue([name: "switch0", value: "on", deviceId: 0, descriptionText: "",
-                                          displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
-      println "               6"
-      break
-    case 7:
-      switchObject.setValue([name: "switch0", value: "off", deviceId: 0, descriptionText: "",
-                                          displayed: true, linkText: "", isStateChange: false, unit: "", data: []])
-      println "                   7"
-    default:
-      break
-  }
-}
+appObject.setValue([name: "Touched", value: "touched", deviceId: "touchedSensorID0", descriptionText: "",
+displayed: true, linkText: "", isStateChange: false, unit: "", data: [info: "info"]])
+appObject.setValue([name: "nfcTouch", value: "touched", deviceId: "nfcSensorID0", 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"]])