diff --git a/homeassistant/components/powerwall/binary_sensor.py b/homeassistant/components/powerwall/binary_sensor.py index 4e1c639aa65..889e6c192ef 100644 --- a/homeassistant/components/powerwall/binary_sensor.py +++ b/homeassistant/components/powerwall/binary_sensor.py @@ -1,9 +1,10 @@ -"""Support for August sensors.""" +"""Support for powerwall binary sensors.""" import logging from tesla_powerwall import GridStatus from homeassistant.components.binary_sensor import ( + DEVICE_CLASS_BATTERY_CHARGING, DEVICE_CLASS_CONNECTIVITY, BinarySensorDevice, ) @@ -13,13 +14,16 @@ from .const import ( ATTR_GRID_CODE, ATTR_NOMINAL_SYSTEM_POWER, ATTR_REGION, + CHARGING_MARGIN_OF_ERROR, DOMAIN, POWERWALL_API_DEVICE_TYPE, POWERWALL_API_GRID_STATUS, + POWERWALL_API_METERS, POWERWALL_API_SERIAL_NUMBERS, POWERWALL_API_SITE_INFO, POWERWALL_API_SITEMASTER, POWERWALL_API_STATUS, + POWERWALL_BATTERY_METER, POWERWALL_COORDINATOR, ) from .entity import PowerWallEntity @@ -42,6 +46,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities): PowerWallRunningSensor, PowerWallGridStatusSensor, PowerWallConnectedSensor, + PowerWallChargingStatusSensor, ): entities.append( sensor_class( @@ -131,3 +136,32 @@ class PowerWallGridStatusSensor(PowerWallEntity, BinarySensorDevice): def is_on(self): """Grid is online.""" return self._coordinator.data[POWERWALL_API_GRID_STATUS] == GridStatus.CONNECTED + + +class PowerWallChargingStatusSensor(PowerWallEntity, BinarySensorDevice): + """Representation of an Powerwall grid status sensor.""" + + @property + def name(self): + """Device Name.""" + return "Powerwall Charging" + + @property + def device_class(self): + """Device Class.""" + return DEVICE_CLASS_BATTERY_CHARGING + + @property + def unique_id(self): + """Device Uniqueid.""" + return f"{self.base_unique_id}_powerwall_charging" + + @property + def is_on(self): + """Grid is online.""" + return ( + self._coordinator.data[POWERWALL_API_METERS][ + POWERWALL_BATTERY_METER + ].instant_power + < CHARGING_MARGIN_OF_ERROR + ) diff --git a/homeassistant/components/powerwall/const.py b/homeassistant/components/powerwall/const.py index 9f652bea5f5..91e501da28f 100644 --- a/homeassistant/components/powerwall/const.py +++ b/homeassistant/components/powerwall/const.py @@ -42,6 +42,12 @@ POWERWALL_GRID_ONLINE = "SystemGridConnected" POWERWALL_CONNECTED_KEY = "connected_to_tesla" POWERWALL_RUNNING_KEY = "running" +POWERWALL_BATTERY_METER = "battery" + +# We only declare charging if they are getting +# at least 40W incoming as measuring the fields +# is not an exact science because of interference +CHARGING_MARGIN_OF_ERROR = -40 MODEL = "PowerWall 2" MANUFACTURER = "Tesla" diff --git a/tests/components/powerwall/test_binary_sensor.py b/tests/components/powerwall/test_binary_sensor.py index e2af4cf05e9..c8a081de573 100644 --- a/tests/components/powerwall/test_binary_sensor.py +++ b/tests/components/powerwall/test_binary_sensor.py @@ -52,3 +52,13 @@ async def test_sensors(hass): # Only test for a subset of attributes in case # HA changes the implementation and a new one appears assert all(item in state.attributes.items() for item in expected_attributes.items()) + + state = hass.states.get("binary_sensor.powerwall_charging") + assert state.state == STATE_ON + expected_attributes = { + "friendly_name": "Powerwall Charging", + "device_class": "battery_charging", + } + # Only test for a subset of attributes in case + # HA changes the implementation and a new one appears + assert all(item in state.attributes.items() for item in expected_attributes.items())