hass-core/homeassistant/components/somfy/cover.py
tetienne 0a7919a279 Somfy open api (#19548)
* CREATE Somfy component

* CREATE cover Somfy platform

* USE somfy id as unique id

* UPDATE all the devices in one call to limit the number of call

* FIX Don't load devices if not yet configured

* IMP Replace configurator by a simple notification

* ADD log in case state does not match

* IMP wording

* REMOVE debug stuf

* ADD support for tilt position

* UPDATE requirements

* FIX Use code instead of authorization response

 - Will allow to setup Somfy without https

* HANDLE stateless devices (Somfy RTS)

* FIX import locally 3rd party library

* UPDATE pymfy to 0.4.3

* ADD missing docstring

* FIX For Somfy 100 means closed and 0 opened

* FIX position can be None

* ENHANCE error management when error 500 occurs at setup

* FIX indent

* ROLLBACK tilt modification

 - See https://community.home-assistant.io/t/somfy-tahoma-official-api/61448/90?u=tetienne

* FIX Look for capability instead of state

* DON'T use exception to test if a feature is available

* UPDATE dependency

* ADD device_info property

* AVOID object creation in each method

* REMOVE unused constants

* ADD missing doc

* IMP Only make one call to add_entities

* USE dict[key] instead of get method

* IMP Don't pass hass object to the entities

* FIX Don't end logging messages with period

* USE config entries instead of a cache file

* IMPLEMENT async_unload_entry

* CONSOLIDATE package

 - see home-assistant/architecture#124

* UPDATE to pymfy 0.5.1

* SIMPLIFY config flow

* ADD French translation

* FIX 80 vs 79 max length

* ABORT flow asap

* FIX A tupple was returned

* MIGRATE to manifest.json

* ADD a placeholder async_setup_platform coroutine

 - It's currently required and expected by the platform helper.

* FIX codeowner

* ADD missing translations file

* USE new external step

* UPGRADE pymfy version

* Close Somfy tab automatically

* ADD manufacturer

  - Somfy only for the moment.

* HANDLE missing code or state in Somfy request

* REMOVE unused strings

* DECLARE somfy component to use config_flow

* APPLY static check remarks

* FIX async method cannot be called from sync context

* FIX only unload what has been loaded during entry setup

* DON't catch them all

* DON'T log full stacktrace

* ABORT conflig flow if configuration missing

* OMIT Somfy files for coverage

* ADD tests about Somfy config flow

* ADD pymfy to the test dependencies
2019-06-11 08:45:34 -07:00

114 lines
3.5 KiB
Python

"""
Support for Somfy Covers.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/cover.somfy/
"""
from homeassistant.components.cover import CoverDevice, ATTR_POSITION, \
ATTR_TILT_POSITION
from homeassistant.components.somfy import DOMAIN, SomfyEntity, DEVICES, API
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the Somfy cover platform."""
def get_covers():
"""Retrieve covers."""
from pymfy.api.devices.category import Category
categories = {Category.ROLLER_SHUTTER.value,
Category.INTERIOR_BLIND.value,
Category.EXTERIOR_BLIND.value}
devices = hass.data[DOMAIN][DEVICES]
return [SomfyCover(cover, hass.data[DOMAIN][API]) for cover in
devices if
categories & set(cover.categories)]
async_add_entities(await hass.async_add_executor_job(get_covers), True)
async def async_setup_platform(hass, config, async_add_entities,
discovery_info=None):
"""Old way of setting up platform.
Can only be called when a user accidentally mentions the platform in their
config. But even in that case it would have been ignored.
"""
pass
class SomfyCover(SomfyEntity, CoverDevice):
"""Representation of a Somfy cover device."""
def __init__(self, device, api):
"""Initialize the Somfy device."""
from pymfy.api.devices.blind import Blind
super().__init__(device, api)
self.cover = Blind(self.device, self.api)
async def async_update(self):
"""Update the device with the latest data."""
from pymfy.api.devices.blind import Blind
await super().async_update()
self.cover = Blind(self.device, self.api)
def close_cover(self, **kwargs):
"""Close the cover."""
self.cover.close()
def open_cover(self, **kwargs):
"""Open the cover."""
self.cover.open()
def stop_cover(self, **kwargs):
"""Stop the cover."""
self.cover.stop()
def set_cover_position(self, **kwargs):
"""Move the cover shutter to a specific position."""
self.cover.set_position(100 - kwargs[ATTR_POSITION])
@property
def current_cover_position(self):
"""Return the current position of cover shutter."""
position = None
if self.has_capability('position'):
position = 100 - self.cover.get_position()
return position
@property
def is_closed(self):
"""Return if the cover is closed."""
is_closed = None
if self.has_capability('position'):
is_closed = self.cover.is_closed()
return is_closed
@property
def current_cover_tilt_position(self):
"""Return current position of cover tilt.
None is unknown, 0 is closed, 100 is fully open.
"""
orientation = None
if self.has_capability('rotation'):
orientation = 100 - self.cover.orientation
return orientation
def set_cover_tilt_position(self, **kwargs):
"""Move the cover tilt to a specific position."""
self.cover.orientation = kwargs[ATTR_TILT_POSITION]
def open_cover_tilt(self, **kwargs):
"""Open the cover tilt."""
self.cover.orientation = 100
def close_cover_tilt(self, **kwargs):
"""Close the cover tilt."""
self.cover.orientation = 0
def stop_cover_tilt(self, **kwargs):
"""Stop the cover."""
self.cover.stop()