Read British Gas Hive Heating temperature

In this subforum you can show projects you have made, or you are busy with. Please create your own topic.

Moderator: leecollings

Calzor Suzay
Posts: 145
Joined: Tuesday 08 July 2014 15:10
Target OS: -
Domoticz version: 4.9700
Location: UK
Contact:

Re: Read British Gas Hive Heating temperature

Post by Calzor Suzay »

Every five minutes is good for me as I just use it as a reporting tool, making it a continuous feed would obviously benefit people who want to act upon it via Domoticz. The only thing I can think might be an issue would BGas feel their servers are being spammed and limit connections over time.
Not sure as you can leave the web page open and that updates itself as it goes :)
Calzor Suzay
Posts: 145
Joined: Tuesday 08 July 2014 15:10
Target OS: -
Domoticz version: 4.9700
Location: UK
Contact:

Re: Read British Gas Hive Heating temperature

Post by Calzor Suzay »

MikeF wrote:I guess you could do something like:

Code: Select all

if [ $temp != "0" ]; then
	domoTemp=$(curl -s "http://<DOMO IP:PORT>/json.htm?type=command&param=udevice&nvalue=0&idx=<IDX>&svalue=${temp}")
fi
Haven't tried it though.
I can see the logic in the code but I still get the 0° blips so not sure how it's getting them.
aturi83
Posts: 5
Joined: Tuesday 07 November 2017 16:27
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Read British Gas Hive Heating temperature

Post by aturi83 »

Hi just installed this into my new setup. When running the python script i get the following error:

Code: Select all

Traceback (most recent call last):
  File "/home/pi/domoticz/scripts/hive2domo.py", line 70, in <module>
    makeRequest(url,payload)
  File "/home/pi/domoticz/scripts/hive2domo.py", line 41, in makeRequest
    print e.code
AttributeError: 'URLError' object has no attribute 'code'
I think some of the URL's have changed from the original ones posted. Any tips on where to start? I have Hive mk2 (the shiny one!)
MikeF
Posts: 350
Joined: Sunday 19 April 2015 0:36
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.2
Location: UK
Contact:

Re: Read British Gas Hive Heating temperature

Post by MikeF »

Yep, Hive API / URLs changed a while back.

Try this (replace <XXXX>'s with your values):
Spoiler: show

Code: Select all

#!/usr/bin/env python

'''
Python script to send data from Hive to Domoticz.

Replace XXX's with your values.
'''

import requests
import json

# Replace with your Domoticz idx's
insideIdx = '<XX>'
targetIdx = '<XX>'
thermIdx = '<XX>'
heatingIdx = '<XX>'

# Replace with your Domoticz URL & port
DomoReadURL   = 'http://<XXXX:XXXX>/json.htm?type=devices&rid='
DomoWriteURL  = 'http://<XXXX:XXXX>/json.htm?type=command&param=udevice&nvalue=0&idx='
DomoSwitchURL = 'http://<XXXX:XXXX>/json.htm?type=command&param=switchlight&idx='

requests.packages.urllib3.disable_warnings()

def domoticzread(idx, var):
   url = DomoReadURL + idx
   response = requests.get(url)
   jsonData = json.loads(response.text)
   result = jsonData['result'][0][var]
   return result;

# Hive

# log on to Hive
# Replace with your Hive user id and password
payload = {'username':'<XXXX>', 'password':'<XXXX>'}
headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
url = 'https://beekeeper-uk.hivehome.com/1.0/gateway/login'
r = requests.post(url, headers=headers, data=json.dumps(payload), verify=False)

#print(json.dumps(r.json(), indent=2))

sessionId = r.json()["token"]
#print sessionId

headers = {'Content-Type': 'application/vnd.alertme.zoo-6.2+json', 'Accept': 'application/vnd.alertme.zoo-6.2+json', \
	'X-AlertMe-Client': 'swagger', 'X-Omnia-Access-Token': sessionId}
url = 'https://api.prod.bgchprod.info:443/omnia/nodes'
r = requests.get(url, headers=headers, verify=False)

#print(json.dumps(r.json()["nodes"][2], indent=2))

# read node (Note: node number may be different / may change if new Hive devices added)
nodeId=r.json()["nodes"][2]["id"]
#print nodeId

# get values from Hive
temp = r.json()["nodes"][2]["attributes"]["temperature"]["reportedValue"]
targetTemp = r.json()["nodes"][2]["attributes"]["targetHeatTemperature"]["reportedValue"]
heating = r.json()["nodes"][2]["attributes"]["stateHeatingRelay"]["reportedValue"]

# log out from Hive
headers = {'Content-Type': 'application/vnd.alertme.zoo-6.1+json', 'Accept': 'application/vnd.alertme.zoo-6.2+json', \
	'X-AlertMe-Client': 'Hive Web Dashboard', 'X-Omnia-Access-Token': sessionId}
url = 'https://api.prod.bgchprod.info:443/omnia/auth/sessions/' + sessionId
r = requests.delete(url, headers=headers, verify=False)

# Domoticz

# get last values from Domoticz
last_temp = domoticzread(insideIdx, 'Temp')
last_target = domoticzread(targetIdx, 'Temp')
last_heating = domoticzread(heatingIdx, 'Status')

# change some values
temp = round(temp, 1)

if targetTemp < 7.0: targetTemp = 7.0

if heating == "ON":
	heating="On"
else:
	heating="Off"

print 'new','old'
print temp, last_temp
print targetTemp, last_target
print heating, last_heating

# send values to Domoticz (only send some if changed)
url = DomoWriteURL + insideIdx + '&svalue=' + str(temp)
r = requests.get(url)

if targetTemp != last_target:
	url = DomoWriteURL + targetIdx + '&svalue=' + str(targetTemp)
	r = requests.get(url)

	url = DomoWriteURL + thermIdx + '&svalue=' + str(targetTemp)
	r = requests.get(url)

if heating != last_heating:
	url = DomoSwitchURL + heatingIdx + '&switchcmd=' + heating
	r = requests.get(url)
	
aturi83
Posts: 5
Joined: Tuesday 07 November 2017 16:27
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Read British Gas Hive Heating temperature

Post by aturi83 »

MikeF wrote: Tuesday 07 November 2017 23:42 Yep, Hive API / URLs changed a while back.

Try this (replace <XXXX>'s with your values):
I must have some kind of bash config problem. Added the configs into it and now have:

Code: Select all

-bash: $'\nPython script to send data from Hive to Domoticz.\n\nReplace XXXs with your values.\n': command not found
-bash: import: command not found
-bash: import: command not found
-bash: insideIdx: command not found
-bash: targetIdx: command not found
-bash: thermIdx: command not found
-bash: heatingIdx: command not found
-bash: DomoReadURL: command not found
-bash: DomoWriteURL: command not found
-bash: DomoSwitchURL: command not found
-bash: hive.bash: line 25: syntax error near unexpected token `def'
-bash: hive.bash: line 25: `def domoticzread(idx, var):''
Made a hello world script, which executes correctly. Not sure whats going on. Sorry to be a pain.
aturi83
Posts: 5
Joined: Tuesday 07 November 2017 16:27
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Read British Gas Hive Heating temperature

Post by aturi83 »

Ok after working through some things - had to install module "requests" I now have the following error

Code: Select all

Traceback (most recent call last):
  File "./hive.sh", line 58, in <module>
    temp = r.json()["nodes"][2]["attributes"]["temperature"]["reportedValue"]
KeyError: 'temperature'
MikeF
Posts: 350
Joined: Sunday 19 April 2015 0:36
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.2
Location: UK
Contact:

Re: Read British Gas Hive Heating temperature

Post by MikeF »

Hi @aturi83,

The problem with this script is that I never worked out how to detect which node corresponds to the Hive receiver. For me, it's node 2, but it depends on what else is on your Hive system.

In the 3 lines following '# get values from Hive', try changing the number [2] (e.g., to [1] or [3]) - it's a little bit hit and miss, I'm afraid. :?
aturi83
Posts: 5
Joined: Tuesday 07 November 2017 16:27
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Read British Gas Hive Heating temperature

Post by aturi83 »

Took a few attempts but managed to track down the correct ID. Dont make it easy this stuff do they...

A new set of error messages at the end. However got lots more data now, including schedule, frost protection temp settings etc.

Code: Select all

Traceback (most recent call last):
  File "./hive.sh", line 71, in <module>
    last_temp = domoticzread(insideIdx, 'Temp')
  File "./hive.sh", line 28, in domoticzread
    jsonData = json.loads(response.text)
  File "/usr/lib/python2.7/json/__init__.py", line 339, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 364, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded
MikeF
Posts: 350
Joined: Sunday 19 April 2015 0:36
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.2
Location: UK
Contact:

Re: Read British Gas Hive Heating temperature

Post by MikeF »

I think the problem here may be that you have not set up dummy devices in Domoticz to receive the values from this script - see lines 13 to 16. The first two are temperature devices, the third is a thermostat / setpoint, and the last is an on/off switch. (I may have mentioned this originally - it was a while ago when I first published this script.)
aturi83
Posts: 5
Joined: Tuesday 07 November 2017 16:27
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Read British Gas Hive Heating temperature

Post by aturi83 »

MikeF wrote: Tuesday 14 November 2017 19:59 I think the problem here may be that you have not set up dummy devices in Domoticz to receive the values from this script - see lines 13 to 16. The first two are temperature devices, the third is a thermostat / setpoint, and the last is an on/off switch. (I may have mentioned this originally - it was a while ago when I first published this script.)
Setup as described, in fact i removed the dummy device and set it up from scratch.

The data above the error is correct

Code: Select all

    "targetHeatTemperature": {
      "targetExpiryTime": 1510697424984, 
      "reportReceivedTime": 1510698605897, 
      "propertyStatus": "COMPLETE", 
      "targetSetTXId": "e56e60fa-0d45-4c52-9f76-7029377109ae", 
      "reportedValue": 11.5, 
      "targetSetTime": 1510697124984, 
      "displayValue": 11.5, 
      "targetValue": 11.5, 
      "reportChangedTime": 1510697125488
    }, 
    "minHeatTemperature": {
      "displayValue": 5.0, 
      "reportReceivedTime": 1510698605897, 
      "reportChangedTime": 1508372857836, 
      "reportedValue": 5.0
    }, 
    "holidayMode": {
      "displayValue": {
        "targetHeatTemperature": 1.0
      }, 
      "reportReceivedTime": 1510698605897, 
      "reportChangedTime": 1509790193862, 
      "reportedValue": {
        "targetHeatTemperature": 1.0
      }
    }, 
    "failureStatus": {
      "displayValue": "NORMAL", 
      "reportReceivedTime": 1510698605897, 
      "reportChangedTime": 1509633035417, 
      "reportedValue": "NORMAL"
    }, 
    "nodeType": {
      "displayValue": "http://alertme.com/schema/json/node.class.thermostat.json#", 
      "reportReceivedTime": 1510699203908, 
      "reportChangedTime": 1508372853584, 
      "reportedValue": "http://alertme.com/schema/json/node.class.thermostat.json#"
    }, 
    "activeScheduleLock": {
      "targetExpiryTime": 1510605381449, 
      "reportReceivedTime": 1510698605897, 
      "propertyStatus": "COMPLETE", 
      "targetSetTXId": "7cbb4270-0380-4963-b7ed-2fdef9de06ea", 
      "reportedValue": true, 
      "targetSetTime": 1510605081449, 
      "displayValue": true, 
      "targetValue": true, 
      "reportChangedTime": 1510656121698
    }, 
    "activeHeatCoolMode": {
      "targetExpiryTime": 1510605381449, 
      "reportReceivedTime": 1510698605897, 
      "propertyStatus": "COMPLETE", 
      "targetSetTXId": "7cbb4270-0380-4963-b7ed-2fdef9de06ea", 
      "reportedValue": "HEAT", 
      "targetSetTime": 1510605081449, 
      "displayValue": "HEAT", 
      "targetValue": "BOOST", 
      "reportChangedTime": 1510608681517
    }, 
    "frostProtectTemperature": {
      "displayValue": 7.0, 
      "reportReceivedTime": 1510698605897, 
      "reportChangedTime": 1508372857836, 
      "reportedValue": 7.0
    }
Its not getting passed into domoticz though. I'll keep playing :D
imcfarla
Posts: 64
Joined: Monday 04 December 2017 13:18
Target OS: Linux
Domoticz version:
Contact:

Re: Read British Gas Hive Heating temperature

Post by imcfarla »

I have updated the script so that it will search for the Hive node instead of you having to guess it (mine was 8!)

Code: Select all

#!/usr/bin/env python

'''
Python script to send data from Hive to Domoticz.

Replace XXX's with your values.
'''

import requests
import json
import sys

# Replace with your Domoticz idx's
domoHost = 'XXX'
domoPort = 'XXX'
insideIdx = 'XXX'
targetIdx = 'XXX'
thermIdx = 'XXX'
heatingIdx = 'XXX'

# Replace with your Hive credentials
hiveUser = 'XXX'
hivePass = 'XXX'

# Domoticz URL & port
DomoReadURL   = 'http://'+domoHost+':'+domoPort+'/json.htm?type=devices&rid='
DomoWriteURL  = 'http://'+domoHost+':'+domoPort+'/json.htm?type=command&param=udevice&nvalue=0&idx='
DomoSwitchURL = 'http://'+domoHost+':'+domoPort+'/json.htm?type=command&param=switchlight&idx='

requests.packages.urllib3.disable_warnings()

def domoticzread(idx, var):
   url = DomoReadURL + idx
   response = requests.get(url)
   jsonData = json.loads(response.text)
   result = jsonData['result'][0][var]
   return result;

def find_key_in_list(d, value):
    if isinstance(d, list):
        t = list(d)
        for v in d:
            if isinstance(v, dict):
                p = find_key(v, value)
                if not p:
                    t.remove(v)
        return t

def find_key(d, value):
    for k,v in d.items():
        if isinstance(v, dict):
            p = find_key(v, value)
            if p:
                return [k] + p
        elif v == value:
            return [k]

# Hive
# log on to Hive
payload = {'username':hiveUser, 'password':hivePass}
headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
url = 'https://beekeeper-uk.hivehome.com/1.0/gateway/login'
r = requests.post(url, headers=headers, data=json.dumps(payload), verify=False)
sessionId = r.json()["token"]

headers = {'Content-Type': 'application/vnd.alertme.zoo-6.2+json', 'Accept': 'application/vnd.alertme.zoo-6.2+json', \
        'X-AlertMe-Client': 'swagger', 'X-Omnia-Access-Token': sessionId}
url = 'https://api.prod.bgchprod.info:443/omnia/nodes'
r = requests.get(url, headers=headers, verify=False)

# Find thermostat node
d = r.json()["nodes"]
x = find_key_in_list(d,"http://alertme.com/schema/json/node.class.thermostat.json#")
if x:
    if x[0]["id"] == x[1]["parentNodeId"]:
        thermostat = x[1]
    elif x[1]["id"] == x[0]["parentNodeId"]:
        thermostat = x[0]
else:
     print("No thermostat found")
     thermostat = False

# get values from Hive
if thermostat:
    temp = thermostat["attributes"]["temperature"]["reportedValue"]
    targetTemp = thermostat["attributes"]["targetHeatTemperature"]["reportedValue"]
    heating = thermostat["attributes"]["stateHeatingRelay"]["reportedValue"]

# log out from Hive
headers = {'Content-Type': 'application/vnd.alertme.zoo-6.1+json', 'Accept': 'application/vnd.alertme.zoo-6.2+json', \
        'X-AlertMe-Client': 'Hive Web Dashboard', 'X-Omnia-Access-Token': sessionId}
url = 'https://api.prod.bgchprod.info:443/omnia/auth/sessions/' + sessionId
r = requests.delete(url, headers=headers, verify=False)

if not thermostat:
    sys.exit() # Quit if there is no thermostat found

# Domoticz
# get last values from Domoticz
last_temp = domoticzread(insideIdx, 'Temp')
last_target = domoticzread(targetIdx, 'Temp')
last_heating = domoticzread(heatingIdx, 'Status')

# change some values
temp = round(temp, 1)

if targetTemp < 7.0: targetTemp = 7.0

if heating == "ON":
        heating="On"
else:
        heating="Off"

print 'new','old'
print temp, last_temp
print targetTemp, last_target
print heating, last_heating

# send values to Domoticz (only send some if changed)
url = DomoWriteURL + insideIdx + '&svalue=' + str(temp)
r = requests.get(url)
url = DomoWriteURL + targetIdx + '&svalue=' + str(targetTemp)
r = requests.get(url)

if targetTemp != last_target:
        url = DomoWriteURL + thermIdx + '&svalue=' + str(targetTemp)
        r = requests.get(url)

if heating != last_heating:
        url = DomoSwitchURL + heatingIdx + '&switchcmd=' + heating
        r = requests.get(url)

MikeF
Posts: 350
Joined: Sunday 19 April 2015 0:36
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.2
Location: UK
Contact:

Re: Read British Gas Hive Heating temperature

Post by MikeF »

Hi imcfarla,

Thanks for this - I never got round to it!

However, it's not working for me, as I get 'NameError: name 'thermostat' is not defined'. This because neither of these tests is true:

Code: Select all

    if x[0]["id"] == x[1]["parentNodeId"]:
        thermostat = x[1]
    elif x[1]["id"] == x[0]["parentNodeId"]:
        thermostat = x[0]
x[0]["parentNodeId"] and x[1]["parentNodeId"] have the same value; x[0]["id"] & x[1]["id"] are different.

Any ideas?
imcfarla
Posts: 64
Joined: Monday 04 December 2017 13:18
Target OS: Linux
Domoticz version:
Contact:

Re: Read British Gas Hive Heating temperature

Post by imcfarla »

No - can you send me the json data?
I have 2 thermostat devices listed in the json, one of which is the child and that one has the temperatures.

I have spent tonight adding lights into the script
I have only got the simple dimmable ones so that is all that is catered for
To use it just add a new virtual device of type switch to the dummy hardware. Then go to the switches page and edit the new switch and change the type to dimmer.

WIP:
I have also tried to send throught the battery and signal state if the thermostat but it does not show in my devices list

Code: Select all

#!/usr/bin/env python

'''
Python script to send data from Hive to Domoticz.

Replace XXX's with your values.
'''

import requests
import json
import sys

# Replace with your Domoticz idx's
domoHost = 'XXX'
domoPort = 'XXX'
insideIdx = 'XXX'
targetIdx = 'XXX'
thermIdx = 'XXX'
heatingIdx = 'XXX'

# Dictionary of on/off light names and idx's don't include dimmers
lights = {}

# Dictionary of dimmable light names and idx's
# e.g. dimmers = {"Bedroom":5,"Porch":6,"Stairwell":7}
dimmers = {}

# Replace with your Hive credentials
hiveUser = 'XXX'
hivePass = 'XXX'

# Domoticz URL & port
DomoReadURL   = 'http://'+domoHost+':'+domoPort+'/json.htm?type=devices&rid='
DomoWriteURL  = 'http://'+domoHost+':'+domoPort+'/json.htm?type=command&param=udevice&nvalue=0&idx='
DomoSwitchURL = 'http://'+domoHost+':'+domoPort+'/json.htm?type=command&param=switchlight&idx='

requests.packages.urllib3.disable_warnings()

def domoticzread(idx, var):
   url = DomoReadURL + idx
   response = requests.get(url)
   jsonData = json.loads(response.text)
   result = jsonData['result'][0][var]
   return result;

def find_key_in_list(d, value):
    if isinstance(d, list):
        t = list(d)
        for v in d:
            if isinstance(v, dict):
                p = find_key(v, value)
                if not p:
                    t.remove(v)
        return t

def find_key(d, value):
    for k,v in d.items():
        if isinstance(v, dict):
            p = find_key(v, value)
            if p:
                return [k] + p
        elif v == value:
            return [k]

def merge_dicts(*dict_args):
    """
    Given any number of dicts, shallow copy and merge into a new dict,
    precedence goes to key value pairs in latter dicts.
    """
    result = {}
    for dictionary in dict_args:
        result.update(dictionary)
    return result

# Hive
# log on to Hive
payload = {'username':hiveUser, 'password':hivePass}
headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
url = 'https://beekeeper-uk.hivehome.com/1.0/gateway/login'
r = requests.post(url, headers=headers, data=json.dumps(payload), verify=False)
sessionId = r.json()["token"]

headers = {'Content-Type': 'application/vnd.alertme.zoo-6.2+json', 'Accept': 'application/vnd.alertme.zoo-6.2+json', \
        'X-AlertMe-Client': 'swagger', 'X-Omnia-Access-Token': sessionId}
url = 'https://api.prod.bgchprod.info:443/omnia/nodes'
r = requests.get(url, headers=headers, verify=False)

# Find thermostat node
d = r.json()["nodes"]
x = find_key_in_list(d,"http://alertme.com/schema/json/node.class.thermostat.json#")
if x:
    if x[0]["id"] == x[1]["parentNodeId"]:
        thermostat = x[1]
    elif x[1]["id"] == x[0]["parentNodeId"]:
        thermostat = x[0]
else:
     print("No thermostat found")
     thermostat = False

# get values from Hive
if thermostat:
    temp = thermostat["attributes"]["temperature"]["reportedValue"]
    targetTemp = thermostat["attributes"]["targetHeatTemperature"]["reportedValue"]
    heating = thermostat["attributes"]["stateHeatingRelay"]["reportedValue"]

x = find_key_in_list(d,"http://alertme.com/schema/json/node.class.thermostatui.json#")
if x:
    battery = x[0]["attributes"]["batteryLevel"]["reportedValue"]
    rawRssi = 0-x[0]["attributes"]["RSSI"]["reportedValue"]
    rssi = 12*rawRssi/100

state = {}
brightness = {}
x = find_key_in_list(d,"http://alertme.com/schema/json/node.class.light.json#")
if x:
    for l in x:
        # On/Off
        try:
            idx = merge_dicts(lights, dimmers)[l["name"]]
        except:
            idx = False
        if idx:
            state[idx] = "O" + l["attributes"]["state"]["reportedValue"][1:3].lower()
        # Brightness
        try:
            idx = dimmers[l["name"]]
        except:
            idx = False
        if idx:
            if state[idx] == "Off":
                brightness[idx] = 0
            else:
                brightness[idx] = l["attributes"]["brightness"]["reportedValue"]
else:
    print("No lights found")

# log out from Hive
headers = {'Content-Type': 'application/vnd.alertme.zoo-6.1+json', 'Accept': 'application/vnd.alertme.zoo-6.2+json', \
        'X-AlertMe-Client': 'Hive Web Dashboard', 'X-Omnia-Access-Token': sessionId}
url = 'https://api.prod.bgchprod.info:443/omnia/auth/sessions/' + sessionId
r = requests.delete(url, headers=headers, verify=False)

if not thermostat:
    sys.exit() # Quit if there is no thermostat found
#sys.exit()
# Domoticz
# get last values from Domoticz
last_temp = domoticzread(insideIdx, 'Temp')
last_target = domoticzread(targetIdx, 'Temp')
last_heating = domoticzread(heatingIdx, 'Status')

# change some values
temp = round(temp, 1)

if targetTemp < 7.0: targetTemp = 7.0

if heating == "ON":
        heating="On"
else:
        heating="Off"

print 'new','old'
print temp, last_temp
print targetTemp, last_target
print heating, last_heating
print 'battery: ' + str(battery)
print 'rssi: ' + str(rssi)
print state
print brightness

# send values to Domoticz (only send some if changed)
url = DomoWriteURL + insideIdx + '&svalue=' + str(temp)
r = requests.get(url)
url = DomoWriteURL + targetIdx + '&svalue=' + str(targetTemp)
r = requests.get(url)

if targetTemp != last_target:
    url = DomoWriteURL + thermIdx + '&svalue=' + str(targetTemp) + '&battery=' + str(battery) + '&rssi=' + str(rssi)
    print url
    r = requests.get(url)

if heating != last_heating:
    url = DomoSwitchURL + heatingIdx + '&switchcmd=' + heating
    r = requests.get(url)

for k,v in brightness.items():
    url = DomoSwitchURL + str(k) + '&switchcmd=Set%20Level&level=' + str(v)
    r = requests.get(url)

for k,v in state.items():
    url = DomoSwitchURL + str(k) + '&switchcmd=' + v
    r = requests.get(url)
MikeF
Posts: 350
Joined: Sunday 19 April 2015 0:36
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.2
Location: UK
Contact:

Re: Read British Gas Hive Heating temperature

Post by MikeF »

OK, solved my earlier 'problem'
- I also have 2 thermostat devices listed in the json, but these both have id's which are different to both of the parentNodeId's.

Instead, I look in 'attributes' for a key which I know is only in the child device (the one that has the temperatures) - in this case, 'stateHeatingRelay':

Code: Select all

if x:
	y = x[0]["attributes"]
	z = x[1]["attributes"]
	k = "stateHeatingRelay"
	
	if k in y:
		thermostat = y
	elif k in z:
		thermostat = z
else:
	thermostat = False
(and remove ["attributes"] in the subsequent lines).

Works for me!
MikeF
Posts: 350
Joined: Sunday 19 April 2015 0:36
Target OS: Raspberry Pi / ODroid
Domoticz version: V2022.2
Location: UK
Contact:

Re: Read British Gas Hive Heating temperature

Post by MikeF »

imcfarla wrote: Monday 04 December 2017 23:53 I have also tried to send through the battery and signal state of the thermostat but it does not show in my devices list
In my system, these can be found under ["nodes"][1] - where "name" = "Hive2".
I can get the values using this:

Code: Select all

x = find_key_in_list(d,"Hive2")

if x:
	print x[0]["attributes"]["batteryVoltage"]["reportedValue"]
	print x[0]["attributes"]["RSSI"]["reportedValue"]
imcfarla
Posts: 64
Joined: Monday 04 December 2017 13:18
Target OS: Linux
Domoticz version:
Contact:

Re: Read British Gas Hive Heating temperature

Post by imcfarla »

Ok change in tack...

I now have a proper plugin that detects (thermostat only) and adds all the devices for you!

place this code in a folder called plugin.py in a folder called Hive in the plugins directory in your domoticz folder.
i.e.
.../domoticz/plugins/Hive/plugin.py

restart domoticz <- important otherwise the plugin will not be detected.
Then go to setup and you should be able to choose Hive plugin in the Type dropdown.
Add your Hive username and password and click Add at the bottom.

Code: Select all

'''
<plugin key="HivePlug" name="Hive Plugin" author="imcfarla and mikef" version="0.1" wikilink="http://www.domoticz.com/wiki/plugins/plugin.html" externallink="https://www.google.com/">
    <params>
        <param field="Username" label="Hive Username" width="200px" required="true" default=""/>
        <param field="Password" label="Hive Password" width="200px" required="true" default=""/>
        <param field="Mode1" label="Heartbeat Multiplier" width="30px" required="true" default="6"/>
        <param field="Mode6" label="Debug" width="75px">
            <options>
                <option label="True" value="Debug"/>
                <option label="False" value="Normal"  default="true" />
            </options>
        </param>
    </params>
</plugin>
'''
import Domoticz
import sys
import json
sys.path.append('/usr/lib/python3/dist-packages')
from urllib.request import Request, urlopen
from urllib.parse import urlencode

def find_key_in_list(d, value):
    if isinstance(d, list):
        t = list(d)
        for v in d:
            if isinstance(v, dict):
                p = find_key(v, value)
                if not p:
                    t.remove(v)
        return t

def find_key(d, value):
    for (k, v) in d.items():
        if isinstance(v, dict):
            p = find_key(v, value)
            if p:
                return [k] + p
        elif v == value:
            return [k]
    
def merge_dicts(*dict_args):
    '''
    Given any number of dicts, shallow copy and merge into a new dict,
    precedence goes to key value pairs in latter dicts.
    '''
    result = { }
    for dictionary in dict_args:
        result.update(dictionary)
    return result

class BasePlugin:
    enabled = False
    
    def __init__(self):
        self.sessionId = ''
        self.counter = 0
        self.multiplier = 10
    
    def onStart(self):
        Domoticz.Log('Staring')
        if Parameters["Mode6"] == "Debug":
            Domoticz.Debugging(1)
        
        self.multiplier = int(Parameters['Mode1'])
        self.counter = self.multiplier #update immediately

        if self.sessionId == '':
            Domoticz.Debug('Creating Session')
            payload = {'username':Parameters["Username"], 'password':Parameters["Password"]}
            headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
            url = 'https://beekeeper-uk.hivehome.com/1.0/gateway/login'
            print(urlencode(payload).encode('ascii'))
            req = Request(url, data = json.dumps(payload).encode('ascii'), headers = headers, unverifiable = True)
            r = urlopen(req).read().decode('utf-8')
            self.sessionId = json.loads(r)['token']
        Domoticz.Debug(self.sessionId)
        d = self.GetDevices()
        thermostat = self.GetThermostat(d)
        if len(Devices) == 0:
            Domoticz.Log('Creating Devices')
            if thermostat:
                Domoticz.Device(Name = 'Thermostat', Unit = 1, Type = 242, Subtype = 1, DeviceID = thermostat['id']).Create()
                Domoticz.Device(Name = 'Heating', Unit = 2, TypeName = 'Switch', Switchtype = 0, DeviceID ='Hive_Heating').Create()
                Domoticz.Device(Name = 'Inside', Unit = 3, TypeName = 'Temperature', DeviceID = 'Hive_Inside').Create()
                Domoticz.Device(Name = 'Target', Unit = 6, TypeName = 'Temperature', DeviceID = 'Hive_Target').Create()
        else:
            Domoticz.Log(str(len(Devices)) + ' Devices')
            for unit in Devices:
                Domoticz.Debug(Devices[unit].Name)
    
    def onStop(self):
        Domoticz.Log('Stop')
        headers = {'Content-Type': 'application/vnd.alertme.zoo-6.1+json', 'Accept': 'application/vnd.alertme.zoo-6.2+json', \
        'X-AlertMe-Client': 'Hive Web Dashboard', 'X-Omnia-Access-Token': self.sessionId }
        url = 'https://api.prod.bgchprod.info:443/omnia/auth/sessions/' + self.sessionId
        req = Request(url, headers = headers)
        req.get_method = lambda : 'PUT'
        try:
            r = urlopen(req).read()
        except Exception as e:
            Domoticz.Debug(str(e))
    
    def onConnect(self, Connection, Status, Description):
        Domoticz.Debug('onConnect called')
    
    def onMessage(self, Connection, Data, Status, Extra):
        Domoticz.Debug('onMessage called')
    
    def onCommand(self, Unit, Command, Level, Hue):
        Domoticz.Debug('onCommand called for Unit ' + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level))
    
    def onNotification(self, Name, Subject, Text, Status, Priority, Sound, ImageFile):
        Domoticz.Debug('Notification: ' + Name + ',' + Subject + ',' + Text + ',' + Status + ',' + str(Priority) + ',' + Sound + ',' + ImageFile)
    
    def onDisconnect(self, Connection):
        Domoticz.Debug('onDisconnect called')
    
    def onHeartbeat(self):
        Domoticz.Debug('onHeartbeat called')
        if self.counter >= self.multiplier:
            Domoticz.Log('Getting Data')
            self.counter = 0
            d = self.GetDevices()
            Domoticz.Debug('Getting Temperatures')
            thermostat = self.GetThermostat(d)
            # get the temperature and heating states
            temp = thermostat["attributes"]["temperature"]["reportedValue"]
            Domoticz.Debug('Temp = ' + str(temp))
            targetTemp = thermostat["attributes"]["targetHeatTemperature"]["reportedValue"]
            if targetTemp < 7.0: targetTemp = 7.0
            Domoticz.Debug('Target = ' + str(targetTemp))
            heating = thermostat["attributes"]["stateHeatingRelay"]["reportedValue"]
            Domoticz.Debug('Heating = ' + heating)
            Domoticz.Debug('Getting Battery Status')
            thermostatui = self.GetThermostatUI(d)
            # get the battery and rssi values
            thermostat_battery = thermostatui["attributes"]["batteryLevel"]["reportedValue"]
            Domoticz.Debug('Battery = ' + str(thermostat_battery))
            thermostat_rssi = 12*((0 - thermostatui["attributes"]["RSSI"]["reportedValue"])/100)
            Domoticz.Debug('RSSI = ' + str(thermostat_rssi))
            # Loop through the devices and update temperatures
            Domoticz.Debug('Updating Devices')
            for unit in Devices:
                if Devices[unit].DeviceID == "Hive_Inside":
                    Devices[unit].Update(nValue=int(temp), sValue=str(temp))
                if Devices[unit].DeviceID == "Hive_Target":
                    Devices[unit].Update(nValue=int(targetTemp), sValue=str(targetTemp))
                if Devices[unit].DeviceID == "Hive_Heating":
                    if heating == 'ON':
                        if Devices[unit].nValue == 0:
                            Devices[unit].Update(nValue=1, sValue='On')
                    else:
                        if Devices[unit].nValue == 1:
                            Devices[unit].Update(nValue=0, sValue='Off')

            # Loop through the devices from Hive and update statuses where appropriate
            Domoticz.Debug('Checking Nodes')
            for node in d:
                #Domoticz.Debug('Node = ' + node['id'])
                for unit in Devices.keys():
                    #Domoticz.Debug('Unit ' + str(unit))
                    #Domoticz.Debug('Device ' + Devices[unit].DeviceID)
                    if node['id'] == Devices[unit].DeviceID:
                        Domoticz.Debug('Found ' + Devices[unit].Name)
                        if Devices[unit].Type == 242: #Thermostat
                            Devices[unit].Update(nValue = int(targetTemp), sValue = str(targetTemp), BatteryLevel = int(thermostat_battery), SignalLevel = int(thermostat_rssi)) 
 
        else:
            self.counter += 1
            Domoticz.Debug('Counter = ' + str(self.counter))

    def GetDevices(self):
            headers = {'Content-Type': 'application/vnd.alertme.zoo-6.2+json', 'Accept': 'application/vnd.alertme.zoo-6.2+json', \
                       'X-AlertMe-Client': 'swagger', 'X-Omnia-Access-Token': self.sessionId}
            url = 'https://api.prod.bgchprod.info:443/omnia/nodes'
            req = Request(url, headers = headers, unverifiable = True)
            try:
                r = urlopen(req).read().decode('utf-8')
            except Exception:
                print('Exception')
            return json.loads(r)['nodes']

    def GetThermostat(self, d):
        x = find_key_in_list(d, 'http://alertme.com/schema/json/node.class.thermostat.json#')
        if x:
            k = 'stateHeatingRelay'
            if k in x[0]['attributes']:
                thermostat = x[0]
            elif k in x[1]['attributes']:
                thermostat = x[1]
            else:
                thermostat = False
        else:
            thermostat = False
        return thermostat

    def GetThermostatUI(self, d):
        thermostatui = False
        x = find_key_in_list(d, 'http://alertme.com/schema/json/node.class.thermostatui.json#')
        if x:
            thermostatui = x[0]
        else: # Try a Hive2 thermostat
            x = find_key_in_list(d,"Hive2")
            if x:
                thermostatui = x[0]
        return thermostatui

_plugin = BasePlugin()

def onStart():
    _plugin.onStart()

def onStop():
    _plugin.onStop()

def onConnect(Connection, Status, Description):
    _plugin.onConnect(Connection, Status, Description)

def onMessage(Connection, Data, Status, Extra):
    _plugin.onMessage(Connection, Data, Status, Extra)

def onCommand(Unit, Command, Level, Hue):
    _plugin.onCommand(Unit, Command, Level, Hue)

def onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile):
    _plugin.onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile)

def onDisconnect(Connection):
    _plugin.onDisconnect(Connection)

def onHeartbeat():
    _plugin.onHeartbeat()

def DumpConfigToLog():
    for x in Parameters:
        if Parameters[x] != '':
            Domoticz.Debug("'" + x + "':'" + str(Parameters[x]) + "'")
    Domoticz.Debug('Device count: ' + str(len(Devices)))
    for x in Devices:
        Domoticz.Debug('Device:           ' + str(x) + ' - ' + str(Devices[x]))
        Domoticz.Debug("Device ID:       '" + str(Devices[x].ID) + "'")
        Domoticz.Debug("Device Name:     '" + Devices[x].Name + "'")
        Domoticz.Debug('Device nValue:    ' + str(Devices[x].nValue))
        Domoticz.Debug("Device sValue:   '" + Devices[x].sValue + "'")
        Domoticz.Debug('Device LastLevel: ' + str(Devices[x].LastLevel))
   
sach
Posts: 111
Joined: Wednesday 12 October 2016 14:33
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Read British Gas Hive Heating temperature

Post by sach »

Nice work.....looking forward to trying this out.
imcfarla
Posts: 64
Joined: Monday 04 December 2017 13:18
Target OS: Linux
Domoticz version:
Contact:

Re: Read British Gas Hive Heating temperature

Post by imcfarla »

Added in lights, plugs and control of the devices. Setting the temperature in Domoticz now updates Hive.

A side effect is that you can now set a light to be any percentage rather than just a multiple of 5 - wake up light here we come...

Note:
Only works for Active Light Dimmable as I haven't got any Cool to Warm or Colour Changing
ActivePlug should work but again I haven't got any so I can't test.

The Heartbeat multiplier defines how many heartbeats before it processes the data from Hive - I started off with 6 (60s) as the default but now I have added in control this really should just be 1 (10s) otherwise you wait too long before the dashboard updates to say you have switched on a light.

Same instructions apply:
place this code in a folder called plugin.py in a folder called Hive in the plugins directory in your domoticz folder.
i.e.
.../domoticz/plugins/Hive/plugin.py

restart domoticz <- important otherwise the plugin will not be detected.
Then go to setup and you should be able to choose Hive plugin in the Type dropdown.
Add your Hive username and password and click Add at the bottom.

Code: Select all

'''
<plugin key="HivePlug" name="Hive Plugin" author="imcfarla and mikef" version="0.2" wikilink="http://www.domoticz.com/wiki/plugins/plugin.html" externallink="https://www.google.com/">
    <params>
        <param field="Username" label="Hive Username" width="200px" required="true" default=""/>
        <param field="Password" label="Hive Password" width="200px" required="true" default=""/>
        <param field="Mode1" label="Heartbeat Multiplier" width="30px" required="true" default="1"/>
        <param field="Mode6" label="Debug" width="75px">
            <options>
                <option label="True" value="Debug"/>
                <option label="False" value="Normal"  default="true" />
            </options>
        </param>
    </params>
</plugin>
'''
import Domoticz
import sys
import json
sys.path.append('/usr/lib/python3/dist-packages')
from urllib.request import Request, urlopen
from urllib.parse import urlencode

def find_key_in_list(d, value):
    if isinstance(d, list):
        t = list(d)
        for v in d:
            if isinstance(v, dict):
                p = find_key(v, value)
                if not p:
                    t.remove(v)
        return t

def find_key(d, value):
    for (k, v) in d.items():
        if isinstance(v, dict):
            p = find_key(v, value)
            if p:
                return [k] + p
        elif v == value:
            return [k]

def merge_dicts(*dict_args):
    '''
    Given any number of dicts, shallow copy and merge into a new dict,
    precedence goes to key value pairs in latter dicts.
    '''
    result = { }
    for dictionary in dict_args:
        result.update(dictionary)
    return result

class BasePlugin:
    enabled = False

    def __init__(self):
        self.sessionId = ''
        self.counter = 0
        self.multiplier = 10
        self.lightsSet = set()

    def onStart(self):
        Domoticz.Log('Starting')
        if Parameters["Mode6"] == "Debug":
            Domoticz.Debugging(1)

        self.multiplier = int(Parameters['Mode1'])
        self.counter = self.multiplier #update immediately

        if self.sessionId == '':
            Domoticz.Log('Creating Session')
            payload = {'username':Parameters["Username"], 'password':Parameters["Password"]}
            headers = {'Content-Type': 'application/json', 'Accept': 'application/json'}
            url = 'https://beekeeper-uk.hivehome.com/1.0/gateway/login'
            req = Request(url, data = json.dumps(payload).encode('ascii'), headers = headers, unverifiable = True)
            r = urlopen(req).read().decode('utf-8')
            self.sessionId = json.loads(r)['token']
        Domoticz.Debug(self.sessionId)

    def onStop(self):
        Domoticz.Log('Deleting Session')
        headers = {'Content-Type': 'application/vnd.alertme.zoo-6.1+json', 'Accept': 'application/vnd.alertme.zoo-6.2+json', \
        'X-AlertMe-Client': 'Hive Web Dashboard', 'X-Omnia-Access-Token': self.sessionId }
        url = 'https://api.prod.bgchprod.info:443/omnia/auth/sessions/' + self.sessionId
        req = Request(url, headers = headers)
        req.get_method = lambda : 'DELETE'
        try:
            r = urlopen(req).read()
        except Exception as e:
            Domoticz.Log(str(e))

    def onConnect(self, Connection, Status, Description):
        Domoticz.Debug('onConnect called')

    def onMessage(self, Connection, Data, Status, Extra):
        Domoticz.Debug('onMessage called')

    def onCommand(self, Unit, Command, Level, Hue):
        Domoticz.Log('onCommand called for Unit ' + str(Unit) + ": Parameter '" + str(Command) + "', Level: " + str(Level))
        Domoticz.Debug(str(Devices[Unit].Type))
        Domoticz.Debug(str(Devices[Unit].SubType))
        Domoticz.Debug(Devices[Unit].DeviceID)
        Domoticz.Debug(str(Devices[Unit].sValue))
        headers = {'Content-Type': 'application/vnd.alertme.zoo-6.2+json', 'Accept': 'application/vnd.alertme.zoo-6.2+json', \
                   'X-AlertMe-Client': 'swagger', 'X-Omnia-Access-Token': self.sessionId}
        url = 'https://api.prod.bgchprod.info:443/omnia/nodes/' + Devices[Unit].DeviceID
        if self.isLight(Unit):
            Domoticz.Log("Setting Light Parameters")
            if str(Command) == "Set Level":
                payload = self.CreateLightPayload("ON", Level)
            if str(Command) == "On":
                payload = self.CreateLightPayload("ON", Devices[Unit].LastLevel)
            if str(Command) == "Off":
                payload = self.CreateLightPayload("OFF", Devices[Unit].LastLevel)
        elif self.isThermostat(Unit):
            payload = self.CreateThermostatPayload(Level)
        elif self.isActivePlug(Unit):
            payload = self.CreateActivePlugPayload(Level)
        else:
            payload = ""
            Domoticz.Log("Unknown Device Type")
        if payload != "":
            req = Request(url, data = json.dumps(payload).encode('ascii'), headers = headers, unverifiable = True)
            req.get_method = lambda : 'PUT'
            try:
                r = urlopen(req).read().decode('utf-8')
            except Exception as e:
                Domoticz.Log(str(e))

    def onNotification(self, Name, Subject, Text, Status, Priority, Sound, ImageFile):
        Domoticz.Debug('Notification: ' + Name + ',' + Subject + ',' + Text + ',' + Status + ',' + str(Priority) + ',' + Sound + ',' + ImageFile)

    def onDisconnect(self, Connection):
        Domoticz.Debug('onDisconnect called')

    def onHeartbeat(self):
        Domoticz.Debug('onHeartbeat called')
        if self.counter >= self.multiplier:
            foundInsideDevice = False
            foundTargetDevice = False
            foundHeatingDevice = False
            foundThermostatDevice = False

            Domoticz.Debug('Getting Data')
            self.counter = 1
            d = self.GetDevices()
            Domoticz.Debug('Getting Temperatures')
            thermostat = self.GetThermostat(d)
            if thermostat:
                # get the temperature and heating states
                temp = thermostat["attributes"]["temperature"]["reportedValue"]
                Domoticz.Debug('Temp = ' + str(temp))
                targetTemp = thermostat["attributes"]["targetHeatTemperature"]["reportedValue"]
                if targetTemp < 7.0: targetTemp = 7.0
                Domoticz.Debug('Target = ' + str(targetTemp))
                heating = thermostat["attributes"]["stateHeatingRelay"]["reportedValue"]
                Domoticz.Debug('Heating = ' + heating)
                Domoticz.Debug('Getting Battery Status')
                thermostatui = self.GetThermostatUI(d)
                # get the battery and rssi values
                thermostat_battery = thermostatui["attributes"]["batteryLevel"]["reportedValue"]
                Domoticz.Debug('Battery = ' + str(thermostat_battery))
                thermostat_rssi = 12*((0 - thermostatui["attributes"]["RSSI"]["reportedValue"])/100)
                Domoticz.Debug('RSSI = ' + str(thermostat_rssi))
                # Loop through the devices and update temperatures
                Domoticz.Debug('Updating Devices')
                for unit in Devices:
                    if Devices[unit].DeviceID == "Hive_Inside":
                        Devices[unit].Update(nValue=int(temp), sValue=str(temp))
                        foundInsideDevice = True
                    if Devices[unit].DeviceID == "Hive_Target":
                        Devices[unit].Update(nValue=int(targetTemp), sValue=str(targetTemp))
                        foundTargetDevice = True
                    if Devices[unit].DeviceID == "Hive_Heating":
                        foundHeatingDevice = True
                        if heating == 'ON':
                            if Devices[unit].nValue == 0:
                                Devices[unit].Update(nValue=1, sValue='On')
                        else:
                            if Devices[unit].nValue == 1:
                                Devices[unit].Update(nValue=0, sValue='Off')
                    if Devices[unit].DeviceID == thermostat['id']:
                        foundThermostatDevice = True
                        if Devices[unit].Type == 242: #Thermostat
                            Devices[unit].Update(nValue = int(targetTemp), sValue = str(targetTemp), BatteryLevel = int(thermostat_battery), SignalLevel = int(thermostat_rssi))
                if foundInsideDevice == False:
                    Domoticz.Device(Name = 'Inside', Unit = self.GetNextUnit(False), TypeName = 'Temperature', DeviceID = 'Hive_Inside').Create()
                    self.counter = self.multiplier
                if foundTargetDevice == False:
                    Domoticz.Device(Name = 'Target', Unit = self.GetNextUnit(False), TypeName = 'Temperature', DeviceID = 'Hive_Target').Create()
                    self.counter = self.multiplier
                if foundHeatingDevice == False:
                    Domoticz.Device(Name = 'Heating', Unit = self.GetNextUnit(False), TypeName = 'Switch', Switchtype = 0, DeviceID ='Hive_Heating').Create()
                    self.counter = self.multiplier
                if foundThermostatDevice == False:
                    Domoticz.Device(Name = 'Thermostat', Unit = self.GetNextUnit(False), Type = 242, Subtype = 1, DeviceID = thermostat['id']).Create()
                    self.counter = self.multiplier

            lights = self.GetLights(d)
            if lights:
                for node in lights:
                    for unit in Devices:
                        if node['id'] == Devices[unit].DeviceID:
                            if unit not in set(self.lightsSet):
                                self.lightsSet.add(unit)
                            if node["attributes"]["state"]["reportedValue"] == "OFF":
                                if Devices[unit].nValue != 0:
                                    Devices[unit].Update(nValue=0, sValue='Off')
                            else:
                                Domoticz.Debug("State: " + Devices[unit].sValue)
                                Domoticz.Debug("Brightness Target: " + str(Devices[unit].LastLevel))
                                Domoticz.Debug("Brightness: " + str(node["attributes"]["brightness"]["reportedValue"]))
                                if Devices[unit].LastLevel != int(node["attributes"]["brightness"]["reportedValue"]) or Devices[unit].sValue == 'Off':
                                    Devices[unit].Update(nValue=2, sValue=str(node["attributes"]["brightness"]["reportedValue"])) # 2 = Set Level
                            break
                    else:
                        Domoticz.Log("Light not found " + node["name"])
                        newUnit = self.GetNextUnit(False)
                        Domoticz.Device(Name = node["name"], Unit = newUnit, Type=244, Subtype=73, Switchtype=7, DeviceID = node['id']).Create()
                        if node["attributes"]["state"]["reportedValue"] == "OFF":
                            Devices[newUnit].Update(nValue=0, sValue='Off')
                        else:
                            Devices[newUnit].Update(nValue=2, sValue=str(node["attributes"]["brightness"]["reportedValue"])) # 2 = Set Level
            activeplugs = self.GetActivePlugs(d)
            if activeplugs:
                for node in activeplugs:
                    for unit in Devices:
                        if node['id'] == Devices[unit].DeviceID:
                            if node["attributes"]["state"]["reportedValue"] == "OFF":
                                if Devices[unit].nValue != 0:
                                    Devices[unit].Update(nValue=0, sValue='Off')
                            else:
                                Domoticz.Debug("State: " + Devices[unit].sValue)
                                if Devices[unit].nValue != 1:
                                    Devices[unit].Update(nValue=1, sValue='On')
                            break
                    else:
                        Domoticz.Log("ActivePlug not found " + node["name"])
                        newUnit = self.GetNextUnit(False)
                        Domoticz.Device(Name = node["name"], Unit = newUnit, Type=244, Subtype=73, Switchtype=0, DeviceID = node['id']).Create()
                        if node["attributes"]["state"]["reportedValue"] == "OFF":
                            Devices[newUnit].Update(nValue=0, sValue='Off')
                        else:
                            Devices[unit].Update(nValue=1, sValue='On')
        else:
            self.counter += 1
            Domoticz.Debug('Counter = ' + str(self.counter))

    def GetDevices(self):
            headers = {'Content-Type': 'application/vnd.alertme.zoo-6.2+json', 'Accept': 'application/vnd.alertme.zoo-6.2+json', \
                       'X-AlertMe-Client': 'swagger', 'X-Omnia-Access-Token': self.sessionId}
            url = 'https://api.prod.bgchprod.info:443/omnia/nodes'
            req = Request(url, headers = headers, unverifiable = True)
            try:
                r = urlopen(req).read().decode('utf-8')
            except Exception as e:
                Domoticz.Log(str(e))
            return json.loads(r)['nodes']

    def GetThermostat(self, d):
        x = find_key_in_list(d, 'http://alertme.com/schema/json/node.class.thermostat.json#')
        if x:
            k = 'stateHeatingRelay'
            if k in x[0]['attributes']:
                thermostat = x[0]
            elif k in x[1]['attributes']:
                thermostat = x[1]
            else:
                thermostat = False
        else:
            thermostat = False
        return thermostat

    def GetThermostatUI(self, d):
        thermostatui = False
        x = find_key_in_list(d, 'http://alertme.com/schema/json/node.class.thermostatui.json#')
        if x:
            thermostatui = x[0]
        else: # Try a Hive2 thermostat
            x = find_key_in_list(d,"Hive2")
            if x:
                thermostatui = x[0]
        return thermostatui

    def GetLights(self, d):
        lights = False
        x = find_key_in_list(d,"http://alertme.com/schema/json/node.class.light.json#")
        if x:
            lights = x
        return lights

    def GetActivePlugs(self, d):
        plugs = False
        x = find_key_in_list(d,"http://alertme.com/schema/json/node.class.smartplug.json#")
        if x:
            lights = x
        return plugs

    def GetNextUnit(self, unit):
        if not unit:
            nextUnit = len(Devices) + 1
        else:
            nextUnit = unit +1
        if nextUnit in Devices or nextUnit <= 1:
            nextUnit = self.GetNextUnit(nextUnit)
        return nextUnit

    def CreateLightPayload(self, State, Brightness):
        response = {}
        nodes = []
        attributes = {}
        state = {}
        brightness = {}
        brightness["targetValue"] = Brightness
        state["targetValue"] = State
        attributes["attributes"] = {"brightness":brightness,"state":state}
        nodes.append(attributes)
        response["nodes"] = nodes
        return response

    def CreateThermostatPayload(self, Temperature):
        response = {}
        nodes = []
        attributes = {}
        targetHeatTemperature = {}
        targetHeatTemperature["targetValue"] = Temperature
        attributes["attributes"] = {"targetHeatTemperature":targetHeatTemperature}
        nodes.append(attributes)
        response["nodes"] = nodes
        return response

    def CreateActivePlugPayload(self, State):
        response = {}
        nodes = []
        attributes = {}
        state = {}
        state["targetValue"] = State
        attributes["attributes"] = {"state":state}
        nodes.append(attributes)
        response["nodes"] = nodes
        return response

    def isLight(self, Unit):
        Domoticz.Debug(str(self.lightsSet))
        if Devices[Unit].Type == 244 and Devices[Unit].SubType == 73 and Unit in self.lightsSet:
            return True
        else:
            return False

    def isThermostat(self, Unit):
        if Devices[Unit].Type == 242:
            return True
        else:
            return False

    def isActivePlug(self, Unit):
        if Devices[Unit].Type == 244 and Devices[Unit].SubType == 73 and Unit not in self.lightsSet and Devices[Unit].DeviceID != "Hive_Heating":
            return True
        else:
            return False

_plugin = BasePlugin()

def onStart():
    _plugin.onStart()

def onStop():
    _plugin.onStop()

def onConnect(Connection, Status, Description):
    _plugin.onConnect(Connection, Status, Description)

def onMessage(Connection, Data, Status, Extra):
    _plugin.onMessage(Connection, Data, Status, Extra)

def onCommand(Unit, Command, Level, Hue):
    _plugin.onCommand(Unit, Command, Level, Hue)

def onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile):
    _plugin.onNotification(Name, Subject, Text, Status, Priority, Sound, ImageFile)

def onDisconnect(Connection):
    _plugin.onDisconnect(Connection)

def onHeartbeat():
    _plugin.onHeartbeat()

def DumpConfigToLog():
    for x in Parameters:
        if Parameters[x] != '':
            Domoticz.Debug("'" + x + "':'" + str(Parameters[x]) + "'")
    Domoticz.Debug('Device count: ' + str(len(Devices)))
    for x in Devices:
        Domoticz.Debug('Device:           ' + str(x) + ' - ' + str(Devices[x]))
        Domoticz.Debug("Device ID:       '" + str(Devices[x].ID) + "'")
        Domoticz.Debug("Device Name:     '" + Devices[x].Name + "'")
        Domoticz.Debug('Device nValue:    ' + str(Devices[x].nValue))
        Domoticz.Debug("Device sValue:   '" + Devices[x].sValue + "'")
        Domoticz.Debug('Device LastLevel: ' + str(Devices[x].LastLevel))
sach
Posts: 111
Joined: Wednesday 12 October 2016 14:33
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Read British Gas Hive Heating temperature

Post by sach »

Just got some bulbs in last week. Should hopefully have some time tomorrow to try this out.
sach
Posts: 111
Joined: Wednesday 12 October 2016 14:33
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Read British Gas Hive Heating temperature

Post by sach »

This is brilliant.....works great for heating. Not had a chance to try lights just yet.
You should get this added to the Python Plugins list and maybe setup a separate thread for it.
With Hive launching in Europe soon I'm sure it's going to get popular.
Excellent work sir!
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 0 guests