diff --git a/CODEOWNERS b/CODEOWNERS index aedfcea7e96..28ce29ec29a 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -717,7 +717,7 @@ homeassistant/components/ps4/* @ktnrg45 tests/components/ps4/* @ktnrg45 homeassistant/components/push/* @dgomes tests/components/push/* @dgomes -homeassistant/components/pvoutput/* @fabaff +homeassistant/components/pvoutput/* @fabaff @frenck homeassistant/components/pvpc_hourly_pricing/* @azogue tests/components/pvpc_hourly_pricing/* @azogue homeassistant/components/qbittorrent/* @geoffreylagaisse diff --git a/homeassistant/components/pvoutput/manifest.json b/homeassistant/components/pvoutput/manifest.json index af40cf7eca4..d349aa33849 100644 --- a/homeassistant/components/pvoutput/manifest.json +++ b/homeassistant/components/pvoutput/manifest.json @@ -2,7 +2,7 @@ "domain": "pvoutput", "name": "PVOutput", "documentation": "https://www.home-assistant.io/integrations/pvoutput", - "after_dependencies": ["rest"], - "codeowners": ["@fabaff"], + "codeowners": ["@fabaff", "@frenck"], + "requirements": ["pvo==0.1.0"], "iot_class": "cloud_polling" } diff --git a/homeassistant/components/pvoutput/sensor.py b/homeassistant/components/pvoutput/sensor.py index 4f745666020..a18c5cc40b6 100644 --- a/homeassistant/components/pvoutput/sensor.py +++ b/homeassistant/components/pvoutput/sensor.py @@ -1,13 +1,12 @@ """Support for getting collected information from PVOutput.""" from __future__ import annotations -from collections import namedtuple from datetime import timedelta import logging +from pvo import PVOutput, PVOutputError import voluptuous as vol -from homeassistant.components.rest.data import RestData from homeassistant.components.sensor import ( PLATFORM_SCHEMA, SensorDeviceClass, @@ -15,19 +14,15 @@ from homeassistant.components.sensor import ( SensorStateClass, ) from homeassistant.const import ( - ATTR_DATE, ATTR_TEMPERATURE, - ATTR_TIME, ATTR_VOLTAGE, CONF_API_KEY, CONF_NAME, ENERGY_WATT_HOUR, ) -from homeassistant.core import callback import homeassistant.helpers.config_validation as cv _LOGGER = logging.getLogger(__name__) -_ENDPOINT = "https://pvoutput.org/service/r2/getstatus.jsp" ATTR_ENERGY_GENERATION = "energy_generation" ATTR_POWER_GENERATION = "power_generation" @@ -38,7 +33,6 @@ ATTR_EFFICIENCY = "efficiency" CONF_SYSTEM_ID = "system_id" DEFAULT_NAME = "PVOutput" -DEFAULT_VERIFY_SSL = True SCAN_INTERVAL = timedelta(minutes=2) @@ -54,21 +48,19 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the PVOutput sensor.""" name = config.get(CONF_NAME) - api_key = config.get(CONF_API_KEY) - system_id = config.get(CONF_SYSTEM_ID) - method = "GET" - payload = auth = None - verify_ssl = DEFAULT_VERIFY_SSL - headers = {"X-Pvoutput-Apikey": api_key, "X-Pvoutput-SystemId": system_id} - rest = RestData(hass, method, _ENDPOINT, auth, headers, None, payload, verify_ssl) - await rest.async_update() + pvoutput = PVOutput( + api_key=config[CONF_API_KEY], + system_id=config[CONF_SYSTEM_ID], + ) - if rest.data is None: + try: + status = await pvoutput.status() + except PVOutputError: _LOGGER.error("Unable to fetch data from PVOutput") return False - async_add_entities([PvoutputSensor(rest, name)]) + async_add_entities([PvoutputSensor(pvoutput, status, name)]) class PvoutputSensor(SensorEntity): @@ -78,62 +70,30 @@ class PvoutputSensor(SensorEntity): _attr_device_class = SensorDeviceClass.ENERGY _attr_native_unit_of_measurement = ENERGY_WATT_HOUR - def __init__(self, rest, name): + def __init__(self, pvoutput, status, name): """Initialize a PVOutput sensor.""" - self.rest = rest self._attr_name = name - self.pvcoutput = None - self.status = namedtuple( - "status", - [ - ATTR_DATE, - ATTR_TIME, - ATTR_ENERGY_GENERATION, - ATTR_POWER_GENERATION, - ATTR_ENERGY_CONSUMPTION, - ATTR_POWER_CONSUMPTION, - ATTR_EFFICIENCY, - ATTR_TEMPERATURE, - ATTR_VOLTAGE, - ], - ) + self.pvoutput = pvoutput + self.status = status @property def native_value(self): """Return the state of the device.""" - if self.pvcoutput is not None: - return self.pvcoutput.energy_generation - return None + return self.status.energy_generation @property def extra_state_attributes(self): """Return the state attributes of the monitored installation.""" - if self.pvcoutput is not None: - return { - ATTR_ENERGY_GENERATION: self.pvcoutput.energy_generation, - ATTR_POWER_GENERATION: self.pvcoutput.power_generation, - ATTR_ENERGY_CONSUMPTION: self.pvcoutput.energy_consumption, - ATTR_POWER_CONSUMPTION: self.pvcoutput.power_consumption, - ATTR_EFFICIENCY: self.pvcoutput.efficiency, - ATTR_TEMPERATURE: self.pvcoutput.temperature, - ATTR_VOLTAGE: self.pvcoutput.voltage, - } + return { + ATTR_ENERGY_GENERATION: self.status.energy_generation, + ATTR_POWER_GENERATION: self.status.power_generation, + ATTR_ENERGY_CONSUMPTION: self.status.energy_consumption, + ATTR_POWER_CONSUMPTION: self.status.power_consumption, + ATTR_EFFICIENCY: self.status.normalized_ouput, + ATTR_TEMPERATURE: self.status.temperature, + ATTR_VOLTAGE: self.status.voltage, + } async def async_update(self): """Get the latest data from the PVOutput API and updates the state.""" - await self.rest.async_update() - self._async_update_from_rest_data() - - async def async_added_to_hass(self): - """Ensure the data from the initial update is reflected in the state.""" - self._async_update_from_rest_data() - - @callback - def _async_update_from_rest_data(self): - """Update state from the rest data.""" - try: - # https://pvoutput.org/help/api_specification.html#get-status-service - self.pvcoutput = self.status._make(self.rest.data.split(",")) - except TypeError: - self.pvcoutput = None - _LOGGER.error("Unable to fetch data from PVOutput. %s", self.rest.data) + self.status = await self.pvoutput.status() diff --git a/requirements_all.txt b/requirements_all.txt index 0a4f7bfc6a7..de80c1b96d8 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -1291,6 +1291,9 @@ pushbullet.py==0.11.0 # homeassistant.components.pushover pushover_complete==1.1.1 +# homeassistant.components.pvoutput +pvo==0.1.0 + # homeassistant.components.rpi_gpio_pwm pwmled==1.6.7