diff --git a/openevsehttp/const.py b/openevsehttp/const.py index d381640..d247381 100644 --- a/openevsehttp/const.py +++ b/openevsehttp/const.py @@ -23,6 +23,8 @@ TTF = "time_to_full_charge" VOLTAGE = "voltage" SHAPER_LIVE = "shaper_live_pwr" +HOME_BATTERY_SOC = "home_battery_soc" +HOME_BATTERY_POWER = "home_battery_power" TYPE = "type" VALUE = "value" RELEASE = "release" diff --git a/openevsehttp/sensors.py b/openevsehttp/sensors.py index 1693925..d4830e7 100644 --- a/openevsehttp/sensors.py +++ b/openevsehttp/sensors.py @@ -6,7 +6,16 @@ from collections.abc import Mapping from typing import Any -from .const import BAT_LVL, BAT_RANGE, GRID, SOLAR, TTF, VOLTAGE +from .const import ( + BAT_LVL, + BAT_RANGE, + GRID, + HOME_BATTERY_POWER, + HOME_BATTERY_SOC, + SOLAR, + TTF, + VOLTAGE, +) from .exceptions import UnsupportedFeature _LOGGER = logging.getLogger(__name__) @@ -122,6 +131,34 @@ async def soc( response = await self.process_request(url=url, method="post", data=data) _LOGGER.debug("SOC response: %s", self._normalize_response(response)) + # Home/powerwall battery HTTP Posting + async def home_battery( + self, + soc: int | None = None, + power: int | None = None, + ) -> None: + """Send pushed home/powerwall battery data to the charger.""" + if not self._version_check("4.1.0"): + _LOGGER.debug("Feature not supported for older firmware.") + raise UnsupportedFeature + + url = f"{self.url}status" + data = {} + + if soc is not None: + data[HOME_BATTERY_SOC] = soc + if power is not None: + data[HOME_BATTERY_POWER] = power + + if not data: + _LOGGER.info("No home battery data to send to device.") + else: + _LOGGER.debug("Posting home battery data: %s", data) + response = await self.process_request(url=url, method="post", data=data) + _LOGGER.debug( + "Home battery response: %s", self._normalize_response(response) + ) + # Shaper HTTP Posting async def set_shaper_live_pwr(self, power: int) -> None: """Send pushed sensor data to shaper.""" diff --git a/tests/test_sensors.py b/tests/test_sensors.py index c9149c6..2f87372 100644 --- a/tests/test_sensors.py +++ b/tests/test_sensors.py @@ -88,6 +88,44 @@ async def test_soc(test_charger, test_charger_v2, mock_aioclient, caplog): await test_charger_v2.ws_disconnect() +# ── home_battery ───────────────────────────────────────────────────── + + +async def test_home_battery(test_charger, test_charger_v2, mock_aioclient, caplog): + """Test home_battery function.""" + await test_charger.update() + mock_aioclient.post( + TEST_URL_STATUS, + status=200, + body='{"home_battery_soc": 82, "home_battery_power": -1500}', + repeat=True, + ) + with caplog.at_level(logging.DEBUG): + await test_charger.home_battery(82, -1500) + assert ( + "Posting home battery data: {'home_battery_soc': 82, 'home_battery_power': -1500}" + in caplog.text + ) + assert ( + "Home battery response: {'home_battery_soc': 82, 'home_battery_power': -1500}" + in caplog.text + ) + + await test_charger.home_battery(soc=50) + assert "Posting home battery data: {'home_battery_soc': 50}" in caplog.text + + await test_charger.home_battery() + assert "No home battery data to send to device." in caplog.text + await test_charger.ws_disconnect() + + await test_charger_v2.update() + with pytest.raises(UnsupportedFeature): + with caplog.at_level(logging.DEBUG): + await test_charger_v2.home_battery(50, -100) + assert "Feature not supported for older firmware." in caplog.text + await test_charger_v2.ws_disconnect() + + # ── voltage ──────────────────────────────────────────────────────────