-
-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Added sensors for available wheel of fortune spins
- Loading branch information
1 parent
b402c06
commit 6273784
Showing
9 changed files
with
382 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
11 changes: 11 additions & 0 deletions
11
custom_components/octopus_energy/api_client/wheel_of_fortune.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
class WheelOfFortuneSpinsResponse: | ||
electricity: int | ||
gas: int | ||
|
||
def __init__( | ||
self, | ||
electricity: int, | ||
gas: int | ||
): | ||
self.electricity = electricity | ||
self.gas = gas |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
75 changes: 75 additions & 0 deletions
75
custom_components/octopus_energy/coordinators/wheel_of_fortune.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import logging | ||
from datetime import datetime, timedelta | ||
|
||
from homeassistant.util.dt import (now) | ||
from homeassistant.helpers.update_coordinator import ( | ||
DataUpdateCoordinator | ||
) | ||
|
||
from ..const import ( | ||
COORDINATOR_REFRESH_IN_SECONDS, | ||
DOMAIN, | ||
DATA_CLIENT, | ||
DATA_ACCOUNT_ID, | ||
DATA_WHEEL_OF_FORTUNE_SPINS, | ||
) | ||
|
||
from ..api_client import OctopusEnergyApiClient | ||
from ..api_client.saving_sessions import SavingSession | ||
from ..api_client.wheel_of_fortune import WheelOfFortuneSpinsResponse | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
class WheelOfFortuneSpinsCoordinatorResult: | ||
last_retrieved: datetime | ||
spins: WheelOfFortuneSpinsResponse | ||
|
||
def __init__(self, last_retrieved: datetime, spins: WheelOfFortuneSpinsResponse): | ||
self.last_retrieved = last_retrieved | ||
self.spins = spins | ||
|
||
async def async_refresh_wheel_of_fortune_spins( | ||
current: datetime, | ||
client: OctopusEnergyApiClient, | ||
account_id: str, | ||
existing_result: WheelOfFortuneSpinsCoordinatorResult | ||
) -> WheelOfFortuneSpinsCoordinatorResult: | ||
if existing_result is None or current.minute % 30 == 0: | ||
try: | ||
result = await client.async_get_wheel_of_fortune_spins(account_id) | ||
|
||
return WheelOfFortuneSpinsCoordinatorResult(current, result) | ||
except: | ||
_LOGGER.debug('Failed to retrieve wheel of fortune spins') | ||
|
||
return existing_result | ||
|
||
async def async_setup_wheel_of_fortune_spins_coordinator(hass, account_id: str): | ||
async def async_update_data(): | ||
"""Fetch data from API endpoint.""" | ||
current = now() | ||
client: OctopusEnergyApiClient = hass.data[DOMAIN][DATA_CLIENT] | ||
|
||
hass.data[DOMAIN][DATA_WHEEL_OF_FORTUNE_SPINS] = await async_refresh_wheel_of_fortune_spins( | ||
current, | ||
client, | ||
account_id, | ||
hass.data[DOMAIN][DATA_WHEEL_OF_FORTUNE_SPINS] if DATA_WHEEL_OF_FORTUNE_SPINS in hass.data[DOMAIN] else None | ||
) | ||
|
||
return hass.data[DOMAIN][DATA_WHEEL_OF_FORTUNE_SPINS] | ||
|
||
coordinator = DataUpdateCoordinator( | ||
hass, | ||
_LOGGER, | ||
name=f"{account_id}_wheel_of_fortune_spins", | ||
update_method=async_update_data, | ||
# Because of how we're using the data, we'll update every minute, but we will only actually retrieve | ||
# data every 30 minutes | ||
update_interval=timedelta(seconds=COORDINATOR_REFRESH_IN_SECONDS), | ||
always_update=True | ||
) | ||
|
||
await coordinator.async_config_entry_first_refresh() | ||
|
||
return coordinator |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
79 changes: 79 additions & 0 deletions
79
custom_components/octopus_energy/wheel_of_fortune/electricity_spins.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import logging | ||
|
||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers.entity import generate_entity_id | ||
from homeassistant.helpers.update_coordinator import ( | ||
CoordinatorEntity, | ||
) | ||
from homeassistant.components.sensor import ( | ||
RestoreSensor, | ||
SensorStateClass | ||
) | ||
from ..utils import account_id_to_unique_key | ||
from ..coordinators.wheel_of_fortune import WheelOfFortuneSpinsCoordinatorResult | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
class OctopusEnergyWheelOfFortuneElectricitySpins(CoordinatorEntity, RestoreSensor): | ||
"""Sensor for current wheel of fortune spins for electricity""" | ||
|
||
def __init__(self, hass: HomeAssistant, coordinator, account_id: str): | ||
"""Init sensor.""" | ||
CoordinatorEntity.__init__(self, coordinator) | ||
|
||
self._account_id = account_id | ||
self._state = None | ||
self._attributes = { | ||
"last_evaluated": None | ||
} | ||
self._last_evaluated = None | ||
|
||
self.entity_id = generate_entity_id("sensor.{}", self.unique_id, hass=hass) | ||
|
||
@property | ||
def unique_id(self): | ||
"""The id of the sensor.""" | ||
return f"octopus_energy_{account_id_to_unique_key(self._account_id)}_wheel_of_fortune_spins_electricity" | ||
|
||
@property | ||
def name(self): | ||
"""Name of the sensor.""" | ||
return f"Octopus Energy {self._account_id} Wheel Of Fortune Spins Electricity" | ||
|
||
@property | ||
def icon(self): | ||
"""Icon of the sensor.""" | ||
return "mdi:star-circle" | ||
|
||
@property | ||
def extra_state_attributes(self): | ||
"""Attributes of the sensor.""" | ||
return self._attributes | ||
|
||
@property | ||
def state_class(self): | ||
"""The state class of sensor""" | ||
return SensorStateClass.TOTAL | ||
|
||
@property | ||
def state(self): | ||
result: WheelOfFortuneSpinsCoordinatorResult = self.coordinator.data if self.coordinator is not None and self.coordinator.data is not None else None | ||
if result is not None: | ||
self._state = result.spins.electricity | ||
self._attributes["last_evaluated"] = result.last_retrieved | ||
|
||
return self._state | ||
|
||
async def async_added_to_hass(self): | ||
"""Call when entity about to be added to hass.""" | ||
# If not None, we got an initial value. | ||
await super().async_added_to_hass() | ||
state = await self.async_get_last_state() | ||
|
||
if state is not None and self._state is None: | ||
self._state = state.state | ||
self._attributes = {} | ||
for x in state.attributes.keys(): | ||
self._attributes[x] = state.attributes[x] | ||
|
||
_LOGGER.debug(f'Restored OctopusEnergyWheelOfFortuneElectricitySpins state: {self._state}') |
79 changes: 79 additions & 0 deletions
79
custom_components/octopus_energy/wheel_of_fortune/gas_spins.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import logging | ||
|
||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers.entity import generate_entity_id | ||
from homeassistant.helpers.update_coordinator import ( | ||
CoordinatorEntity, | ||
) | ||
from homeassistant.components.sensor import ( | ||
RestoreSensor, | ||
SensorStateClass | ||
) | ||
from ..utils import account_id_to_unique_key | ||
from ..coordinators.wheel_of_fortune import WheelOfFortuneSpinsCoordinatorResult | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
class OctopusEnergyWheelOfFortuneGasSpins(CoordinatorEntity, RestoreSensor): | ||
"""Sensor for current wheel of fortune spins for gas""" | ||
|
||
def __init__(self, hass: HomeAssistant, coordinator, account_id: str): | ||
"""Init sensor.""" | ||
CoordinatorEntity.__init__(self, coordinator) | ||
|
||
self._account_id = account_id | ||
self._state = None | ||
self._attributes = { | ||
"last_evaluated": None | ||
} | ||
self._last_evaluated = None | ||
|
||
self.entity_id = generate_entity_id("sensor.{}", self.unique_id, hass=hass) | ||
|
||
@property | ||
def unique_id(self): | ||
"""The id of the sensor.""" | ||
return f"octopus_energy_{account_id_to_unique_key(self._account_id)}_wheel_of_fortune_spins_gas" | ||
|
||
@property | ||
def name(self): | ||
"""Name of the sensor.""" | ||
return f"Octopus Energy {self._account_id} Wheel Of Fortune Spins Gas" | ||
|
||
@property | ||
def icon(self): | ||
"""Icon of the sensor.""" | ||
return "mdi:star-circle" | ||
|
||
@property | ||
def extra_state_attributes(self): | ||
"""Attributes of the sensor.""" | ||
return self._attributes | ||
|
||
@property | ||
def state_class(self): | ||
"""The state class of sensor""" | ||
return SensorStateClass.TOTAL | ||
|
||
@property | ||
def state(self): | ||
result: WheelOfFortuneSpinsCoordinatorResult = self.coordinator.data if self.coordinator is not None and self.coordinator.data is not None else None | ||
if result is not None: | ||
self._state = result.spins.gas | ||
self._attributes["last_evaluated"] = result.last_retrieved | ||
|
||
return self._state | ||
|
||
async def async_added_to_hass(self): | ||
"""Call when entity about to be added to hass.""" | ||
# If not None, we got an initial value. | ||
await super().async_added_to_hass() | ||
state = await self.async_get_last_state() | ||
|
||
if state is not None and self._state is None: | ||
self._state = state.state | ||
self._attributes = {} | ||
for x in state.attributes.keys(): | ||
self._attributes[x] = state.attributes[x] | ||
|
||
_LOGGER.debug(f'Restored OctopusEnergyWheelOfFortuneGasSpins state: {self._state}') |
21 changes: 21 additions & 0 deletions
21
tests/integration/api_client/test_get_wheel_of_fortune_spins.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import pytest | ||
|
||
from integration import get_test_context | ||
from custom_components.octopus_energy.api_client import OctopusEnergyApiClient | ||
|
||
@pytest.mark.asyncio | ||
async def test_when_get_wheel_of_fortune_spins_called_then_spins_are_returned(): | ||
# Arrange | ||
context = get_test_context() | ||
|
||
client = OctopusEnergyApiClient(context["api_key"]) | ||
account_id = context["account_id"] | ||
|
||
# Act | ||
result = await client.async_get_wheel_of_fortune_spins(account_id) | ||
|
||
# Assert | ||
assert result is not None | ||
|
||
assert result.electricity >= 0 | ||
assert result.gas >= 0 |
Oops, something went wrong.