diff --git a/homeassistant/components/powerwall/__init__.py b/homeassistant/components/powerwall/__init__.py index 2dc19a0771d..fcf44fcf9b1 100644 --- a/homeassistant/components/powerwall/__init__.py +++ b/homeassistant/components/powerwall/__init__.py @@ -4,7 +4,7 @@ from datetime import timedelta import logging import requests -from tesla_powerwall import APIChangedError, Powerwall, PowerwallUnreachableError +from tesla_powerwall import MissingAttributeError, Powerwall, PowerwallUnreachableError import voluptuous as vol from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry @@ -72,9 +72,7 @@ async def _migrate_old_unique_ids(hass, entry_id, powerwall_data): # The old unique_id ended with the nomianal_system_engery_kWh so we can use that # to find the old base unique_id and extract the device_suffix. normalized_energy_index = ( - len(parts) - - 1 - - parts[::-1].index(str(site_info.nominal_system_energy_kWh)) + len(parts) - 1 - parts[::-1].index(str(site_info.nominal_system_energy)) ) device_suffix = parts[normalized_energy_index + 1 :] @@ -90,7 +88,9 @@ async def _migrate_old_unique_ids(hass, entry_id, powerwall_data): await entity_registry.async_migrate_entries(hass, entry_id, _async_migrator) -async def _async_handle_api_changed_error(hass: HomeAssistant, error: APIChangedError): +async def _async_handle_api_changed_error( + hass: HomeAssistant, error: MissingAttributeError +): # The error might include some important information about what exactly changed. _LOGGER.error(str(error)) hass.components.persistent_notification.async_create( @@ -116,7 +116,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): except PowerwallUnreachableError as err: http_session.close() raise ConfigEntryNotReady from err - except APIChangedError as err: + except MissingAttributeError as err: http_session.close() await _async_handle_api_changed_error(hass, err) return False @@ -135,7 +135,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry): ) except PowerwallUnreachableError as err: raise UpdateFailed("Unable to fetch data from powerwall") from err - except APIChangedError as err: + except MissingAttributeError as err: await _async_handle_api_changed_error(hass, err) hass.data[DOMAIN][entry.entry_id][POWERWALL_API_CHANGED] = True # Returns the cached data. This data can also be None diff --git a/homeassistant/components/powerwall/binary_sensor.py b/homeassistant/components/powerwall/binary_sensor.py index f064616c5ab..1d38e167134 100644 --- a/homeassistant/components/powerwall/binary_sensor.py +++ b/homeassistant/components/powerwall/binary_sensor.py @@ -19,7 +19,6 @@ from .const import ( POWERWALL_API_SITE_INFO, POWERWALL_API_SITEMASTER, POWERWALL_API_STATUS, - POWERWALL_BATTERY_METER, POWERWALL_COORDINATOR, ) from .entity import PowerWallEntity @@ -74,7 +73,7 @@ class PowerWallRunningSensor(PowerWallEntity, BinarySensorEntity): @property def is_on(self): """Get the powerwall running state.""" - return self.coordinator.data[POWERWALL_API_SITEMASTER].running + return self.coordinator.data[POWERWALL_API_SITEMASTER].is_running class PowerWallConnectedSensor(PowerWallEntity, BinarySensorEntity): @@ -98,7 +97,7 @@ class PowerWallConnectedSensor(PowerWallEntity, BinarySensorEntity): @property def is_on(self): """Get the powerwall connected to tesla state.""" - return self.coordinator.data[POWERWALL_API_SITEMASTER].connected_to_tesla + return self.coordinator.data[POWERWALL_API_SITEMASTER].is_connected_to_tesla class PowerWallGridStatusSensor(PowerWallEntity, BinarySensorEntity): @@ -147,6 +146,4 @@ class PowerWallChargingStatusSensor(PowerWallEntity, BinarySensorEntity): def is_on(self): """Powerwall is charging.""" # is_sending_to returns true for values greater than 100 watts - return self.coordinator.data[POWERWALL_API_METERS][ - POWERWALL_BATTERY_METER - ].is_sending_to() + return self.coordinator.data[POWERWALL_API_METERS].battery.is_sending_to() diff --git a/homeassistant/components/powerwall/config_flow.py b/homeassistant/components/powerwall/config_flow.py index fd44949e386..eb23ce4e030 100644 --- a/homeassistant/components/powerwall/config_flow.py +++ b/homeassistant/components/powerwall/config_flow.py @@ -1,7 +1,7 @@ """Config flow for Tesla Powerwall integration.""" import logging -from tesla_powerwall import APIChangedError, Powerwall, PowerwallUnreachableError +from tesla_powerwall import MissingAttributeError, Powerwall, PowerwallUnreachableError import voluptuous as vol from homeassistant import config_entries, core, exceptions @@ -27,7 +27,7 @@ async def validate_input(hass: core.HomeAssistant, data): site_info = await hass.async_add_executor_job(power_wall.get_site_info) except PowerwallUnreachableError as err: raise CannotConnect from err - except APIChangedError as err: + except MissingAttributeError as err: # Only log the exception without the traceback _LOGGER.error(str(err)) raise WrongVersion from err diff --git a/homeassistant/components/powerwall/const.py b/homeassistant/components/powerwall/const.py index caf08679652..6dd4558a98c 100644 --- a/homeassistant/components/powerwall/const.py +++ b/homeassistant/components/powerwall/const.py @@ -29,8 +29,6 @@ POWERWALL_API_SERIAL_NUMBERS = "serial_numbers" POWERWALL_HTTP_SESSION = "http_session" -POWERWALL_BATTERY_METER = "battery" - MODEL = "PowerWall 2" MANUFACTURER = "Tesla" diff --git a/homeassistant/components/powerwall/manifest.json b/homeassistant/components/powerwall/manifest.json index 930da38edde..be83f6825e7 100644 --- a/homeassistant/components/powerwall/manifest.json +++ b/homeassistant/components/powerwall/manifest.json @@ -3,6 +3,6 @@ "name": "Tesla Powerwall", "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/powerwall", - "requirements": ["tesla-powerwall==0.2.12"], + "requirements": ["tesla-powerwall==0.3.3"], "codeowners": ["@bdraco", "@jrester"] } diff --git a/homeassistant/components/powerwall/sensor.py b/homeassistant/components/powerwall/sensor.py index ff8830c3970..5026d2fb357 100644 --- a/homeassistant/components/powerwall/sensor.py +++ b/homeassistant/components/powerwall/sensor.py @@ -1,7 +1,7 @@ """Support for August sensors.""" import logging -from tesla_powerwall import MeterType, convert_to_kw +from tesla_powerwall import MeterType from homeassistant.const import DEVICE_CLASS_BATTERY, DEVICE_CLASS_POWER, PERCENTAGE @@ -85,7 +85,7 @@ class PowerWallChargeSensor(PowerWallEntity): @property def state(self): """Get the current value in percentage.""" - return self.coordinator.data[POWERWALL_API_CHARGE] + return round(self.coordinator.data[POWERWALL_API_CHARGE]) class PowerWallEnergySensor(PowerWallEntity): @@ -131,18 +131,18 @@ class PowerWallEnergySensor(PowerWallEntity): """Get the current value in kW.""" return ( self.coordinator.data[POWERWALL_API_METERS] - .get(self._meter) + .get_meter(self._meter) .get_power(precision=3) ) @property def device_state_attributes(self): """Return the device specific state attributes.""" - meter = self.coordinator.data[POWERWALL_API_METERS].get(self._meter) + meter = self.coordinator.data[POWERWALL_API_METERS].get_meter(self._meter) return { ATTR_FREQUENCY: round(meter.frequency, 1), - ATTR_ENERGY_EXPORTED: convert_to_kw(meter.energy_exported), - ATTR_ENERGY_IMPORTED: convert_to_kw(meter.energy_imported), - ATTR_INSTANT_AVERAGE_VOLTAGE: round(meter.instant_average_voltage, 1), + ATTR_ENERGY_EXPORTED: meter.get_energy_exported(), + ATTR_ENERGY_IMPORTED: meter.get_energy_imported(), + ATTR_INSTANT_AVERAGE_VOLTAGE: round(meter.avarage_voltage, 1), ATTR_IS_ACTIVE: meter.is_active(), } diff --git a/requirements_all.txt b/requirements_all.txt index 04e72054761..c3f7b8c610f 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2152,7 +2152,7 @@ temperusb==1.5.3 # tensorflow==2.3.0 # homeassistant.components.powerwall -tesla-powerwall==0.2.12 +tesla-powerwall==0.3.3 # homeassistant.components.tesla teslajsonpy==0.10.4 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index e1540eecf47..eb29306c8fc 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1005,7 +1005,7 @@ surepy==0.2.6 tellduslive==0.10.11 # homeassistant.components.powerwall -tesla-powerwall==0.2.12 +tesla-powerwall==0.3.3 # homeassistant.components.tesla teslajsonpy==0.10.4 diff --git a/tests/components/powerwall/mocks.py b/tests/components/powerwall/mocks.py index a384725daa8..6beb31c293a 100644 --- a/tests/components/powerwall/mocks.py +++ b/tests/components/powerwall/mocks.py @@ -6,11 +6,11 @@ import os from tesla_powerwall import ( DeviceType, GridStatus, - MetersAggregateResponse, + MetersAggregates, Powerwall, - PowerwallStatusResponse, - SiteInfoResponse, - SitemasterResponse, + PowerwallStatus, + SiteInfo, + SiteMaster, ) from homeassistant.components.powerwall.const import DOMAIN @@ -29,12 +29,12 @@ async def _mock_powerwall_with_fixtures(hass): device_type = await _async_load_json_fixture(hass, "device_type.json") return _mock_powerwall_return_value( - site_info=SiteInfoResponse(site_info), - charge=47, - sitemaster=SitemasterResponse(sitemaster), - meters=MetersAggregateResponse(meters), + site_info=SiteInfo(site_info), + charge=47.34587394586, + sitemaster=SiteMaster(sitemaster), + meters=MetersAggregates(meters), grid_status=GridStatus.CONNECTED, - status=PowerwallStatusResponse(status), + status=PowerwallStatus(status), device_type=DeviceType(device_type["device_type"]), serial_numbers=["TG0123456789AB", "TG9876543210BA"], ) @@ -66,10 +66,9 @@ def _mock_powerwall_return_value( async def _mock_powerwall_site_name(hass, site_name): powerwall_mock = MagicMock(Powerwall("1.2.3.4")) - site_info_resp = SiteInfoResponse( - await _async_load_json_fixture(hass, "site_info.json") - ) - site_info_resp.site_name = site_name + site_info_resp = SiteInfo(await _async_load_json_fixture(hass, "site_info.json")) + # Sets site_info_resp.site_name to return site_name + site_info_resp.response["site_name"] = site_name powerwall_mock.get_site_info = Mock(return_value=site_info_resp) return powerwall_mock diff --git a/tests/components/powerwall/test_config_flow.py b/tests/components/powerwall/test_config_flow.py index 9f72f1900f0..5f9445debe0 100644 --- a/tests/components/powerwall/test_config_flow.py +++ b/tests/components/powerwall/test_config_flow.py @@ -1,6 +1,6 @@ """Test the Powerwall config flow.""" -from tesla_powerwall import APIChangedError, PowerwallUnreachableError +from tesla_powerwall import MissingAttributeError, PowerwallUnreachableError from homeassistant import config_entries, setup from homeassistant.components.powerwall.const import DOMAIN @@ -99,7 +99,9 @@ async def test_form_wrong_version(hass): DOMAIN, context={"source": config_entries.SOURCE_USER} ) - mock_powerwall = _mock_powerwall_side_effect(site_info=APIChangedError(object, {})) + mock_powerwall = _mock_powerwall_side_effect( + site_info=MissingAttributeError({}, "") + ) with patch( "homeassistant.components.powerwall.config_flow.Powerwall",