Package: geniushub-client
geniushub-clientThis is a Python library to provide access to aGenius Hubby abstracting itsRESTful API. It usesaiohttpand is therefore async-friendly.This library can use either theofficalv1 APIwith ahub token, or thelatestv3 API(using your ownusername and password). In either case, the library will return v1-compatible results wherever possible (this is not a trivial task).If you use the v3 API, you can interrogate the hub directly, rather than via Heat Genius' own servers. Note that the v3 API is undocumented, and so this functionality may break at any time. In fact, the v3 to v1 conversion if best efforts and may even be broken as is for some edge cases - it was tested with HW, on/off (i.e. smart plugs), and radiators only.It is a WIP, and may be missing some functionality. In addition, there are some other limitations (see below).It is based upon work by@GeoffAtHomeand [@zxdavb]](https://github.com/manzanotti/geniushub-client/commits?author=zxdavb) - thanks!Current limitationsCurrent limitations & to-dos include:ghclient.pyis not completeschedules are read-onlywhen using the v3 API, zones sometimes have the wrong value foroccupiedThe library will return v1 API responses wherever possible, however:the only code available to reverse-engineer is from the web app, butthe Web app does not correlate completely with the v1 API (e.g. issue messages, occupied state)Thus, always check your output against the corresponding v1 API response rather than the web app.InstallationEither clone this repository and runpython setup.py install, or install from pip usingpip install geniushub-client.Using the LibrarySeeghclient.pyfor example code. You can also useghclient.pyfor ad-hoc queries:pythonghclient.py-?There are two distinct options for accessing a Genius Hub:Option 1:hub tokenonly:requires a hub token obtained fromhttps://my.geniushub.co.uk/tokensuses the v1 API - which is well-documentedinterrogates Heat Genius' own servers (so is slower)Option 2: hubhostname/addresswithuser credentials:requires yourusername&password, as used withhttps://www.geniushub.co.uk/appuses the v3 API - results are WIP and may not be what you expectinterrogates the hub directly (so is faster), via port :1223HUB_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsInZlc..."HUB_ADDRESS="my-geniushub.dyndns.com"USERNAME="my-username"PASSWORD="my-password"pythonghclient.py${HUB_TOKEN}issues

pythonghclient.py${HUB_ADDRESS}-u${USERNAME}-p${PASSWORD}zones-vYou can compare any output to the 'official' API (v1 response):curl-H"authorization: Bearer${HUB_TOKEN}"-XGEThttps://my.geniushub.co.uk/v1/zones/summary
pythonghclient.py${HUB_TOKEN}zones

curl-H"authorization: Bearer${HUB_TOKEN}"-XGEThttps://my.geniushub.co.uk/v1/devices
pythonghclient.py${HUB_ADDRESS}-u${USERNAME}-p${PASSWORD}devices-v

curl-H"authorization: Bearer${HUB_TOKEN}"-XGEThttps://my.geniushub.co.uk/v1/issues
pythonghclient.py${HUB_ADDRESS}-u${USERNAME}-p${PASSWORD}issuesYou can obtain the 'raw' v3 API responses (i.e. the JSON is not converted to the v1 schema):pythonghclient.py${HUB_ADDRESS}-u${USERNAME}-p${PASSWORD}zones-vvv
pythonghclient.py${HUB_ADDRESS}-u${USERNAME}-p${PASSWORD}devices-vvvTo obtain the 'official' v3 API responses takes a little work.  First, use python to obtain aHASH:>>>fromhashlibimportsha256>>>hash=sha256()>>>hash.update(("my_username"+"my_password").encode('utf-8'))>>>print(hash.hexdigest())001b24f45b...Then you can usecurl:curl--user${USERNAME}:${HASH}-XGEThttp://${HUB_ADDRESS}:1223/v3/zonesAdvanced FeaturesWhen used as a library, there is the option to utilize the referencing module's ownaiohttp.ClientSession()(recommended).Here is an example, but seeghclient.pyfor a more complete example:importasyncioimportaiohttpfromgeniushubclientimportGeniusHubmy_session=aiohttp.ClientSession()...ifnot(usernameorpassword):hub=GeniusHub(hub_id=hub_address,username=username,password=password,session=my_session)else:hub=GeniusHub(hub_id=hub_token,session=my_session)awaithub.update()# enumerate all zones, devices and issueshub.verbosity=0# same as v1/zones/summary, v1/devices/summaryprint(hub.zones)hub.verbosity=1# default, same as v1/zones, v1/devices, v1/issuesprint(hub.devices)print(hub.zone_by_id[3].data["temperature"])print(hub.device_by_id["2-2"].data)awaitmy_session.close()Unit testsPlease see the README.md file in the tests folder for more details on unit tests protocol.QA/CI via CircleCIQA includes comparing JSON fromcURLwith output from this app usingdiff, for example:(venv)root@hostname:~/$curl-XGEThttps://my.geniushub.co.uk/v1/zones-H"authorization: Bearer${HUB_TOKEN}"|\python-c"import sys, json; print(json.dumps(json.load(sys.stdin, parse_float=lambda x: int(float(x))), indent=4, sort_keys=True))">a.out(venv)root@hostname:~/$pythonghclient.py${HUB_ADDRESS}-u${USERNAME}-p${PASSWORD}zones-v|\python-c"import sys, json; print(json.dumps(json.load(sys.stdin, parse_float=lambda x: int(float(x))), indent=4, sort_keys=True))">b.out(venv)root@hostname:~/$diffa.outb.out