Git Product home page Git Product logo

python-overkiz-api's Introduction

Python client for OverKiz API

A fully async and easy to use API client for the (internal) OverKiz API. You can use this client to interact with smart devices connected to the OverKiz platform, used by various vendors like Somfy TaHoma and Atlantic Cozytouch.

This package is mainly used by Home Assistant Core, to offer the Overkiz integration. If you want to use this package in your own project, you can use the following examples to get started, or look at the Home Assistant Code for more examples.

Supported hubs

  • Atlantic Cozytouch
  • Bouygues Flexom
  • Hitachi Hi Kumo
  • Nexity Eugénie
  • Rexel Energeasy Connect
  • Simu (LiveIn2)
  • Somfy Connexoon IO
  • Somfy Connexoon RTS
  • Somfy TaHoma
  • Somfy TaHoma Switch
  • Thermor Cozytouch

Installation

pip install pyoverkiz

Getting started

Cloud API

import asyncio
import time

from pyoverkiz.const import SUPPORTED_SERVERS
from pyoverkiz.client import OverkizClient

USERNAME = ""
PASSWORD = ""

async def main() -> None:
    async with OverkizClient(USERNAME, PASSWORD, server=SUPPORTED_SERVERS["somfy_europe"]) as client:
        try:
            await client.login()
        except Exception as exception:  # pylint: disable=broad-except
            print(exception)
            return

        devices = await client.get_devices()

        for device in devices:
            print(f"{device.label} ({device.id}) - {device.controllable_name}")
            print(f"{device.widget} - {device.ui_class}")

        while True:
            events = await client.fetch_events()
            print(events)

            time.sleep(2)

asyncio.run(main())

Local API

import asyncio
import time
import aiohttp

from pyoverkiz.client import OverkizClient
from pyoverkiz.const import SUPPORTED_SERVERS, OverkizServer

USERNAME = ""
PASSWORD = ""
LOCAL_GATEWAY = "gateway-xxxx-xxxx-xxxx.local" # or use the IP address of your gateway
VERIFY_SSL = True # set verify_ssl to False if you don't use the .local hostname

async def main() -> None:
    token = "" # you can set the token here for testing purposes, to re-use an earlier generated token

    if not token:
        # Generate new token via Cloud API
        async with OverkizClient(
            username=USERNAME, password=PASSWORD, server=SUPPORTED_SERVERS["somfy_europe"]
        ) as client:

            await client.login()
            gateways = await client.get_gateways()

            for gateway in gateways:
                token = await client.generate_local_token(gateway.id)
                await client.activate_local_token(gateway_id=gateway.id, token=token, label="Home Assistant/local-dev")
                print(f"Token for {gateway.label} ({gateway.id}):")
                print(token)  # save this token for future use

    # Local Connection
    session = aiohttp.ClientSession(
        connector=aiohttp.TCPConnector(verify_ssl=VERIFY_SSL))

    async with OverkizClient(
        username="", password="", token=token, session=session, verify_ssl=VERIFY_SSL, server=OverkizServer(
            name="Somfy TaHoma (local)",
            endpoint=f"https://{LOCAL_GATEWAY}:8443/enduser-mobile-web/1/enduserAPI/",
            manufacturer="Somfy",
            configuration_url=None,
        )
    ) as client:
        await client.login()

        print("Local API connection succesfull!")

        print(await client.get_api_version())

        setup = await client.get_setup()
        print(setup)

        devices = await client.get_devices()
        print(devices)

        for device in devices:
            print(f"{device.label} ({device.id}) - {device.controllable_name}")
            print(f"{device.widget} - {device.ui_class}")

        while True:
            events = await client.fetch_events()
            print(events)

            time.sleep(2)

asyncio.run(main())

Development

Devcontainer

If you use Visual Studio Code with Docker or GitHub CodeSpaces, you can leverage the available devcontainer. This will install all required dependencies and tools and has the right Python version available. Easy!

Manual

  • For Linux, install pyenv using pyenv-installer

  • For MacOS, run brew install pyenv

  • Don't forget to update your .bashrc file (or similar):

    export PATH="~/.pyenv/bin:$PATH"
    eval "$(pyenv init -)"
    
  • Install the required dependencies

  • Install poetry: curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python

  • Clone this repository

  • cd python-overkiz-api

  • Install the required Python version: pyenv install

  • Init the project: poetry install

  • Run poetry run pre-commit install

python-overkiz-api's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

python-overkiz-api's Issues

Frequently updating device states

I wrote an overkiz2mqtt script and noticed that the device states are refreshed once every 10 minutes. The Overkiz server allows me to call get_state() every minute but the data is only actually different after 10 minutes. I am mostly interested in io:MiddleWaterTemperatureState from my io:AtlanticDomesticHotWaterProductionV2_CV4E_IOComponent so I tried calling client.execute_command(device.device_url, "refreshMiddleWaterTemperature") which works but seems rate limited. After calling it about 50 times in one session I get:

TooManyRequestsException while executing refreshMiddleWaterTemperature: Too many requests, try again later

Restarting the session after this works but it feels like a hack (and a violation). I was hoping that the fetch_events() would help but this only gives me io:MiddleWaterTemperatureState after I issue a refreshMiddleWaterTemperature command. So even the 10 minute updates are missed using fetch_events().

What is the supported way of retrieving near-real-time state information from Overkiz?

Improve test suite

I have still quite some device definitions (setup.json) that I need to anonymize, but which we can use in our test suite eventually. This should cover almost all scenarios, and perhaps can even be used for end-to-end testing in HA.

Screen Shot 2021-10-12 at 09 23 42

Since pyoverkiz 1.3.0 the API is not working with SIMU devices

Hello,

As a big fan of the API I have recently upgraded from pyoverkiz 1.2.0 to 1.3.6 and I noticed that the api no longer works with SIMU devices (using LiveIn2 gateway) starting from version 1.3.0. I assume that comes from the fact of introduction of OAuth as I'm getting error "error.invalid.grant" starting with version 1.3.0, when using "somfy_europe" servers.

Would it possible to add specific server details for SIMU (LiveIn2) devices?

Thank you in advance.

Best Regards,
Dawid

Undocumented backwards incompatibility in version 1.4.0

Hello, I found that the most recent version 1.4.0 of pyoverkiz probably introduces some breaking changes, which are not recorded in release notes.

  1. Parameter position changing, would cause unexpected argument passing if calling the function with all positional arguments.
    1. session from 5th to 6th in function pyoverkiz.client.OverkizClient.__init__
    2. Swap name and timestamp in function pyoverkiz.models.Event.__init__
    3. Move one position right of qualified_name, type, values in function pyoverkiz.models.StateDefinition.__init__
  2. Add optional parameters, would cause inconsistent signature if a subclass overrides the method.
    1. Parameter widget_name in method pyoverkiz.models.Device.__init__
    2. Parameter token in method pyoverkiz.client.OverkizClient.__init__
    3. Parameter name in method pyoverkiz.models.StateDefinition.__init__

To make it easier to understand the impact of the breaking changes, I write a short code snippet that reproduces the breaking changes.
The following code runs well in 1.3.14 but gets crashed in 1.4.0.

pyoverkiz.models.Event(1, EventName.ACTION_GROUP_CREATED)
# parameter `name` accepts argument `1` (the timestamp in 1.3.14) 
# and parameter `timestamp` accepts argument from `EventName.ACTION_GROUP_CREATED` (the name in 1.3.14).

Maybe recording these changes in release notes helps to avoid user confusion during updating this version?

Kind regrads,

@eXceediDeaL

Full list of ui class

We found the full list of ui class here

AdjustableSlatsRollerShutter
AirSensor
Alarm
Awning
Ballast
Camera
CarButtonSensor
CircuitBreaker
ConfigurationComponent
ConsumptionSensor
ContactSensor
Curtain
Dock
DoorLock
ElectricitySensor
EvoHome
ExteriorHeatingSystem
ExteriorScreen
ExteriorVenetianBlind
GarageDoor
GasSensor
Gate
Generic
GenericSensor
GroupConfiguration
HeatPumpSystem
HeatingSystem
HitachiHeatingSystem
HumiditySensor
IRBlasterController
IntrusionSensor
Light
LightSensor
MusicPlayer
NetworkComponent
OccupancySensor
OnOff
Oven
Pergola
Pod
ProtocolGateway
RainSensor
RemoteController
RollerShutter
Screen
Shutter
Siren
SmokeSensor
SunIntensitySensor
SunSensor
SwimmingPool
SwingingShutter
TemperatureSensor
ThermalEnergySensor
ThirdPartyGateway
VenetianBlind
VentilationSystem
WashingMachine
WaterHeatingSystem
WaterSensor
WeatherSensor
Wifi
WindSensor
Window
WindowHandle

We have to create an enum with these values.

Implement auth factory

As discussed it would be good to implement some kind of authentication factory per server.

Eventually it would be great to investigate

Manufacturers

  • Atlantic Cozytouch -> JWT / OAuth?

# CozyTouch authentication using jwt
if self.server == SUPPORTED_SERVERS["atlantic_cozytouch"]:
jwt = await self.cozytouch_login()
payload = {"jwt": jwt}

Need to investigate if we can just pass this as a Bearer token to requests as well.

  • Hi Kumo -> classic /login

  • Nexity Eugénie -> ssoToken / OAuth?

    elif self.server == SUPPORTED_SERVERS["nexity"]:
    sso_token = await self.nexity_login()
    user_id = self.username.replace("@", "_-_") # Replace @ for _-_
    payload = {"ssoToken": sso_token, "userId": user_id}

    Need to investigate if we can just pass this as a Bearer token to requests as well.

  • Rexel Energeasy Connect -> broken (uses Azure B2C without user/password flow)
    Tracked in iMicknl/ha-tahoma#591.

  • Somfy (Europe) -> OAuth

Uses bearer token in header, need to handle token refresh
Would the Somfy official API client id / secret work as well?

  • Somfy (other) -> classic /login

  • Local auth (all, jailbroken)
    Tracked in #187

Endpoint is different (/enduser-mobile-web/1/enduserAPI/) and requires X-Auth-Token header.
/login endpoint doesn't exist, verify with checking another endpoint (/setup?).

self.headers.update ({
     "X-Auth-Token": self.api_token
})

refresh_states function no longer work

Hi,
Since 2022-03-29 08:36:51 UTC (apparently after a server maintenance) the function « refresh_states() » in client.py no longer works. I get an exception with the message «Content type 'application/octet-stream' not supported ». I use the the 1.3.10 release but same result with 1.3.12 and 1.3.13.
Thanks,
Franck.

Rebrand to pyoverkiz / python-overkiz-api

It would make sense to deprecate the previous version and release a stable 1.0 version called pyoverkiz. This will be a breaking change, since we also can rename the TahomaClient to OverkizClient.

Flexom v2 integration

Hey team,

Is there any chance we could have a Flexom v2 (Ubiant) integration ? Maybe with this client
The actual Flexom integration only works with Flexom v3.

Thanks 👍

Support Tahoma v1 without `twilight_city`

Configuring an Overkiz integration in Home Assistant Core 2022.10.5 (not a custom integration) with a Tahoma v1 box currently fails with the following error:

Logger: homeassistant.config_entries
Source: components/overkiz/__init__.py:61
First occurred: 22:08:48 (1 occurrences)
Last logged: 22:08:48

Error setting up entry [email protected] for overkiz
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/config_entries.py", line 365, in async_setup
    result = await component.async_setup_entry(hass, self)
  File "/usr/src/homeassistant/homeassistant/components/overkiz/__init__.py", line 61, in async_setup_entry
    setup, scenarios = await asyncio.gather(
  File "/usr/local/lib/python3.10/site-packages/backoff/_async.py", line 133, in retry
    ret = await target(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/pyoverkiz/client.py", line 389, in get_setup
    setup = Setup(**humps.decamelize(response))
  File "/usr/local/lib/python3.10/site-packages/pyoverkiz/models.py", line 61, in __init__
    self.location = Location(**location) if location else None
TypeError: Location.__init__() missing 1 required keyword-only argument: 'twilight_city'

Restarting Home Assistant does not help.

Add extra enum values

2021-11-16 08:07:47 WARNING (MainThread) [pyhoma.enums] Unsupported value SomfyProtectCurrentTokenCompletedEvent has been returned for <enum 'EventName'>
2021-11-16 08:10:17 WARNING (MainThread) [pyhoma.enums] Unsupported value GroupTriggeredEvent has been returned for <enum 'EventName'>
2021-11-16 13:21:39 WARNING (MainThread) [pyhoma.enums] Unsupported value SomfyProtectCurrentTokenFailedEvent has been returned for <enum 'EventName'>
2021-11-16 13:21:39 WARNING (MainThread) [pyhoma.enums] Unsupported value CloudSynchronizationFailedEvent has been returned for <enum 'EventName'>

See iMicknl/ha-tahoma#649 (comment)

Missing steps for installation / ModuleNotFoundError: No module named 'pyoverkiz.const'; 'pyoverkiz' is not a package

Hi

According the readme file, I m running debian 11 with python 3.9 on a virtual machine and I try to get running the overkiz api.

To replicate the problem you can do the followings actions :

  1. Open a session with a standard user ( no root )

  2. Install package
    pip install pyoverkiz

  3. create test script into test.py and paste the code provided on the readme file

  4. run the script
    python test.py

Result
Traceback (most recent call last):
File "/usr/lib/python3.9/runpy.py", line 188, in _run_module_as_main
mod_name, mod_spec, code = _get_module_details(mod_name, _Error)
File "/usr/lib/python3.9/runpy.py", line 111, in _get_module_details
import(pkg_name)
File "/home/xxx/test.py", line 14, in
from pyoverkiz.client import OverkizClient
File "/home/xxx/pyoverkiz.py", line 4, in
from pyoverkiz.const import SUPPORTED_SERVERS
ModuleNotFoundError: No module named 'pyoverkiz.const'; 'pyoverkiz' is not a package

I guess it s missing to set some varaibles to handle the correct path to the package

Thanks by advance

Write in cozytouch

Hello, is there a way to write in cozytouch, like to change the target temperature of a heater for example.

enum 'FailureType' is missing NOT_TRANSMITTED = 20001

After adding TIME_OUT_ON_TRANSMITTED_COMMAND = 20002 I now get 20001 on a regular basis.

Unsupported value 20001 has been returned for <enum 'FailureType'>

My overkiz event log caught it:

"failed_commands": [{"device_url": "io://0841-xxx-xxx/1008xxxx#1", "rank": 0, "failure_type": "TIME_OUT_ON_TRANSMIT"}], "failure_type": "TIME_OUT_ON_TRANSMIT", "failure_type_code": "UNKNOWN", "name": "EXECUTION_STATE_CHANGED", "new_state": "FAILED", "old_state": "NOT_TRANSMITTED"

TypeError: HistoryExecution.__init__() missing 1 required keyword-only argument: 'end_time'

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/aiohttp/web_protocol.py", line 433, in _handle_request
    resp = await request_handler(request)
  File "/usr/local/lib/python3.10/site-packages/aiohttp/web_app.py", line 504, in _handle
    resp = await handler(request)
  File "/usr/local/lib/python3.10/site-packages/aiohttp/web_middlewares.py", line 117, in impl
    return await handler(request)
  File "/workspaces/home-assistant-core/homeassistant/components/http/security_filter.py", line 60, in security_filter_middleware
    return await handler(request)
  File "/workspaces/home-assistant-core/homeassistant/components/http/forwarded.py", line 100, in forwarded_middleware
    return await handler(request)
  File "/workspaces/home-assistant-core/homeassistant/components/http/request_context.py", line 28, in request_context_middleware
    return await handler(request)
  File "/workspaces/home-assistant-core/homeassistant/components/http/ban.py", line 80, in ban_middleware
    return await handler(request)
  File "/workspaces/home-assistant-core/homeassistant/components/http/auth.py", line 235, in auth_middleware
    return await handler(request)
  File "/workspaces/home-assistant-core/homeassistant/components/http/view.py", line 146, in handle
    result = await result
  File "/workspaces/home-assistant-core/homeassistant/components/diagnostics/__init__.py", line 265, in get
    data = await info.device_diagnostics(hass, config_entry, device)
  File "/workspaces/home-assistant-core/homeassistant/components/overkiz/diagnostics.py", line 54, in async_get_device_diagnostics
    for execution in await client.get_execution_history()
  File "/home/vscode/.local/lib/python3.10/site-packages/backoff/_async.py", line 151, in retry
    ret = await target(*args, **kwargs)
  File "/home/vscode/.local/lib/python3.10/site-packages/pyoverkiz/client.py", line 477, in get_execution_history
    execution_history = [HistoryExecution(**h) for h in humps.decamelize(response)]
  File "/home/vscode/.local/lib/python3.10/site-packages/pyoverkiz/client.py", line 477, in <listcomp>
    execution_history = [HistoryExecution(**h) for h in humps.decamelize(response)]
TypeError: HistoryExecution.__init__() missing 1 required keyword-only argument: 'end_time'

Bad credentials while server is under maintenance

Today the atlantic_cozytouch server keeps saying Bad credentials but when I start the Cozytouch iOS app it says:

Server currently under maintenance, please try again later

It would be great if we can figure out the way the app detects this and do the same in the API library.

client.get_setup() - Different responses with Cloud and Local API

Running client.get_setup() with the cloud API on a Somfy TaHoma server, I get the first item
"id": "SETUP-xxx-xxxx-xxxx"
which seems to be correct.

Running client.get_setup() with the local API on the Somfy local server, I get the first item
"id": "_CountingAttr(counter=82, _default=None, repr=<function obfuscate_id at 0x7fff295e1580>, eq=True, order=True, hash=None, init=True, on_setattr=None, alias=None, metadata={})"
making the response difficult to exploit as a Json string.

I suspect this behavior not as expected ?
Could you please advise .
Thanks

Rework execute_action_group

See https://github.com/iMicknl/python-tahoma-api/blob/master/tahoma_api/client.py#L104

I suggest renaming this method to send_commands. It will be more user friendly.

  • This method must take also a device url as parameter. It's not the case.
  • A list of Command is taken as a parameter, must not convert as a json when set in the payload.
{"label":"Volet du bureau - Régler à 28% - TaHoma PC","actions":[{"deviceURL":"io://xxxxxx:5978000","commands":[{"name":"setClosure","parameters":[28]}]}]}

Too many requests, try again later

Hi,

Is there any way to get around the "Too many requests, try again later" error?

I want to be able to make a smart button that can close, open and stop a blind. Currently this isn't possible as one command after another creates this issue.

Any help would be appreciated, thank you.

Bad credentials

Hello,

first, thanks for sharing all your findings on overkiz for Cozytouch.
I have 2 Cozytouch accounts (2 different houses):

  • The first one has been created 2 years ago. It is for a house where 6 Atlantic(thermor) hearted are connected through a Cozytouch bridge.
  • The second account, created some days ago, is for another house where I only have an Atlantic Aqueo water heater connected through WiFI.

1- I can successfully log in cozytouch app with both account (and can manage my devices)
2- This python script works fine with the first account (house with cozytouch bridge)
3- I’m facing a « Bad credentials » error when tryin to use this script with the second account.

Am I missing something ? Is there a different overkiz/Atlantic server for WiFi-managed devices ?
Thanks for your help

Add support for SSO token

Nexity requires a SSOToken for login, and we currently don't support this in the API.

However, this will add additional complexity since we add the user and pass to the constructor of the TahomaClient, and not just at the login().

'Attempt to decode JSON with unexpected mimetype: '

I'm currently unable to open my covers using Home Assistant. I did not restart yet since I thought the errors might be useful to handle in the future.

0, message='Attempt to decode JSON with unexpected mimetype: ', url=URL('https://tahomalink.com/enduser-mobile-web/enduserAPI/exec/apply')
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 125, in handle_call_service
    await hass.services.async_call(
  File "/usr/src/homeassistant/homeassistant/core.py", line 1308, in async_call
    task.result()
  File "/usr/src/homeassistant/homeassistant/core.py", line 1343, in _execute_service
    await handler.func(service_call)
  File "/usr/src/homeassistant/homeassistant/helpers/entity_component.py", line 208, in handle_service
    await self.hass.helpers.service.entity_service_call(
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 454, in entity_service_call
    future.result()  # pop exception if have
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 583, in async_request_call
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/service.py", line 485, in _handle_entity_call
    await result
  File "/config/custom_components/tahoma/cover.py", line 199, in async_open_cover
    await self.async_execute_command(
  File "/config/custom_components/tahoma/tahoma_device.py", line 155, in async_execute_command
    await self.coordinator.client.execute_command(
  File "/usr/local/lib/python3.8/site-packages/pyhoma/client.py", line 157, in execute_command
    return await self.execute_commands(device_url, [command], label)
  File "/usr/local/lib/python3.8/site-packages/pyhoma/client.py", line 170, in execute_commands
    response = await self.__post("exec/apply", payload)
  File "/usr/local/lib/python3.8/site-packages/pyhoma/client.py", line 196, in __post
    await self.check_response(response)
  File "/usr/local/lib/python3.8/site-packages/pyhoma/client.py", line 209, in check_response
    result = await response.json()
  File "/usr/local/lib/python3.8/site-packages/aiohttp/client_reqrep.py", line 1026, in json
    raise ContentTypeError(
aiohttp.client_exceptions.ContentTypeError: 0, message='Attempt to decode JSON with unexpected mimetype: ', url=URL('https://tahomalink.com/enduser-mobile-web/enduserAPI/exec/apply')
Failed to call service cover/open_cover. 0, message='Attempt to decode JSON with unexpected mimetype: ', url=URL('https://tahomalink.com/enduser-mobile-web/enduserAPI/exec/apply')

It looks like this started happening after getting the following error:

Logger: custom_components.tahoma
Source: helpers/update_coordinator.py:165
Integration: Somfy TaHoma (documentation, issues)
First occurred: 7:07:09 AM (1 occurrences)
Last logged: 7:07:09 AM

Error fetching TaHoma Event Fetcher data: Error communicating with the TaHoma API: Cannot connect to host tahomalink.com:443 ssl:default [Connect call failed ('178.32.15.131', 443)]

Hope this helps :) Problem was solved immediately after restart. So it seems to me it lost connection but never tried to reconnect?

/exec/apply delivers http error 415 (unsupported mediatype) if charset is defined

I am currently implementing a .NET version of the Tahoma (local) API. I got an unsupported mediatype error on "/exec/apply".
The reason was the charset parameter of the "application/json" content type which is created by default in .NET.

Usually the ContentType header allows to specify also a character set (like charset=UTF-8).
See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type

I was able to implement a work arround, but I think the Tahoma server (new Tahoma Switch) should accept a charset parameter for the content type.

ValueError: 9 is not a valid DataType / Event loop is closed

First of all, I would to thank you for this great project to provide an easy to consume Python wrapper.

I tried to use it with my Somfy System by:

  • creating a new env python -m venv env and activate it
  • install the package pip install pyhoma
  • copy and paste the getting started example to a new script file start.py
  • entered my somfy credentials for username and password
  • starting it with python start.py

Unfortunately I recieved the following Error Messages

(env) c:\github\test-pyhoma>python start.py
ValueError: 9 is not a valid DataType
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "start.py", line 29, in
asyncio.run(main())
File "C:\Python38\lib\asyncio\runners.py", line 43, in run
return loop.run_until_complete(main)
File "C:\Python38\lib\asyncio\base_events.py", line 616, in run_until_complete
return future.result()
File "start.py", line 17, in main
devices = await client.get_devices()
File "c:\github\test-pyhoma\env\lib\site-packages\backoff_async.py", line 133, in retry
ret = await target(*args, **kwargs)
File "c:\github\test-pyhoma\env\lib\site-packages\pyhoma\client.py", line 117, in get_devices
devices = [Device(**d) for d in humps.decamelize(response)]
File "c:\github\test-pyhoma\env\lib\site-packages\pyhoma\client.py", line 117, in
devices = [Device(**d) for d in humps.decamelize(response)]
File "c:\github\test-pyhoma\env\lib\site-packages\pyhoma\models.py", line 64, in init
self.attributes = States(attributes) if attributes else None
File "c:\github\test-pyhoma\env\lib\site-packages\pyhoma\models.py", line 160, in init
self._states = [State(**state) for state in states]
File "c:\github\test-pyhoma\env\lib\site-packages\pyhoma\models.py", line 160, in
self._states = [State(**state) for state in states]
File "c:\github\test-pyhoma\env\lib\site-packages\pyhoma\models.py", line 155, in init
self.type = DataType(type)
File "C:\Python38\lib\enum.py", line 304, in call
return cls.new(cls, value)
File "C:\Python38\lib\enum.py", line 595, in new
raise exc
File "C:\Python38\lib\enum.py", line 579, in new
result = cls.missing(value)
File "C:\Python38\lib\enum.py", line 608, in missing
raise ValueError("%r is not a valid %s" % (value, cls.name))
ValueError: 9 is not a valid DataType
Exception ignored in: <function _ProactorBasePipeTransport.del at 0x000001D020474D30>
Traceback (most recent call last):
File "C:\Python38\lib\asyncio\proactor_events.py", line 116, in del
self.close()
File "C:\Python38\lib\asyncio\proactor_events.py", line 108, in close
self._loop.call_soon(self._call_connection_lost, None)
File "C:\Python38\lib\asyncio\base_events.py", line 719, in call_soon
self._check_closed()
File "C:\Python38\lib\asyncio\base_events.py", line 508, in _check_closed
raise RuntimeError('Event loop is closed')
RuntimeError: Event loop is closed

May someone has an idea, what is going wrong here?

Add /setup endpoint

We currently don't use this in ha-tahoma, but it makes sense to have this endpoint in our API client as well. I use this a lot to retrieve full setup details of users I am helping.

get_current_execution crashes

2020-07-28 16:21:19 ERROR (MainThread) [custom_components.tahoma] Unexpected error fetching TaHoma Event Fetcher data: type object argument after ** must be a mapping, not str
Traceback (most recent call last):
  File "/Users/vlb/PycharmProjects/ha-tahoma/venv/lib/python3.7/site-packages/homeassistant/helpers/update_coordinator.py", line 139, in async_refresh
    self.data = await self._async_update_data()
  File "/Users/vlb/PycharmProjects/ha-tahoma/Config/custom_components/tahoma/coordinator.py", line 51, in _async_update_data
    execution = await self.client.get_current_execution(event.exec_id)
  File "/Users/vlb/PycharmProjects/ha-tahoma/venv/lib/python3.7/site-packages/tahoma_api/client.py", line 124, in get_current_execution
    executions = [Execution(**e) for e in humps.decamelize(response)]
  File "/Users/vlb/PycharmProjects/ha-tahoma/venv/lib/python3.7/site-packages/tahoma_api/client.py", line 124, in <listcomp>
    executions = [Execution(**e) for e in humps.decamelize(response)]
TypeError: type object argument after ** must be a mapping, not str

Device returns a state without value

Somfy Thermostat can return the following states that crashes line 139 of models.py:

{'deviceStates': [{'name': 'core:BatteryLevelState',
                    'type': 2,
                    'value': '83.0'},
                   {'name': 'core:DerogationActivationState',
                    'type': 3,
                    'value': 'inactive'},
                   {'name': 'core:DerogatedTargetTemperatureState',
                    'type': 2,
                    'value': '16.0'},
                   {'name': 'somfythermostat:DerogationHeatingModeState',
                    'type': 3,
                    'value': 'manualMode'},
                   {'name': 'somfythermostat:DerogationTypeState',
                    'type': 3,
                    'value': 'further_notice'},
                   {'name': 'core:DerogationStartDateTimeState',
                    'type': 5,
                    'value': '1596438624000'},
                   {'name': 'core:DerogationEndDateTimeState', 'type': 0}],    <<====================
  'deviceURL': 'somfythermostat://SOMFY_THERMOSTAT-2479/xxx#1',
  'name': 'DeviceStateChangedEvent',
  'setupOID': 'xxx',
  'timestamp': 1596438652475},

Support for "Sauter Smart Control" (Brandt brand)

Hello,

I have a Sauter oven and I saw that the mobile app "Sauter Smart Control" is based on Overkiz.
It has the same look and feel than the Brandt app. Sauter is a brand of the Brandt group so it makes sense.

So I tried to login with Brandt Smart Control on the HA Integration, but I got a login failed error.
Out of curiosity, I tried to log in with my Sauter credentials on the Brandt Smart Control and it failed.

I had a look at the DNS request made to the server from my mobile app, and the host is the same than the one used for Server.BRANDT: ha3-1.overkiz.com.

Server.BRANDT: OverkizServer(
        name="Brandt Smart Control",
        endpoint="https://ha3-1.overkiz.com/enduser-mobile-web/enduserAPI/",
        manufacturer="Brandt",
        configuration_url=None,
    ),

I also found the same path /enduser-mobile-web/enduserAPI/ by having a quick look at the dex files of the APK, without decompiling it.
Maybe there's a dedicated API endpoint on the same server. I am not sure yet since I did not setup traffic interception.
Or, maybe there's an additional parameter in the POST request for the login, or a dedicated header for brands affiliated to Brandt.

Did you see such setup with multiple brands hosted on the same server / endpoint?

ServerDisconnectedError - add possibility to tweak keep-alive setting

Initially reported in iMicknl/ha-tahoma#191. ServerDisconnectedError can be faced when we open to many requests.

Try setting the client to tell the server to close the connection after each request:

self._session = aiohttp.ClientSession(
...
headers={"Connection": "close"},
)

HTTP keep-alive allows the same connection to be used for multiple requests, which can improve performance, especially over HTTPS, where the connection handshake can be lengthy. But the server may have a limit as to how long it's willing to keep the connection alive or how many requests it will accept on the same connection. When the limit runs out, it closes the connection.

Originally posted by @rogerdahl in aio-libs/aiohttp#850 (comment)

Add `ServerIsDownForMaintenance` exception, catch 503 statuscode

Apparently they update their service quite often lately, with some planned downtime. Would be good to catch this error gracefully, instead of spamming the log with their HTML page.

2020-10-23 06:11:34 DEBUG (MainThread) [custom_components.tahoma.coordinator] Unknown error while requesting https://tahomalink.com/enduser-mobile-web/enduserAPI/events/4ffb38c0-ac10-3401-4cd1-e427614e1f4c/fetch. 503 - <html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Overkiz - Universal HomeControl</title>
  <!-- PROD1 -->
  <style>
   body {
        font-family: Arial, Verdana, Helvetica, sans-serif;
	font-size: 10pt;
	color: black;
   } 
  </style>
</head>
<body>
<div align="center">
<br/><br/><br/><br/>
<table border="0" width="90%">
  <tr>
    <td width="50%" align="center"><img src="/error/overkiz_logo.gif"/></td>
    <td>
      <p class="intro">
        <b>Server is down for maintenance</b><br/>
        <br/>
        We are sorry for the inconvenience.<br/>
        Please try again in a few minutes.
      </p>
    </td>
  </tr>
</table>
</div>
</body>

</html>

Properly type `device_states` list in Event and cast in pyoverkiz

2022-01-06 16:04:02 DEBUG (MainThread) [homeassistant.components.overkiz.coordinator] Event(timestamp=1641485041949, name=<EventName.DEVICE_STATE_CHANGED: 'DeviceStateChangedEvent'>, setupoid=_CountingAttr(counter=304, _default=None, repr=<function obfuscate_id at 0x7f6a0df93c10>, eq=True, order=True, hash=None, init=True, on_setattr=None, metadata={}), owner_key=None, type=None, sub_type=None, time_to_next_state=None, failed_commands=None, failure_type_code=None, failure_type=None, condition_groupoid=None, place_oid=None, label=None, metadata=None, camera_id=None, deleted_raw_devices_count=None, protocol_type=None, gateway_id=None, exec_id=None, device_url=io://****-****-3293/5046564, device_states=[State(name='core:LightIntensityState', type=<DataType.INTEGER: 1>, value='83'), State(name='core:OnOffState', type=<DataType.STRING: 3>, value='on')], old_state=None, new_state=None)

Currently we cast the device_states values in our coordinator in ha-tahoma, however this is quite complex and shouldn't be there in my opinion. + we currently type that we give back a state, instead of a str.

Atlantic Cozytouch not available ?

Hello, i'm trying to access the server altantic_cozytouch, but it tell me this error: Cannot connect to host apis.groupe-atlantic.com:443 ssl:default [The specified network name is no longer available.]

It's only me or not ?

Unsupported value 20002 has been returned for <enum 'FailureType'>

I received 60 of these warnings this morning. They were two in a row. The two minutes gap is caused by a sleep from my app.

Sep 20 08:07:48 nasty python3[3163548]: WARNING:pyoverkiz.enums.general:Unsupported value 20002 has been returned for <enum 'FailureType'>
Sep 20 08:07:48 nasty python3[3163548]: WARNING:pyoverkiz.enums.general:Unsupported value 20002 has been returned for <enum 'FailureType'>
Sep 20 08:09:49 nasty python3[3163548]: WARNING:pyoverkiz.enums.general:Unsupported value 20002 has been returned for <enum 'FailureType'>
Sep 20 08:09:49 nasty python3[3163548]: WARNING:pyoverkiz.enums.general:Unsupported value 20002 has been returned for <enum 'FailureType'>

Unfortunately I don't have any more context. The API seemed to be working fine and my app was retrieving data from the atalantic-cozytouch server as usual. Looking at the timing of the warnings it is either caused by client.execute_command() or client.get_state().

Improve CI/CD

  • Add release drafter
  • Add auto changelog generator
  • Change version number programatically before publish to PyPi

@vlebourl would you like to implement the release drafter here as well? Would be good to have this repo as automated as possible. :-)

get_local_tokens (local) - Error expecting expiration_time

Hi Mickael,

I am triying to use the get_local_tokens command of your API but I receive the following error:

TypeError: LocalToken.__init__() missing 1 required keyword-only argument: 'expiration_time'

as it seems that the overkiz server does not include the "expiration_time" parameter in its response for the Get available tokens request.

Any suggestion ?

Gateway is Tahoma V2

Need a simple tuto to execute a little python program

Hello,

Thank you very much for your program.

I would like to make a little Python script to simply open or close my Roller Shutter, for exemple, and I don't know how to use this API.

Could you, please, provide us a little tuto to explain how the API works ?

I've executed the script from the Readme file and I have this information :
Volet Cuisine (rts://1231-xxxx-2819/xxxxxxxx) - rts:RollerShutterRTSComponent UpDownRollerShutter - RollerShutter
But for the rest I don't know what to do...

Thanks !

Bad credentials response

I'm using the simple login example from the README.md - this always worked. For both my accounts. Both are North America Somfy, and the main difference is the email address. One has a plus in it, e.g. [email protected], and the other one doesn't.

Since a few hours ago the email with a plus stopped working with this error:
{'errorCode': 'AUTHENTICATION_ERROR', 'error': 'Bad credentials'}

The other one still works. I independently confirmed that logging in and out still works through the Tahoma app for both accounts.

I'm led to believe that the reason that pyoverkiz doesn't work anymore is simply because of the plus-sign in the email.

Can you confirm this?

Excessing DNS query for tahomalink.com

This is probably because of a configuration at the Somfy side (their dns records have a ttl of 0), this causes the lookup to happen almost every second (in home assistant). Can you do some internal caching?

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.