Community
OpenEnergyMonitor

OpenEnergyMonitor Community

Script for feeding Honeywell Evohome data into Emoncms

Here is my latest offering which I will run with for a while and soak test it. It removes the need for a shellscript to run it and I hope has error checking to keep it running.

#!/usr/bin/python
import requests
import json
import time
import math
from sys import exit

USERNAME = 'xxxxx'
PASSWORD = 'xxx'

while True:
    # Initial JSON POST to the website to return your userdata
    url = 'https://tccna.honeywell.com/WebAPI/api/Session'
    postdata = {'Username': USERNAME, 'Password': PASSWORD, 'ApplicationId': '91db1612-73fd-4500-91b2-e63b069b185c'}
    header = {'content-type': 'application/json'}
    # get sessionID
    data = json.dumps(postdata)
    response = requests.post(url, data=data, headers=header)
    str_response = response.content.decode("utf-8")

    #print(str_response)
    userinfo = json.loads(str_response)

    if 'userInfo' not in userinfo: 
        #print "not allowed - header"
        # sleep for 5 minutes
        time.sleep(300)
        continue

    # here havea  connection so can get data
    userid = userinfo['userInfo']['userID']
    sessionId = userinfo["sessionId"]

    # setup and receive data then loop and extract temperature for each device
    params = ""
    url = 'https://tccna.honeywell.com/WebAPI/api/locations?userId=%s&allData=True' % userid
    header['sessionId'] = sessionId
    response = requests.get(url, data=json.dumps(postdata), headers=header)
    str_response = response.content.decode("utf-8")
    #print(str_response)
    fullData = json.loads(str_response)[0]
    #print(fullData)
    if 'devices' not in fullData: 
        #print "not allowed - data"
        time.sleep(300)
        continue


    for device in fullData['devices']:
        stemp = ""
        if params != "": params += ","
        # Add device current temperature
        if device['thermostatModelType'] == "DOMESTIC_HOT_WATER": params += "hot_water_temp:"
        else:  params += device['name'] + "_temp:"
        stemp = str(round(device['thermostat']['indoorTemperature'],1))
        #stemp = str(math.ceil((device['thermostat']['indoorTemperature'])*10)/10)
        params += stemp

    #now generate the insert into emoncms
    url = "http://xxx.xxx.xxx.xxx/emoncms/input/post.json?node=evohome&apikey=8fd1xxxxxxxxxxxxxxxxxxxxxxx4fc2&json={"
    url += params + "}"
    #print(url)
    response = requests.get(url, headers=header)

    # debug - read the response and print it
    str_response = response.content.decode("utf-8")
    #print(str_response)

    del params
  
    time.sleep(300)

apart from replacing the shellscript with the py script there is no real difference from the instructions before.
Hope this is useful…

Edit - Munged API key. BT, Moderator

This gives an example of the output I have on a tablet ( this has lost its ability to be able to charge - a common USB fault ) so it sits in a prominent place. ( Note this is from a web-page on my main computer so the formatting is more complete on the tablet.

This is created by having a html page that calls 2 screens from Emoncms and combines them using iframes. I had to trigger a re-load every 5 minutes because the graphs do not move with time but the values outside the graphs do - maybe a weird defect with emoncms as within emoncms they do update. However it works and I am pleased with the result.

The next improvement would be to combine all into one Emoncms screen but that would involve pulling data directly from Agile source rather than using the app.

I use requests and have gotten bit by this one, or rather the lack of including it…

From https://requests.readthedocs.io/en/master/user/quickstart/

You can tell Requests to stop waiting for a response after a given number of seconds with the timeout parameter. Nearly all production code should use this parameter in nearly all requests. Failure to do so can cause your program to hang indefinitely:

requests.get('https://github.com/', timeout=0.001) Traceback (most recent call last): File "<stdin>", line 1, in <module> requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)

Note

timeout is not a time limit on the entire response download; rather, an exception is raised if the server has not issued a response for timeout seconds (more precisely, if no bytes have been received on the underlying socket for timeout seconds). If no timeout is specified explicitly, requests do not time out.

1 Like

Thanks for that - good to learn about the timeouts and interesting article. If you were the one who removed my api key thanks as well.
I have put the timeouts in - interestingly needed to increase timeout to 1 sec on the honeywell request.

YVW, S.

I figured you’d find it useful. (I sure did)

Yes, that was me. :wink:

1 Like