0

I've asked this question already but I think I asked it in the wrong way, or at least I might be barking up the wrong tree with where the problem lies.

I've got a Python/Flask script with the following route:

@app.route('/heatingadjust')
def heatingadjust(hiveSessionId=None, score=None):
        import requests
        import time
        import datetime
        import MySQLdb
        conn = MySQLdb.connect(host="localhost", user = "admin", passwd = "xxxxxxxxxx", db = "mydb")
        cursor = conn.cursor()
        cursor.execute("select score from OccScore")
        data = cursor.fetchone()
        score = data[0]

        url = "https://api.prod.bgchprod.info:443/omnia/users"
        if 'hiveSessionId' in session:
                hiveSessionId = session['hiveSessionId']
                headers = {
                    'Content-Type': "application/vnd.alertme.zoo-6.1+json",
                    'Accept': "application/vnd.alertme.zoo-6.1+json",
                    'X-Omnia-Client': "Hive Web Dashboard",
                    'X-Omnia-Access-Token': hiveSessionId,
                    'Cache-Control': "no-cache"
                    }
                response = requests.request("GET", url, headers=headers)
                data=response.json()
                if 'errors' in data:
                        return redirect(url_for('hivelogin'))
        if (score == 0):
            url = "https://api-prod.bgchprod.info:443/omnia/nodes/xxxxxxxxxx"
            payload = "{\n    \"nodes\": [{\n        \"attributes\": {\n            \"targetHeatTemperature\": {\n                \"targetValue\": 15\n            }\n        }\n    }]\n}"        
            headers = {
                'Content-Type': "application/vnd.alertme.zoo-6.1+json",
                'Accept': "application/vnd.alertme.zoo-6.1+json",
                'X-Omnia-Client': "Dashboard",
                'X-Omnia-Access-token': hiveSessionId,
                'Cache-Control': "no-cache",
             }
            response = requests.request("PUT", url, data=payload, headers=headers)
        else:
            url = "https://api-prod.bgchprod.info:443/omnia/nodes/xxxxxxx"
            payload = "{\n    \"nodes\": [{\n        \"attributes\": {\n            \"targetHeatTemperature\": {\n                \"targetValue\": 18\n            }\n        }\n    }]\n}"        
            headers = {
                'Content-Type': "application/vnd.alertme.zoo-6.1+json",
                'Accept': "application/vnd.alertme.zoo-6.1+json",
                'X-Omnia-Client': "Dashboard",
                'X-Omnia-Access-token': hiveSessionId,
                'Cache-Control': "no-cache",
             }
            response = requests.request("PUT", url, data=payload, headers=headers)

        return str(score)

Basically, I've got one route that gets called using wget that sniffs for Bluetooth devices, increments as score if it finds a device and writes the score to a MySQL table. This is to see if there's anyone at home.

This route reads the score and turns the heating off using the Hive api if the house is empty. Called from the URL, it does exactly what it should and I can see the heating get turned off.

However, what I'm trying to do is call a script with the wget from crontab.

The crontab runs and I can see it in syslog. The apache access log shows the URL being called.

But the heating doesn't get turned off as it does if I call the exact same thing through the browser.

I have a suspicion from something else I saw that it might be down to wget not liking the fact that another URL is called.

Can anyone tell me if my suspicion is correct? I've seen something else about using urllib instead of wget but I don't know what I'd need to change to call the URL with the headers.

2
  • Are you asking whether wget http://your-flask-instance is failing because the Flask route makes its own HTTP request and wget "doesn't like that"? No, that's a nonsense idea. Commented Nov 1, 2018 at 20:41
  • I guess I am. Only because I read something about wget and redirects. Just clutching at straws so I put 2 + 2 = 5 Commented Nov 1, 2018 at 21:26

1 Answer 1

1

My guess is that the wget request doesn't provide a session cookie and therefore no hiveSessionId in the session. Because then 'X-Omnia-Access-token': None the request to the Omnia service is rejected.

(I'm a bit confused about the two parameters, hiveSessionId and score. The hive session ID gets overwritten by the value from the session if it exists, and the score is always overwritten by the value from the database.)

Side note: you can use json.dumps() to build the payload:

payload = json.dumps({
    "nodes": [
        {
            "attributes": {"targetHeatTemperature": {"targetValue": 18}}
        }
    ]
})
Sign up to request clarification or add additional context in comments.

6 Comments

The session cookie idea makes sense. I can't think of a way round that one with my limited knowledge. The hivesessionid thing... I can't remember why I did that. Something to do with keeping the session alive or making sure that I'm still logged in. Yes, score is always overwritten from the database. There's another route that writes the score after checking if anyone is at home. This route then gets the score from the database and either turns the heating up if the score > 0 (someone's at home) or down if it's 0 (nobody at home)
(As an aside, I wanted to learn Python with zero knowledge. Creating a bunch of scripts that detect home occupancy based on Bluetooth, read and write from MySQL, interact with an 3rd party API, switch on lights at home, etc, is my take on a "Hello world". Possibly should have started with something easier as the learning curve is making my head spin!
Check out the wget man page for options --load-cookies, --save-cookies and --keep-session-cookies. Perhaps you can build a cookies.txt from inspecting the relevant cookies in your browser.
Thanks @digitalarbeiter. You were right on the mark with the session variable. What I've done for the moment is add in the authentication at the start of my code. It just means it grabs a new token from Hive every time it runs rather than trying to use the token in the session variable. The script runs every 30 minutes and I think the tokens only last for 20 minutes if there's no activity so re-authenticating is probably necessary anyway. I now have proper geofencing on my heating on HiveHome - they don't support it like Nest and Tado so I'm made up.
Cool, congrats! (And do be careful lest not everybody on the internet can control your heating :-) )
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.