Normalize line endings

This commit is contained in:
Andrew Marks 2020-07-22 10:30:57 -04:00
parent fbbbe039db
commit 0cdb851ff2
5 changed files with 271 additions and 254 deletions

10
.gitattributes vendored Normal file
View File

@ -0,0 +1,10 @@
# Generic stuff
* text=auto
# Source files
# ============
*.py text diff=python eol=lf
# Config and data files
*.json text eol=lf
*.yaml text eol=lf

266
.gitignore vendored
View File

@ -1,133 +1,133 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# IDE files
.idea/
.vscode/
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# IDE files
.idea/
.vscode/

View File

@ -1,115 +1,115 @@
"""Shark IQ Integration"""
import async_timeout
import asyncio
import logging
import voluptuous as vol
from homeassistant import config_entries, exceptions
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from sharkiqpy import (
AylaApi,
SharkIqAuthError,
get_ayla_api,
)
from .const import COMPONENTS, DOMAIN, SHARKIQ_SESSION
_LOGGER = logging.getLogger(__name__)
CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA)
class CannotConnect(exceptions.HomeAssistantError):
"""Error to indicate we cannot connect."""
pass
async def async_setup(hass, config):
"""Set up the sharkiq environment"""
hass.data.setdefault(DOMAIN, {})
if DOMAIN not in config:
return True
for index, conf in enumerate(config[DOMAIN]):
_LOGGER.debug("Importing Shark IQ #%d (Username: %s)", index, conf[CONF_USERNAME])
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data=conf,
)
)
async def async_connect_or_timeout(ayla_api: AylaApi) -> AylaApi:
"""Connect to vacuum."""
try:
with async_timeout.timeout(10):
_LOGGER.debug("Initialize connection to Ayla networks API")
await ayla_api.async_sign_in()
except SharkIqAuthError as exc:
_LOGGER.error("Error to connect to Shark IQ api")
raise CannotConnect from exc
except asyncio.TimeoutError as exc:
_LOGGER.error("Timeout expired")
raise CannotConnect from exc
return ayla_api
async def async_setup_entry(hass, config_entry):
"""Set the config entry up."""
# Set up sharkiq platforms with config entry
ayla_api = get_ayla_api(
username=config_entry.data[CONF_USERNAME],
password=config_entry.data[CONF_PASSWORD],
websession=hass.helpers.aiohttp_client.async_get_clientsession()
)
try:
if not await async_connect_or_timeout(ayla_api):
return False
except CannotConnect as exc:
raise exceptions.ConfigEntryNotReady from exc
hass.data[DOMAIN][config_entry.entry_id] = {
SHARKIQ_SESSION: ayla_api
}
for component in COMPONENTS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(config_entry, component)
)
if not config_entry.update_listeners:
config_entry.add_update_listener(async_update_options)
return True
async def async_disconnect_or_timeout(ayla_api):
"""Disconnect to vacuum."""
_LOGGER.debug("Disconnecting from Ayla Api")
with async_timeout.timeout(3):
await ayla_api.async_sign_out()
return True
async def async_update_options(hass, config_entry):
"""Update options."""
await hass.config_entries.async_reload(config_entry.entry_id)
async def async_unload_entry(hass, config_entry):
"""Unload a config entry."""
unload_ok = all(
await asyncio.gather(
*[
hass.config_entries.async_forward_entry_unload(config_entry, component)
for component in COMPONENTS
]
)
)
if unload_ok:
domain_data = hass.data[DOMAIN][config_entry.entry_id]
await async_disconnect_or_timeout(ayla_api=domain_data[SHARKIQ_SESSION])
hass.data[DOMAIN].pop(config_entry.entry_id)
return unload_ok
"""Shark IQ Integration"""
import async_timeout
import asyncio
import logging
import voluptuous as vol
from homeassistant import config_entries, exceptions
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME
from sharkiqpy import (
AylaApi,
SharkIqAuthError,
get_ayla_api,
)
from .const import COMPONENTS, DOMAIN, SHARKIQ_SESSION
_LOGGER = logging.getLogger(__name__)
CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({})}, extra=vol.ALLOW_EXTRA)
class CannotConnect(exceptions.HomeAssistantError):
"""Error to indicate we cannot connect."""
pass
async def async_setup(hass, config):
"""Set up the sharkiq environment"""
hass.data.setdefault(DOMAIN, {})
if DOMAIN not in config:
return True
for index, conf in enumerate(config[DOMAIN]):
_LOGGER.debug("Importing Shark IQ #%d (Username: %s)", index, conf[CONF_USERNAME])
hass.async_create_task(
hass.config_entries.flow.async_init(
DOMAIN, context={"source": config_entries.SOURCE_IMPORT}, data=conf,
)
)
async def async_connect_or_timeout(ayla_api: AylaApi) -> AylaApi:
"""Connect to vacuum."""
try:
with async_timeout.timeout(10):
_LOGGER.debug("Initialize connection to Ayla networks API")
await ayla_api.async_sign_in()
except SharkIqAuthError as exc:
_LOGGER.error("Error to connect to Shark IQ api")
raise CannotConnect from exc
except asyncio.TimeoutError as exc:
_LOGGER.error("Timeout expired")
raise CannotConnect from exc
return ayla_api
async def async_setup_entry(hass, config_entry):
"""Set the config entry up."""
# Set up sharkiq platforms with config entry
ayla_api = get_ayla_api(
username=config_entry.data[CONF_USERNAME],
password=config_entry.data[CONF_PASSWORD],
websession=hass.helpers.aiohttp_client.async_get_clientsession()
)
try:
if not await async_connect_or_timeout(ayla_api):
return False
except CannotConnect as exc:
raise exceptions.ConfigEntryNotReady from exc
hass.data[DOMAIN][config_entry.entry_id] = {
SHARKIQ_SESSION: ayla_api
}
for component in COMPONENTS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(config_entry, component)
)
if not config_entry.update_listeners:
config_entry.add_update_listener(async_update_options)
return True
async def async_disconnect_or_timeout(ayla_api):
"""Disconnect to vacuum."""
_LOGGER.debug("Disconnecting from Ayla Api")
with async_timeout.timeout(3):
await ayla_api.async_sign_out()
return True
async def async_update_options(hass, config_entry):
"""Update options."""
await hass.config_entries.async_reload(config_entry.entry_id)
async def async_unload_entry(hass, config_entry):
"""Unload a config entry."""
unload_ok = all(
await asyncio.gather(
*[
hass.config_entries.async_forward_entry_unload(config_entry, component)
for component in COMPONENTS
]
)
)
if unload_ok:
domain_data = hass.data[DOMAIN][config_entry.entry_id]
await async_disconnect_or_timeout(ayla_api=domain_data[SHARKIQ_SESSION])
hass.data[DOMAIN].pop(config_entry.entry_id)
return unload_ok

View File

@ -3,7 +3,7 @@
"name": "Shark IQ",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/sharkiq",
"requirements": ["sharkiqpy==0.1.0"],
"requirements": ["sharkiqpy==0.1.1"],
"dependencies": [],
"codeowners": ["@ajmarks"]
}

View File

@ -105,11 +105,7 @@ class SharkVacuumEntity(StateVacuumEntity):
@property
def is_docked(self) -> Optional[bool]:
"""Is vacuum docked"""
docked_status = self.sharkiq.get_property_value(Properties.DOCKED_STATUS)
if docked_status is None:
return None
else:
return docked_status == 1
return self.sharkiq.get_property_value(Properties.DOCKED_STATUS)
@property
def error_code(self) -> Optional[int]:
@ -230,3 +226,14 @@ class SharkVacuumEntity(StateVacuumEntity):
def fan_speed_list(self):
"""Get the list of available fan speed steps of the vacuum cleaner."""
return list(FAN_SPEEDS_MAP.keys())
# Various attributes we want to expose
@property
def recharge_resume(self) -> Optional[bool]:
"""Recharge and resume mode active"""
return self.sharkiq.get_property_value(Properties.RECHARGE_RESUME)
@property
def rssi(self) -> Optional[int]:
"""WiFi RSSI"""
return self.sharkiq.get_property_value(Properties.RSSI)