Update groveStreams.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 def installed() {
82         log.debug "Installed with settings: ${settings}"
83
84         initialize()
85 }
86
87 def updated() {
88         log.debug "Updated with settings: ${settings}"
89
90         unsubscribe()
91         initialize()
92 }
93
94 def initialize() {
95 }
96
97 private device(it, type) {
98         it ? [id: it.id, label: it.label, type: type] : null
99 }
100
101 //API Mapping
102 mappings {
103    path("/getalldevices") {
104     action: [
105         GET: "getAllDevices"
106    ]
107   }
108   /*
109   path("/thermostat/setcool/:id/:temp") {
110     action: [
111       GET: "setCoolTemp"
112     ]
113   }
114   path("/thermostat/setheat/:id/:temp") {
115     action: [
116       GET: "setHeatTemp"
117     ]
118   }
119   path("/thermostat/setfanmode/:id/:mode") {
120     action: [
121       GET: "setFanMode"
122     ]
123   }
124   path("/thermostat/setmode/:id/:mode") {
125     action: [
126       GET: "setThermostatMode"
127     ]
128   }
129   path("/thermostat/:id") {
130     action: [
131       GET: "getThermostatStatus"
132     ]
133   }
134   */
135   path("/light/dim/:id/:dim") {
136     action: [
137       GET: "setLevelStatus"
138     ]
139   }
140   path("/light/kelvin/:id/:kelvin") {
141     action: [
142       GET: "setKelvin"
143     ]
144   }
145   path("/colorlight/:id/:hue/:sat") {
146     action: [
147       GET: "setColor"
148     ]
149   }
150   path("/light/status/:id") {
151     action: [
152       GET: "getLightStatus"
153     ]
154   }
155   path("/light/on/:id") {
156     action: [
157       GET: "turnOnLight"
158     ]
159   }
160   path("/light/off/:id") {
161     action: [
162       GET: "turnOffLight"
163     ]
164   }
165   path("/doorlocks/lock/:id") {
166     action: [
167       GET: "lockDoorLock"
168     ]
169   }
170   path("/doorlocks/unlock/:id") {
171     action: [
172       GET: "unlockDoorLock"
173     ]
174   }
175   path("/doorlocks/:id") {
176     action: [
177       GET: "getDoorLockStatus"
178     ]
179   }
180   path("/contacts/:id") {
181     action: [
182         GET: "getContactStatus"
183     ]
184   }
185   path("/smoke/:id") {
186     action: [
187         GET: "getSmokeStatus"
188         ]
189   }
190     path("/shades/open/:id") {
191     action: [
192       GET: "openShade"
193     ]
194   }
195   path("/shades/preset/:id") {
196     action: [
197       GET: "presetShade"
198     ]
199   }
200   path("/shades/close/:id") {
201     action: [
202       GET: "closeShade"
203     ]
204   }
205         path("/shades/:id") {
206     action: [
207         GET: "getShadeStatus"
208         ]
209 }
210     path("/garage/open/:id") {
211     action: [
212       GET: "openGarage"
213     ]
214   }
215   path("/garage/close/:id") {
216     action: [
217       GET: "closeGarage"
218     ]
219   }
220         path("/garage/:id") {
221     action: [
222                 GET: "getGarageStatus"
223         ]
224   }
225     path("/watersensors/:id") {
226     action: [
227                 GET: "getWaterSensorStatus"
228         ]
229   }
230         path("/tempsensors/:id") {
231     action: [
232       GET: "getTempSensorsStatus"
233     ]
234   }
235   path("/meters/:id") {
236     action: [
237       GET: "getMeterStatus"
238     ]
239   }
240   path("/batteries/:id") {
241     action: [
242       GET: "getBatteryStatus"
243     ]
244   }
245         path("/presences/:id") {
246     action: [
247       GET: "getPresenceStatus"
248     ]
249   }
250         path("/motions/:id") {
251     action: [
252       GET: "getMotionStatus"
253     ]
254   }
255         path("/outlets/:id") {
256     action: [
257       GET: "getOutletStatus"
258     ]
259   }
260         path("/outlets/turnon/:id") {
261     action: [
262       GET: "turnOnOutlet"
263     ]
264   }
265   path("/outlets/turnoff/:id") {
266     action: [
267       GET: "turnOffOutlet"
268     ]
269   }
270   path("/switches/turnon/:id") {
271     action: [
272       GET: "turnOnSwitch"
273     ]
274   }
275   path("/switches/turnoff/:id") {
276     action: [
277       GET: "turnOffSwitch"
278     ]
279   }
280   path("/switches/:id") {
281     action: [
282       GET: "getSwitchStatus"
283     ]
284   }
285 }
286
287 //API Methods
288 def getAllDevices() {
289     def locks_list = locks.collect{device(it,"Lock")}
290     /*def thermo_list = thermostats.collect{device(it,"Thermostat")}*/
291     def colors_list = colors.collect{device(it,"Color")}
292     def kelvin_list = kelvin.collect{device(it,"Kelvin")}
293     def contact_list = contact.collect{device(it,"Contact Sensor")}
294     def smokes_list = smoke_alarms.collect{device(it,"Smoke Alarm")}
295     def shades_list = shades.collect{device(it,"Window Shade")}
296     def garage_list = garage.collect{device(it,"Garage Door")}
297     def water_sensors_list = water_sensors.collect{device(it,"Water Sensor")}
298     def presences_list = presence_sensors.collect{device(it,"Presence")}
299     def motions_list = motions.collect{device(it,"Motion")}
300         def outlets_list = outlets.collect{device(it,"Outlet")}
301     def switches_list = switches.collect{device(it,"Switch")}
302     def switchlevels_list = switchlevels.collect{device(it,"Switch Level")}
303     def temp_list = temperature_sensors.collect{device(it,"Temperature")}
304     def meters_list = meters.collect{device(it,"Power Meters")}
305     def battery_list = batteries.collect{device(it,"Batteries")}
306     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
307 }
308
309 //thermostat
310 /*
311 def setCoolTemp() {
312         def device = thermostats.find { it.id == params.id }
313         if (!device) {
314             httpError(404, "Device not found")
315         } else {
316             if(device.hasCommand("setCoolingSetpoint")) {
317                 device.setCoolingSetpoint(params.temp.toInteger());
318                 return [result_action: "200"]
319             }
320             else {
321                 httpError(510, "Not supported!")
322             }
323        }
324 }
325 def setHeatTemp() {
326         def device = thermostats.find { it.id == params.id }
327         if (!device) {
328             httpError(404, "Device not found")
329         } else {
330             if(device.hasCommand("setHeatingSetpoint")) {
331                 device.setHeatingSetpoint(params.temp.toInteger());
332                 return [result_action: "200"]
333             }
334             else {
335                 httpError(510, "Not supported!")
336             }
337        }
338 }
339 def setFanMode() {
340         def device = thermostats.find { it.id == params.id }
341         if (!device) {
342             httpError(404, "Device not found")
343         } else {
344         if(device.hasCommand("setThermostatFanMode")) {
345                 device.setThermostatFanMode(params.mode);
346                 return [result_action: "200"]
347             }
348             else {
349                 httpError(510, "Not supported!")
350             }
351        }
352 }
353 def setThermostatMode() {
354         def device = thermostats.find { it.id == params.id }
355         if (!device) {
356             httpError(404, "Device not found")
357         } else {
358         if(device.hasCommand("setThermostatMode")) {
359                 device.setThermostatMode(params.mode);
360                 return [result_action: "200"]
361             }
362             else {
363                 httpError(510, "Not supported!")
364             }
365        }
366 }
367 def getThermostatStatus() {
368         def device = thermostats.find{ it.id == params.id }
369     if (!device) {
370             httpError(404, "Device not found")
371         } else {
372                 return [ThermostatOperatingState: device.currentValue('thermostatOperatingState'), ThermostatSetpoint: device.currentValue('thermostatSetpoint'), 
373                                 ThermostatFanMode: device.currentValue('thermostatFanMode'), ThermostatMode: device.currentValue('thermostatMode')]
374         }
375 }
376 */
377 //light
378 def turnOnLight() {
379     def device = switches.find { it.id == params.id }
380         if (!device) {
381             httpError(404, "Device not found")
382         } else {
383             device.on();
384                   
385             return [Device_id: params.id, result_action: "200"]
386         }
387     }
388
389 def turnOffLight() {
390     def device = switches.find { it.id == params.id }
391         if (!device) {
392             httpError(404, "Device not found")
393         } else {
394             device.off();
395                   
396             return [Device_id: params.id, result_action: "200"]
397         }
398 }
399
400 def getLightStatus() {
401         def device = switches.find{ it.id == params.id }
402     if (!device) {
403             httpError(404, "Device not found")
404         } else {
405                 return [Status: device.currentValue('switch'), Dim: getLevelStatus(params.id), Color: getColorStatus(params.id), Kelvin: getKelvinStatus(params.id)]
406         }
407 }
408
409 //color control
410 def setColor() {
411     def device = colors.find { it.id == params.id }
412         if (!device) {
413             httpError(404, "Device not found")
414         } else {
415                 
416             def map = [hue:params.hue.toInteger(), saturation:params.sat.toInteger()]
417             
418             device.setColor(map);
419                   
420             return [Device_id: params.id, result_action: "200"]
421     }
422 }
423
424 def getColorStatus(id) {
425         def device = colors.find { it.id == id }
426     if (!device) {
427             return [Color: "none"]
428         } else {
429                 return [hue: device.currentValue('hue'), saturation: device.currentValue('saturation')]
430         }
431 }
432
433 //kelvin control
434 def setKelvin() {
435     def device = kelvin.find { it.id == params.id }
436         if (!device) {
437             httpError(404, "Device not found")
438         } else {
439         
440             device.setColorTemperature(params.kelvin.toInteger());
441                   
442             return [Device_id: params.id, result_action: "200"]
443     }
444 }
445
446 def getKelvinStatus(id) {
447         def device = kelvin.find { it.id == id }
448     if (!device) {
449             return [kelvin: "none"]
450         } else {
451                 return [kelvin: device.currentValue('colorTemperature')]
452         }
453 }
454
455 //switch level
456 def getLevelStatus() {
457         def device = switchlevels.find { it.id == params.id }
458     if (!device) {
459             [Level: "No dimmer"]
460         } else {
461                 return [Level: device.currentValue('level')]
462         }
463 }
464
465 def getLevelStatus(id) {
466         def device = switchlevels.find { it.id == id }
467     if (!device) {
468             [Level: "No dimmer"]
469         } else {
470                 return [Level: device.currentValue('level')]
471         }
472 }
473
474
475 def setLevelStatus() {
476         def device = switchlevels.find { it.id == params.id }
477     def level = params.dim
478     if (!device) {
479             httpError(404, "Device not found")
480         } else {
481                 device.setLevel(level.toInteger())
482                 return [result_action: "200", Level: device.currentValue('level')]
483         }
484 }
485
486
487 //contact sensors
488 def getContactStatus() {
489         def device = contact.find { it.id == params.id }
490     if (!device) {
491             httpError(404, "Device not found")
492         } else {
493                 def args = getTempSensorsStatus(device.id)
494                 return [Device_state: device.currentValue('contact')] + args
495         }
496 }
497
498 //smoke detectors
499 def getSmokeStatus() {
500         def device = smoke_alarms.find { it.id == params.id }
501     if (!device) {
502             httpError(404, "Device not found")
503         } else {
504         def bat = getBatteryStatus(device.id)
505                 return [Device_state: device.currentValue('smoke')] + bat
506         }
507 }
508
509 //garage
510 def getGarageStatus() {
511         def device = garage.find { it.id == params.id }
512     if (!device) {
513             httpError(404, "Device not found")
514         } else {
515                 return [Device_state: device.currentValue('door')]
516         }
517 }
518
519 def openGarage() {
520     def device = garage.find { it.id == params.id }
521     if (!device) {
522             httpError(404, "Device not found")
523         } else {
524             
525             device.open();
526                   
527             return [Device_id: params.id, result_action: "200"]                              
528             }
529     }
530
531 def closeGarage() {
532         def device = garage.find { it.id == params.id }
533     if (!device) {
534             httpError(404, "Device not found")
535         } else {
536             
537             device.close();
538                   
539             return [Device_id: params.id, result_action: "200"]                              
540             }
541     }
542 //shades
543 def getShadeStatus() {
544         def device = shades.find { it.id == params.id }
545     if (!device) {
546             httpError(404, "Device not found")
547         } else {
548                 return [Device_state: device.currentValue('windowShade')]
549         }
550 }
551
552 def openShade() {
553     def device = shades.find { it.id == params.id }
554     if (!device) {
555             httpError(404, "Device not found")
556         } else {
557             
558             device.open();
559                   
560             return [Device_id: params.id, result_action: "200"]                              
561             }
562     }
563     
564 def presetShade() {
565     def device = shades.find { it.id == params.id }
566     if (!device) {
567             httpError(404, "Device not found")
568         } else {
569             
570             device.presetPosition();
571                   
572             return [Device_id: params.id, result_action: "200"]                              
573             }
574     }
575
576 def closeShade() {
577         def device = shades.find { it.id == params.id }
578     if (!device) {
579             httpError(404, "Device not found")
580         } else {
581             
582             device.close();
583                   
584             return [Device_id: params.id, result_action: "200"]                              
585             }
586     }
587
588 //water sensor
589 def getWaterSensorStatus() {
590         def device = water_sensors.find { it.id == params.id }
591     if (!device) {
592             httpError(404, "Device not found")
593         } else {
594                 def bat = getBatteryStatus(device.id)
595                 return [Device_state: device.currentValue('water')] + bat
596         }
597 }
598 //batteries
599 def getBatteryStatus() {
600         def device = batteries.find { it.id == params.id }
601     if (!device) {
602             httpError(404, "Device not found")
603         } else {
604                 return [Device_state: device.latestValue("battery")]
605         }
606 }
607
608 def getBatteryStatus(id) {
609         def device = batteries.find { it.id == id }
610     if (!device) {
611             return []
612         } else {
613                 return [battery_state: device.latestValue("battery")]
614         }
615 }
616
617 //LOCKS
618 def getDoorLockStatus() {
619         def device = locks.find { it.id == params.id }
620     if (!device) {
621             httpError(404, "Device not found")
622         } else {
623                 def bat = getBatteryStatus(device.id)
624                 return [Device_state: device.currentValue('lock')] + bat
625         }
626 }
627
628 def lockDoorLock() {
629     def device = locks.find { it.id == params.id }
630     if (!device) {
631             httpError(404, "Device not found")
632         } else {
633             
634             device.lock();
635                   
636             return [Device_id: params.id, result_action: "200"]                              
637             }
638     }
639
640 def unlockDoorLock() {
641         def device = locks.find { it.id == params.id }
642     if (!device) {
643             httpError(404, "Device not found")
644         } else {
645             
646             device.unlock();
647                   
648             return [Device_id: params.id, result_action: "200"]                              
649             }
650     }
651 //PRESENCE
652 def getPresenceStatus() {
653
654         def device = presence_sensors.find { it.id == params.id }
655     if (!device) {
656             httpError(404, "Device not found")
657         } else {
658         def bat = getBatteryStatus(device.id)
659                 return [Device_state: device.currentValue('presence')] + bat
660    }
661 }
662
663 //MOTION
664 def getMotionStatus() {
665
666         def device = motions.find { it.id == params.id }
667     if (!device) {
668             httpError(404, "Device not found")
669         } else {
670                 def args = getTempSensorsStatus(device.id)
671                 return [Device_state: device.currentValue('motion')] + args
672    }
673 }
674
675 //OUTLET
676 def getOutletStatus() {
677
678     def device = outlets.find { it.id == params.id }
679     if (!device) {
680             device = switches.find { it.id == params.id }
681             if(!device) {
682                 httpError(404, "Device not found")
683                 }
684      }
685      def watt = getMeterStatus(device.id)
686         
687      return [Device_state: device.currentValue('switch')] + watt
688 }
689
690 def getMeterStatus() {
691
692     def device = meters.find { it.id == params.id }
693         if (!device) {
694             httpError(404, "Device not found")
695         } else {
696                 return [Device_id: device.id, Device_type: device.type, Current_watt: device.currentValue("power")]
697   }
698 }
699
700 def getMeterStatus(id) {
701
702     def device = meters.find { it.id == id }
703         if (!device) {
704             return []
705         } else {
706                 return [Current_watt: device.currentValue("power")]
707   }
708 }
709
710
711 def turnOnOutlet() {
712     def device = outlets.find { it.id == params.id }
713     if (!device) {
714             device = switches.find { it.id == params.id }
715             if(!device) {
716                 httpError(404, "Device not found")
717                 }
718      }
719      
720      device.on();
721                   
722      return [Device_id: params.id, result_action: "200"]
723 }
724
725 def turnOffOutlet() {
726     def device = outlets.find { it.id == params.id }
727     if (!device) {
728             device = switches.find { it.id == params.id }
729             if(!device) {
730                 httpError(404, "Device not found")
731                 }
732      }
733             
734      device.off();
735                   
736      return [Device_id: params.id, result_action: "200"]
737 }
738
739 //SWITCH
740 def getSwitchStatus() {
741         def device = switches.find { it.id == params.id }
742     if (!device) {
743             httpError(404, "Device not found")
744         } else {
745                 return [Device_state: device.currentValue('switch'), Dim: getLevelStatus(params.id)]
746         }
747 }
748
749 def turnOnSwitch() {
750     def device = switches.find { it.id == params.id }
751         if (!device) {
752             httpError(404, "Device not found")
753         } else {
754             
755             device.on();
756                   
757             return [Device_id: params.id, result_action: "200"]
758         }
759 }
760
761 def turnOffSwitch() {
762     def device = switches.find { it.id == params.id }
763         if (!device) {
764             httpError(404, "Device not found")
765         } else {
766             
767             device.off();
768                   
769             return [Device_id: params.id, result_action: "200"]
770         }
771 }
772
773
774 //TEMPERATURE
775 def getTempSensorsStatus() {
776     def device = temperature_sensors.find { it.id == params.id }
777     if (!device) {
778             httpError(404, "Device not found")
779         } else {
780                 def bat = getBatteryStatus(device.id)
781             def scale = [Scale: location.temperatureScale]
782                 return [Device_state: device.currentValue('temperature')] + scale + bat
783    }
784 }
785
786 def getTempSensorsStatus(id) {  
787     def device = temperature_sensors.find { it.id == id }
788     if (!device) {
789             return []
790         } else {
791                 def bat = getBatteryStatus(device.id)
792                 return [temperature: device.currentValue('temperature')] + bat
793                 }
794    }