If you get a 503 response right away but just need to wait a minute (or so) before trying again, and you were in a SmartApp, you could implement logic something like this:
def wakeUpCar() {
try {
httpGet(uri: 'http://website.com/foo') { response ->
log.debug "Response status: ${response.status}"
}
} catch (groovyx.net.http.HttpResponseException e) {
def status = e.response.status
if (status == 503) {
// Call getCarData in 90 seconds
runIn(90, "getCarData", [overwrite: false])
}
}
}
def getCarData() {
try {
httpGet(uri: 'http://website.com/foo') { response ->
log.debug "Response status: ${response.status}"
}
} catch (groovyx.net.http.HttpResponseException e) {
def status = e.response.status
// Wait long enough to make this code unreachable.
}
}
This would only function within a SmartApp, however, as our scheduling code hasn’t been ported over to DeviceTypes yet.
Since there’s not a way to do this in a DeviceType, you’re going to need to reorganize your code into what we call a “service manager” SmartApp, along with an accompanying DeviceType that is probably a bit simpler than your current DeviceType; that’s the pattern we follow for our Cloud-Connected Devices (DropCam, WeMo, Sonos, etc), as it allows for things like multi-page device setup and discovery scenarios that require the user to wait for a minute or more, which you may need if the initial GET /vehicles call gives you a 503. If you’re in our IDE and click “Browse SmartApps”, you can check out DropCam (Connect) and Wemo (Connect) source code to get a taste of what that would be like. You would use a SmartApp to manage the collection of Tesla user credentials, then once you’ve received that, you can issue a HTTP request to get a list of Teslas (GET /vehicles). The SmartApp can be configured with a “refreshInterval” that tells our mobile apps to keep asking for a particular page in the SmartApp, and once a response finally comes back from the Tesla API, your page will allow the user to confirm creation of your Tesla device(s), and you will create a child device from within the SmartApp which has all the information it needs to function. The Tesla DeviceType would then mostly delegate to the parent on lock and unlock commands (and handle tile rendering for our “Things” view, in addition to Capability declarations, which allow other SmartApps to use the Tesla anywhere the Lock capability is asked for). It might end up being something like the following (this is a skeleton and requires implementation details):
SmartApp: Tesla (Connect)
preferences {
page(name: "loginToTesla", title: "Tesla", nextPage: "listAvailableTeslas") {
input("username", "text", title: "Username", description: "Your TeslaMotors.com username")
input("password", "password", title: "Password", description: "Your TeslaMotors.com password")
}
page(name: "listAvailableTeslas", title: "Tesla")
}
def listAvailableTeslas() {
// Make call to Tesla API to discover available Tesla vehicles.
// Handle 503 response and reissue request if necessary.
// Store them in state.vehiclesDiscovered, which will make them show up on this page.
getVehicles()
def vehiclesDiscovered = state.vehiclesDiscovered
dynamicPage(name: "listAvailableTeslas", refreshInterval: 5) {
section("Select a vehicle...") {
input "selectedVehicles", "enum", required:false, title:"Select Tesla Vehicles \n(${vehiclesDiscovered.size() ?: 0} found)", multiple:true, options: vehiclesDiscovered
}
}
}
def installed() {
selectedVehicles?.each { vehicle ->
// Vehicle should have both the VIN and vehicle id, so you can possibly use either for our DNI (3rd argument, a unique Device Network Identifier)
addChildDevice("reese", "Tesla", vehicle.vin, null, [label: "My Tesla", data: ["vin": vehicle.vin, "vehicleId": vehicle.vehicle_id]])
}
}
def lock(vehicleId) {
// Make call to Tesla API to lock vehicle
}
def unlock(vehicleId) {
// Make call to Tesla API to unlock vehicle
}
DeviceType: Tesla (needs a namespace of “reese” and name of “Tesla” for the SmartApp above to be able to find it)
def lock() {
parent.lock(device.currentValue("vehicleId"))
}
def unlock() {
parent.unlock(device.currentValue("vehicleId"))
}