Update keep-me-cozy.groovy
[smartapps.git] / official / weatherbug-home.groovy
1 /**
2  *  WeatherBug Home
3  *
4  *  Copyright 2015 WeatherBug
5  *
6  */
7 definition(
8     name: "WeatherBug Home",
9     namespace: "WeatherBug",
10     author: "WeatherBug Home",
11     description: "WeatherBug Home",
12     category: "My Apps",
13     iconUrl: "http://stg.static.myenergy.enqa.co/apps/wbhc/v2/images/weatherbughomemedium.png",
14     iconX2Url: "http://stg.static.myenergy.enqa.co/apps/wbhc/v2/images/weatherbughomemedium.png",
15     iconX3Url: "http://stg.static.myenergy.enqa.co/apps/wbhc/v2/images/weatherbughome.png",
16     oauth: [displayName: "WeatherBug Home", displayLink: "http://weatherbughome.com/"])
17
18
19 preferences {
20         section("Select thermostats") {
21         input "thermostatDevice", "capability.thermostat", multiple: true
22     }
23 }
24
25 mappings {
26   path("/appInfo") {    action: [      GET: "getAppInfo"    ]  }
27   path("/getLocation") {    action: [      GET: "getLoc"    ]  }
28   path("/currentReport/:id") {    action: [      GET: "getCurrentReport"    ]  }
29   path("/setTemp/:temp/:id") {    action: [      POST: "setTemperature", GET: "setTemperature"    ]  }
30 }
31
32 /**
33  * This API call will be leveraged by a WeatherBug Home Service to retrieve
34  * data from the installed SmartApp, including the location data, and 
35  * a list of the devices that were authorized to be accessed.  The WeatherBug
36  * Home Service will leverage this data to represent the connected devices as well as their
37  * location and associated the data with a WeatherBug user account.
38  * Privacy Policy: http://weatherbughome.com/privacy/
39  * @return Location, including id, latitude, longitude, zip code, and name, and the list of devices
40  */
41 def getAppInfo() {
42    def devices = thermostatDevice
43    def lat = location.latitude
44    def lon = location.longitude
45    if(!(devices instanceof Collection))
46    {
47      devices = [devices]
48    }
49    return [
50                         Id: UUID.randomUUID().toString(),
51             Code: 200,
52             ErrorMessage: null,
53                         Result: [ "Devices": devices, 
54                         "Location":[
55                 "Id": location.id, 
56                 "Latitude":lat,
57                 "Longitude":lon,
58                 "ZipCode":location.zipCode,
59                 "Name":location.name
60                 ]
61             ]
62          ]
63 }
64
65 /**
66  * This API call will be leveraged by a WeatherBug Home Service to retrieve
67  * location data from the installed SmartApp.  The WeatherBug
68  * Home Service will leverage this data to associate the location to a WeatherBug Home account
69  * Privacy Policy: http://weatherbughome.com/privacy/
70  *
71  * @return Location, including id, latitude, longitude, zip code, and name
72  */
73 def getLoc() {
74    return [
75                 Id: UUID.randomUUID().toString(),
76         Code: 200,
77         ErrorMessage: null,
78         Result: [
79         "Id": location.id, 
80         "Latitude":location.latitude,
81         "Longitude":location.longitude,
82         "ZipCode":location.zipCode,
83         "Name":location.name]
84     ]
85 }
86
87 /**
88  * This API call will be leveraged by a WeatherBug Home Service to retrieve
89  * thermostat data and store it for display to a WeatherBug user.
90  * Privacy Policy: http://weatherbughome.com/privacy/
91  *
92  * @param id The id of the device to get data for
93  * @return Thermostat data including temperature, set points, running modes, and operating states
94  */
95 def getCurrentReport() {
96         log.debug "device id parameter=" + params.id
97     def unixTime = (int)((new Date().getTime() / 1000))
98     def device = thermostatDevice.find{ it.id == params.id}
99     
100     if(device == null)
101     {
102         return [
103                 Id: UUID.randomUUID().toString(),
104             Code: 404,
105             ErrorMessage: "Device not found. id=" + params.id,
106             Result: null
107         ]
108     }
109     return [
110                 Id: UUID.randomUUID().toString(),
111             Code: 200,
112             ErrorMessage: null,
113             Result: [
114                 DeviceId: device.id, 
115                 LocationId: location.id, 
116                 ReportType: 2, 
117                 ReportList: [ 
118                     [Key: "Temperature", Value: GetOrDefault(device, "temperature")], 
119                         [Key: "ThermostatSetpoint", Value: GetOrDefault(device, "thermostatSetpoint")],
120                     [Key: "CoolingSetpoint", Value: GetOrDefault(device, "coolingSetpoint")],
121                     [Key: "HeatingSetpoint", Value: GetOrDefault(device, "heatingSetpoint")],
122                     [Key: "ThermostatMode", Value: GetOrDefault(device, "thermostatMode")],
123                     [Key: "ThermostatFanMode", Value: GetOrDefault(device, "thermostatFanMode")],
124                     [Key: "ThermostatOperatingState", Value: GetOrDefault(device, "thermostatOperatingState")]
125                 ],
126                 UnixTime: unixTime
127             ]
128         ]
129 }
130
131 /**
132  * This API call will be leveraged by a WeatherBug Home Service to set
133  * the thermostat setpoint.
134  * Privacy Policy: http://weatherbughome.com/privacy/
135  *
136  * @param id The id of the device to set
137  * @return Indication of whether the operation succeeded or failed
138  
139 def setTemperature() {
140         log.debug "device id parameter=" + params.id
141         def device = thermostatDevice.find{ it.id == params.id}
142     if(device != null)
143     {
144         def mode = device.latestState('thermostatMode').stringValue
145         def value = params.temp as Integer
146         log.trace "Suggested temperature: $value, $mode"
147         if ( mode == "cool")
148             device.setCoolingSetpoint(value)
149         else if ( mode == "heat")
150             device.setHeatingSetpoint(value)           
151         return [
152                 Id: UUID.randomUUID().toString(),
153             Code: 200,
154             ErrorMessage: null,
155             Result: null
156         ]
157     }
158     return [
159                 Id: UUID.randomUUID().toString(),
160             Code : 404,
161             ErrorMessage: "Device not found. id=" + params.id,
162             Result: null
163         ]
164 }
165 */
166
167
168 def installed() {
169         log.debug "Installed with settings: ${settings}"
170         initialize()
171 }
172
173 /**
174  * The updated event will be pushed to a WeatherBug Home Service to notify the system to take appropriate action.
175  * Data that will be sent includes the list of devices, and location data
176  * Privacy Policy: http://weatherbughome.com/privacy/
177  */
178 def updated() {
179         log.debug "Updated with settings: ${settings}"
180     log.debug "Updated with state: ${state}"
181         log.debug "Updated with location ${location} ${location.id} ${location.name}"
182     unsubscribe()
183     initialize()
184         def postParams = [
185                 uri: 'https://smartthingsrec.api.earthnetworks.com/api/v1/receive/smartapp/update',
186                 body:  [ 
187                         "Devices": devices, 
188                         "Location":[
189                                 "Id": location.id, 
190                                 "Latitude":location.latitude,
191                                 "Longitude":location.longitude,
192                                 "ZipCode":location.zipCode,
193                                 "Name":location.name
194                         ]
195            ]
196     ]
197     sendToWeatherBug(postParams)
198 }
199
200 /*
201 * Subscribe to changes on the thermostat attributes
202 */
203 def initialize() {
204         log.trace "initialize enter"
205     subscribe(thermostatDevice, "heatingSetpoint", pushLatest)
206     subscribe(thermostatDevice, "coolingSetpoint", pushLatest)
207     subscribe(thermostatDevice, "thermostatSetpoint", pushLatest)
208     subscribe(thermostatDevice, "thermostatMode", pushLatest)
209     subscribe(thermostatDevice, "thermostatFanMode", pushLatest)
210     subscribe(thermostatDevice, "thermostatOperatingState", pushLatest)
211     subscribe(thermostatDevice, "temperature", pushLatest)
212 }
213
214 /**
215  * The uninstall event will be pushed to a WeatherBug Home Service to notify the system to take appropriate action.
216  * Data that will be sent includes the list of devices, and location data
217  * Privacy Policy: http://weatherbughome.com/privacy/
218  */
219 def uninstalled() {
220         log.trace "uninstall entered"
221     def postParams = [
222         uri: 'https://smartthingsrec.api.earthnetworks.com/api/v1/receive/smartapp/delete',
223         body:  [ 
224                 "Devices": devices, 
225             "Location":[
226                 "Id": location.id, 
227                 "Latitude":location.latitude,
228                 "Longitude":location.longitude,
229                 "ZipCode":location.zipCode,
230                 "Name":location.name
231             ]
232        ]
233     ]
234     sendToWeatherBug(postParams)
235 }
236
237 /**
238  * This method will push the latest thermostat data to the WeatherBug Home Service so it can store
239  * and display the data to the WeatherBug user.  Data pushed includes the thermostat data as well
240  * as location id.
241  * Privacy Policy: http://weatherbughome.com/privacy/
242  */
243 def pushLatest(evt) {
244         def unixTime = (int)((new Date().getTime() / 1000))
245     def device = thermostatDevice.find{ it.id == evt.deviceId}
246     def postParams = [
247         uri: 'https://smartthingsrec.api.earthnetworks.com/api/v1/receive',
248         body: [
249                 DeviceId: evt.deviceId, 
250             LocationId: location.id,
251             ReportType: 2, 
252             ReportList: [ 
253                         [Key: "Temperature", Value: GetOrDefault(device, "temperature")], 
254                 [Key: "ThermostatSetpoint", Value: GetOrDefault(device, "thermostatSetpoint")],
255                         [Key: "CoolingSetpoint", Value: GetOrDefault(device, "coolingSetpoint")],
256                         [Key: "HeatingSetpoint", Value: GetOrDefault(device, "heatingSetpoint")],
257                 [Key: "ThermostatMode", Value: GetOrDefault(device, "thermostatMode")],
258                 [Key: "ThermostatFanMode", Value: GetOrDefault(device, "thermostatFanMode")],
259                 [Key: "ThermostatOperatingState", Value: GetOrDefault(device, "thermostatOperatingState")]
260                 ], 
261             UnixTime: unixTime
262         ]
263     ]
264     log.debug postParams
265     sendToWeatherBug(postParams)
266 }
267
268 /*
269 * This method attempts to get the value of a device attribute, but if an error occurs null is returned
270 * @return The device attribute value, or null
271 */
272 def GetOrDefault(device, attrib)
273 {
274         def val
275         try{
276         val = device.latestValue(attrib)
277     
278     }catch(ex)
279     {
280         log.debug "Failed to get attribute " + attrib + " from device " + device
281         val = null
282     }
283     return val
284 }
285
286 /*
287 * Convenience method that sends data to WeatherBug, logging any exceptions that may occur
288 * Privacy Policy: http://weatherbughome.com/privacy/
289 */
290 def sendToWeatherBug(postParams)
291 {
292         try{
293         log.debug postParams
294         httpPostJson(postParams) { resp ->
295                 resp.headers.each {
296            log.debug "${it.name} : ${it.value}"
297         }
298         log.debug "response contentType: ${resp.contentType}"
299         log.debug "response data: ${resp.data}"
300         }
301         log.debug "Communication with WeatherBug succeeded";
302     
303     }catch(ex)
304     {
305         log.debug "Communication with WeatherBug failed.\n${ex}";
306     }
307 }