Decoded - EvoHome API access to control remotely.

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts
  • roydonaldson
    Automated Home Guru
    • Jan 2013
    • 205

    Decoded - EvoHome API access to control remotely.

    Hi there,

    Having the new EvoHome and the new apps to control it, I was disappointed upon contacting Honeywell that they told me there was no API to access this from anything but their apps. It seems a shame, as their US wifi thermostats have a limited Beta 1 of API access going on right now (all-bet very limited Beta).

    I thought I'd have a look at the app and see if I could understand what they were doing. Initially I simply fired up a copy of Wireshark and sniffed all the traffic from the app to the internet. This did not prove particularly useful, as upon reading the packet trace, I could see that all of the traffic was encrypted and was completely using HTTPS to communicate to the Honeywell web server. What it did show me however, was that it was talking to rs.alarmnet.com, which is the same web site that the US is using and in fact you can login to the US website and use their website to do stuff with their US based thermostats.

    Now, I had to work out how to go about decrypting HTTPS traffic to the website. With a bit of effort I think I now have a setup that let's me decode and read the API access that the apps are using. The next step for me to check this out is to write some Python code that replicates what the app is doing and to query the website from a Linux box just to chekc out my findings are correct.

    Initially it looks like the app is doing:

    POST to HTTPS://rs.alarmnet.com/TotalConnect...PI/api/Session with the parameters:

    {
    "Username": "your username",
    "Password": "your password",
    "ApplicationId": "not sure if this is app or user specific yet, so have removed value in meantime"
    }

    It then returns the following JSON data:

    {
    "sessionId": "B4E8FE94-F397-4706-85D4-11AEB7D4ADCB",
    "userInfo": {
    "userID": your numeric userid,
    "username": "your username",
    "firstname": "your firstname",
    "lastname": "your lastname",
    "streetAddress": "your address line 1",
    "city": "your city",
    "state": "",
    "zipcode": "your postcode",
    "country": "GB",
    "telephone": "",
    "userLanguage": "en-GB",
    "isActivated": true,
    "deviceCount": 0
    },
    "latestEulaAccepted": true
    }

    The app next sends a JSON request for all the info about your site:

    POST to HTTPS://rs.alarmnet.com/TotalConnect...ns?userId=your userid&allData=True

    this then returns a JSON response with the full details of your site.

    Next it requests details on your gateway:

    POST to HTTPS://rs.alarmnet.com/TotalConnect...ocationId=your location&allData=False

    this then returns a JSON response:

    [{
    "gatewayID": XXXXXX,
    "mac": "YYYYYYYYYYYY",
    "crc": "ZZZZ",
    "locationId": your locationID,
    "isUpgrading": false
    }]


    I'm not publicly going to publish how I sniffed and decrypted all this traffic as I do not think it needs to be public knowledge, suffice it to say that the app is very secure and without access to kit and your iDevice, then you cannot break into the the app normally. You need physical access to the iDevice to change config on it to do this.

    However, if anyone who is more interested in how to use the API and has more knowledge than I to make use of it, please get in touch via PM.

    Roy.
  • roydonaldson
    Automated Home Guru
    • Jan 2013
    • 205

    #2
    Having been tested by a number of corporate firewalls, I've now managed to put together a basic python script to login to the Honeywell website and pull back my userdata. If you run this, then you should be able to retrieve your info which you can then post back to get your site info out of:

    -------------
    import requests
    import json

    url = 'https://rs.alarmnet.com/TotalConnectComfort/WebAPI/api/Session'
    postdata = {'Username':'<your username>','Password':'<your password>','ApplicationId':'91db1612-73fd-4500-91b2-e63b069b185c'}
    headers = {'content-type':'application/json'}

    response = requests.post(url,data=json.dumps(postdata),header s=headers)

    print response.content
    --------------

    Easiest way I found to do this was to just spin up an Amazon web services AMI instance and run it in python in there.
    Last edited by roydonaldson; 26 March 2014, 04:51 PM.

    Comment

    • watchforstock
      Automated Home Jr Member
      • Mar 2014
      • 20

      #3
      Extending this a little bit, this script then pulls the full detail that Roy mentions above

      Code:
      import requests
      import json
      
      USERNAME = 'USERNAME'
      PASSWORD = 'PASSWORD'
      
      url = 'https://rs.alarmnet.com/TotalConnectComfort/WebAPI/api/Session'
      postdata = {'Username':USERNAME,'Password':PASSWORD,'ApplicationId':'91db1612-73fd-4500-91b2-e63b069b185c'}
      headers = {'content-type':'application/json'}
      
      response = requests.post(url,data=json.dumps(postdata),headers=headers)
      
      print response.content
      
      userData = json.loads(response.content)
      
      userId = userData['userInfo']['userID']
      sessionId = userData['sessionId']
      
      url = 'https://rs.alarmnet.com/TotalConnectComfort/WebAPI/api/locations?userId=%s&allData=True' % userId
      
      headers['sessionId'] = sessionId
      
      response = requests.get(url,data=json.dumps(postdata),headers=headers)
      
      print response.content
      This provides (amongst other things) the current readings from all of the zones which might be of use to people who want to log this information elsewhere.

      Andrew
      Last edited by watchforstock; 27 March 2014, 11:18 PM.

      Comment

      • roydonaldson
        Automated Home Guru
        • Jan 2013
        • 205

        #4
        I've now managed to write python scripts that Set Economy mode and Away mode running on a Raspberry Pi. I will post these scripts tomorrow for people to use.

        Next step is to connect the Raspberry Pi to my house alarm outputs. I want to have the Raspberry Pi monitor the state of the house alarm and if it sees it Full Set, then send Economy mode to the Honeywell EvoHome.

        I'd also like to be able to set it up to monitor the temperatures in all my zones and save these to a file.

        Roy.
        Last edited by roydonaldson; 30 March 2014, 06:41 PM.

        Comment

        • watchforstock
          Automated Home Jr Member
          • Mar 2014
          • 20

          #5
          I now use a slight modification to the script below to store the temperatures from each of the zones to a database (integrated into an existing house temperature monitoring system. I run it as a cron task every 5 minutes and it's been very solid so far

          Code:
          import requests
          import json
          
          USERNAME = 'USERNAME'
          PASSWORD = 'PASSWORD'
          
          url = 'https://rs.alarmnet.com/TotalConnectComfort/WebAPI/api/Session'
          postdata = {'Username':USERNAME,'Password':PASSWORD,'ApplicationId':'91db1612-73fd-4500-91b2-e63b069b185c'}
          headers = {'content-type':'application/json'}
          
          response = requests.post(url,data=json.dumps(postdata),headers=headers)
          
          userData = json.loads(response.content)
          
          userId = userData['userInfo']['userID']
          sessionId = userData['sessionId']
          
          url = 'https://rs.alarmnet.com/TotalConnectComfort/WebAPI/api/locations?userId=%s&allData=True' % userId
          
          headers['sessionId'] = sessionId
          
          response = requests.get(url,data=json.dumps(postdata),headers=headers)
          
          fullData = json.loads(response.content)[0]
          
          for device in fullData['devices']:
              print device['thermostatModelType'], device['deviceID'], device['name'], device['thermostat']['indoorTemperature']
          It would be easy to change the print line near the end to write to a file or database to store these values for further analysis

          Comment

          • watchforstock
            Automated Home Jr Member
            • Mar 2014
            • 20

            #6
            I'm now tracking my code for an API in a github repository: https://github.com/watchforstock/evohome-client

            If anyone wants to contribute code I'm happy to merge it in

            Andrew

            Comment

            • ukhauk
              Automated Home Jr Member
              • Apr 2006
              • 22

              #7
              Hi Roy are you in a position to share the scripts that Set Economy mode and Away mode running on a Raspberry Pi ? what type of alarm system are you monitoring ? I have had some joy with comfort.

              Comment

              • roydonaldson
                Automated Home Guru
                • Jan 2013
                • 205

                #8
                Code to Set Away Mode Permanent:

                -----------------

                # Set Away Mode Permanent via Honeywell EvoHome Web API

                # Load required libraries
                import requests
                import json

                # Ser your login details in the 2 fields below
                USERNAME = 'rYour UserID'
                PASSWORD = 'Your Password'

                # Initial JSON POST to the website to return your userdata
                url = 'https://rs.alarmnet.com/TotalConnectComfort/WebAPI/api/Session'
                postdata = {'Username':USERNAME, 'Password':PASSWORD, 'ApplicationId':'91db1612-73fd-4500-91b2-e63b069b185c'}
                headers = {'content-type':'application/json'}
                response = requests.post(url,data=json.dumps(postdata),header s=headers)
                userinfo = json.loads(response.content)

                # Extract the sessionId and your userid from the response
                userid = userinfo['userInfo']['userID']
                sessionId = userinfo['sessionId']

                print ('your userid is', userid)

                # Next, using your userid, get all the data back about your site
                url = 'https://rs.alarmnet.com/TotalConnectComfort/WebAPI/api/locations?userId=%s&allData=True' % userid
                headers['sessionId'] = sessionId
                response = requests.get(url,data=json.dumps(postdata),headers =headers)
                locationinfo = json.loads(response.content)

                # Extract the locationID from the response
                locationID = locationinfo[0]['locationID']

                print ('your location is', locationID)

                # Now create and set Away Mode Permanent
                url = 'https://rs.alarmnet.com/TotalConnectComfort/WebAPI/api/evoTouchSystems?locationId=%s' % locationID
                postdata = {'QuickAction':'Away','QuickActionNextTime':''}
                response = requests.put(url,data=json.dumps(postdata),headers =headers)

                Comment

                • roydonaldson
                  Automated Home Guru
                  • Jan 2013
                  • 205

                  #9
                  Code to Set Economy mode Permanent:

                  --------

                  # Set Economy Mode Permanent via Honeywell EvoHome Web API

                  # Load required libraries
                  import requests
                  import json

                  # Ser your login details in the 2 fields below
                  USERNAME = 'Your UserID'
                  PASSWORD = 'Your Password'

                  # Initial JSON POST to the website to return your userdata
                  url = 'https://rs.alarmnet.com/TotalConnectComfort/WebAPI/api/Session'
                  postdata = {'Username':USERNAME, 'Password':PASSWORD, 'ApplicationId':'91db1612-73fd-4500-91b2-e63b069b185c'}
                  headers = {'content-type':'application/json'}
                  response = requests.post(url,data=json.dumps(postdata),header s=headers)
                  userinfo = json.loads(response.content)

                  # Extract the sessionId and your userid from the response
                  userid = userinfo['userInfo']['userID']
                  sessionId = userinfo['sessionId']

                  print ('your userid is', userid)

                  # Next, using your userid, get all the data back about your site
                  url = 'https://rs.alarmnet.com/TotalConnectComfort/WebAPI/api/locations?userId=%s&allData=True' % userid
                  headers['sessionId'] = sessionId
                  response = requests.get(url,data=json.dumps(postdata),headers =headers)
                  locationinfo = json.loads(response.content)

                  # Extract the locationID from the response
                  locationID = locationinfo[0]['locationID']

                  print ('your location is', locationID)

                  # Now create and set Economy Mode Permanent
                  url = 'https://rs.alarmnet.com/TotalConnectComfort/WebAPI/api/evoTouchSystems?locationId=%s' % locationID
                  postdata = {'QuickAction':'AutoWithEco','QuickActionNextTime' :''}
                  response = requests.put(url,data=json.dumps(postdata),headers =headers)

                  Comment

                  • roydonaldson
                    Automated Home Guru
                    • Jan 2013
                    • 205

                    #10
                    I haven't sniffed it yet, but I'd guess that if you want to set this to end at a certain time that you'd need to set the time in the 'QuickActioneNextTime' field:

                    # Now create and set Economy Mode Permanent
                    url = 'https://rs.alarmnet.com/TotalConnectComfort/WebAPI/api/evoTouchSystems?locationId=%s' % locationID
                    postdata = {'QuickAction':'AutoWithEco','QuickActionNextTime' :''}
                    response = requests.put(url,data=json.dumps(postdata),headers =headers)

                    Comment

                    • watchforstock
                      Automated Home Jr Member
                      • Mar 2014
                      • 20

                      #11
                      I've just pushed a bunch of updates to my python library at https://github.com/watchforstock/evohome-client

                      This now includes the ability to choose each of the various modes either on a permanent or timed basis as well as overriding individual zones. The documentation is still playing catch-up, but if you have any trouble give me a shout and I'll try to help

                      Andrew

                      Comment

                      • eXOBeX
                        Automated Home Lurker
                        • Jan 2014
                        • 1

                        #12
                        Interesting to see this work in progress. You shouldn't have to be doing it (there's no reason for Honeywell not to offer API or web access) but there y'go.

                        Have you considered decoding the link between gateway and server instead of gateway and app? Communicating with the gateway (via a Pi running a web server on the same network, for example) would cut Honeywell's servers out of the loop completely, useful if Honeywell decide they're end-of-life and try to push a replacement product.

                        For what it's worth I've installed Wireshark today to see what the gateway is up to. I'm unfamiliar with Wireshark so forgive any noobishness

                        First thing it does is looks for the local router, then makes a HTTPS request (from port 30000 to dest port 443) to auiredir1.alarmnet.com (204.141.57.100).
                        After a brief chat it then turns its attention to auiredir2.alarmnet.com (204.141.57.101), again HTTPS but this time with a source port of 30001.
                        Next is more HTTPS to 12.149.218.73 (registered to ADI), incrementing the source port once more.
                        The cycle then repeats over and over, with the gateway sending snippets of data to auiredir1.alarmnet.com, auiredir2.alarmnet.com and 12.149.218.73 and incrementing the source port counter each time. Most data packets I saw were 170 bytes or less, the third ever auiredir2 packet being the only exception at 634 bytes.

                        None of these three appear to make the first move, the Evohome gateway calls them first.
                        Last edited by eXOBeX; 3 May 2014, 02:44 PM.

                        Comment

                        • bruce_miranda
                          Automated Home Legend
                          • Jul 2014
                          • 2307

                          #13
                          Has anyone figured out how to get the outdoor temperature from a installed sensor. There is a field but it always returns 128.0000

                          Comment

                          • watchforstock
                            Automated Home Jr Member
                            • Mar 2014
                            • 20

                            #14
                            Are you looking at all the data the remote system returns?

                            If you're using my python client, you can do:

                            from evohomeclient import EvohomeClient

                            client = EvohomeClient('username', 'password')
                            client.temperatures() # necessary to populate the data
                            print client.full_data


                            If the right information is contained there you'll be hopefully able to see it and work out where it's coming back. I don't have an outdoor sensor so never specifically looked for its output.

                            Let us know how you get on

                            Comment

                            • bruce_miranda
                              Automated Home Legend
                              • Jul 2014
                              • 2307

                              #15
                              Originally posted by watchforstock View Post
                              Are you looking at all the data the remote system returns?

                              If you're using my python client, you can do:

                              from evohomeclient import EvohomeClient

                              client = EvohomeClient('username', 'password')
                              client.temperatures() # necessary to populate the data
                              print client.full_data


                              If the right information is contained there you'll be hopefully able to see it and work out where it's coming back. I don't have an outdoor sensor so never specifically looked for its output.

                              Let us know how you get on
                              There is something wrong with your code here. I get a return of None with the code above. All other calls as per your documentation works OK.
                              Also anyone noticed the fact that the developers at Honeywell can't spell too "outdootHumidityAvailable" is one of the variables used. :-)
                              Last edited by bruce_miranda; 23 September 2014, 10:28 PM.

                              Comment

                              Working...
                              X