diff --git a/custom_components/checkwatt/__init__.py b/custom_components/checkwatt/__init__.py index 47705db..dfcabb9 100644 --- a/custom_components/checkwatt/__init__.py +++ b/custom_components/checkwatt/__init__.py @@ -57,6 +57,8 @@ class CheckwattResp(TypedDict): price_zone: str annual_revenue: float annual_fees: float + battery_power: float + battery_soc: float async def update_listener(hass: HomeAssistant, entry): @@ -129,6 +131,8 @@ async def _async_update_data(self) -> CheckwattResp: raise InvalidAuth if not await cw_inst.get_customer_details(): raise UpdateFailed("Unknown error get_customer_details") + if not await cw_inst.get_energy_flow(): + raise UpdateFailed("Unknown error get_energy_flow") # Prevent slow funcion to be called at boot. # The revenue sensors will be updated after ca 1 min @@ -189,6 +193,9 @@ async def _async_update_data(self) -> CheckwattResp: "battery_charge_peak": cw_inst.battery_charge_peak, "battery_discharge_peak": cw_inst.battery_discharge_peak, } + if cw_inst.energy_data is not None: + resp["battery_power"] = cw_inst.battery_power + resp["battery_soc"] = cw_inst.battery_soc # Use self stored variant of revenue parameters as they are not always fetched if self.today_revenue is not None: diff --git a/custom_components/checkwatt/const.py b/custom_components/checkwatt/const.py index 969c119..0ee4e50 100644 --- a/custom_components/checkwatt/const.py +++ b/custom_components/checkwatt/const.py @@ -1,4 +1,4 @@ -"""Constants for the Checkwatt integration.""" +"""Constants for the CheckWatt integration.""" from typing import Final DOMAIN = "checkwatt" @@ -8,8 +8,8 @@ CONF_UPDATE_INTERVAL = 1 CONF_UPDATE_INTERVAL_FCRD = 15 ATTRIBUTION = "Data provided by CheckWatt EnergyInBalance" -MANUFACTURER = "Checkwatt" -CHECKWATT_MODEL = "Checkwatt" +MANUFACTURER = "CheckWatt" +CHECKWATT_MODEL = "CheckWatt" CONF_DETAILED_SENSORS: Final = "show_details" CONF_DETAILED_ATTRIBUTES: Final = "show_detailed_attributes" @@ -17,13 +17,14 @@ # Misc P_UNKNOWN = "Unknown" -# Checkwatt Sensor Attributes +# CheckWatt Sensor Attributes # NOTE Keep these names aligned with strings.json # C_ADR = "street_address" C_ANNUAL_FEES = "annual_fees" C_ANNUAL_FEE_RATE = "annual_fee_rate" C_ANNUAL_GROSS = "annual_gross_income" +C_BATTERY_POWER = "battery_power" C_CHARGE_PEAK = "charge_peak" C_CITY = "city" C_DISCHARGE_PEAK = "discharge_peak" diff --git a/custom_components/checkwatt/manifest.json b/custom_components/checkwatt/manifest.json index bfdd518..5425ac3 100644 --- a/custom_components/checkwatt/manifest.json +++ b/custom_components/checkwatt/manifest.json @@ -12,8 +12,8 @@ "homekit": {}, "iot_class": "cloud_polling", "issue_tracker": "https://github.com/faanskit/ha-checkwatt/issues", - "requirements": ["pycheckwatt>=0.1.4"], + "requirements": ["pycheckwatt>=0.1.5"], "ssdp": [], - "version": "0.1.0", + "version": "0.1.1", "zeroconf": [] } diff --git a/custom_components/checkwatt/sensor.py b/custom_components/checkwatt/sensor.py index 27ee11c..d71618c 100644 --- a/custom_components/checkwatt/sensor.py +++ b/custom_components/checkwatt/sensor.py @@ -11,7 +11,7 @@ SensorStateClass, ) from homeassistant.config_entries import ConfigEntry -from homeassistant.const import UnitOfEnergy +from homeassistant.const import PERCENTAGE, UnitOfEnergy from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -24,6 +24,7 @@ C_ANNUAL_FEE_RATE, C_ANNUAL_FEES, C_ANNUAL_GROSS, + C_BATTERY_POWER, C_CHARGE_PEAK, C_CITY, C_DISCHARGE_PEAK, @@ -72,6 +73,15 @@ state_class=SensorStateClass.TOTAL, translation_key="annual_yield_sensor", ), + "battery": SensorEntityDescription( + key="battery_soc", + name="CheckWatt Battery SoC", + icon="mdi:battery-medium", + device_class=SensorDeviceClass.BATTERY, + native_unit_of_measurement=PERCENTAGE, + state_class=SensorStateClass.TOTAL, + translation_key="battery_soc_sensor", + ), } @@ -166,6 +176,8 @@ async def async_setup_entry( entities.append( CheckwattAnnualSensor(coordinator, description, use_detailed_attributes) ) + elif key == "battery": + entities.append(CheckwattBatterySoCSensor(coordinator, description)) if use_detailed_sensors: _LOGGER.debug( @@ -601,3 +613,40 @@ def native_value(self) -> str | None: if self.vat_key == "inc_vat": return round(self._coordinator.data["spot_price"] * 1.25, 3) return round(self._coordinator.data["spot_price"], 3) + + +class CheckwattBatterySoCSensor(AbstractCheckwattSensor): + """Representation of a CheckWatt Battery SoC sensor.""" + + def __init__( + self, + coordinator: CheckwattCoordinator, + description: SensorEntityDescription, + ) -> None: + """Initialize the sensor.""" + _LOGGER.debug("Creating %s sensor", description.name) + super().__init__(coordinator=coordinator, description=description) + + async def async_update(self) -> None: + """Get the latest data and updates the states.""" + if "battery_power" in self._coordinator.data: + self._attr_extra_state_attributes.update( + {C_BATTERY_POWER: self._coordinator.data["battery_power"]} + ) + self._attr_available = True + + @callback + def _handle_coordinator_update(self) -> None: + """Get the latest data and updates the states.""" + if "battery_soc" in self._coordinator.data: + self._attr_native_value = self._coordinator.data["battery_soc"] + if "battery_power" in self._coordinator.data: + self._attr_extra_state_attributes.update( + {C_BATTERY_POWER: self._coordinator.data["battery_power"]} + ) + super()._handle_coordinator_update() + + @property + def native_value(self) -> str | None: + """Get the latest state value.""" + return self._coordinator.data["battery_soc"] diff --git a/custom_components/checkwatt/strings.json b/custom_components/checkwatt/strings.json index 0e80f3d..e6e3689 100644 --- a/custom_components/checkwatt/strings.json +++ b/custom_components/checkwatt/strings.json @@ -34,7 +34,7 @@ "entity": { "sensor": { "daily_yield_sensor": { - "name": "CheckWatt Daily Yield", + "name": "CheckWatt Daily Net Income", "state_attributes": { "street_address": { "name": "Street Address" @@ -90,7 +90,7 @@ } }, "annual_yield_sensor": { - "name": "CheckWatt Annual Yield", + "name": "CheckWatt Annual Net Income", "state_attributes": { "street_address": { "name": "Street Address" @@ -145,6 +145,14 @@ "name": "VAT" } } + }, + "battery_soc_sensor": { + "name": "Battery SoC", + "state_attributes": { + "battery_power": { + "name": "Battery Power" + } + } } } } diff --git a/custom_components/checkwatt/translations/en.json b/custom_components/checkwatt/translations/en.json index a88653b..ba67b10 100644 --- a/custom_components/checkwatt/translations/en.json +++ b/custom_components/checkwatt/translations/en.json @@ -34,7 +34,7 @@ "entity": { "sensor": { "daily_yield_sensor": { - "name": "CheckWatt Daily Yield", + "name": "CheckWatt Daily Net Income", "state_attributes": { "street_address": { "name": "Street Address" @@ -90,7 +90,7 @@ } }, "annual_yield_sensor": { - "name": "CheckWatt Annual Yield", + "name": "CheckWatt Annual Net Income", "state_attributes": { "street_address": { "name": "Street Address" @@ -145,6 +145,14 @@ "name": "VAT" } } + }, + "battery_soc_sensor": { + "name": "Battery SoC", + "state_attributes": { + "battery_power": { + "name": "Battery Power" + } + } } } } diff --git a/custom_components/checkwatt/translations/sv.json b/custom_components/checkwatt/translations/sv.json index 26a7579..7c71b7e 100644 --- a/custom_components/checkwatt/translations/sv.json +++ b/custom_components/checkwatt/translations/sv.json @@ -145,6 +145,14 @@ "name": "Moms" } } + }, + "battery_soc_sensor": { + "name": "Batteriladdning", + "state_attributes": { + "battery_power": { + "name": "Batterieffekt" + } + } } } }