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 //thermostat
311 /*
312 def setCoolTemp() {
313         def device = thermostats.find { it.id == params.id }
314         if (!device) {
315             httpError(404, "Device not found")
316         } else {
317             if(device.hasCommand("setCoolingSetpoint")) {
318                 device.setCoolingSetpoint(params.temp.toInteger());
319                 return [result_action: "200"]
320             }
321             else {
322                 httpError(510, "Not supported!")
323             }
324        }
325 }
326 def setHeatTemp() {
327         def device = thermostats.find { it.id == params.id }
328         if (!device) {
329             httpError(404, "Device not found")
330         } else {
331             if(device.hasCommand("setHeatingSetpoint")) {
332                 device.setHeatingSetpoint(params.temp.toInteger());
333                 return [result_action: "200"]
334             }
335             else {
336                 httpError(510, "Not supported!")
337             }
338        }
339 }
340 def setFanMode() {
341         def device = thermostats.find { it.id == params.id }
342         if (!device) {
343             httpError(404, "Device not found")
344         } else {
345         if(device.hasCommand("setThermostatFanMode")) {
346                 device.setThermostatFanMode(params.mode);
347                 return [result_action: "200"]
348             }
349             else {
350                 httpError(510, "Not supported!")
351             }
352        }
353 }
354 def setThermostatMode() {
355         def device = thermostats.find { it.id == params.id }
356         if (!device) {
357             httpError(404, "Device not found")
358         } else {
359         if(device.hasCommand("setThermostatMode")) {
360                 device.setThermostatMode(params.mode);
361                 return [result_action: "200"]
362             }
363             else {
364                 httpError(510, "Not supported!")
365             }
366        }
367 }
368 def getThermostatStatus() {
369         def device = thermostats.find{ it.id == params.id }
370     if (!device) {
371             httpError(404, "Device not found")
372         } else {
373                 return [ThermostatOperatingState: device.currentValue('thermostatOperatingState'), ThermostatSetpoint: device.currentValue('thermostatSetpoint'), 
374                                 ThermostatFanMode: device.currentValue('thermostatFanMode'), ThermostatMode: device.currentValue('thermostatMode')]
375         }
376 }
377 */
378 //light
379 def turnOnLight() {
380     def device = switches.find { it.id == params.id }
381         if (!device) {
382             httpError(404, "Device not found")
383         } else {
384             device.on();
385                   
386             return [Device_id: params.id, result_action: "200"]
387         }
388     }
389
390 def turnOffLight() {
391     def device = switches.find { it.id == params.id }
392         if (!device) {
393             httpError(404, "Device not found")
394         } else {
395             device.off();
396                   
397             return [Device_id: params.id, result_action: "200"]
398         }
399 }
400
401 def getLightStatus() {
402         def device = switches.find{ it.id == params.id }
403     if (!device) {
404             httpError(404, "Device not found")
405         } else {
406                 return [Status: device.currentValue('switch'), Dim: getLevelStatus(params.id), Color: getColorStatus(params.id), Kelvin: getKelvinStatus(params.id)]
407         }
408 }
409
410 //color control
411 def setColor() {
412     def device = colors.find { it.id == params.id }
413         if (!device) {
414             httpError(404, "Device not found")
415         } else {
416                 
417             def map = [hue:params.hue.toInteger(), saturation:params.sat.toInteger()]
418             
419             device.setColor(map);
420                   
421             return [Device_id: params.id, result_action: "200"]
422     }
423 }
424
425 def getColorStatus(id) {
426         def device = colors.find { it.id == id }
427     if (!device) {
428             return [Color: "none"]
429         } else {
430                 return [hue: device.currentValue('hue'), saturation: device.currentValue('saturation')]
431         }
432 }
433
434 //kelvin control
435 def setKelvin() {
436     def device = kelvin.find { it.id == params.id }
437         if (!device) {
438             httpError(404, "Device not found")
439         } else {
440         
441             device.setColorTemperature(params.kelvin.toInteger());
442                   
443             return [Device_id: params.id, result_action: "200"]
444     }
445 }
446
447 def getKelvinStatus(id) {
448         def device = kelvin.find { it.id == id }
449     if (!device) {
450             return [kelvin: "none"]
451         } else {
452                 return [kelvin: device.currentValue('colorTemperature')]
453         }
454 }
455
456 //switch level
457 def getLevelStatus() {
458         def device = switchlevels.find { it.id == params.id }
459     if (!device) {
460             [Level: "No dimmer"]
461         } else {
462                 return [Level: device.currentValue('level')]
463         }
464 }
465
466 def getLevelStatus(id) {
467         def device = switchlevels.find { it.id == id }
468     if (!device) {
469             [Level: "No dimmer"]
470         } else {
471                 return [Level: device.currentValue('level')]
472         }
473 }
474
475
476 def setLevelStatus() {
477         def device = switchlevels.find { it.id == params.id }
478     def level = params.dim
479     if (!device) {
480             httpError(404, "Device not found")
481         } else {
482                 device.setLevel(level.toInteger())
483                 return [result_action: "200", Level: device.currentValue('level')]
484         }
485 }
486
487
488 //contact sensors
489 def getContactStatus() {
490         def device = contact.find { it.id == params.id }
491     if (!device) {
492             httpError(404, "Device not found")
493         } else {
494                 def args = getTempSensorsStatus(device.id)
495                 return [Device_state: device.currentValue('contact')] + args
496         }
497 }
498
499 //smoke detectors
500 def getSmokeStatus() {
501         def device = smoke_alarms.find { it.id == params.id }
502     if (!device) {
503             httpError(404, "Device not found")
504         } else {
505         def bat = getBatteryStatus(device.id)
506                 return [Device_state: device.currentValue('smoke')] + bat
507         }
508 }
509
510 //garage
511 def getGarageStatus() {
512         def device = garage.find { it.id == params.id }
513     if (!device) {
514             httpError(404, "Device not found")
515         } else {
516                 return [Device_state: device.currentValue('door')]
517         }
518 }
519
520 def openGarage() {
521     def device = garage.find { it.id == params.id }
522     if (!device) {
523             httpError(404, "Device not found")
524         } else {
525             
526             device.open();
527                   
528             return [Device_id: params.id, result_action: "200"]                              
529             }
530     }
531
532 def closeGarage() {
533         def device = garage.find { it.id == params.id }
534     if (!device) {
535             httpError(404, "Device not found")
536         } else {
537             
538             device.close();
539                   
540             return [Device_id: params.id, result_action: "200"]                              
541             }
542     }
543 //shades
544 def getShadeStatus() {
545         def device = shades.find { it.id == params.id }
546     if (!device) {
547             httpError(404, "Device not found")
548         } else {
549                 return [Device_state: device.currentValue('windowShade')]
550         }
551 }
552
553 def openShade() {
554     def device = shades.find { it.id == params.id }
555     if (!device) {
556             httpError(404, "Device not found")
557         } else {
558             
559             device.open();
560                   
561             return [Device_id: params.id, result_action: "200"]                              
562             }
563     }
564     
565 def presetShade() {
566     def device = shades.find { it.id == params.id }
567     if (!device) {
568             httpError(404, "Device not found")
569         } else {
570             
571             device.presetPosition();
572                   
573             return [Device_id: params.id, result_action: "200"]                              
574             }
575     }
576
577 def closeShade() {
578         def device = shades.find { it.id == params.id }
579     if (!device) {
580             httpError(404, "Device not found")
581         } else {
582             
583             device.close();
584                   
585             return [Device_id: params.id, result_action: "200"]                              
586             }
587     }
588
589 //water sensor
590 def getWaterSensorStatus() {
591         def device = water_sensors.find { it.id == params.id }
592     if (!device) {
593             httpError(404, "Device not found")
594         } else {
595                 def bat = getBatteryStatus(device.id)
596                 return [Device_state: device.currentValue('water')] + bat
597         }
598 }
599 //batteries
600 def getBatteryStatus() {
601         def device = batteries.find { it.id == params.id }
602     if (!device) {
603             httpError(404, "Device not found")
604         } else {
605                 return [Device_state: device.latestValue("battery")]
606         }
607 }
608
609 def getBatteryStatus(id) {
610         def device = batteries.find { it.id == id }
611     if (!device) {
612             return []
613         } else {
614                 return [battery_state: device.latestValue("battery")]
615         }
616 }
617
618 //LOCKS
619 def getDoorLockStatus() {
620         def device = locks.find { it.id == params.id }
621     if (!device) {
622             httpError(404, "Device not found")
623         } else {
624                 def bat = getBatteryStatus(device.id)
625                 return [Device_state: device.currentValue('lock')] + bat
626         }
627 }
628
629 def lockDoorLock() {
630     def device = locks.find { it.id == params.id }
631     if (!device) {
632             httpError(404, "Device not found")
633         } else {
634             
635             device.lock();
636                   
637             return [Device_id: params.id, result_action: "200"]                              
638             }
639     }
640
641 def unlockDoorLock() {
642         def device = locks.find { it.id == params.id }
643     if (!device) {
644             httpError(404, "Device not found")
645         } else {
646             
647             device.unlock();
648                   
649             return [Device_id: params.id, result_action: "200"]                              
650             }
651     }
652 //PRESENCE
653 def getPresenceStatus() {
654
655         def device = presence_sensors.find { it.id == params.id }
656     if (!device) {
657             httpError(404, "Device not found")
658         } else {
659         def bat = getBatteryStatus(device.id)
660                 return [Device_state: device.currentValue('presence')] + bat
661    }
662 }
663
664 //MOTION
665 def getMotionStatus() {
666
667         def device = motions.find { it.id == params.id }
668     if (!device) {
669             httpError(404, "Device not found")
670         } else {
671                 def args = getTempSensorsStatus(device.id)
672                 return [Device_state: device.currentValue('motion')] + args
673    }
674 }
675
676 //OUTLET
677 def getOutletStatus() {
678
679     def device = outlets.find { it.id == params.id }
680     if (!device) {
681             device = switches.find { it.id == params.id }
682             if(!device) {
683                 httpError(404, "Device not found")
684                 }
685      }
686      def watt = getMeterStatus(device.id)
687         
688      return [Device_state: device.currentValue('switch')] + watt
689 }
690
691 def getMeterStatus() {
692
693     def device = meters.find { it.id == params.id }
694         if (!device) {
695             httpError(404, "Device not found")
696         } else {
697                 return [Device_id: device.id, Device_type: device.type, Current_watt: device.currentValue("power")]
698   }
699 }
700
701 def getMeterStatus(id) {
702
703     def device = meters.find { it.id == id }
704         if (!device) {
705             return []
706         } else {
707                 return [Current_watt: device.currentValue("power")]
708   }
709 }
710
711
712 def turnOnOutlet() {
713     def device = outlets.find { it.id == params.id }
714     if (!device) {
715             device = switches.find { it.id == params.id }
716             if(!device) {
717                 httpError(404, "Device not found")
718                 }
719      }
720      
721      device.on();
722                   
723      return [Device_id: params.id, result_action: "200"]
724 }
725
726 def turnOffOutlet() {
727     def device = outlets.find { it.id == params.id }
728     if (!device) {
729             device = switches.find { it.id == params.id }
730             if(!device) {
731                 httpError(404, "Device not found")
732                 }
733      }
734             
735      device.off();
736                   
737      return [Device_id: params.id, result_action: "200"]
738 }
739
740 //SWITCH
741 def getSwitchStatus() {
742         def device = switches.find { it.id == params.id }
743     if (!device) {
744             httpError(404, "Device not found")
745         } else {
746                 return [Device_state: device.currentValue('switch'), Dim: getLevelStatus(params.id)]
747         }
748 }
749
750 def turnOnSwitch() {
751     def device = switches.find { it.id == params.id }
752         if (!device) {
753             httpError(404, "Device not found")
754         } else {
755             
756             device.on();
757                   
758             return [Device_id: params.id, result_action: "200"]
759         }
760 }
761
762 def turnOffSwitch() {
763     def device = switches.find { it.id == params.id }
764         if (!device) {
765             httpError(404, "Device not found")
766         } else {
767             
768             device.off();
769                   
770             return [Device_id: params.id, result_action: "200"]
771         }
772 }
773
774
775 //TEMPERATURE
776 def getTempSensorsStatus() {
777     def device = temperature_sensors.find { it.id == params.id }
778     if (!device) {
779             httpError(404, "Device not found")
780         } else {
781                 def bat = getBatteryStatus(device.id)
782             def scale = [Scale: location.temperatureScale]
783                 return [Device_state: device.currentValue('temperature')] + scale + bat
784    }
785 }
786
787 def getTempSensorsStatus(id) {  
788     def device = temperature_sensors.find { it.id == id }
789     if (!device) {
790             return []
791         } else {
792                 def bat = getBatteryStatus(device.id)
793                 return [temperature: device.currentValue('temperature')] + bat
794                 }
795    }