MadPatrick / somfy

Tahoma/Conexoon plugin for IO blinds, this plugin require internet connexion and a Somfy account
GNU General Public License v3.0
14 stars 3 forks source link

Create access to local API #15

Closed JanJaapKo closed 1 year ago

JanJaapKo commented 1 year ago

The Somfy box offers also a local API, which will replace at some point the web based API. With this improvement we will add support from the plugin to the local API.

API description: https://github.com/Somfy-Developer/Somfy-TaHoma-Developer-Mode

ab10002 commented 1 year ago

Insecure but I'm connected! Please Select:20 20 /usr/lib/python3/dist-packages/urllib3/connection.py:362: SubjectAltNameWarning: Certificate for 0000-0000-0000.local has no subjectAltName, falling back to check for a commonName for now. This feature is being removed by major browsers and deprecated by RFC 2818. (See https://github.com/shazow/urllib3/issues/497 for details.) SubjectAltNameWarning { "protocolVersion": "2022.4.4-10" } Press Enter to continue...

in /ect/host: ipaddress pin.local

in tahoma_local.py: import urllib3 urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

And:

        #self.base_url = "https://gateway-" + str(pin) + ".local:" + str(port) + "/enduser-mobile-web/1/enduserAPI"
        self.base_url = "https://" + str(pin) + ".local:" + str(port) + "/enduser-mobile-web/1/enduserAPI"
ab10002 commented 1 year ago

Have you seen this website ?

https://somfy-developer.github.io/Somfy-TaHoma-Developer-Mode/#/

and the integration in Homeassistance

https://github.com/home-assistant/core/pull/71644/files

Maybe it helps

Yes and this one; https://www.postman.com/descent-module-geologist-46261774/workspace/somfy-api-s/collection/22623012-1ae7d722-6a6b-4427-915e-b714969a9c00

ab10002 commented 1 year ago

This is nicer;

import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()

Please Select:20 20 { "protocolVersion": "2022.4.4-10" } Press Enter to continue...

ab10002 commented 1 year ago

20 works okay now

MadPatrick commented 1 year ago

I'm still getting this error

`Traceback (most recent call last): File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 672, in urlopen chunked=chunked, File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 376, in _make_request self._validate_conn(conn) File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 994, in _validate_conn conn.connect() File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/connection.py", line 408, in connect sslcontext=context, File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/util/ssl.py", line 370, in ssl_wrap_socket return context.wrap_socket(sock, server_hostname=server_hostname) File "/usr/lib64/python3.6/ssl.py", line 365, in wrap_socket _context=self, _session=session) File "/usr/lib64/python3.6/ssl.py", line 776, in init self.do_handshake() File "/usr/lib64/python3.6/ssl.py", line 1036, in do_handshake self._sslobj.do_handshake() File "/usr/lib64/python3.6/ssl.py", line 648, in do_handshake self._sslobj.do_handshake() ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:877)

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "/usr/lib/python3.6/site-packages/requests/adapters.py", line 438, in send timeout=timeout File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/connectionpool.py", line 720, in urlopen method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2] File "/usr/lib/python3.6/site-packages/requests/packages/urllib3/util/retry.py", line 436, in increment raise MaxRetryError(_pool, url, error or ResponseError(cause)) requests.packages.urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='xxxx-xxxx-xxxx.local', port=8443): Max retries exceeded with url: /enduser-mobile-web/1/enduserAPI/apiVersion (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:877)'),))

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "test_tahoma.py", line 70, in response = theBox.get_version() File "/var/domoticz/plugins/somfy/tahoma_local.py", line 144, in get_version response = requests.get(self.base_url + "/apiVersion", headers=self.headers_json) File "/usr/lib/python3.6/site-packages/requests/api.py", line 72, in get return request('get', url, params=params, kwargs) File "/usr/lib/python3.6/site-packages/requests/api.py", line 58, in request return session.request(method=method, url=url, kwargs) File "/usr/lib/python3.6/site-packages/requests/sessions.py", line 530, in request resp = self.send(prep, send_kwargs) File "/usr/lib/python3.6/site-packages/requests/sessions.py", line 651, in send r = adapter.send(request, kwargs) File "/usr/lib/python3.6/site-packages/requests/adapters.py", line 502, in send raise ConnectionError(e, request=request) requests.exceptions.ConnectionError: HTTPSConnectionPool(host='xxxx-xxxx-xxxx.local', port=8443): Max retries exceeded with url: /enduser-mobile-web/1/enduserAPI/apiVersion (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:877)'),)) `

ab10002 commented 1 year ago

Did you edit the new params.py??

MadPatrick commented 1 year ago

Yes and also /etc/host

ab10002 commented 1 year ago

It's like my first error. Maybe a compleet new clone helps?

MadPatrick commented 1 year ago

Unfortunately. Getting the same error

ab10002 commented 1 year ago

Or python, ssl version different

ab10002 commented 1 year ago

openssl version OpenSSL 1.1.1n 15 Mar 2022

python3 --version Python 3.7.3

I'v read somewhere that ssl had issues with certificaions

MadPatrick commented 1 year ago

My homeserver is running on Centos7, so not fully up-to-date:

openssl version
OpenSSL 1.0.2k-fips  26 Jan 2017

python3 -V
Python 3.6.8

Tried on on Debian 11 test VM

openssl version
OpenSSL 1.1.1n 15 Mar 2022

python3 --version
Python 3.9.2

Same problem

MadPatrick commented 1 year ago

Looks like a common issue with uncertified HTTPS and cerificates

https://sectigostore.com/page/what-is-an-ssl-certificate_verify_failed-error-and-how-do-i-resolve-it/ https://stackoverflow.com/questions/27835619/urllib-and-ssl-certificate-verify-failed-error https://www.howtouselinux.com/post/ssl-certificate_verify_failed-in-python

Can we by-pass this check ?

ab10002 commented 1 year ago

Looks like a common issue with uncertified HTTPS and cerificates

https://sectigostore.com/page/what-is-an-ssl-certificate_verify_failed-error-and-how-do-i-resolve-it/ https://stackoverflow.com/questions/27835619/urllib-and-ssl-certificate-verify-failed-error https://www.howtouselinux.com/post/ssl-certificate_verify_failed-in-python

Can we by-pass this check ?

Is allready done by: import requests.packages.urllib3 requests.packages.urllib3.disable_warnings()

ab10002 commented 1 year ago

btw, i had to do pip3 install consolemenu AND console-menu

JanJaapKo commented 1 year ago

Did you try this? pip3 install --upgrade certifi

MadPatrick commented 1 year ago

yes

ab10002 commented 1 year ago

very odd, i'm on Debian 10 too

ab10002 commented 1 year ago

pip3 list Package Version


ansiwrap 0.8.4 asn1crypto 0.24.0 certifi 2018.8.24 chardet 3.0.4 console-menu 0.7.1 ConsoleMenu 1.0.1 cryptography 2.6.1 debugpy 1.6.3 entrypoints 0.3 httplib2 0.11.3 idna 2.6 keyring 17.1.1 keyrings.alt 3.1.1 pip 18.1 pycrypto 2.6.1 pycurl 7.43.0.2 PyGObject 3.30.4 PySimpleSOAP 1.16.2 python-apt 1.8.4.3 python-debian 0.1.35 python-debianbts 2.8.2 pyxdg 0.25 reportbug 7.5.3-deb10u1 requests 2.21.0 SecretStorage 2.3.1 setuptools 40.8.0 six 1.12.0 textwrap3 0.9.2 urllib3 1.24.1 wheel 0.32.3

MadPatrick commented 1 year ago

when i try with my windows webbrowser to connect i'm NOT able to find the box with https://xxxx-xxxx-xxxx.local:8443/enduser-mobile-web/1/enduserAPI

When i do https://gateway-xxxx-xxxx-xxxx.local:8443/enduser-mobile-web/1/enduserAPI

I can connect with a certifcate error image

MadPatrick commented 1 year ago

Package Version


ansiwrap 0.8.4 attrs 20.2.0 babelfish 0.6.0 backoff 1.10.0 backoff-utils 1.0.1 certifi 2022.9.14 cffi 1.14.2 chardet 3.0.4 Cheetah3 3.2.5 cheroot 8.4.2 CherryPy 18.6.0 configobj 5.0.6 console-menu 0.7.1 ConsoleMenu 1.0.1 cryptography 3.1 distro 1.5.0 feedparser 5.2.1 guessit 3.3.1 idna 2.10 importlib-metadata 1.7.0 importlib-resources 3.0.0 jaraco.classes 3.1.0 jaraco.collections 3.0.0 jaraco.functools 3.0.1 jaraco.text 3.2.0 Jinja2 2.11.1 jsonschema 3.2.0 MarkupSafe 0.23 more-itertools 8.5.0 notify2 0.3.1 pip 21.3 portend 2.6 puremagic 1.11 pycparser 2.20 pyroute2 0.4.13 pyrsistent 0.16.0 PySocks 1.6.8 python-dateutil 2.8.2 pytz 2020.1 rebulk 3.0.1 requests 2.14.2 rfc3986 1.3.0 rpm 4.11.3 sabyenc3 4.0.2 setuptools 39.2.0 six 1.14.0 templated-dictionary 1.1 tempora 4.0.0 textwrap3 0.9.2 urllib3 1.25.6 validator-collection 1.4.2 zc.lockfile 2.0 zipp 3.1.0

ab10002 commented 1 year ago

urllib3 versions are different..

JanJaapKo commented 1 year ago

and certifi too

MadPatrick commented 1 year ago

Mine looks newer then ab10002

ab10002 commented 1 year ago

Okay, i upgrade these two packages.. And yes, i'v got these errors too!

MadPatrick commented 1 year ago

Okay, i upgrade these two packages.. And yes, i'v got these errors too!

Ok. So you could reproduce them. Not good.... but good, because i lost track on solutions

ab10002 commented 1 year ago

You can try this: python3 -m pip3 install urllib3==1.24.1

MadPatrick commented 1 year ago

pip3 list

Same problem. Also tried to go back to older certifi version pip3 install certifi==2018.8.24

No success

ab10002 commented 1 year ago

Your python version? 3.6 is too old for domiticz; Installation Prerequisites Python version 3.7 or higher required & Domoticz version 2022.1 (due to extended plugin framework) or greater.

First, Follow the Domoticz guide on Using Python Plugins.

To install:

sudo apt-get update sudo apt-get install python3 libpython3-dev libpython3.7-dev sudo apt-get install python3-requests

MadPatrick commented 1 year ago

Centos7 is runing on 3.6.8 and is the latest version available

As mention above i've tried on Debian11 with Python3.9 and same issue

ab10002 commented 1 year ago

I did a fresh install Debian 11.5, python 3.9: pi@vm-domoticz:~/domoticz/plugins/somfy$ python3 test_tahoma.py Traceback (most recent call last): File "/home/pi/domoticz/plugins/somfy/test_tahoma.py", line 18, in mymenu = consolemenu.SelectionMenu(menuoptions) AttributeError: module 'consolemenu' has no attribute 'SelectionMenu'

JanJaapKo commented 1 year ago

You need to install console-menu as well....

I did some googling and found this on installation of certificates: https://raspberrypi.stackexchange.com/questions/76419/entrusted-certificates-installation

Can you try to install the certificate metion on the page in the very first comment here?

ab10002 commented 1 year ago

You need to install console-menu as well....

I have allready👍 console-menu 0.7.1 ConsoleMenu 1.0.1

MadPatrick commented 1 year ago

Same here. I've tried on Debian 11 with python 3.9.2 and on Rasberry PI with 3.7.3 Both are give the same error

python3 test_tahoma.py
Traceback (most recent call last):
  File "/var/domoticz/somfy/test_tahoma.py", line 18, in <module>
    mymenu = consolemenu.SelectionMenu(menuoptions)
AttributeError: module 'consolemenu' has no attribute 'SelectionMenu'
MadPatrick commented 1 year ago

I did some googling and found this on installation of certificates: https://raspberrypi.stackexchange.com/questions/76419/entrusted-certificates-installation

Can you try to install the certificate metion on the page in the very first comment here?

I've tried it and added the entrust_l1k.crt, but same problem when trying with lynx to enter the link (console menu is not working) ;-)

lynx https://gateway-xxxx-xxxx-xxxx.local:8443/enduser-mobile-web/1/enduserAPI

MadPatrick commented 1 year ago

I did a fresh install Debian 11.5, python 3.9: pi@vm-domoticz:~/domoticz/plugins/somfy$ python3 test_tahoma.py Traceback (most recent call last): File "/home/pi/domoticz/plugins/somfy/test_tahoma.py", line 18, in mymenu = consolemenu.SelectionMenu(menuoptions) AttributeError: module 'consolemenu' has no attribute 'SelectionMenu'

Looks like an Debian issue. I've tried a test script (https://github.com/aegirhall/console-menu) on Debian11, Raspberry Pi and Centos7 The script is working on Centos7 and not on Debian11 and PI Centos7 - python3.6.8 Debian - python 3.9.2 PI - python 3.7.3

ab10002 commented 1 year ago

I'm gona test with a lower debian version. New is not always good🤣

ab10002 commented 1 year ago

YES, Debian 11.3 is okay!

With: sudo apt install python3-venv python3-pip

Did a reinstall on debian 11.5 that's now working too!

ab10002 commented 1 year ago

I did some googling and found this on installation of certificates: https://raspberrypi.stackexchange.com/questions/76419/entrusted-certificates-installation

Can you try to install the certificate metion on the page in the very first comment here?

Had also a cert issue and solved

dpkg-reconfigure ca-certificates

ab10002 commented 1 year ago

Import certificate:

sudo mkdir /usr/share/ca-certificates/local

cd /usr/share/ca-certificates/local sudo wget https://ca.overkiz.com/overkiz-root-ca-2048.crt

sudo dpkg-reconfigure ca-certificates

select yes, local/overkiz-root-ca-2048.crt and yes

ab10002 commented 1 year ago

Getting local API devices: test_tahoma.py:

import time
import logging
import json
import consolemenu
#import tahoma
from tahoma_local import TahomaWebApi as tahoma
from tahoma_local import SomfyBox
import exceptions
from params import *

logging.basicConfig(format='%(asctime)s - %(levelname)-8s - %(filename)-18s - %(message)s', filename='somfy_test.log',
                    level=logging.DEBUG)
logging.info("=== starting test run ===")

#menuoptions = ['0 exit',"1 log in", "2 register", "3 check log in", "4 generate toke", "5 activate token", "6 get tokens", "7 delete token", 
#    "10 get devices", "11 get events", "12 send command",
#    "20 get local API version"]
menuoptions = ['0 exit',"1 log in", "2 register", "3 check log in", "4 generate toke", "5 activate token", "6 get tokens", "7 delete token", 
    "10 get local devices", "11 get local events", "12 send command",
    "20 get local API version"]
mymenu = consolemenu.SelectionMenu(menuoptions)

device_list = list()

tahoma = tahoma()
theBox = SomfyBox(p_pin, p_port)

if tahoma.cookie is None:
    tahoma.cookie = dict(JSESSIONID='F290EEAEC03B4838EBDA4B0CD0034BAB')

if True:
    while True:
        for i in menuoptions:
            print(i) 
        x = int(input("Please Select:"))
        print(x)
        if x == 0: 
            logging.info("== end test run ===")
            exit()
        if x == 1: #log in
            status = False
            try:
                status = tahoma.tahoma_login(p_email, p_password)
            except exceptions.LoginFailure as exp:
                print("Failed to login: " + str(exp))
            if tahoma.cookie is None:
                tahoma.cookie = dict(JSESSIONID='F290EEAEC03B4838EBDA4B0CD0034BAB')
            print("login status: "+str(status))
        if x == 2: # registyer listener
            tahoma.register_listener()
            if tahoma.listenerId is None:
                tahoma.listenerId = 'b4e62511-ac10-3e01-60e0-9b9f656aea77'
        if x == 3: print(str(tahoma.logged_in)) #check log in
        if x == 4: #generate token
            response = tahoma.generate_token(p_pin)
            print(json.dumps(response, sort_keys = True, indent=4))
        if x == 5: #activate token
            response = tahoma.activate_token(p_pin)
            print(json.dumps(response, sort_keys = True, indent=4))
        if x == 6: #get list of tokens
            response = tahoma.get_tokens(p_pin)
            print(json.dumps(response, sort_keys = True, indent=4))
        if x == 7:#delete token
            uuid = input("Please enter uuid to delete:")
            response = tahoma.delete_tokens(p_pin, uuid)
            print(json.dumps(response, sort_keys = True, indent=4))
        #if x == 10: print(tahoma.get_devices(device_list))
        if x == 10: #get devices of local API
            response = theBox.get_devices()
            print(json.dumps(response, sort_keys = True, indent=4))
        input("Press Enter to continue...")
        #if x == 11: print(tahoma.get_events())
        if x == 11: #get events of local API
            response = theBox.get_events()
            print(json.dumps(response, sort_keys = True, indent=4))
        input("Press Enter to continue...")
        if x == 12: 
            data = '{"actions": [{"commands": [{"name": "open"}], "deviceURL": "io://1237-2024-7920/10464619"}], "label": "Domoticz - Somfy - Kamer_Klein - open"}'
            print(tahoma.tahoma_command(json.dumps(data)))
        if x == 20: #get version of local API
            response = theBox.get_version()
            print(json.dumps(response, sort_keys = True, indent=4))
        input("Press Enter to continue...")
        # except (ValueError) as err:
            # print("error in menu keuze")
else:
    logging.error("initialisation failed")
ab10002 commented 1 year ago

tahoma_local.py:


from lib2to3.pgen2 import tokenize
import requests
import logging
import exceptions
import urllib.parse
import datetime
import time
import json

try:
    import DomoticzEx as Domoticz
except ImportError:
    import fakeDomoticz as Domoticz

import requests.packages.urllib3
requests.packages.urllib3.disable_warnings()

class TahomaWebApi:
    def __init__(self):
        self.base_url = "https://ha101-1.overkiz.com"
        self.headers_url = {"Content-Type": "application/x-www-form-urlencoded"}
        self.headers_json = {"Content-Type": "application/json"}
        self.login_url = "/enduser-mobile-web/enduserAPI/login"
        self.timeout = 10
        self.__expiry_date = datetime.datetime.now()
        self.logged_in_expiry_days = 6
        self.cookie = None
        self.token = None
        self.__logged_in = False

    @property
    def logged_in(self):
        logging.debug("checking logged in status: self.__logged_in = "+str(self.__logged_in)+" and self.__expiry_date >= datetime.datetime.now() = " + str(self.__expiry_date >= datetime.datetime.now()))
        if self.__logged_in and (self.__expiry_date >= datetime.datetime.now()):
            return True
        else:
            return False

    def tahoma_login(self, username, password):
        data = {"userId": username, "userPassword": password}
        response = requests.post(self.base_url + self.login_url, headers=self.headers_url, data=data, timeout=self.timeout)
        Data = response.json()
        logging.debug("Login respone: status_code: '"+str(response.status_code)+"' reponse body: '"+str(Data)+"'")

        if (response.status_code == 200 and not self.__logged_in):
            self.__logged_in = True
            self.__expiry_date = datetime.datetime.now() + datetime.timedelta(days=self.logged_in_expiry_days)
            logging.info("Tahoma authentication succeeded, login valid until " + self.__expiry_date.strftime("%Y-%m-%d %H:%M:%S"))
            #self.cookie = response.cookies
            self.cookie = response.cookies
            logging.debug("login: cookies: '"+ str(response.cookies)+"', headers: '"+str(response.headers)+"'")
            #self.register_listener()

        elif ((response.status_code == 401) or (response.status_code == 400)):
            strData = Data["error"]
            #logging.error("Tahoma error: must reconnect")
            self.__logged_in = False
            self.cookie = None
            self.listenerId = None

            if ("Too many" in strData):
                logging.error("Too many connections, must wait")
                #self.heartbeat = True
                raise exceptions.LoginFailure("Too many connections, must wait")
            elif ("Bad credentials" in strData):
                logging.error("login failed: Bad credentials, please update credentials and restart plugin")
                #self.heartbeat =  False
                raise exceptions.LoginFailure("Bad credentials, please update credentials and restart plugin")
            else:
                logging.error("login failed, unhandled reason: "+strData)
                raise exceptions.LoginFailure("login failed, unhandled reason: "+strData)

            if (not self.__logged_in):
                self.tahoma_login(username, password)
                return
        return self.__logged_in

    def generate_token(self, pin):
        url_gen = "/enduser-mobile-web/enduserAPI/config/"+pin+"/local/tokens/generate"
        logging.debug("generate token: url_gen = '" + url_gen + "'")
        logging.debug("generate token: cookie = '" + str(self.cookie) + "'")
        response = requests.get(self.base_url + url_gen, headers=self.headers_json, cookies=self.cookie)

        if response.status_code == 200:
            self.token = response.json()['token']
            logging.debug("succeeded to activate token: " + str(self.token))
        elif ((response.status_code == 401) or (response.status_code == 400)):
            self.__logged_in = False
            self.cookie = None
            logging.error("failed to generate token")
            raise exceptions.LoginFailure("failed to generate token")
        return response.json()

    def activate_token(self, pin):
        url_act = "/enduser-mobile-web/enduserAPI/config/"+pin+"/local/tokens"
        data_act = {"label": "Domoticz token", "token": self.token, "scope": "devmode"}
        response = requests.post(self.base_url + url_act, headers=self.headers_json, json=data_act, cookies=self.cookie)

        if response.status_code == 200:
            #self.token = response.json()['token']
            logging.debug("succeeded to activate token: " + str(self.token))
        elif ((response.status_code == 401) or (response.status_code == 400)):
            self.__logged_in = False
            self.cookie = None
            logging.error("failed to activate token")
            raise exceptions.LoginFailure("failed to activate token")
        return response.json()

    def get_tokens(self, pin):
        url_act = "/enduser-mobile-web/enduserAPI/config/"+pin+"/local/tokens/devmode"
        response = requests.get(self.base_url + url_act, headers=self.headers_json, cookies=self.cookie)

        if response.status_code == 200:
            #self.token = response.json()['token']
            logging.debug("succeeded to get tokens: " + str(response.json()))
        elif ((response.status_code == 401) or (response.status_code == 400)):
            self.__logged_in = False
            self.cookie = None
            logging.error("failed to get tokens")
            raise exceptions.LoginFailure("failed to get tokens")
        return response.json()

    def delete_tokens(self, pin, uuid):
        url_del = "/enduser-mobile-web/enduserAPI/config/"+pin+"/local/tokens/"+str(uuid)
        response = requests.delete(self.base_url + url_del, headers=self.headers_json, cookies=self.cookie)

        if response.status_code == 200:
            logging.debug("succeeded to delete token: " + str(response.json()))
        elif ((response.status_code == 401) or (response.status_code == 400)):
            self.__logged_in = False
            self.cookie = None
            logging.error("failed to delete token")
            raise exceptions.LoginFailure("failed to delete tokens")
        return response.json()

class SomfyBox:
    def __init__(self, pin, port):
        self.base_url = "https://" + str(pin) + ".local:" + str(port) + "/enduser-mobile-web/1/enduserAPI"
        #self.headers_json = {"Content-Type": "application/json", "Authorization": "Bearer "}
        self.headers_json = {"Content-Type": "application/json", "Authorization": "Bearer 1234567890xxxxxxxxxx"} # put here generated 20char token

    def set_token(self, token):
        self.headers_json["Authorization"] = "Bearer " + str(token)

    def get_version(self):
        response = requests.get(self.base_url + "/apiVersion", headers=self.headers_json)
        if response.status_code == 200:
            logging.debug("succeeded to get API version: " + str(response.json()))
        elif ((response.status_code == 401) or (response.status_code == 400)):
            self.__logged_in = False
            self.cookie = None
            logging.error("failed to get API version")
            raise exceptions.LoginFailure("failed to get API version")
        return response.json()

    def get_devices(self):
        #response = requests.get(self.base_url + "/apiVersion", headers=self.headers_json)
        response = requests.get(self.base_url + "/setup/devices", headers=self.headers_json)
        print (response)
        if response.status_code == 200:
            logging.debug("succeeded to get local API devices: " + str(response.json()))
        elif ((response.status_code == 401) or (response.status_code == 400)):
            self.__logged_in = False
            self.cookie = None
            logging.error("failed to get local API devices")
            raise exceptions.LoginFailure("failed to get local API devices")
        return response.json()

    def get_events(self):
        #response = requests.get(self.base_url + "/apiVersion", headers=self.headers_json)
        response = requests.get(self.base_url + "/events/<uuid>fetch", headers=self.headers_json)
        print (response)
        if response.status_code == 200:
            logging.debug("succeeded to get local API events: " + str(response.json()))
        elif ((response.status_code == 401) or (response.status_code == 400)):
            self.__logged_in = False
            self.cookie = None
            logging.error("failed to get local API events")
            raise exceptions.LoginFailure("failed to get local API events")
        return response.json()

    def new_method(self):
        self.set_token()
JanJaapKo commented 1 year ago

@ab10002 does this get_events method work? That endpoint you're using is not documented....

I've pushed a new version with at least the get_devices in. I will move it into another branch now to restructure the existing bit such that it will get the same interface towards Domoticz as the new local interface. This will make it easier to maintain. Will provide instructions how to pull later

ab10002 commented 1 year ago

@ab10002 does this get_events method work? That endpoint you're using is not documented....

I've pushed a new version with at least the get_devices in. I will move it into another branch now to restructure the existing bit such that it will get the same interface towards Domoticz as the new local interface. This will make it easier to maintain. Will provide instructions how to pull later

No, getting the right uuid is a problem

JanJaapKo commented 1 year ago

OK get it, that should be the listener ID. Just pushed new version. Be sure to do 23 before 24 (otherwise a nice error will be thrown)

ab10002 commented 1 year ago

Please Select:23 23 Traceback (most recent call last): File "/home/pi/somfy/test_tahoma.py", line 79, in response = theBox.register_listener() File "/home/pi/somfy/tahoma_local.py", line 205, in register_listener raise exceptions.LoginFailure("failed to get local API events") exceptions.LoginFailure: failed to get local API events

2022-09-26 20:28:57,198 - INFO     - test_tahoma.py     - === starting test run ===
2022-09-26 20:29:04,696 - DEBUG    - connectionpool.py  - Starting new HTTPS connection (1): 0000-0000-0000.local:8443
2022-09-26 20:29:04,827 - DEBUG    - connectionpool.py  - https://0000-0000-0000.local:8443 "POST /enduser-mobile-web/1/enduserAPI/events/register HTTP/1.1" 401 77
2022-09-26 20:29:04,828 - DEBUG    - tahoma_local.py    - <Response [401]>
2022-09-26 20:29:04,828 - ERROR    - tahoma_local.py    - failed to get local API events
ab10002 commented 1 year ago

Maybe this is missing for the local API?? (except for getting version) --header 'Authorization: Bearer 62ecd0f3cdda9a49c2c1'

JanJaapKo commented 1 year ago

401 is indeed not authorised error. Did you do the login steps first to get the token?

ab10002 commented 1 year ago

Yes but faik is that not nessecary for local

JanJaapKo commented 1 year ago

You always need a token in the header (it is the Bearer token). I'll figure something to re-use existing tokens, that is (at least during test) a bit more efficient. For now, I'll throw an error on no token.

So for now you need steps: 1, 4, 5, and then any of the 20's