Nest Thermostat Hot Water controlled by Alexa

Share the joy
  •  
  •  


For anyone that has a Nest thermostat and an Amazon Alexa, they will know there is one feature distinctly lacking. Voice boosting of the hot water. After further investigation, this is not only missing from he Alexa app but is missing from the actual API. I think that this is probably due to the function being UK only.

Initially I took to the community pages to get more information. The first post dates back to Oct ’16 and the official line was “Thanks for letting us know that this is an important feature. Duly noted! We have communicated the extremely strong interest to our development team. The request is in the queue for consideration and will be seriously considered. We value your input, and we do not discuss future schedules or internal planning in this community.” This was mid August some time. Request #1 got closed for comments and so did all other threads. #2, #3 and finally #4. As a result of this I decided to make my own.

If you want to do this, you will need the following:
– Amazon Alexa
– UK Nest Thermostat (and online account)
– IFTTT account
– Webspace to host some php files

The basics of how this works are as follows:
1. Ask Alexa to trigger an IFTTT applet. By saying “Alexa trigger …..” Alexa knows that the following commands will be passed to IFTTT. My phrase was “Alexa trigger hot water boost” Thats the IFT part.
2. Configure the applet to use webhooks that will open a php file on a server. That’s the TT part.
3. The php file calls the class and boosts the hot water for a defined time. My aim was to make this as easy to follow as possible.

The drawback of this in its current state is that there is no feedback from Alexa if it has work or even if you have said the correct thing. Any time you say “Alexa trigger ….” she responds with “sending request to IFTTT” and doesn’t even know if there is an applet that matches you request.

As a bit of a disclaimer, I have only tested on a single UK Nest on my account so cannot guarantee that it will work with any others. Provided as is with no warranty etc. Feedback would be greatly appreciated either in the comments or on GitHub.

I have everything I need, how do I do it?
Step 1: Download the files (or fork) from Github. -> https://github.com/rdiver/nest-php-api-hot-water
Step 2: Edit the example files, setting a random key and enter your nest username and password. Then upload them with the class to your webspace and make a note of the url. The key variable is purely for security reasons, so that even if someone knows the url, they cannot do anything without the key, which can be any random character set. (within reason, I would stick to A-Z a-z 0-1)
Step 3: Link Alexa and IFTTT. -> https://www.amazon.com/gp/help/customer/display.html?nodeId=201790640
Step 4: Create the applet. Its pretty easy, screen 6 outlines the options to pass the key to your web page. The example code does output all of the calls to the web pages to a file called test.txt to make it easier to debug.
(1) (2) (3)
(4) (5) (6)

Step 5: Ask Alexa to “trigger hot water boost”!

Technical Information (incase anyone wants to port to different language)
If you ended up here you probably came through the Nest Community pages where you were searching regarding the lack of Hot Water API exposure. I know that not everyone will want to use PHP so I’m going to try and break down the basics of the reverse engineering so that you can port the code to another language / platform. This is only my understanding and could totally be wrong!

So basically I worked backwards. I started by looking at the calls for boosting the hot water and found this.

As highlighted in red, I need several things to boost the hot water. Firstly I need the request url, which is also referred to as the transport url. This was already covered in the library I forked but it can be found when you log in.
Secondly I need to create the payload that can be seen above.
session: From reading this post I worked out that the session variable was not required.
op: MERGE – this is fixed.
hot_water_boost_time_to_end: This is the epooch time that you would like the boost to end.
base_object_revision & object_key: object_key is the id of your nest thermostat, and my understanding is that the website creates a snapshot of the device settings used by the website called base_object_revision. After searching through the requests (for a long time) I found one that looked promising. The website makes the following call which returns the information I need.

From the code you will see that I only request the device bucket meaning I only get the information that I need.

I tried to make the code as simple as possible, so it will be easy to use or replicate/port. Any questions please ask.

74 Comments

  • hey there. great post, something I’ve been wanting for over a year!

    I’m trying to convert to python. My first request works fine and I get the userID etc, but the second request to get the bucket data fails with a 401 unauthorized. You don’t appear to be using an authenticated connection when you do it? any ideas whay might be going wrong? I don’t know PHP – you’re posting a json payload aren’t you?
    thanks

  • Jon Andrews

    excuse the simple question…but I love that someone has been able to take what NEST cant be bothered to do and brought the much-needed functionality to the system

    I personally don’t have any web space open to me so was wondering if it is possible to host these files on a local computer, specifically an Rpi as I already have one running HA Bridge that is both running 24/7 AND a low-cost small device taking up no room

    Thnks in advance

    Jon

    • rdiver

      Hi Jon, from a quick read I think the ha-bridge may do it for you without IFTTT. But I could be wrong.
      You could in theory, put the PHP files onto the raspberry pi so that they are accessible from a url. such as http://192.168.0.11/somefolder/boostfiles.php and then add it as a custom device.
      From https://github.com/bwssytems/ha-bridge it says:
      “The Add/Edit Tab

      Another way to add a device is through the Manual Add Tab. This allows you to manually enter the name, the on and off URLs and select if there are custom handling with the type of call that can be made. This allows for control of anything that has a distinct request that can be executed so you are not limited to the Vera, Harmony, Nest or other Hue.”

      So my understanding is you could get it to call he local php files on the pi and execute through Alexa that way. Does that make sense? I’ve never used ha-bridge so the info is the result of a quick google. Hope it helps.

      • Jon Andrews

        in the process of getting this to work with HAB, I’ve installed the required files and also created the required boost.php module.

        Im not sure if I’m doing something wrong but I cannot work out how to trigger the PHP module from a command line (within my rPi) to make sure it’s working (before progressing). When I try to execute it, It responds saying access denied if I don’t append the preset key onto the command….but if I put the key on the end it doesn’t recognise the module to be run.

        Im sure Im doing something silly wrong, but as programming, in general, isn’t really my thing Im happy to put my hands up and ask for some assistance.

        • langstroth

          I can confirm the ha-bridge method does work if you don’t want to host the PHP files remotely. Essentially
          HA-Bridge (which simulates Phillips lightng hub) —-> web server ——> call to Shell script ——–> PHP script.

          In theory the bridge can call the PHP directly, but I couldn’t get it to work, so went down the shell script and simple web server (web.py) route. The set up is running on a Pi that I already had running monitoring a weather station and solar panels.

  • slicker55

    I have tried to follow these instructions very carefully but sadly, after several attempts I cannot get things to work. Alexa refers the trigger to IFTTT but the thermostat does not respond. I suspect it’s down to where my files are being hosted. Can anyone recommend a tried and tested on-line service which is free?

  • A BIG thanks to rdiver for sharing your expertise and taking the time to explain everything so clearly.
    I followed your instructions very carefully and now I can control my hot water boost using voice commands via Alexa – FANTASTIC WORK!

    • rdiver

      Glad it worked. Mines still going strong, I’m assuming that if they can be bothered to implement this, it’s unlikely they will fix my way.

  • Robert Bradley

    Fantastic implementation

    My use case is a little different, I use Home Assistant with this api to display current status and a switch to boost when needed.

    I have a bash script that invoked the call to php.

    The issue comes in that home assistant regularly checks the boost time remaining and the on off status. Nest are wise to us hammering the website and block you temporarily.

    I have witnessed this while using the api and have the error. You could test it by asking Alexa the status of the hot water a few times in a row, or running the php script a few times – though a browser probably has some sort of cookie or session persistence.

    My question: is it possible to reuse the cookie / auth key from the initial request between script calls.

    Eg a check to see if a valid cookie exists if not generate a new one

    Maybe the blocking is not the cookie and maybe it’s done on connection(DDOS protection), just a thought

    • rdiver

      Hi Rob, if you could keep the php call open then I don’t see why you couldn’t just keep calling the methods using the initial auth. PHP isn’t really suited to this though as it will timeout.


      $nest = new Nest($uname,$pwrd);
      while(1) {
      $status = getHotWaterStatus();
      sleep(10);
      }

      This would constantly poll.

  • Will P

    Hi rdiver – many thanks for this guide.

    A quick question, I’ve managed to get this set up and can hit the URL’s and receive a HTTP 200 response.

    The thing is, the boost doesn’t always come on. The same happens with my cancel boost command, I’ll get the HTTP 200 response but it didn’t actually cancel it.

    I’ve got IFTTT but at the moment I am just hitting the url in a browser to see if I can get it working but its only working now and again.

    My set up is a little different in that I have 2 nests set up on the account, one for downstairs and hot water and one for upstairs.

    On some occasions this error is thrown:

    [01-Sep-2018 16:36:16 UTC] PHP Fatal error: Uncaught exception ‘Exception’ with message ‘Error during GET of ‘/v2/mobile/user.’: malformed’ in /home/anotheri/public_html/nest/nest-php-api.php:117
    Stack trace:
    #0 /home/anotheri/public_html/nest/nest-php-api.php(84): Nest->curlGet(‘/v2/mobile/user…’)
    #1 /home/anotheri/public_html/nest/nest-php-api.php(63): Nest->getHotWaterStatus()
    #2 /home/anotheri/public_html/nest/cancel_hot_water.php(19): Nest->setHotWaterBoost(0)
    #3 {main}
    thrown in /home/anotheri/public_html/nest/nest-php-api.php on line 117

    Any ideas?? I should caveat all of this by saying I’m not an engineer or a dev!

    • rdiver

      Hi Will, when writing I do remember noting that I was not sure how it would work with 2 nests. I think you could get round this by fixing the device id.
      If you add print_r($response); to line 41 of nest-php-api.php file, and post it I might be able to offer some advice.

      • Will P

        Hi rDiver, only coming back to this now. I managed to find on a thread in the nest forum that if I changed these lines and the value from 0 to 1, it works for when you have more than one thermostat!

        $this->deviceid = $response[‘updated_buckets’][1][‘object_key’];
        $this->object_base_id = $response[‘updated_buckets’][1][‘object_revision’];

        Seems to be working the last few times I’ve tried it. Unlike originally last year when it kept working intermittently.

        Would this make sense as to why it’s working this time or just dumb luck?

        • rdiver

          I have though about updating this to a constant at the top. No reason why this works now and didn’t work before. This is the way to access a second nest.

  • Adam

    Hi all,

    I’ve found a way to do this without using IFTTT or hosting anything. Might be an alternative to some?

    First purchase the Sonoff Basic – ​https://www.amazon.co.uk/Switch-Automation-Wireless-Control-Android/dp/B077G7FNBJ/ref=mp_s_a_1_1?ie=UTF8&qid=1536646148&sr=8-1&pi=AC_SX236_SY340_FMwebp_QL65&keywords=sonoff+basic&dpPl=1&dpID=51axPVgclDL&ref=plSrch

    Now you’ll need to give the relay a permanent supply on the input terminals but your heatlink has this already.​ Then if you follow the cable from terminal 6 of your heatlink you should find that this will connect onto the brown conductor of your hot water pump. We want to install a cable from the output of the relay to this brown core on the hot water pump (you need to keep the cable from terminal 6 installed to this core as well). This then enables the relay to energise the motor within the pump and close the connection required to turn on your hot water.

    You’ll need to install the Ewelink app and set the device up within the app, which is very simple (please note that the Sonoff connects to the 2.4ghz frequency of your router). I of course named the relay Hot Water.

    Once the app is installed you need to go into the loop timer on the bottom right​. Untick “after” and then set the time to your desired boost time in my case 1hour.

    At this stage you can test the cabling and the device are working by manually turning the relay on and off within the app. I set my boost time to 2 minutes whilst testing to ensure the relay was turned off.

    Lastly you’ll need to go into your Alexa app and install the Ewelink skill and link your account. Then add devices within the Alexa app and hey presto! “Alexa, turn on the Hot Water” and it will turn off after your pre-defined time.

    As above the Boost won’t register on the Nest as we are bypassing it.

    If anyone needs any help just let me know!

    • rdiver

      Yes this would also work. I thought about something similar for my bathroom lights as they have a fan so hue bulbs wouldn’t work. The caveat with this is it requires knowledge of (and competency with) mains electricity and this is very different to a coding solution.

  • Alan

    Hi,

    I have php 5.6.0 running in IIS on an old windows home server.
    When running the script, I get the below error in the php log (and 500 error in browser) – any idea what the problem is?

    php-api.php(63): Nest->getHotWaterStatus()
    #2 C:\example_boost_hot_water.php(18): Nest->setHotWaterBoost(60)
    #3 {main}
    thrown in C:\nest-php-api.php on line 117

    [16-Sep-2018 15:08:36 Europe/Minsk] PHP Notice: Trying to get property of non-object in C:\Program Files\Windows Server\Bin\WebApps\Site\Water\nest-php-api.php on line 30
    [16-Sep-2018 15:08:36 Europe/Minsk] PHP Notice: Trying to get property of non-object in C:\Program Files\Windows Server\Bin\WebApps\Site\Water\nest-php-api.php on line 31
    [16-Sep-2018 15:08:36 Europe/Minsk] PHP Notice: Trying to get property of non-object in C:\Program Files\Windows Server\Bin\WebApps\Site\Water\nest-php-api.php on line 32
    [16-Sep-2018 15:08:36 Europe/Minsk] PHP Notice: Trying to get property of non-object in C:\Program Files\Windows Server\Bin\WebApps\Site\Water\nest-php-api.php on line 32

    [16-Sep-2018 15:08:36 Europe/Minsk] PHP Fatal error: Uncaught exception ‘Exception’ with message ‘Error during GET of ‘/v2/mobile/user.’: malformed’ in C:\nest-php-api.php:117
    Stack trace:

    #0 C:\nest-php-api.php(84): Nest->curlGet(‘/v2/mobile/user…’)

    #1 C:\nest-php-api.php(63): Nest->getHotWaterStatus()

    #2 C:\example_boost_hot_water.php(18): Nest->setHotWaterBoost(60)

    #3 {main}
    thrown in C:\nest-php-api.php on line 117

      • Alan McCormick

        I thought that but curl appears fine (tried a few test scripts).

        phpinfo shows:

        cURL support enabled
        cURL Information 7.36.0

        and curl works from a cmd:

        C:\Users\Administrator>curl –version
        curl 7.61.1 (i386-pc-win32) libcurl/7.61.1 OpenSSL/1.1.1 (WinSSL) zlib/1.2.11 br
        otli/1.0.6 WinIDN libssh2/1.8.0 nghttp2/1.33.0
        Release-Date: 2018-09-05
        Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s
        rtsp scp sftp smb smbs smtp smtps telnet tftp
        Features: AsynchDNS IDN IPv6 Largefile SSPI Kerberos SPNEGO NTLM SSL libz brotli
        TLS-SRP HTTP2 HTTPS-proxy MultiSSL

        Time to buy a synology I think…

        • rdiver

          Ok, just had another look at your error.
          It looks like the $json doesn’t have a value and as such doesn’t get decoded.
          If you add a print_r($json) or a var_dump($json) at line 28, what does it say? (Maybe sanitise before posting!) I’m guessing that it doesn’t contain the access_token, or userid, or urls fields.

          This would lead me to believe there is a problem with the curlPost on line 24. Invalid username and password?

  • David Evans

    Hi all,

    I completed to above and works great. Where i stepped away from the above instruction was to in integrate with Smart things rather than IFTTT. This is actioned via a customer Device Handler (URI Button) which you load on via the IDE portal.

    This allows for a button on Action Tiles to be created while to can continue to use Alexa. You could also link it to a simple Z wave / Zigbee push button also.

    I also created a bespoke routine on my Alexa account so i can just say, ‘Alexa, Boost Hot Water’. Excellent work by rdiver

    Thanks

    • rdiver

      Hi David, any advice on where to look for details on creating a bespoke routine for Alexa? Boost hot water seems much better than trigger hot water boost. Would be great if I could ask Alexa if the hot water is on too!

  • cephalopod

    It’s working fantastic now, thank you so much for all your efforts! Some feedback…
    1. I had to add timezone to the DateTime call in the supplied example PHP code, or I had fatal errors causing 500s.
    2. Is there any way of using tokens or such to call the Nest API, instead of putting Nest account credentials in a PHP file which can downloaded off the website?…. bit worried about security 🙂

    Cheers rdiver!

    • rdiver

      For 1, something that I didn’t really think about was time zones, my understanding was that it ran off UTC time. Can you share your changes?
      For 2, I don’t know, I am essentially exploiting scripting of the web app, as the official API doesn’t open up hot water.
      If you were bothered, you could have the username and password passed with the call as its https.
      You could also encrypt the username and password and pass a key to make it easier. I mean non are ideal, but by passing a decryption key its only one thing to pass with the time. openssl_encrypt would probably be a good place to start.

  • Reggs11

    Just wanted to say thanks to Rdiver for this great script!
    I run a Homeseer home automation system on a dedicated windows box at home.
    There is a $30 Nest plugin available that has always lacked the ability to boost hot water (and now I understand why) to the lament of all of us UK users.
    The same Homeseer box also runs HA Bridge, so that I can run pretty much any Homeseer event with a simple call to Alexa.
    All I did to get this running was to install XAMPP server and then I created some of my own PHP scripts based on your own.
    I don’t know PHP and had to remove the ‘$access_key’ checks as none of the scripts would run (missing token error) as I assume they are for IFTTT?
    Anyway, everything is hosted locally so I then created a simple HA Bridge event so that I can say ‘Alexa, turn on the hot water’ and
    the hot water will boost for as long as I have it set to boost for in the relevant PHP script that gets called directly.
    HA Bridge can handle ‘offs’ as well very easily with direct PHP script calls.
    Great stuff Rdiver!

    • rdiver

      Hi Reggs11, thats great! Glad it worked.

      The access_key part was a validation to ensure that when the page is called, it can only be called with someone who knows the access key. Kind of like how you can only see private youtube videos or dropbox files with a link.
      The idea being, you randomly generate a key on something like https://passwordsgenerator.net that has only letters and numbers… say “g4yKkraOWtH3xHiV”. Put this as the access_key variable on the php page.
      Then when you call the page, you would do http://www.page.com/path/example_boost_hot_water.php?key=g4yKkraOWtH3xHiV and that would allow only that link to access the page. Hope that makes sense.

      It not fully secure as if not using https there are ways to get urls. Its just better than a blank URL if its being hosted on the internet and not locally.

  • Rich Simpson

    Really want to get this to work, have the files hosted and they are throwing an error 500. The key is ok (without it I get different error)

    Error log is:
    [29-Nov-2018 15:03:33 UTC] PHP Fatal error: Uncaught exception ‘Exception’ with message ‘Error during GET of ‘/v2/mobile/user.’: malformed’ in /home/******/public_html/richnest/nest-php-api.php:117
    Stack trace:
    #0 /home/********/public_html/richnest/nest-php-api.php(84): Nest->curlGet(‘/v2/mobile/user…’)
    #1 /home/********/public_html/richnest/nest-php-api.php(63): Nest->getHotWaterStatus()
    #2 /home/*******/public_html/richnest/boost_hot_water.php(22): Nest->setHotWaterBoost(60)
    #3 {main}
    thrown in /home/********/public_html/richnest/nest-php-api.php on line 117

    Any idea where I am going wrong?

    • rdiver

      Hi Rich, just looking it appears I didn’t throw an error at curlPost so it could also be failing before that. If you add

      if(curl_errno($ch) != 0)
      {
      throw new Exception("Error during GET of '$url': " . curl_error($ch));
      }

      to link 147. So after the curl_exc I would guess the error moves to there. But this doesn’t really matter.
      Malformed means that the url (or package) wasn’t correct. My guess is that the login is incorrect.
      One way to check this would be to add print_r($this->deviceid); to the end of the public function __construct.
      Then you should see something along the lines of device.09BB01AC43242FFU. If not there is something wrong with the login.

      UPDATE: I have just tested with bad login details and I get the following:
      Fatal error: Uncaught exception 'Exception' with message 'Error during GET of '/v2/mobile/user.': malformed' in /nest-php-api.php:117 Stack trace: #0 nest-php-api.php(84): Nest->curlGet('/v2/mobile/user...') #1 /nest-php-api.php(63): Nest->getHotWaterStatus() #2 /cancel_hot_water.php(21): Nest->setHotWaterBoost(0) #3 {main} thrown in /nest-php-api.php on line 117

      So I would guess that is your problem.

      UPDATE 2: I have updated the github file to add better error checking for login failure. Would be worth a try first.

      • Rich Simpson

        Hi, and thanks for looking at this with me! I get a user error but the login email and password is 100% correct. I wondered if it is because it uses special characters like $or%? But when I tried to change it the password has to include special characters.

        The error log says:

        [11-Dec-2018 12:39:43 UTC] PHP Fatal error: Uncaught exception ‘Exception’ with message ‘Login error {“error”:”access_denied”,”error_description”:”invalid user credentials”,”instance_id”:”776ac579-bae3-4a40-9d94-87faab4344d9″}’ in /home/sharpeso/public_html/richnest/nest-php-api.php:30
        Stack trace:
        #0 /home/sharpeso/public_html/richnest/boost_hot_water.php(20): Nest->__construct(‘richard.simpson…’, ”)
        #1 {main}
        thrown in /home/sharpeso/public_html/richnest/nest-php-api.php on line 30

        • rdiver

          Hmm…. my password contains a $ but this is ignored as long as you dont use ” (quotation marks) around the password. Single ones ( ‘ ) ignore special characters. Are you using single or double for the password?
          Alternatively if using double quotes you could escape the character. So basically add a \ .. pa\$\$word for example.

          • Rich Simpson

            Ah it began with a $ and was in “$***********” changed to a different password without a character (thought nest insisted you had one but had read that incorrectly) and it’s working. Brilliant!!! Thank you so much for looking at the comments mate

  • Gary

    Hi rdiver,

    I am hoping you can help. I have followed the instructions but i cannot get the Alexa part working.
    I have hosted the files on infinity free and i can confirm when i copy the URL into a browser it executes the nest hot water command and i get {“success”:true,”code”:200,”data”:”Boom, hot water changed. Or you set it to the same as before.”} and its fine and the water boosts…. However when i try and tie this into the IFTTT webhook nothing seems to happen. Alexa accepts the command, the activity log shows it runs and there is no error however the nest does nothing.
    The IFTTT and alexa are working together as i tried a nest trigger command but for some reason i cant get this webhook trigger to work.
    I would be very grateful if you could provide some help on how i can get this 2nd part working.
    Many thanks

    • rdiver

      The only thing I can think is the content type is wrong. For mine it is application/x-www-form-urlencoded. I have updated image (f) to reflect that in the post.
      This allows the passing of the key for security purposes. Did this work?

  • Gary

    Hi rdiver,
    Thanks for responding, I appreciate your time.
    I’ll tried application/json content type as I could see that in the php files but I havnt tried the other content type so will give it a whirl.
    My URL is
    http://alexawilson.epizy.com/boost_hot_water.php?key=
    Does that look about right to you? There is no ingredient or anything I else I need to put? Its a standard GET command.
    Do you know of anything that IFTTT webhooks might need that I could be missing?
    Thanks

    • rdiver

      Hi Gary, if you don’t use application/x-www-form-urlencoded then I don’t think the key gets correctly passed / processed so it wont work. I’m almost certain that if you change that it will work.

      • gary

        Hi rdiver,
        So I tried change the application but no joy. I have tried everything but I just cannot get it working? ive tried testing the webhook via the webhook tester site and setting up a “trigger test” applet from Alexa and I get pings so it can execute the applet from my account by Alexa. I have tried coping the URL directly from the IFTTT applet into the webrowser and when I hit enter the hot water boost kicks in. I have copied everything exact but I don’t know why I can execute the command directly through the URL but cannot execute it through IFTTTT applet it is really frustrating!!

  • Gary

    I would never have even thought about that, thank you finding out for me.
    Do you think this is common on most free web hosting accounts? What other options do I have in terms of hosting sites/applications?? I have google drive but have heard that you can’t execute from a google drive? Is there any other free type services that you use/know of that I could look at?
    Thanks

    • rdiver

      Sorry Gary, I’m at a bit of a loss. You could set up a dynamic dns and then run it from a raspberry pi or similar on your own network. This would require port forwarding on your router though.

    • rdiver

      Hi Gary, I had a play with google app cloud and it could be done on this free for a year. No idea what the cost would be after that though.

  • Ade

    Hi rdiver,

    Thank you very much for developing this script, I have used it reliably for controlling my hot water without any issues. However I am now looking at migrating it to run on Google App Engine and have noticed that when executing the boost script, it appears to work correctly and turn on the hot water but the “getHotWaterStatus” function doesn’t appear to return correctly and returns a null value, thus resulting in the return message stating “For some reason, the hot water was not changed”.

    Through my troubleshooting and with my limited php knowledge, this is as far as I’ve narrowed it down to. I tried adding a 10 second sleep between the request to boost and the status check, in case it was a delay in returning the status but this didn’t help.

    I also noticed in the server logs that it kept reporting “PHP Notice: Undefined index: device in nest-php-api.php on line 93” which corresponds to “return array(“hot_water_active”=>$json[‘device’][$device_serial][‘hot_water_active’],”hot_water_boost_time_to_end”=>$json[‘device’][$device_serial][‘hot_water_boost_time_to_end’]);”

    While this does not affect the functionality, I was hoping to leverage the status check in adding some more functionality if possible, to confirm the status back through Alexa, so any ideas about how to fix this would be appreciated.

    Thanks.

    • rdiver

      Hi Ade, I had a play with google app cloud and it worked fine for me. Do you have more than one nest?

      The files I used were….

      app.ymal
      runtime: php55
      api_version: 1
      handlers:
      # Serve images as static resources.
      - url: /(.+\.(gif|png|jpg))$
      static_files: \1
      upload: .+\.(gif|png|jpg)$
      application_readable: true
      # Serve php scripts.
      - url: /(.+\.php)$
      script: \1

      php.ini
      ; This is a simple php.ini file on App Engine
      ; It enables output buffering for all requests by overriding the
      ; default setting of the PHP interpreter.
      output_buffering = "On"
      extension=php_curl.dll

  • Ade

    Hi rdiver,

    Thank you for the prompt response.

    I only have one thermostat in my account and I was using a slightly different yaml but loading “curl.so” in the php.ini, so I thought to try all your files instead and I’m still able to reproduce the error.

    To clarify, I am testing the URL via a browser and viewing the json returned when the script is called. In each case, when the boost script is called it successfully turns on the hot water, but the returned value says an error occurred ({“error”:{“code”:400,”text”:”Bad Request”,”message”:”For some reason, the hot water was not changed”}})
    This doesn’t happen on the cancel script as it returns ({“success”:true,”code”:200,”data”:”Boom, hot water changed. Or you set it to the same as before.”}). Also, looking in the Stacktrace logs I am still seeing the warnings about using an undefined index.

    This is really odd if you aren’t able to reproduce these but any ideas on where next to look would be appreciated. Thank you once again for all your time, I really appreciate your help.

    • rdiver

      Hmmm…. now that is interesting because the cancel is just a set to 0. This leads me to believe that it’s an issue with the check on line 68.

      Set boost
      $return = $nest->setHotWaterBoost(60);

      Cancel boost
      $return = $nest->setHotWaterBoost(0);

      First I would try changing 0 on the cancel boost php to 30 and see what happens. If it stops working then I would try the following.

      Can you replace line 73 of nest-php-api.php
      from
      return json_encode($return);
      to
      $return = array_merge($return, $status);
      return json_encode($return);

      This will tell you what the getHotWaterStatus returns as part of the response.

  • Ade

    So, I tried your suggestion and changed the cancel boost value to 30 and sure enough, it began returning the same error. Changed it back to 0 and it returns success.

    I then modified the nest-php-api.php as you suggested and here are the results:

    1. Executing the cancel boost with value of 0:
    {“success”:true,”code”:200,”data”:”Boom, hot water changed. Or you set it to the same as before.”,”hot_water_active”:null,”hot_water_boost_time_to_end”:null}

    2. Executing the boost with value of 60:
    {“error”:{“code”:400,”text”:”Bad Request”,”message”:”For some reason, the hot water was not changed”},”hot_water_active”:null,”hot_water_boost_time_to_end”:null}

    It appears the hot_water-boost_time_to_end is not being retrieved correctly for some reason.

    • rdiver

      I’m really struggling here. The fact that it works on another php service, and I can’t replicate on my google app engine is really strange.

      Had another go and here is what I did.
      Created project (this must be linked to a billing account otherwise it wont work as I found, rules out the free version!)
      Choose europe-west2 server when prompted.
      Load files (including the php.ini and as I used the app.ymal https://cloud.google.com/appengine/docs/standard/php/config/appref)
      deploy
      run.
      For me it works, so unless I can debug your instance of it running I cant seem to recreate the issue. I could prob help with this but it would mean changing the nest password temporarily and adding me to your google app project.

      • Ade

        I don’t think it has to do with the app engine actually. I went and reviewed the contents of the test.txt document on my webserver where I’ve been running this till now, and found that ever since I started using the script it has been returning that message. I suppose I never noticed it because I only tested it via IFTTT and it worked.

        So I think it might have something to do with my nest account. Could you test creating a second user in your account and use those credentials to test the script? In my nest account I created a secondary user specifically for running the script, separate from my primary nest account login.

        • rdiver

          Hi Ade, yeah I can definitely try that but it might not be until the weekend. As an interim, if you could you try using your primary login account and tell me if that works? If so then we can narrow it down to the second account and I can find out why.

          • Ade

            So it looks like this is definitely the issue. Just tested using the primary user account and got the below. I appreciate the help in narrowing this down and identifying the cause.

            Boost:
            {“success”:true,”code”:200,”data”:”Boom, hot water changed. Or you set it to the same as before.”,”hot_water_active”:false,”hot_water_boost_time_to_end”:1545328696}

            Cancel:
            {“success”:true,”code”:200,”data”:”Boom, hot water changed. Or you set it to the same as before.”,”hot_water_active”:true,”hot_water_boost_time_to_end”:0}

  • malbry

    Hi,

    Thanks so much for this excellent solution. I have two thermostats and needed to change the following lines:

    $this->deviceid = $response[‘updated_buckets’][0][‘object_key’];
    $this->object_base_id = $response[‘updated_buckets’][0][‘object_revision’];

    from [0] to [1] to get it to work for my set-up.

    Also changed the following line:

    else $epooch = time() + (30 * $minutes);

    from 30 to 60 (I think that’s a bug?)

    Thanks so much again.

    • rdiver

      Glad it helped! I actually stopped looking at the Nest forums after I fixed it so never even realised that someone else had taken my work, changed the licence, introduced a new bug (that hasn’t been in any of my versions) and then posted it as their own! Don’t know if to be flattered or pissed off!

  • mkc

    Hi,

    This is almost exactly what I was hoping to find for my Nest, thanks.

    I found that Nest do sell a secondary temperature sensor but not in the UK and because the temperature can fluctuate so much in my poorly insulated upstairs I’ve found keeping the thermostat in one room just doesnt work without constant adjustment, so I thought a raspberry pi could save me some effort.

    Anyway… has anyone been able to use this approach to adjust the temperature? I’ve been trying the PUT request directly in postman but I keep getting a 400 error.

    The payload is:
    {“objects”:[{“base_object_revision”:-xxxx”object_key”:”xxxxxxxxxxxxxxx,”op”:”MERGE”,”value”:
    {“target_temperature”:18.6615}}]}

    With the authorization and content type application/json in the header. Any ideas would be great.

  • Hi,

    This works great if you don’t have 2-step authentication on but if you do (which is wise) then it can’t and doesn’t work.

    Any ideas how to deal with this?

    Thanks for your work so far!

    • rdiver

      Hi Chris, nope I’m fairly sure that there is no way what so ever to make this work with 2FA.

      Actually it may be possible as its an SMS message. You could use an IFTTT trigger to push the 2FA authentication SMS to the script.
      It is however, a second exploit on top of the first one. Much easier to make an account for Alexa and give it a ridiculously long random password. You could then look to encrypt the password and pass a decryption key as part of the authentication token. That way, the username and password would be encrypted in the php and be completely useless without the key. If that makes sense?

      I have also in the past, added an IP filter too, so that the page can only be executed by my home IP. Done through using a DDNS (no-ip etc) and http://php.net/manual/en/function.gethostbyname.php

      Although as I write this, I’m not sure I’ve looked at or resolved the not using a primary account issue.

  • malbry

    Hi again,

    I’m wondering if a recent Nest update has broken this solution? It was working for me, but now – without me changing anything – I get a 200 OK response but the hot water doesn’t turn on. Anyone else having difficulties?

    Thanks.

  • malbry

    Ignore my last comment. I’m running the PHP script on a RaspPi and, after rebooting the system, it started working again. Sorry for the false alarm.

  • gary

    getting this error trying to use your script
    “`Fatal error: Uncaught exception ‘Exception’ with message ‘Error during POST of ‘https://home.nest.com/user/login’: SSL certificate problem: unable to get local issuer certificate’ in F:\Ampps\www\nest-php-api.php on line 153“`

    is it no longer working? or have i done something wrong

  • Gaz

    Getting an error even after disabling 2FA

    Fatal error: Uncaught exception ‘Exception’ with message ‘Error during POST of ‘https://home.nest.com/user/login’: SSL certificate problem: unable to get local issuer certificate’ in F:\Ampps\www\nest-php-api.php on line 153

    Any ideas? Have I done something wrong?

  • slicker55

    @rdiver
    Your ingenious workaround has been faithfully working since July 2018 (see earlier post)
    However, earlier today I noticed that Tigger Boost no longer turns on the hot water.
    I disabled 2FA and all good again 🙂
    Is there any way to implement 2FA into your workaround?
    Thanks once again for an excellent piece of work 🙂

    • rdiver

      Sadly not. The point of 2FA is a human in the loop test. Usually tied to some hardware too.

      As Nest moves away from its api to the google home stuff, I might be able to change it but for now, it’s a workaround.

  • slicker55

    @rdiver

    Hello again,
    All was well until I forgot to revisit the hosting site and the free domain has now been archived.
    I have paid for one month ($3) to give me time to find an alternative free hosting and get it working again
    I recall you telling me that only certain hosting sites allow files containing the key at the end of the file name.
    How do find hosting sites which allow these types of files?
    I don’t know what these types of files are called?
    What would be a good search term?
    Thanks in advance….

    • rdiver

      Hi, I seem to think this is to do with the call to the webhost from ifttt not the key added to the end.
      Yes the key is only to add a bit of security (that hopefully was changed from default!), it could easily be removed.

      I seem to recall if you dig through the comments, I got it to work on google cloud that is free for a year.

  • slicker55

    I can’t find a hosting site which handles files with the key extension appended to the end of the filename?
    Would you be able to make boost and cancel files which don’t have a key?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.