mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Hydroquebec component use now asyncio (#10795)
* Hydroquebec component use now asyncio * Add tests * Improve coverage * fix tests * Remove useless try/except and associated tests
This commit is contained in:
parent
0664bf31a2
commit
8742ce035a
@ -532,7 +532,6 @@ omit =
|
|||||||
homeassistant/components/sensor/haveibeenpwned.py
|
homeassistant/components/sensor/haveibeenpwned.py
|
||||||
homeassistant/components/sensor/hp_ilo.py
|
homeassistant/components/sensor/hp_ilo.py
|
||||||
homeassistant/components/sensor/htu21d.py
|
homeassistant/components/sensor/htu21d.py
|
||||||
homeassistant/components/sensor/hydroquebec.py
|
|
||||||
homeassistant/components/sensor/imap.py
|
homeassistant/components/sensor/imap.py
|
||||||
homeassistant/components/sensor/imap_email_content.py
|
homeassistant/components/sensor/imap_email_content.py
|
||||||
homeassistant/components/sensor/influxdb.py
|
homeassistant/components/sensor/influxdb.py
|
||||||
|
@ -7,10 +7,10 @@ https://www.hydroquebec.com/portail/en/group/clientele/portrait-de-consommation
|
|||||||
For more details about this platform, please refer to the documentation at
|
For more details about this platform, please refer to the documentation at
|
||||||
https://home-assistant.io/components/sensor.hydroquebec/
|
https://home-assistant.io/components/sensor.hydroquebec/
|
||||||
"""
|
"""
|
||||||
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
import requests
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
||||||
@ -21,7 +21,7 @@ from homeassistant.helpers.entity import Entity
|
|||||||
from homeassistant.util import Throttle
|
from homeassistant.util import Throttle
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
REQUIREMENTS = ['pyhydroquebec==1.3.1']
|
REQUIREMENTS = ['pyhydroquebec==2.0.2']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -93,7 +93,8 @@ DAILY_MAP = (('yesterday_total_consumption', 'consoTotalQuot'),
|
|||||||
('yesterday_higher_price_consumption', 'consoHautQuot'))
|
('yesterday_higher_price_consumption', 'consoHautQuot'))
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
@asyncio.coroutine
|
||||||
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Set up the HydroQuebec sensor."""
|
"""Set up the HydroQuebec sensor."""
|
||||||
# Create a data fetcher to support all of the configured sensors. Then make
|
# Create a data fetcher to support all of the configured sensors. Then make
|
||||||
# the first call to init the data.
|
# the first call to init the data.
|
||||||
@ -102,13 +103,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
password = config.get(CONF_PASSWORD)
|
password = config.get(CONF_PASSWORD)
|
||||||
contract = config.get(CONF_CONTRACT)
|
contract = config.get(CONF_CONTRACT)
|
||||||
|
|
||||||
try:
|
hydroquebec_data = HydroquebecData(username, password, contract)
|
||||||
hydroquebec_data = HydroquebecData(username, password, contract)
|
contracts = yield from hydroquebec_data.get_contract_list()
|
||||||
_LOGGER.info("Contract list: %s",
|
_LOGGER.info("Contract list: %s",
|
||||||
", ".join(hydroquebec_data.get_contract_list()))
|
", ".join(contracts))
|
||||||
except requests.exceptions.HTTPError as error:
|
|
||||||
_LOGGER.error("Failt login: %s", error)
|
|
||||||
return False
|
|
||||||
|
|
||||||
name = config.get(CONF_NAME)
|
name = config.get(CONF_NAME)
|
||||||
|
|
||||||
@ -116,7 +114,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
for variable in config[CONF_MONITORED_VARIABLES]:
|
for variable in config[CONF_MONITORED_VARIABLES]:
|
||||||
sensors.append(HydroQuebecSensor(hydroquebec_data, variable, name))
|
sensors.append(HydroQuebecSensor(hydroquebec_data, variable, name))
|
||||||
|
|
||||||
add_devices(sensors)
|
async_add_devices(sensors, True)
|
||||||
|
|
||||||
|
|
||||||
class HydroQuebecSensor(Entity):
|
class HydroQuebecSensor(Entity):
|
||||||
@ -152,10 +150,11 @@ class HydroQuebecSensor(Entity):
|
|||||||
"""Icon to use in the frontend, if any."""
|
"""Icon to use in the frontend, if any."""
|
||||||
return self._icon
|
return self._icon
|
||||||
|
|
||||||
def update(self):
|
@asyncio.coroutine
|
||||||
|
def async_update(self):
|
||||||
"""Get the latest data from Hydroquebec and update the state."""
|
"""Get the latest data from Hydroquebec and update the state."""
|
||||||
self.hydroquebec_data.update()
|
yield from self.hydroquebec_data.async_update()
|
||||||
if self.type in self.hydroquebec_data.data:
|
if self.hydroquebec_data.data.get(self.type) is not None:
|
||||||
self._state = round(self.hydroquebec_data.data[self.type], 2)
|
self._state = round(self.hydroquebec_data.data[self.type], 2)
|
||||||
|
|
||||||
|
|
||||||
@ -170,23 +169,24 @@ class HydroquebecData(object):
|
|||||||
self._contract = contract
|
self._contract = contract
|
||||||
self.data = {}
|
self.data = {}
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
def get_contract_list(self):
|
def get_contract_list(self):
|
||||||
"""Return the contract list."""
|
"""Return the contract list."""
|
||||||
# Fetch data
|
# Fetch data
|
||||||
self._fetch_data()
|
yield from self._fetch_data()
|
||||||
return self.client.get_contracts()
|
return self.client.get_contracts()
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||||
def _fetch_data(self):
|
def _fetch_data(self):
|
||||||
"""Fetch latest data from HydroQuebec."""
|
"""Fetch latest data from HydroQuebec."""
|
||||||
from pyhydroquebec.client import PyHydroQuebecError
|
|
||||||
try:
|
try:
|
||||||
self.client.fetch_data()
|
yield from self.client.fetch_data()
|
||||||
except PyHydroQuebecError as exp:
|
except BaseException as exp:
|
||||||
_LOGGER.error("Error on receive last Hydroquebec data: %s", exp)
|
_LOGGER.error("Error on receive last Hydroquebec data: %s", exp)
|
||||||
return
|
|
||||||
|
|
||||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
@asyncio.coroutine
|
||||||
def update(self):
|
def async_update(self):
|
||||||
"""Return the latest collected data from HydroQuebec."""
|
"""Return the latest collected data from HydroQuebec."""
|
||||||
self._fetch_data()
|
yield from self._fetch_data()
|
||||||
self.data = self.client.get_data(self._contract)[self._contract]
|
self.data = self.client.get_data(self._contract)[self._contract]
|
||||||
|
@ -698,7 +698,7 @@ pyhiveapi==0.2.5
|
|||||||
pyhomematic==0.1.36
|
pyhomematic==0.1.36
|
||||||
|
|
||||||
# homeassistant.components.sensor.hydroquebec
|
# homeassistant.components.sensor.hydroquebec
|
||||||
pyhydroquebec==1.3.1
|
pyhydroquebec==2.0.2
|
||||||
|
|
||||||
# homeassistant.components.alarm_control_panel.ialarm
|
# homeassistant.components.alarm_control_panel.ialarm
|
||||||
pyialarm==0.2
|
pyialarm==0.2
|
||||||
|
89
tests/components/sensor/test_hydroquebec.py
Normal file
89
tests/components/sensor/test_hydroquebec.py
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
"""The test for the hydroquebec sensor platform."""
|
||||||
|
import asyncio
|
||||||
|
import logging
|
||||||
|
import sys
|
||||||
|
from unittest.mock import MagicMock
|
||||||
|
|
||||||
|
from homeassistant.bootstrap import async_setup_component
|
||||||
|
from homeassistant.components.sensor import hydroquebec
|
||||||
|
from tests.common import assert_setup_component
|
||||||
|
|
||||||
|
|
||||||
|
CONTRACT = "123456789"
|
||||||
|
|
||||||
|
|
||||||
|
class HydroQuebecClientMock():
|
||||||
|
"""Fake Hydroquebec client."""
|
||||||
|
|
||||||
|
def __init__(self, username, password, contract=None):
|
||||||
|
"""Fake Hydroquebec client init."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_data(self, contract):
|
||||||
|
"""Return fake hydroquebec data."""
|
||||||
|
return {CONTRACT: {"balance": 160.12}}
|
||||||
|
|
||||||
|
def get_contracts(self):
|
||||||
|
"""Return fake hydroquebec contracts."""
|
||||||
|
return [CONTRACT]
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def fetch_data(self):
|
||||||
|
"""Return fake fetching data."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class HydroQuebecClientMockError(HydroQuebecClientMock):
|
||||||
|
"""Fake Hydroquebec client error."""
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def fetch_data(self):
|
||||||
|
"""Return fake fetching data."""
|
||||||
|
raise hydroquebec.PyHydroQuebecError("Fake Error")
|
||||||
|
|
||||||
|
|
||||||
|
class PyHydroQuebecErrorMock(BaseException):
|
||||||
|
"""Fake PyHydroquebec Error."""
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_hydroquebec_sensor(loop, hass):
|
||||||
|
"""Test the Hydroquebec number sensor."""
|
||||||
|
sys.modules['pyhydroquebec'] = MagicMock()
|
||||||
|
sys.modules['pyhydroquebec.client'] = MagicMock()
|
||||||
|
sys.modules['pyhydroquebec.client.PyHydroQuebecError'] = \
|
||||||
|
PyHydroQuebecErrorMock
|
||||||
|
import pyhydroquebec.client
|
||||||
|
pyhydroquebec.HydroQuebecClient = HydroQuebecClientMock
|
||||||
|
pyhydroquebec.client.PyHydroQuebecError = PyHydroQuebecErrorMock
|
||||||
|
config = {
|
||||||
|
'sensor': {
|
||||||
|
'platform': 'hydroquebec',
|
||||||
|
'name': 'hydro',
|
||||||
|
'contract': CONTRACT,
|
||||||
|
'username': 'myusername',
|
||||||
|
'password': 'password',
|
||||||
|
'monitored_variables': [
|
||||||
|
'balance',
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
with assert_setup_component(1):
|
||||||
|
yield from async_setup_component(hass, 'sensor', config)
|
||||||
|
state = hass.states.get('sensor.hydro_balance')
|
||||||
|
assert state.state == "160.12"
|
||||||
|
assert state.attributes.get('unit_of_measurement') == "CAD"
|
||||||
|
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def test_error(hass, caplog):
|
||||||
|
"""Test the Hydroquebec sensor errors."""
|
||||||
|
caplog.set_level(logging.ERROR)
|
||||||
|
sys.modules['pyhydroquebec'] = MagicMock()
|
||||||
|
sys.modules['pyhydroquebec.client'] = MagicMock()
|
||||||
|
import pyhydroquebec.client
|
||||||
|
pyhydroquebec.HydroQuebecClient = HydroQuebecClientMockError
|
||||||
|
pyhydroquebec.client.PyHydroQuebecError = BaseException
|
||||||
|
hydro_data = hydroquebec.HydroquebecData('username', 'password')
|
||||||
|
yield from hydro_data._fetch_data()
|
||||||
|
assert "Error on receive last Hydroquebec data: " in caplog.text
|
Loading…
x
Reference in New Issue
Block a user