From 8925e133c7be9d7f3fd889e94cf49891c4208fc7 Mon Sep 17 00:00:00 2001 From: Gideon Date: Wed, 7 Dec 2016 09:17:33 -0800 Subject: [PATCH] MSA-1638: A simple REST API app to control SmartThings' devices through Gideon Smart Home --- smartapps/gideon-api/gideon.src/gideon.groovy | 415 +++++++++++++++--- 1 file changed, 358 insertions(+), 57 deletions(-) diff --git a/smartapps/gideon-api/gideon.src/gideon.groovy b/smartapps/gideon-api/gideon.src/gideon.groovy index b277d25..dc82641 100644 --- a/smartapps/gideon-api/gideon.src/gideon.groovy +++ b/smartapps/gideon-api/gideon.src/gideon.groovy @@ -26,23 +26,44 @@ definition( preferences { + section("Control these contact sensors...") { + input "contact", "capability.contactSensor", multiple:true, required:false + } section("Control these switches...") { - input "switches", "capability.switch", multiple:true + input "switches", "capability.switch", multiple:true, required:false + } + section("Control these smoke alarms...") { + input "smoke_alarms", "capability.smokeDetector", multiple:true, required:false + } + section("Control these window shades...") { + input "shades", "capability.windowShade", multiple:true, required:false + } + section("Control these garage doors...") { + input "garage", "capability.garageDoorControl", multiple:true, required:false + } + section("Control these water sensors...") { + input "water_sensors", "capability.waterSensor", multiple:true, required:false } section("Control these motion sensors...") { - input "motions", "capability.motionSensor", multiple:true + input "motions", "capability.motionSensor", multiple:true, required:false } section("Control these presence sensors...") { - input "presence_sensors", "capability.presenceSensor", multiple:true + input "presence_sensors", "capability.presenceSensor", multiple:true, required:false } section("Control these outlets...") { - input "outlets", "capability.switch", multiple:true + input "outlets", "capability.switch", multiple:true, required:false + } + section("Control these power meters...") { + input "meters", "capability.powerMeter", multiple:true, required:false } section("Control these locks...") { - input "locks", "capability.lock", multiple:true + input "locks", "capability.lock", multiple:true, required:false } - section("Control these locks...") { - input "temperature_sensors", "capability.temperatureMeasurement" + section("Control these temperature sensors...") { + input "temperature_sensors", "capability.temperatureMeasurement", multiple:true, required:false + } + section("Control these batteries...") { + input "batteries", "capability.battery", multiple:true, required:false } } @@ -61,13 +82,13 @@ def updated() { def initialize() { // TODO: subscribe to attributes, devices, locations, etc. - subscribe(outlet, "energy", outletHandler) - subscribe(outlet, "switch", outletHandler) + //subscribe(outlet, "energy", outletHandler) + //subscribe(outlet, "switch", outletHandler) } // TODO: implement event handlers def outletHandler(evt) { - log.debug "$outlet.currentEnergy" + //log.debug "$outlet.currentEnergy" //TODO call G API } @@ -83,9 +104,14 @@ mappings { GET: "getAllDevices" ] } - path("/doorlocks/:id/:command") { + path("/doorlocks/lock/:id") { action: [ - GET: "updateDoorLock" + GET: "lockDoorLock" + ] + } + path("/doorlocks/unlock/:id") { + action: [ + GET: "unlockDoorLock" ] } path("/doorlocks/:id") { @@ -93,10 +119,70 @@ mappings { GET: "getDoorLockStatus" ] } + path("/contacts/:id") { + action: [ + GET: "getContactStatus" + ] + } + path("/smoke/:id") { + action: [ + GET: "getSmokeStatus" + ] + } + path("/shades/open/:id") { + action: [ + GET: "openShade" + ] + } + path("/shades/preset/:id") { + action: [ + GET: "presetShade" + ] + } + path("/shades/close/:id") { + action: [ + GET: "closeShade" + ] + } + path("/shades/:id") { + action: [ + GET: "getShadeStatus" + ] + } + path("/garage/open/:id") { + action: [ + GET: "openGarage" + ] + } + path("/garage/close/:id") { + action: [ + GET: "closeGarage" + ] + } + path("/garage/:id") { + action: [ + GET: "getGarageStatus" + ] + } + path("/watersensors/:id") { + action: [ + GET: "getWaterSensorStatus" + ] + } path("/tempsensors/:id") { action: [ GET: "getTempSensorsStatus" ] + } + path("/meters/:id") { + action: [ + GET: "getMeterStatus" + ] + } + path("/batteries/:id") { + action: [ + GET: "getBatteryStatus" + ] } path("/presences/:id") { action: [ @@ -113,14 +199,29 @@ mappings { GET: "getOutletStatus" ] } - path("/outlets/:id/:command") { + path("/outlets/turnon/:id") { action: [ - GET: "updateOutlet" + GET: "turnOnOutlet" ] } - path("/switches/:command") { + path("/outlets/turnoff/:id") { action: [ - PUT: "updateSwitch" + GET: "turnOffOutlet" + ] + } + path("/switches/turnon/:id") { + action: [ + GET: "turnOnSwitch" + ] + } + path("/switches/turnoff/:id") { + action: [ + GET: "turnOffSwitch" + ] + } + path("/switches/:id") { + action: [ + GET: "getSwitchStatus" ] } } @@ -128,12 +229,149 @@ mappings { //API Methods def getAllDevices() { def locks_list = locks.collect{device(it,"Lock")} + def contact_list = contact.collect{device(it,"Contact Sensor")} + def smokes_list = smoke_alarms.collect{device(it,"Smoke Alarm")} + def shades_list = shades.collect{device(it,"Window Shade")} + def garage_list = garage.collect{device(it,"Garage Door")} + def water_sensors_list = water_sensors.collect{device(it,"Water Sensor")} def presences_list = presence_sensors.collect{device(it,"Presence")} def motions_list = motions.collect{device(it,"Motion")} def outlets_list = outlets.collect{device(it,"Outlet")} def switches_list = switches.collect{device(it,"Switch")} def temp_list = temperature_sensors.collect{device(it,"Temperature")} - return [Locks: locks_list, Presences: presences_list, Motions: motions_list, Outlets: outlets_list, Switches: switches_list, Temperatures: temp_list] + def meters_list = meters.collect{device(it,"Power Meters")} + def battery_list = batteries.collect{device(it,"Batteries")} + return smokes_list + contact_list + water_sensors_list + shades_list + garage_list + locks_list + presences_list + motions_list + outlets_list + switches_list + temp_list + meters_list + battery_list +} + +//contact sensors +def getContactStatus() { + def device = contact.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + def args = getTempSensorsStatus(device.id) + return [Device_state: device.currentValue('contact')] + args + } +} + +//smoke detectors +def getSmokeStatus() { + def device = smoke_alarms.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + def bat = getBatteryStatus(device.id) + return [Device_state: device.currentValue('smoke')] + bat + } +} + +//garage +def getGarageStatus() { + def device = garage.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + return [Device_state: device.currentValue('door')] + } +} + +def openGarage() { + def device = garage.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.open(); + + return [Device_id: params.id, result_action: "200"] + } + } + +def closeGarage() { + def device = garage.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.close(); + + return [Device_id: params.id, result_action: "200"] + } + } +//shades +def getShadeStatus() { + def device = shades.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + return [Device_state: device.currentValue('windowShade')] + } +} + +def openShade() { + def device = shades.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.open(); + + return [Device_id: params.id, result_action: "200"] + } + } + +def presetShade() { + def device = shades.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.presetPosition(); + + return [Device_id: params.id, result_action: "200"] + } + } + +def closeShade() { + def device = shades.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.close(); + + return [Device_id: params.id, result_action: "200"] + } + } + +//water sensor +def getWaterSensorStatus() { + def device = water_sensors.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + def bat = getBatteryStatus(device.id) + return [Device_state: device.currentValue('water')] + bat + } +} +//batteries +def getBatteryStatus() { + def device = batteries.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + return [Device_state: device.latestValue("battery")] + } +} + +def getBatteryStatus(id) { + def device = batteries.find { it.id == id } + if (!device) { + return [] + } else { + return [battery_state: device.latestValue("battery")] + } } //LOCKS @@ -142,30 +380,34 @@ def getDoorLockStatus() { if (!device) { httpError(404, "Device not found") } else { - return [Device_state: device.currentValue('lock')] + def bat = getBatteryStatus(device.id) + return [Device_state: device.currentValue('lock')] + bat } } -def updateDoorLock() { - def command = params.command +def lockDoorLock() { def device = locks.find { it.id == params.id } - if (command){ - if (!device) { + if (!device) { httpError(404, "Device not found") } else { - if(command == "toggle") - { - if(device.currentValue('lock') == "locked") - device.unlock(); - else - device.lock(); + + device.lock(); - return [Device_id: params.id, result_action: "200"] + return [Device_id: params.id, result_action: "200"] } - } } -} +def unlockDoorLock() { + def device = locks.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + + device.unlock(); + + return [Device_id: params.id, result_action: "200"] + } + } //PRESENCE def getPresenceStatus() { @@ -173,7 +415,8 @@ def getPresenceStatus() { if (!device) { httpError(404, "Device not found") } else { - return [Device_state: device.currentValue('presence')] + def bat = getBatteryStatus(device.id) + return [Device_state: device.currentValue('presence')] + bat } } @@ -184,7 +427,8 @@ def getMotionStatus() { if (!device) { httpError(404, "Device not found") } else { - return [Device_state: device.currentValue('motion')] + def args = getTempSensorsStatus(device.id) + return [Device_state: device.currentValue('motion')] + args } } @@ -195,52 +439,98 @@ def getOutletStatus() { if (!device) { httpError(404, "Device not found") } else { - return [Device_state: device.currentSwitch, Current_watt: device.currentValue("energy")] + def watt = getMeterStatus(device.id) + return [Device_state: device.currentSwitch] + watt } } -def updateOutlet() { +def getMeterStatus() { - def command = params.command + def device = meters.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + return [Device_id: device.id, Device_type: device.type, Current_watt: device.currentValue("power")] + } +} + +def getMeterStatus(id) { + + def device = meters.find { it.id == id } + if (!device) { + return [] + } else { + return [Current_watt: device.currentValue("power")] + } +} + +def turnOnOutlet() { def device = outlets.find { it.id == params.id } if (command){ if (!device) { httpError(404, "Device not found") } else { - if(command == "toggle") - { - if(device.currentSwitch == "on") - device.off(); - else - device.on(); + + device.on(); - return [Device_id: params.id, result_action: "200"] - } + return [Device_id: params.id, result_action: "200"] } } -} +} + +def turnOffOutlet() { + def device = outlets.find { it.id == params.id } + if (command){ + if (!device) { + httpError(404, "Device not found") + } else { + + device.off(); + + return [Device_id: params.id, result_action: "200"] + } + } +} //SWITCH -def updateSwitch() { - def command = params.command +def getSwitchStatus() { + def device = switches.find { it.id == params.id } + if (!device) { + httpError(404, "Device not found") + } else { + return [Device_state: device.currentValue('switch')] + } +} + +def turnOnSwitch() { def device = switches.find { it.id == params.id } if (command){ if (!device) { httpError(404, "Device not found") } else { - if(command == "toggle") - { - if(device.currentSwitch == "on") - device.off(); - else - device.on(); + + device.on(); - return [Device_id: params.id, result_action: "200"] - } + return [Device_id: params.id, result_action: "200"] } } } +def turnOffSwitch() { + def device = switches.find { it.id == params.id } + if (command){ + if (!device) { + httpError(404, "Device not found") + } else { + + device.on(); + + return [Device_id: params.id, result_action: "200"] + } + } +} + + //TEMPERATURE def getTempSensorsStatus() { @@ -248,6 +538,17 @@ def getTempSensorsStatus() { if (!device) { httpError(404, "Device not found") } else { - return [Device_state: device.currentValue('temperature')] + def bat = getBatteryStatus(device.id) + return [Device_state: device.currentValue('temperature')] + bat + } +} + +def getTempSensorsStatus(id) { + def device = temperature_sensors.find { it.id == id } + if (!device) { + return [] + } else { + def bat = getBatteryStatus(device.id) + return [temperature: device.currentValue('temperature')] + bat + } } -} \ No newline at end of file