Update gideon-smart-home.groovy
[smartapps.git] / official / gideon-smart-home.groovy
1 /**
2  *  Gideon
3  *
4  *  Copyright 2016 Nicola Russo
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
7  *  in compliance with the License. You may obtain a copy of the License at:
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
12  *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
13  *  for the specific language governing permissions and limitations under the License.
14  *
15  */
16 definition(
17     name: "Gideon Smart Home",
18     namespace: "gideon.api",
19     author: "Braindrain Solutions ltd",
20     description: "Gideon Smart Home SmartApp allows you to connect and control all of your SmartThings devices through the Gideon app, making your SmartThings devices even smarter.",
21     category: "Family",
22     iconUrl: "http://s33.postimg.org/t77u7y7v3/logo.png",
23     iconX2Url: "http://s33.postimg.org/t77u7y7v3/logo.png",
24     iconX3Url: "http://s33.postimg.org/t77u7y7v3/logo.png",
25     oauth: [displayName: "Gideon Smart Home API app", displayLink: "gideon.ai"])
26
27 preferences {
28         section("Control these contact sensors...") {
29         input "contact", "capability.contactSensor", multiple:true, required:false
30     }
31     section("Control these switch levels...") {
32         input "switchlevels", "capability.switchLevel", multiple:true, required:false
33     }
34 /*    section("Control these thermostats...") {
35         input "thermostats", "capability.thermostat", multiple:true, required:false
36     }*/
37     section("Control the color for these devices...") {
38         input "colors", "capability.colorControl", multiple:true, required:false
39     }
40     section("Control the color temperature for these devices...") {
41         input "kelvin", "capability.colorTemperature", multiple:true, required:false
42     }
43         section("Control these switches...") {
44         input "switches", "capability.switch", multiple:true, required:false
45     }
46     section("Control these smoke alarms...") {
47         input "smoke_alarms", "capability.smokeDetector", multiple:true, required:false
48     }
49     section("Control these window shades...") {
50         input "shades", "capability.windowShade", multiple:true, required:false
51     }
52     section("Control these garage doors...") {
53         input "garage", "capability.garageDoorControl", multiple:true, required:false
54     }
55     section("Control these water sensors...") {
56         input "water_sensors", "capability.waterSensor", multiple:true, required:false
57     }
58     section("Control these motion sensors...") {
59         input "motions", "capability.motionSensor", multiple:true, required:false
60     }
61     section("Control these presence sensors...") {
62         input "presence_sensors", "capability.presenceSensor", multiple:true, required:false
63     }
64         section("Control these outlets...") {
65         input "outlets", "capability.outlet", multiple:true, required:false
66     }
67     section("Control these power meters...") {
68         input "meters", "capability.powerMeter", multiple:true, required:false
69     }
70     section("Control these locks...") {
71         input "locks", "capability.lock", multiple:true, required:false
72     }
73     section("Control these temperature sensors...") {
74             input "temperature_sensors", "capability.temperatureMeasurement", multiple:true, required:false
75     }
76     section("Control these batteries...") {
77             input "batteries", "capability.battery", multiple:true, required:false
78     }
79 }
80
81 //API Mapping
82 mappings {
83    path("/getalldevices") {
84     action: [
85         GET: "getAllDevices"
86    ]
87   }
88   /*
89   path("/thermostat/setcool/:id/:temp") {
90     action: [
91       GET: "setCoolTemp"
92     ]
93   }
94   path("/thermostat/setheat/:id/:temp") {
95     action: [
96       GET: "setHeatTemp"
97     ]
98   }
99   path("/thermostat/setfanmode/:id/:mode") {
100     action: [
101       GET: "setFanMode"
102     ]
103   }
104   path("/thermostat/setmode/:id/:mode") {
105     action: [
106       GET: "setThermostatMode"
107     ]
108   }
109   path("/thermostat/:id") {
110     action: [
111       GET: "getThermostatStatus"
112     ]
113   }
114   */
115   path("/light/dim/:id/:dim") {
116     action: [
117       GET: "setLevelStatus"
118     ]
119   }
120   path("/light/kelvin/:id/:kelvin") {
121     action: [
122       GET: "setKelvin"
123     ]
124   }
125   path("/colorlight/:id/:hue/:sat") {
126     action: [
127       GET: "setColor"
128     ]
129   }
130   path("/light/status/:id") {
131     action: [
132       GET: "getLightStatus"
133     ]
134   }
135   path("/light/on/:id") {
136     action: [
137       GET: "turnOnLight"
138     ]
139   }
140   path("/light/off/:id") {
141     action: [
142       GET: "turnOffLight"
143     ]
144   }
145   path("/doorlocks/lock/:id") {
146     action: [
147       GET: "lockDoorLock"
148     ]
149   }
150   path("/doorlocks/unlock/:id") {
151     action: [
152       GET: "unlockDoorLock"
153     ]
154   }
155   path("/doorlocks/:id") {
156     action: [
157       GET: "getDoorLockStatus"
158     ]
159   }
160   path("/contacts/:id") {
161     action: [
162         GET: "getContactStatus"
163     ]
164   }
165   path("/smoke/:id") {
166     action: [
167         GET: "getSmokeStatus"
168         ]
169   }
170     path("/shades/open/:id") {
171     action: [
172       GET: "openShade"
173     ]
174   }
175   path("/shades/preset/:id") {
176     action: [
177       GET: "presetShade"
178     ]
179   }
180   path("/shades/close/:id") {
181     action: [
182       GET: "closeShade"
183     ]
184   }
185         path("/shades/:id") {
186     action: [
187         GET: "getShadeStatus"
188         ]
189 }
190     path("/garage/open/:id") {
191     action: [
192       GET: "openGarage"
193     ]
194   }
195   path("/garage/close/:id") {
196     action: [
197       GET: "closeGarage"
198     ]
199   }
200         path("/garage/:id") {
201     action: [
202                 GET: "getGarageStatus"
203         ]
204   }
205     path("/watersensors/:id") {
206     action: [
207                 GET: "getWaterSensorStatus"
208         ]
209   }
210         path("/tempsensors/:id") {
211     action: [
212       GET: "getTempSensorsStatus"
213     ]
214   }
215   path("/meters/:id") {
216     action: [
217       GET: "getMeterStatus"
218     ]
219   }
220   path("/batteries/:id") {
221     action: [
222       GET: "getBatteryStatus"
223     ]
224   }
225         path("/presences/:id") {
226     action: [
227       GET: "getPresenceStatus"
228     ]
229   }
230         path("/motions/:id") {
231     action: [
232       GET: "getMotionStatus"
233     ]
234   }
235         path("/outlets/:id") {
236     action: [
237       GET: "getOutletStatus"
238     ]
239   }
240         path("/outlets/turnon/:id") {
241     action: [
242       GET: "turnOnOutlet"
243     ]
244   }
245   path("/outlets/turnoff/:id") {
246     action: [
247       GET: "turnOffOutlet"
248     ]
249   }
250   path("/switches/turnon/:id") {
251     action: [
252       GET: "turnOnSwitch"
253     ]
254   }
255   path("/switches/turnoff/:id") {
256     action: [
257       GET: "turnOffSwitch"
258     ]
259   }
260   path("/switches/:id") {
261     action: [
262       GET: "getSwitchStatus"
263     ]
264   }
265 }
266
267 def installed() {
268         log.debug "Installed with settings: ${settings}"
269
270         initialize()
271 }
272
273 def updated() {
274         log.debug "Updated with settings: ${settings}"
275
276         unsubscribe()
277         initialize()
278 }
279
280 def initialize() {
281 }
282
283 private device(it, type) {
284         it ? [id: it.id, label: it.label, type: type] : null
285 }
286
287
288 //API Methods
289 def getAllDevices() {
290     def locks_list = locks.collect{device(it,"Lock")}
291     /*def thermo_list = thermostats.collect{device(it,"Thermostat")}*/
292     def colors_list = colors.collect{device(it,"Color")}
293     def kelvin_list = kelvin.collect{device(it,"Kelvin")}
294     def contact_list = contact.collect{device(it,"Contact Sensor")}
295     def smokes_list = smoke_alarms.collect{device(it,"Smoke Alarm")}
296     def shades_list = shades.collect{device(it,"Window Shade")}
297     def garage_list = garage.collect{device(it,"Garage Door")}
298     def water_sensors_list = water_sensors.collect{device(it,"Water Sensor")}
299     def presences_list = presence_sensors.collect{device(it,"Presence")}
300     def motions_list = motions.collect{device(it,"Motion")}
301         def outlets_list = outlets.collect{device(it,"Outlet")}
302     def switches_list = switches.collect{device(it,"Switch")}
303     def switchlevels_list = switchlevels.collect{device(it,"Switch Level")}
304     def temp_list = temperature_sensors.collect{device(it,"Temperature")}
305     def meters_list = meters.collect{device(it,"Power Meters")}
306     def battery_list = batteries.collect{device(it,"Batteries")}
307     return outlets_list + kelvin_list + colors_list + switchlevels_list + smokes_list + contact_list + water_sensors_list + shades_list + garage_list + locks_list + presences_list + motions_list + switches_list + temp_list + meters_list + battery_list
308 }
309
310 //light
311 def turnOnLight() {
312     def device = switches.find { it.id == params.id }
313         if (!device) {
314             httpError(404, "Device not found")
315         } else {
316             device.on();
317                   
318             return [Device_id: params.id, result_action: "200"]
319         }
320     }
321
322 def turnOffLight() {
323     def device = switches.find { it.id == params.id }
324         if (!device) {
325             httpError(404, "Device not found")
326         } else {
327             device.off();
328                   
329             return [Device_id: params.id, result_action: "200"]
330         }
331 }
332
333 def getLightStatus() {
334         def device = switches.find{ it.id == params.id }
335     if (!device) {
336             httpError(404, "Device not found")
337         } else {
338                 return [Status: device.currentValue('switch'), Dim: getLevelStatus(params.id), Color: getColorStatus(params.id), Kelvin: getKelvinStatus(params.id)]
339         }
340 }
341
342 //color control
343 def setColor() {
344     def device = colors.find { it.id == params.id }
345         if (!device) {
346             httpError(404, "Device not found")
347         } else {
348                 
349             def map = [hue:params.hue.toInteger(), saturation:params.sat.toInteger()]
350             
351             device.setColor(map);
352                   
353             return [Device_id: params.id, result_action: "200"]
354     }
355 }
356
357 def getColorStatus(id) {
358         def device = colors.find { it.id == id }
359     if (!device) {
360             return [Color: "none"]
361         } else {
362                 return [hue: device.currentValue('hue'), saturation: device.currentValue('saturation')]
363         }
364 }
365
366 //kelvin control
367 def setKelvin() {
368     def device = kelvin.find { it.id == params.id }
369         if (!device) {
370             httpError(404, "Device not found")
371         } else {
372         
373             device.setColorTemperature(params.kelvin.toInteger());
374                   
375             return [Device_id: params.id, result_action: "200"]
376     }
377 }
378
379 def getKelvinStatus(id) {
380         def device = kelvin.find { it.id == id }
381     if (!device) {
382             return [kelvin: "none"]
383         } else {
384                 return [kelvin: device.currentValue('colorTemperature')]
385         }
386 }
387
388 //switch level
389 def getLevelStatus() {
390         def device = switchlevels.find { it.id == params.id }
391     if (!device) {
392             [Level: "No dimmer"]
393         } else {
394                 return [Level: device.currentValue('level')]
395         }
396 }
397
398 def getLevelStatus(id) {
399         def device = switchlevels.find { it.id == id }
400     if (!device) {
401             [Level: "No dimmer"]
402         } else {
403                 return [Level: device.currentValue('level')]
404         }
405 }
406
407
408 def setLevelStatus() {
409         def device = switchlevels.find { it.id == params.id }
410     def level = params.dim
411     if (!device) {
412             httpError(404, "Device not found")
413         } else {
414                 device.setLevel(level.toInteger())
415                 return [result_action: "200", Level: device.currentValue('level')]
416         }
417 }
418
419
420 //contact sensors
421 def getContactStatus() {
422         def device = contact.find { it.id == params.id }
423     if (!device) {
424             httpError(404, "Device not found")
425         } else {
426                 def args = getTempSensorsStatus(device.id)
427                 return [Device_state: device.currentValue('contact')] + args
428         }
429 }
430
431 //smoke detectors
432 def getSmokeStatus() {
433         def device = smoke_alarms.find { it.id == params.id }
434     if (!device) {
435             httpError(404, "Device not found")
436         } else {
437         def bat = getBatteryStatus(device.id)
438                 return [Device_state: device.currentValue('smoke')] + bat
439         }
440 }
441
442 //garage
443 def getGarageStatus() {
444         def device = garage.find { it.id == params.id }
445     if (!device) {
446             httpError(404, "Device not found")
447         } else {
448                 return [Device_state: device.currentValue('door')]
449         }
450 }
451
452 def openGarage() {
453     def device = garage.find { it.id == params.id }
454     if (!device) {
455             httpError(404, "Device not found")
456         } else {
457             
458             device.open();
459                   
460             return [Device_id: params.id, result_action: "200"]                              
461             }
462     }
463
464 def closeGarage() {
465         def device = garage.find { it.id == params.id }
466     if (!device) {
467             httpError(404, "Device not found")
468         } else {
469             
470             device.close();
471                   
472             return [Device_id: params.id, result_action: "200"]                              
473             }
474     }
475 //shades
476 def getShadeStatus() {
477         def device = shades.find { it.id == params.id }
478     if (!device) {
479             httpError(404, "Device not found")
480         } else {
481                 return [Device_state: device.currentValue('windowShade')]
482         }
483 }
484
485 def openShade() {
486     def device = shades.find { it.id == params.id }
487     if (!device) {
488             httpError(404, "Device not found")
489         } else {
490             
491             device.open();
492                   
493             return [Device_id: params.id, result_action: "200"]                              
494             }
495     }
496     
497 def presetShade() {
498     def device = shades.find { it.id == params.id }
499     if (!device) {
500             httpError(404, "Device not found")
501         } else {
502             
503             device.presetPosition();
504                   
505             return [Device_id: params.id, result_action: "200"]                              
506             }
507     }
508
509 def closeShade() {
510         def device = shades.find { it.id == params.id }
511     if (!device) {
512             httpError(404, "Device not found")
513         } else {
514             
515             device.close();
516                   
517             return [Device_id: params.id, result_action: "200"]                              
518             }
519     }
520
521 //water sensor
522 def getWaterSensorStatus() {
523         def device = water_sensors.find { it.id == params.id }
524     if (!device) {
525             httpError(404, "Device not found")
526         } else {
527                 def bat = getBatteryStatus(device.id)
528                 return [Device_state: device.currentValue('water')] + bat
529         }
530 }
531 //batteries
532 def getBatteryStatus() {
533         def device = batteries.find { it.id == params.id }
534     if (!device) {
535             httpError(404, "Device not found")
536         } else {
537                 return [Device_state: device.latestValue("battery")]
538         }
539 }
540
541 def getBatteryStatus(id) {
542         def device = batteries.find { it.id == id }
543     if (!device) {
544             return []
545         } else {
546                 return [battery_state: device.latestValue("battery")]
547         }
548 }
549
550 //LOCKS
551 def getDoorLockStatus() {
552         def device = locks.find { it.id == params.id }
553     if (!device) {
554             httpError(404, "Device not found")
555         } else {
556                 def bat = getBatteryStatus(device.id)
557                 return [Device_state: device.currentValue('lock')] + bat
558         }
559 }
560
561 def lockDoorLock() {
562     def device = locks.find { it.id == params.id }
563     if (!device) {
564             httpError(404, "Device not found")
565         } else {
566             
567             device.lock();
568                   
569             return [Device_id: params.id, result_action: "200"]                              
570             }
571     }
572
573 def unlockDoorLock() {
574         def device = locks.find { it.id == params.id }
575     if (!device) {
576             httpError(404, "Device not found")
577         } else {
578             
579             device.unlock();
580                   
581             return [Device_id: params.id, result_action: "200"]                              
582             }
583     }
584 //PRESENCE
585 def getPresenceStatus() {
586
587         def device = presence_sensors.find { it.id == params.id }
588     if (!device) {
589             httpError(404, "Device not found")
590         } else {
591         def bat = getBatteryStatus(device.id)
592                 return [Device_state: device.currentValue('presence')] + bat
593    }
594 }
595
596 //MOTION
597 def getMotionStatus() {
598
599         def device = motions.find { it.id == params.id }
600     if (!device) {
601             httpError(404, "Device not found")
602         } else {
603                 def args = getTempSensorsStatus(device.id)
604                 return [Device_state: device.currentValue('motion')] + args
605    }
606 }
607
608 //OUTLET
609 def getOutletStatus() {
610
611     def device = outlets.find { it.id == params.id }
612     if (!device) {
613             device = switches.find { it.id == params.id }
614             if(!device) {
615                 httpError(404, "Device not found")
616                 }
617      }
618      def watt = getMeterStatus(device.id)
619         
620      return [Device_state: device.currentValue('switch')] + watt
621 }
622
623 def getMeterStatus() {
624
625     def device = meters.find { it.id == params.id }
626         if (!device) {
627             httpError(404, "Device not found")
628         } else {
629                 return [Device_id: device.id, Device_type: device.type, Current_watt: device.currentValue("power")]
630   }
631 }
632
633 def getMeterStatus(id) {
634
635     def device = meters.find { it.id == id }
636         if (!device) {
637             return []
638         } else {
639                 return [Current_watt: device.currentValue("power")]
640   }
641 }
642
643
644 def turnOnOutlet() {
645     def device = outlets.find { it.id == params.id }
646     if (!device) {
647             device = switches.find { it.id == params.id }
648             if(!device) {
649                 httpError(404, "Device not found")
650                 }
651      }
652      
653      device.on();
654                   
655      return [Device_id: params.id, result_action: "200"]
656 }
657
658 def turnOffOutlet() {
659     def device = outlets.find { it.id == params.id }
660     if (!device) {
661             device = switches.find { it.id == params.id }
662             if(!device) {
663                 httpError(404, "Device not found")
664                 }
665      }
666             
667      device.off();
668                   
669      return [Device_id: params.id, result_action: "200"]
670 }
671
672 //SWITCH
673 def getSwitchStatus() {
674         def device = switches.find { it.id == params.id }
675     if (!device) {
676             httpError(404, "Device not found")
677         } else {
678                 return [Device_state: device.currentValue('switch'), Dim: getLevelStatus(params.id)]
679         }
680 }
681
682 def turnOnSwitch() {
683     def device = switches.find { it.id == params.id }
684         if (!device) {
685             httpError(404, "Device not found")
686         } else {
687             
688             device.on();
689                   
690             return [Device_id: params.id, result_action: "200"]
691         }
692 }
693
694 def turnOffSwitch() {
695     def device = switches.find { it.id == params.id }
696         if (!device) {
697             httpError(404, "Device not found")
698         } else {
699             
700             device.off();
701                   
702             return [Device_id: params.id, result_action: "200"]
703         }
704 }
705
706
707 //TEMPERATURE
708 def getTempSensorsStatus() {
709     def device = temperature_sensors.find { it.id == params.id }
710     if (!device) {
711             httpError(404, "Device not found")
712         } else {
713                 def bat = getBatteryStatus(device.id)
714             def scale = [Scale: location.temperatureScale]
715                 return [Device_state: device.currentValue('temperature')] + scale + bat
716    }
717 }
718
719 def getTempSensorsStatus(id) {  
720     def device = temperature_sensors.find { it.id == id }
721     if (!device) {
722             return []
723         } else {
724                 def bat = getBatteryStatus(device.id)
725                 return [temperature: device.currentValue('temperature')] + bat
726                 }
727    }