2

I cannot get my code to set the target temperature (in Android). The code I show below receives an OK status (200) along with the current temperature as the payload. I would expect to have received the new temperature I wrote (65degF). I am using the url:

https://developer-api.nest.com/devices/thermostats/THERMOSTAT-ID/target_temperature_f?auth=AUTH CODE

with my thermostat id and authentication code in place. I also have read and write permissions for my client. When I execute a similar request in a Chrome extension I have, the temperature gets set correctly on the thermostat. Can anyone pinpoint what I'm missing here? Commented out code shows a couple of the things I've tried.

Thanks.

    InputStream is = null;
    String result = "";

    try{

        HttpClient httpclient = new DefaultHttpClient();
        HttpPut httpPut = new HttpPut(url);
        httpPut.addHeader("Content-Type", "application/json");
        httpPut.addHeader("Accept", "application/json");
        //httpPut.addHeader("Connection", "keep-alive");
        httpclient.getParams().setBooleanParameter("http.protocol.expect-continue",false);
        //value.setContentType("application/json");
        httpPut.setEntity(new StringEntity("65");
        HttpResponse response = httpclient.execute(httpPut);
        HttpEntity entity = response.getEntity();
        is = entity.getContent();
        int statusCode = response.getStatusLine().getStatusCode();
        Log.d("StatusCode",Integer.toString(statusCode));

    }catch(Exception e){
        Log.e("log_tag", "Error in http connection "+e.toString());
    }

    // Convert response to string
    try{
        BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        is.close();
        result=sb.toString();
        Log.d("Result",result);
    }catch(Exception e){
        Log.e("log_tag", "Error converting result "+e.toString());
    }
Richard Ev
  • 52,939
  • 59
  • 191
  • 278

4 Answers4

0

This is what I run to change the temperature:

curl -v -L -X PUT "https://developer-api.nest.com/devices/thermostats/<THERMOSTAT ID>/target_temperature_f?auth=<AUTH CODE>" -H "Content-Type: application/json" -d "65"

Could you try modifying your header to look more like what I ran? My only other guess is that target_temperature_f is an integer and it's not being passed as an int.

jfudgeelder
  • 423
  • 3
  • 13
  • I'm not sure how I could edit my header to look anymore like yours. I already have the Content-Type set. As to your second suggestion, I wonder if there's a way to transmit as an int? I know it's a string entity now, but perhaps there's some kind of int entity? I'll see if I can dig anything up. update: No way to differentiate between string or int that I could find – user3822689 Jul 11 '14 at 02:37
  • 1
    StringEntity works fine. You should be able to set the value with it. – Nagesh Susarla Jul 11 '14 at 16:56
0

The value must be passed as an int (F) and half-float (C).

Lev
  • 11
  • 2
0

Can you please tell us what response/code you get back?

Update: It looks like you're using this on Android. I would recommend using HttpsURLConnection on android. Here is an example with HttpsURLConnection

    public static int setThermostatTemperatureF(int temperatureF, String apiUrl) {
      HttpsURLConnection.setFollowRedirects(true);
      BufferedReader reader = null;
      try {
        URL url = new URL(apiUrl);
        HttpsURLConnection ucon = (HttpsURLConnection) url.openConnection();
        ucon.setRequestProperty("Content-Type", "application/json");
        ucon.setRequestMethod("PUT");
        ucon.setDoOutput(true);
        // Write the PUT body
        OutputStreamWriter writer = new OutputStreamWriter(ucon.getOutputStream());
        writer.append(Integer.toString(temperatureF));
        writer.flush();

        return ucon.getResponseCode();
      } catch (MalformedURLException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }
      return -1;
    }

Previous answer: From the code it looks like you may not be following the redirect that is returned by developer-api.nest.com. With HttpClient 4.2 and above you can use the following Redirect Strategy to ensure that the temporary redirect is being followed.

        httpClient.setRedirectStrategy(new DefaultRedirectStrategy() {
          @Override
          protected boolean isRedirectable(String method) {
            return HttpGet.METHOD_NAME.equals(method) ||
                    HttpPut.METHOD_NAME.equals(method);
          }
        });

If you are using an older version then you'd have to implement a redirect handler. Let me know if you need a version of that and I can provide it.

Nagesh Susarla
  • 1,660
  • 10
  • 10
0

You cannot write the target temperature under certain conditions. see the page https://www.developer.nest.com/documentation/error-codes#targettemp for the rules.

Like: you cannot save the target temperature when:

  • the home is in 'away' mode.
  • emergency heat is in use.
  • the hvac is in 'off' mode.
  • the smoke detector has tripped the safety shut-off.
Richard Ev
  • 52,939
  • 59
  • 191
  • 278