Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Outdated Gardena API in py-smart-gardena #57

Open
KleemannT opened this issue May 15, 2020 · 3 comments
Open

Outdated Gardena API in py-smart-gardena #57

KleemannT opened this issue May 15, 2020 · 3 comments

Comments

@KleemannT
Copy link

KleemannT commented May 15, 2020

py-smart-gardena is using the official documented Gardena-API from the Husqvarna website
https://developer.husqvarnagroup.cloud/apis/GARDENA+smart+system+API
which ist based on REST and websocket communication.

If you reverse engineer the JavaScript code of the Browser app (https://smart.gardena.com/) you will find a new API based on Server-Sent Events (SSE) and a GET-request with JSON data.
Have a look at the "Gardena-Binding" source from openHAB, you find a partial implementation of it. The new API has totally new login, locations, devices functions and much more detailled information called "abilities" per device.

I've written some small python programs which get data from this new API, but since I'm not a Python Pro, I could not finish my work. You're welcome to get my "small code" and some hints (Postman scripts) if you rewrite parts of py-smart-gardena.

import json
import pprint
import sseclient
import time
import sys, traceback
import logging

logging.basicConfig(
format='%(asctime)s %(levelname)-8s %(message)s',
level=logging.DEBUG,
datefmt='%Y-%m-%d %H:%M:%S',
filename="events-{}.txt".format(time.strftime("%Y%m%d-%H%M")))

def with_urllib3(url):
"""Get a streaming response for the given event feed using urllib3."""
import urllib3
http = urllib3.PoolManager(timeout=urllib3.Timeout(connect=120.0, read=3600.0))
return http.request(
'GET',
url,
headers={
'accept': 'text/event-stream',
'referer': 'https://smart.gardena.com/',
'origin': 'https://smart.gardena.com/',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'cross-site'
},
preload_content=False)

def with_requests(url):
"""Get a streaming response for the given event feed using requests."""
import requests
headers={
'accept': 'text/event-stream',
'referer': 'https://smart.gardena.com/',
'origin': 'https://smart.gardena.com/',
'sec-fetch-dest': 'empty',
'sec-fetch-mode': 'cors',
'sec-fetch-site': 'cross-site'
}
return requests.get(url, stream=True, headers=headers, timeout=None)

base_url = "https://rt-api.sg.dss.husqvarnagroup.net/bff/v1/events/"
location_id = "059...-...-...0c8"
session = "ey...qJg" #very long session string
url = base_url + location_id + "?session=" + session

#response = with_urllib3(url)
response = with_requests(url)

fmt_date = time.strftime("%Y-%m-%d %H:%M:%S")
print(f"Start: {fmt_date}")

client = sseclient.SSEClient(response)

try:
for event in client.events():
pprint.pprint(json.loads(event.data))

except requests.exceptions.Timeout as e:
print(e)

except KeyboardInterrupt:
print ("Interrupted by KeyboardInterrupt")
#smart_system.quit()
print ("exited by KeyboardInterrupt")
sys.exit(0)
else:
fmt_date = time.strftime("%Y-%m-%d %H:%M:%S")
print(f"End: {fmt_date}")

Get login/auth token:
POST https://smart.gardena.com/v1/auth/token
BODY: {"data":{"type":"token","attributes":{"username":"","password":"","client_id":"smartgarden-jwt-client"}}}

ANSWER BODY:
{
"data": {
"id": "eyJ...yYA #a very long session string ",
"type": "token",
"attributes": {
"expires_in": 863999,
"refresh_token": "a97...-...-...307b",
"provider": "husqvarna",
"user_id": "1b5...-...-...-...ba1",
"scope": "iam:read iam:write",
"client_id": "smartgarden-jwt-client"
}
}
}

@grm
Copy link
Owner

grm commented May 27, 2020

Thx for the update and the insight in the dev.

I will try to update that !

@grm
Copy link
Owner

grm commented May 30, 2020

I will have a deep look into this, but by using an unofficial API, we could have issue regarding breaking change and our integration won't work the time we analyse the changes and make changes to the code.

I am not sure this is the right move to do if we want a stable system (something I want regarding my home automations ;) )

Grm

@grm
Copy link
Owner

grm commented May 31, 2020

And i have a question,what permits this new api that is not permitted by the official API ?
The first versions of python librairies were reverse engeneering ports

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants