Giter VIP home page Giter VIP logo

somfy-open-api's Introduction

This library is an attempt to implement the entire Somfy API in Python 3. Documentation for the Somfy API can be found here.

Get developer credentials

  1. Vist https://developer.somfy.com
  2. Create an account
  3. Open the My Apps menu
  4. Add a new App (for testing, redirect url can be anything in https)
  5. Plug in your details into the test script below.

Supported devices

Somfy currently exposes the following type of devices:

If you find on this page devices not yet handle by this repository, don't hesitate to open an issue.

Installation

pip install pymfy

Limitation

Somfy support sent the following message to third party applications using their API.

Dear customer,

As you might have noticed, we have updated the quota policy of the Somfy Open API, in an ongoing effort to provide the best services to our users.

We are contacting you today to inform you about the new rules we are now applying to the API:
- First of all, no limitation will be applied on the POST /device/{deviceId}/exec endpoint as we want to provide you a total freedom on controlling your devices.
- On the other hand, polling frequency on the GET /site and child endpoints will now have to be under 1 call per minute.

To preserve an efficient and available service to any of our users, we want to keep the usage of the Open API to a usable but reasonable level to everybody. As we will keep monitoring the generated traffic and the potential impacts, be aware that we do reserve the rights to modify the authorized polling frequency or take any additional measure at any time as stated in our General Terms of Use.

Thank you for your understanding.

Example usage

Print all covers position.

import os
import json
from urllib.parse import urlparse, parse_qs

from pymfy.api.devices.roller_shutter import RollerShutter
from pymfy.api.somfy_api import SomfyApi
from pymfy.api.devices.category import Category

client_id = r"<CLIENT_ID>"  # Consumer Key
redir_url = "<REDIR_URL>"  # Callback URL (for testing, can be anything)
secret = r"<secret>"  # Consumer Secret


def get_token():
    try:
        with open(cache_path, "r") as cache:
            return json.loads(cache.read())
    except IOError:
        pass


def set_token(token) -> None:
    with open(cache_path, "w") as cache:
        cache.write(json.dumps(token))


cache_path = "/optional/cache/path"
api = SomfyApi(client_id, secret, redir_url, token=get_token(), token_updater=set_token)
if not os.path.isfile(cache_path):
    authorization_url, _ = api.get_authorization_url()
    print("Please go to {} and authorize access.".format(authorization_url))
    authorization_response = input("Enter the full callback URL")
    code = parse_qs(urlparse(authorization_response).query)["code"][0]
    set_token(api.request_token(code=code))

site_ids = api.get_sites()
devices = api.get_devices(site_ids[0], category=Category.ROLLER_SHUTTER)

covers = [RollerShutter(d, api) for d in devices]

for cover in covers:
    print(
        "Cover {} has the following position: {}".format(
            cover.device.name, cover.get_position()
        )
    )

Contribute

The current documentation does not give enough information to implement all the devices. If you want to contribute to this repository adding new devices, you can create an issue with the output of this script:

import json
import re
from urllib.parse import urlparse, parse_qs
from pymfy.api.somfy_api import SomfyApi


client_id = r"<CLIENT_ID>"  # Consumer Key
redir_url = "<REDIR_URL>"  # Callback URL (for testing, can be anything)
secret = r"<secret>"  # Consumer Secret

api = SomfyApi(client_id, secret, redir_url)
authorization_url, _ = api.get_authorization_url()
print("Please go to {} and authorize access.".format(authorization_url))
authorization_response = input("Enter the full callback URL")
code = parse_qs(urlparse(authorization_response).query)["code"][0]
api.request_token(code=code)

site_ids = [s.id for s in api.get_sites()]
devices = [api.get("/site/" + s_id + "/device").json() for s_id in site_ids]

# Remove personal information
dumps = json.dumps(devices, sort_keys=True, indent=4, separators=(",", ": "))
dumps = re.sub('".*id.*": ".*",\n', "", dumps)

print(dumps)

somfy-open-api's People

Contributors

balloob avatar dependabot-preview[bot] avatar dependabot[bot] avatar nbeernink avatar scop avatar tetienne avatar vlebourl avatar

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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

somfy-open-api's Issues

FileNotFoundError /optional/cache/path

Hello tetienne,

I had a success with the script to get all the devices :)

But I encounter an error with the script to display only the covers, and I don't understand what is missing with this error :

  File "GetCovers.py", line 31, in <module>
    set_token(api.request_token(code=code))
  File "GetCovers.py", line 21, in set_token
    with open(cache_path, 'w') as cache:
FileNotFoundError: [Errno 2] No such file or directory: '/optional/cache/path'

Do you have an idea?

Thank you for your help.

Enhance support for interior blind

device types supported states supported capabilities capability parameters
interior_blind_discrete_generic N/A close
open
stop
identify
none
none
none
none
interior_blind_discrete_orientable N/A close
open
stop
identify
none
none
none
none
interior_blind_positionable_orientable_stateful_generic position
orientation
close
open
position
rotation
stop
identify
none
none
position
orientation
none
none
interior_blind_positionable_stateful_generic position close
open
position
stop
identify
none
none
position
none
none
interior_blind_positionable_stateful_roof position close
open
position
stop
identify
none
none
position
none
none
interior_blind_positionable_stateless_uno N/A close
open
position
stop
identify
none
none
position
none
none

Enhance support for roller shutter

device types supported states supported capabilities capability parameters
roller_shutter_discrete_generic N/A close
open
stop
identify
none
none
none
none
roller_shutter_positionable_orientable_stateful_generic position close
open
position
stop
identify
none
none
position
none
none
roller_shutter_positionable_orientable_stateful_gradhermetic position close
open
position
stop
identify
none
none
position
none
none
roller_shutter_positionable_orientable_stateful_holla position close
open
position
stop
identify
none
none
position
none
none
roller_shutter_positionable_stateful_dual position close
open
position
stop
identify
none
none
position
none
none
roller_shutter_positionable_stateful_generic position close
open
position
stop
identify
none
none
position
none
none
roller_shutter_positionable_stateful_projection position close
open
position
stop
identify
none
none
position
none
none
roller_shutter_positionable_stateful_roof position close
open
position
stop
identify
none
none
position
none
none
roller_shutter_positionable_stateful_rs100 position close
open
position
position_low_speed
stop
identify
none
none
position
position
none
none
roller_shutter_positionable_stateless_uno N/A close
open
position
stop
identify
none
none
position
none
none

interior_blind capabilities

[
    {
        "capabilities": [],
        "categories": [
            "hub"
        ],
                "name": null,
                "states": [],
        "type": "hub_tahoma_2"
    },
    {
        "capabilities": [
            {
                "name": "close",
                "parameters": []
            },
            {
                "name": "identify",
                "parameters": []
            },
            {
                "name": "open",
                "parameters": []
            },
            {
                "name": "stop",
                "parameters": []
            }
        ],
        "categories": [
            "interior_blind"
        ],
                "name": "Living 1",
                "states": [],
        "type": "interior_blind_discrete_generic"
    },
    {
        "capabilities": [
            {
                "name": "close",
                "parameters": []
            },
            {
                "name": "identify",
                "parameters": []
            },
            {
                "name": "open",
                "parameters": []
            },
            {
                "name": "stop",
                "parameters": []
            }
        ],
        "categories": [
            "interior_blind"
        ],
                "name": "Living 2",
                "states": [],
        "type": "interior_blind_discrete_generic"
    },
    {
        "capabilities": [
            {
                "name": "close",
                "parameters": []
            },
            {
                "name": "identify",
                "parameters": []
            },
            {
                "name": "open",
                "parameters": []
            },
            {
                "name": "stop",
                "parameters": []
            }
        ],
        "categories": [
            "interior_blind"
        ],
                "name": "Living 3",
                "states": [],
        "type": "interior_blind_discrete_generic"
    },
    {
        "capabilities": [
            {
                "name": "close",
                "parameters": []
            },
            {
                "name": "identify",
                "parameters": []
            },
            {
                "name": "open",
                "parameters": []
            },
            {
                "name": "stop",
                "parameters": []
            }
        ],
        "categories": [
            "interior_blind"
        ],
                "name": "Living 4",
                "states": [],
        "type": "interior_blind_discrete_generic"
    },
    {
        "capabilities": [
            {
                "name": "close",
                "parameters": []
            },
            {
                "name": "identify",
                "parameters": []
            },
            {
                "name": "open",
                "parameters": []
            },
            {
                "name": "stop",
                "parameters": []
            }
        ],
        "categories": [
            "interior_blind"
        ],
                "name": "Study",
                "states": [],
        "type": "interior_blind_discrete_generic"
    },
    {
        "capabilities": [
            {
                "name": "close",
                "parameters": []
            },
            {
                "name": "identify",
                "parameters": []
            },
            {
                "name": "open",
                "parameters": []
            },
            {
                "name": "stop",
                "parameters": []
            }
        ],
        "categories": [
            "interior_blind"
        ],
                "name": "Kitchen",
                "states": [],
        "type": "interior_blind_discrete_generic"
    }
]

Add ability to wait until command finishes

Hello,

first of all, thanks for developing this API for Somfy.

I'm not sure if this is a bug or feture request, but ss there a possibility how I can wait for some command to finishes? For example, if I want to set position and orientation for blinds, I'm doing it like this:

#...
blind = Blind(device, api)
blind.set_positon(85)
blind.orientation = 50

Lets suppose the blinds are fully down and closed. Then the code starts the position but immediatelly (well, half a second lets say) it sets the orientation which causes the position command to interrupt. The result is the blinds change the position slightly and then sets the orientation. Is there a way how I can wait until first command finishes (in this example set_position) and then run the other one?

Thanks

Somfy's expired certificate

It appears Somfy's certificate expired today: https://api.somfy.com/api/v1/site
Dependent projects (I'm thinking about the Home Assistant integration) doesn't work anymore. France is under lock down and we can't be sure when the certificate will be updated. Also this situation could occur again in the future and/or be have certain use case.

Until then, maybe we could add a parameter to SomfyApi's constructor at https://github.com/tetienne/somfy-open-api/blob/master/pymfy/api/somfy_api.py so that requests are done without certificate verification?

The redirect URI provided does not match registered URI(s).

Bonjour,
souhaitant utiliser l'API Somfy avec python, j'ai créé un compte développeur et installé somfy-open-api. Je teste avec votre script en ligne de commande, on me demande de valider et je suis redirigé vers une page qui me retourne en json : The redirect URI provided does not match registered URI(s).
En redirect URL, j'ai mis une adresse sur mon serveur en https (avec un certificat valide). C'est la même url que sur mon compte développeur somfy. Cette adresse doit-elle avoir une structure particulière ou bien effectuer un traitement ?
En vous remerciant,
Jean

Shutter movements

Hello tetienne,
thanks for this API.
I can get the status of my shutters but I don't understand how to move them.
I'm a novice ... and I don't understand everything in the Somfy documentation ...
thank you

Request to the API sometimes very long

Hi Etienne,

I am still using your great scripts to request the API for my blind 👍

I encounter some kind of issues: sometimes the request to the api can be done very fast,
and some other time, the request is taking a very very long time... (version 0.8 and before)

Installation
1/ with poetry --> it doesn't installs the 0.9.3 (the dependencies are installed)
I have seen you are now using poetry to install pymfy 0.9.3, so let's go for it.
PS: I configured poetry to use python3 (no difference with python 2.7)

$ git clone https://github.com/tetienne/somfy-open-api.git
$ cd somfy-open-api/
$ poetry install
Creating virtualenv pymfy in /home/pi/domoticz/scripts/python/somfy-open-api/.venv
Installing dependencies from lock file

Package operations: 50 installs, 0 updates, 0 removals

  • Installing zipp (3.4.0)
  • Installing importlib-metadata (2.1.1)
  • Installing pyparsing (2.4.7)
  • Installing appdirs (1.4.4)
  • Installing attrs (20.3.0)
  • Installing certifi (2020.12.5)
  • Installing chardet (3.0.4)
  • Installing distlib (0.3.1)
  • Installing filelock (3.0.12)
  • Installing idna (2.10)
  • Installing iniconfig (1.1.1)
  • Installing lazy-object-proxy (1.4.3)
  • Installing packaging (20.7)
  • Installing pluggy (0.13.1)
  • Installing py (1.9.0)
  • Installing six (1.15.0)
  • Installing toml (0.10.2)
  • Installing typed-ast (1.4.1)
  • Installing urllib3 (1.22)
  • Installing wrapt (1.12.1)
  • Installing astroid (2.4.2)
  • Installing cfgv (3.0.0)
  • Installing click (7.1.2)
  • Installing coverage (4.4.2)
  • Installing identify (1.5.10)
  • Installing isort (5.7.0)
  • Installing mccabe (0.6.1)
  • Installing mypy-extensions (0.4.3)
  • Installing nodeenv (1.5.0)
  • Installing oauthlib (3.1.0)
  • Installing pathspec (0.8.1)
  • Installing pycodestyle (2.6.0)
  • Installing pyflakes (2.2.0)
  • Installing pytest (6.2.0)
  • Installing pyyaml (5.3.1)
  • Installing regex (2020.11.13)
  • Installing requests (2.25.0)
  • Installing tokenize-rt (4.0.0)
  • Installing typing-extensions (3.7.4.3)
  • Installing virtualenv (20.2.1)
  • Installing black (20.8b1)
  • Installing flake8 (3.8.4)
  • Installing httpretty (1.0.3)
  • Installing mypy (0.790)
  • Installing pre-commit (2.9.3)
  • Installing pylint (2.6.0)
  • Installing pytest-cov (2.10.1)
  • Installing pyupgrade (2.7.4)
  • Installing requests-oauthlib (1.3.0)
  • Installing tox (3.20.1)

Installing the current project: pymfy (0.9.3)

The package pymfy should be installed, but it doesn't show the package's version with poetry show
And I cannot access it from python.
What's wrong? Can you help me?
2/ with pip --> it installs the version 0.9.4
Following your documentation in the section Install, if I use pip3 install pymfy, after an upgrade of pip, it installs the version 0.9.4.

The issues:
The part very long is this one: api.get_devices(category=Category.ROLLER_SHUTTER)
The other parts to get token and actions are done very quickly.

  1. Why does it take sometimes a so long time? more than 20 secs with timeout (palliative: I made 3 tries in python to do this aciton)
  2. How to investigate it?
  3. Could it be possible to store the devices in a json I could load instead of requesting the api with api.get_devices() ?

Thanks for your support 👍

Auth: An error has occurred

I was trying to list my devices as I have three and Home Assistant only shows one. I cannot connect to the Somfy API via an app I listed myself though.

If I open the [URL] that this script outputs in "Please go to [URL] and authorize access", the following error appears:

An error has occurred
Please try again. If the problem persists, please contact
our technical support team.

Any idea how I can connect the script to the Somfy API?

API down? Or something broken?

For a couple days the integration seems to be broken (without anything in Home Assistant logs).
I tested it in Jupyter to rule out Home Assistant fault, turns out nothing is returned:

devices = api.get_devices(category=Category.ROLLER_SHUTTER)
covers = [RollerShutter(d, api) for d in devices]

print(devices)
print(covers)
[]
[]

I can still control my covers from the Somfy website though.
Am I the only one experiencing this?

Object of type Device is not JSON serializable

Using Connexoon IO
Trying to dump the devices:

Traceback (most recent call last):
  File "test.py", line 20, in <module>
    dumps = json.dumps(devices, sort_keys=True, indent=4, separators=(',', ': '))
  File "/usr/lib/python3.7/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
  File "/usr/lib/python3.7/json/encoder.py", line 201, in encode
    chunks = list(chunks)
  File "/usr/lib/python3.7/json/encoder.py", line 429, in _iterencode
    yield from _iterencode_list(o, _current_indent_level)
  File "/usr/lib/python3.7/json/encoder.py", line 325, in _iterencode_list
    yield from chunks
  File "/usr/lib/python3.7/json/encoder.py", line 438, in _iterencode
    o = _default(o)
  File "/usr/lib/python3.7/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type Device is not JSON serializable

when dumping devices with pprint

[<pymfy.api.model.Device object at 0x7fc847fd1f48>,
 <pymfy.api.model.Device object at 0x7fc847fd1fa8>]

How do i determine what my device is (single blinds)

Refactor lib to allow plugging in own OAuth clients

We're building a free account linking service for Home Assistant. It will allow users to link their third-party accounts via OAuth2 without having to sign up for developer accounts etc.

I've been looking at the different implementations in Home Assistant that could support that, and it seems like the Somfy integration, based on this lib, is a great candidate to be the first implementation.

With the account linking service the client ID and secret will be kept in a cloud service, and all requests for getting access tokens (all grant types) will be routed via it. Authenticated requests to the Somfy API to interact with devices will still be made directly from Home Assistant to Somfy.

But to be able to get it working, we would need to update the SomfyApi class to take an instance of a class that implements get and post. The get_authorization_url and request_token methods could become helpers.

Would you accept a PR for this lib that accomplishes this? Will also update the Home Assistant side.

btw, are you on the Home Assistant Discord? I couldn't find you.

Please go to https://accounts.somfy.com/... and authorize access

@tetienne , thank your for this great idea to provide the Somfy API in Python 3.

  • I followed your instructions from README.md and got developer credentials from https://developer.somfy.com

  • Afterwards I created an venv

python -m venv env

  • Inside this venv I installed pymfy via pip

pip install pymfy

  • I create a script on the basis of your example usage to print all covers position

  • By running this script with

python test.script

I got following response:

Please go to https://accounts.somfy.com/oauth/oauth/v2/auth?response_type=code&client_id=my-secret-id&redirect_uri=https%3A%2F%2Fwww.google.com%2F&state=nZsqHxtz5YImQJv3ME2UE8I3v21d8R and authorize access.

Is this error familiar to you? Might you help me to solve this problem?

How to authenticate ?

Hi @tetienne
I want to try the API to see what it outputs for the Somfy swithes i have but i am unsure what i need from the Somfy API page, on the API page i have Consumer Key, Consumer Secret but you are asking for client_id , redir_url and secret . Alo regarding the callback URL i guess it's equal to redir_urland do i have to have a webserver that is open to the public that the API can be accessed from it or ?

/donnib

Usage unclear for users new to Somfy IO

Hi, I'm going to buy several Somfy IO roller shutters and would like to control them using this library. I'm currently at the shop that sells them trying to interface with their TaHoma box, but I just can't get it to work.

I followed the readme and created a developer account with my own email address and an app which has been authorized for access. When I try to retrieve devices it just returns an empty list, so far so good.

Now I think I need to connect my app to the TaHoma box from the shop, but I just can't figure out how to do it. I looked around in the TaHoma HD app, but I can't find a way to add my app, or create a key or something. I can open the Somfy account from the app, but that only displays the box and when I open it I can only buy SMS alerts.

The FAQ (https://developer.somfy.com/faq-page) has an answer for: "The APIs give access to Somfy products control. What is the process to be followed by users before this control phase to be effective in your app?": First, the users must use the Somfy applications to create their accounts, activate the products and pair end devices with the Somfy hubs (like Somfy motorizations to be paired with TaHoma or Connexoon). Once this is completed and the integration of Somfy APIs in your app done, users can connect their Somfy accounts to your app (through the account linking to be found in your app).

But I can't find the account linking... How do I connect my app to the TaHoma box? Do I need to create a developer account with the same email address which was used for the Somfy account to which the box is registered or something? This could be more clear in the readme.

Crash when initializing the Somfy Thermostat device

Calling method __init__ of Capability "set_target" crashes because the capability has a parameter 'target_temperature' that has a 'condition' element which is not accounted for.
Here is the full json of the capabilities:

{
   "name":"set_target",
   "parameters":[
      {
         "name":"target_mode",
         "type":"string"
      },
      {
         "name":"target_temperature",
         "type":"integer",
         "condition":"< 26"
      },
      {
         "name":"duration",
         "type":"integer"
      },
      {
         "name":"duration_type",
         "type":"string"
      }
   ]
},
{
   "name":"cancel_target",
   "parameters":[

   ]
},
{
   "name":"set_at_home_temperature",
   "parameters":[
      {
         "name":"at_home_temperature",
         "type":"integer"
      }
   ]
},
{
   "name":"set_away_temperature",
   "parameters":[
      {
         "name":"away_temperature",
         "type":"integer"
      }
   ]
},
{
   "name":"set_night_temperature",
   "parameters":[
      {
         "name":"night_temperature",
         "type":"integer"
      }
   ]
},
{
   "name":"set_frost_protection_temperature",
   "parameters":[
      {
         "name":"frost_protection_temperature",
         "type":"integer"
      }
   ]

Add support for camera

device types supported states supported capabilities capability parameters
camera_protect_arcsoft shutter_position shutter_close
shutter_open
none
none
camera_protect_indoor shutter_position shutter_close
shutter_open
none
none
camera_protect_myfox shutter_position shutter_close
shutter_open
none
none
camera_protect_outdoor shutter_position shutter_close
shutter_open
none
none
camera_protect_somfyone shutter_position shutter_close
shutter_open
none
none

Add support for thermostat

device types supported states supported capabilities capability parameters
hvac_programmable_thermostat_radio ambient_temperature
humidity
battery
hvac_state
regulation_state
target_mode
target_temperature
derogation.end_date
derogation.start_date
at_home_temperature
away_temperaturenight_temperature
frost_protection_temperature
set_target
cancel_target
set_at_home_temperature
set_away_temperature
set_night_temperature
set_frost_protection_temperature
target_mode / target_temperature / duration / duration_type
none
at_home_temperature
away_temperature
night_temperature
frost_protection_temperature
hvac_programmable_thermostat_wired ambient_temperature
humidity
battery
hvac_state
regulation_state
target_mode
target_temperature
derogation.end_date
derogation.start_date
at_home_temperature
away_temperature
night_temperature
frost_protection_temperature
set_target
cancel_target
set_at_home_temperature
set_away_temperature
set_night_temperature
set_frost_protection_temperature
target_mode / target_temperature / duration / duration_type
none
at_home_temperature
away_temperature
night_temperature
frost_protection_temperature

Error fetching somfy device update data: No devices returned

Hello Etienne,

since, not the last, but the previous update un december in home assistant I get this message.
All shutters switch to unavailable and come back few minutes later.
(i've two Site ID, one is without device).

Logger: homeassistant.components.somfy
Source: helpers/update_coordinator.py:166
Integration: Somfy (documentation, issues)
First occurred: 7 janvier 2021 à 21:13:57 (81 occurrences)
Last logged: 8:36:24

Error fetching somfy device update data: No devices returned

503 Server Error: Service Unavailable

Hi tetienne,
I replaced my sd card on my raspberry by a new one, and I backuped the old one to restore it on the new one.
I had to refresh the token, and I have an issue.

  • I got the url to authorise : done
  • I copy/paste the url in the console
  • i get a fresh token (I think it's good?)
    but I get the error :
    Traceback (most recent call last): File "getCovers_20191105_2.py", line 33, in <module> devices = api.get_devices(category=Category.ROLLER_SHUTTER) File "/usr/local/lib/python3.7/dist-packages/pymfy/api/somfy_api.py", line 61, in get_devices site_ids = [s.id for s in self.get_sites()] if site_id is None else [site_id] File "/usr/local/lib/python3.7/dist-packages/pymfy/api/somfy_api.py", line 43, in get_sites r.raise_for_status() File "/usr/lib/python3/dist-packages/requests/models.py", line 940, in raise_for_status raise HTTPError(http_error_msg, response=self) requests.exceptions.HTTPError: 503 Server Error: Service Unavailable for url: https://api.somfy. com/api/v1/site

PS: I simply use the script "Print all covers name" with my credentials.

What am i doing wrong?
Could you help me please?
Thank you ;)

Contribution

[
    {
        "capabilities": [],
        "categories": [
            "hub"
        ],
                "name": null,
                "states": [],
        "type": "hub_tahoma_2"
    },
    {
        "capabilities": [
            {
                "name": "close",
                "parameters": []
            },
            {
                "name": "identify",
                "parameters": []
            },
            {
                "name": "open",
                "parameters": []
            },
            {
                "name": "stop",
                "parameters": []
            }
        ],
        "categories": [
            "exterior_blind"
        ],
                "name": "Living",
                "states": [],
        "type": "exterior_blind_discrete_generic"
    },
    {
        "capabilities": [
            {
                "name": "close",
                "parameters": []
            },
            {
                "name": "identify",
                "parameters": []
            },
            {
                "name": "open",
                "parameters": []
            },
            {
                "name": "stop",
                "parameters": []
            }
        ],
        "categories": [
            "exterior_blind"
        ],
                "name": "Keuken 2",
                "states": [],
        "type": "exterior_blind_discrete_generic"
    },
    {
        "capabilities": [
            {
                "name": "close",
                "parameters": []
            },
            {
                "name": "identify",
                "parameters": []
            },
            {
                "name": "open",
                "parameters": []
            },
            {
                "name": "stop",
                "parameters": []
            }
        ],
        "categories": [
            "exterior_blind"
        ],
                "name": "Slaapkamer Noor",
                "states": [],
        "type": "exterior_blind_discrete_generic"
    },
    {
        "capabilities": [
            {
                "name": "close",
                "parameters": []
            },
            {
                "name": "identify",
                "parameters": []
            },
            {
                "name": "open",
                "parameters": []
            },
            {
                "name": "stop",
                "parameters": []
            }
        ],
        "categories": [
            "exterior_blind"
        ],
                "name": "Slaapkamer",
                "states": [],
        "type": "exterior_blind_discrete_generic"
    },
    {
        "capabilities": [
            {
                "name": "close",
                "parameters": []
            },
            {
                "name": "identify",
                "parameters": []
            },
            {
                "name": "open",
                "parameters": []
            },
            {
                "name": "stop",
                "parameters": []
            }
        ],
        "categories": [
            "exterior_blind"
        ],
                "name": "Keuken 1",
                "states": [],
        "type": "exterior_blind_discrete_generic"
    }
]

Add support for exterior blind and orientation

[
  {
    "id": "xxxxxxxxxxxxxxxxxx",
    "type": "hub_connexoon",
    "categories": [
      "hub"
    ],
    "states": [
      
    ],
    "capabilities": [
      
    ],
    "site_id": "xxxxxxxxxx",
    "available": true
  },
  {
    "id": "xxxxxx",
    "type": "exterior_blind_positionable_orientable_stateful_generic",
    "parent_id": "xxxxxxxxxxxx",
    "categories": [
      "exterior_blind"
    ],
    "states": [
      {
        "name": "orientation",
        "value": 100,
        "type": "integer"
      },
      {
        "name": "position",
        "type": "integer"
      }
    ],
    "capabilities": [
      {
        "name": "rotation",
        "parameters": [
          {
            "name": "orientation",
            "type": "integer"
          }
        ]
      },
      {
        "name": "position",
        "parameters": [
          {
            "name": "position",
            "type": "integer"
          }
        ]
      },
      {
        "name": "close",
        "parameters": [
          
        ]
      },
      {
        "name": "identify",
        "parameters": [
          
        ]
      },
      {
        "name": "open",
        "parameters": [
          
        ]
      },
      {
        "name": "stop",
        "parameters": [
          
        ]
      }
    ],
    "site_id": "xxxxxxxx",
    "name": "okno dol",
    "available": true
  }
]

Control duration [feature request]

Hi and I'm happy to report the thermostat works perfectly and without issues for the last month!
I'd like to suggest to implement a mechanism to set the duration of the selected mode. The issue is that when setting the mode after 12 hours or so it reverts to auto. If you have not the somfy app there are issues setting and keeping the preferred mode.

Temperature parameter types in thermostat api

Why limit the type temperature parameters to int? somfy's app accepts .5°C increments, and inputing float values seem to be cast correctly. But having float type parameters for temperature would seem more correct to me.

Can't run the example code

I am trying to initially run the example script without success.
I've created an app:
image

and I've put the client ID and secret in the python code.
as for the redirect URL - I've deployed a mock server that only log the content of the requests it gets.

When I run the Python code I get a URL but when I click it I get this error message:
image

What am I doing wrong?

authorization fails with an error

Hi,

Quick question to check if I'm missing something.

I have an account on https://developer.somfy.com/ and my blinds are linked to this account.
When I use the site API by using the try out option on the portal ( https://developer.somfy.com/somfy-open-api/apis/get/site),
it all works and I get the correct response back.

When I create my own app in the portal (shows up as approved) and I use the client_id/secret and so on with somfy-open-api, it doesn't work. On authorizing with the same account, I always get 'An error has occurred. Please try again. If the problem persists, please contact our technical support team.'

Would this be a problem on the somfy portal or could it be something I'm missing ?

It's also not clear how to contact the technical support team. I tried the contact form but no response.
Do you have a contact ?

Any help or pointers would be appreciated ! :)

Steven

error.invalid.grant

systematic error with pymfy 0.11.0 ; requests_oauthlib 1.3.1 ; Python 3.8.x ;
the same code used to work in 2019 with pymfy 0.5.x . I have the same error with the sample code in the home page for this project.

Handle errors returned by Somfy

Currently, pymfy does not handle any error returned by Somfy. HttpError is raised when the status code is not 200, it’s not accurate enough.

Here the different errors, I was able to find:

{
  "fault": {
    "faultstring": "Invalid access token",
    "detail": {
      "errorcode": "oauth.v2.InvalidAccessToken"
    }
  }
}
{
  "fault": {
    "detail": {
      "errorcode": "policies.ratelimit.QuotaViolation"
    },
    "faultstring": "Rate limit quota violation. Quota limit exceeded."
  }
}
{
  "fault": {
    "faultstring": "Access Token expired",
    "detail": {
      "errorcode": "keymanagement.service.access_token_expired"
    }
  }
}
{
  "uid": "867eaca52921",
  "message": "setup_not_found",
  "transactionId": "4e296110-c90b-11eb-bbf3-619c6ebbae8b",
  "data": null
}
{
  "uid": "fbd3dd6bab14",
  "message": "site_not_found",
  "transactionId": "30703f00-c919-11eb-b171-a9ae9fdd7072",
  "data": null
}
{
  "uid": "dd7bf078a314",
  "message": "ValidateError",
  "transactionId": "2fb262b0-c918-11eb-bbf3-619c6ebbae8b",
  "data": {
    "fields": {
      "command.name": {
        "message": "'name' is required"
      }
    }
  }
}
{
  "uid": "8b09d5a25940",
  "message": "device_not_found",
  "transactionId": "a2753340-c918-11eb-b171-a9ae9fdd7072",
  "data": null
}
̏{
    "uid": "46779aebccfd",
    "message": "definition_not_found",
    "data": null
  }

Rate limit quota violation

Hello @tetienne !

Since two or tree days I have lost all my Somfy covers in my Home Assistant installation ... During HA initialization the call of get_devices return no devices.

I have found that Somfy return a 500 response in GetDevicesBySiteId :

{
   "fault":{
      "detail":{
         "errorcode":"policies.ratelimit.QuotaViolation"
      },
      "faultstring":"Rate limit quota violation. Quota limit exceeded."
   }
}

I have 3 sites available and I thinks that the loop on site_id trigger the rate limitation.

With a breakpoint in L66 and manually wait a little I have all my covers back !

Ideas :

  • Handle this 500 Error code in L73
  • add a wait before calling Somfy API
  • filter on site_id in HA side

What do you think ?

Thanks for your help

Connexoon Access App

hello i have question for you, can you make api for Connexoon Access devices (gate...) ?

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.