Skip to content

Commit

Permalink
Merge branch 'master' into clickaction-urls
Browse files Browse the repository at this point in the history
  • Loading branch information
kylegordon committed Jun 17, 2024
2 parents 938e340 + 7a546aa commit b82b19b
Show file tree
Hide file tree
Showing 91 changed files with 2,583 additions and 1,266 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/esphome-parallel.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ jobs:
cp -R esphome/travis_secrets.yaml.txt esphome/secrets.yaml
- name: Compile all ESPHome ${{matrix.file}}
uses: esphome/build-action@v2
continue-on-error: true
with:
version: dev
yaml_file: ${{matrix.file}}
Expand All @@ -108,7 +109,7 @@ jobs:
final:
name: Final ESPHome check
runs-on: ubuntu-latest
needs: [loop-stable, loop-beta, loop-dev]
needs: [loop-stable, loop-beta]
steps:
- name: Getting your configuration from GitHub
uses: actions/checkout@v4
97 changes: 77 additions & 20 deletions custom_components/octopus_energy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,23 @@
from homeassistant.helpers import device_registry as dr
from homeassistant.components.recorder import get_instance
from homeassistant.util.dt import (utcnow)
from homeassistant.const import (
EVENT_HOMEASSISTANT_STOP
)

from .coordinators.account import AccountCoordinatorResult, async_setup_account_info_coordinator
from .coordinators.intelligent_dispatches import async_setup_intelligent_dispatches_coordinator
from .coordinators.intelligent_settings import async_setup_intelligent_settings_coordinator
from .coordinators.electricity_rates import async_setup_electricity_rates_coordinator
from .coordinators.saving_sessions import async_setup_saving_sessions_coordinators
from .coordinators.greenness_forecast import async_setup_greenness_forecast_coordinator
from .statistics import get_statistic_ids_to_remove
from .intelligent import async_mock_intelligent_data, get_intelligent_features, is_intelligent_tariff, mock_intelligent_device

from .config.main import async_migrate_main_config
from .config.target_rates import async_migrate_target_config
from .utils import get_active_tariff_code
from .utils.tariff_overrides import async_get_tariff_override

from .const import (
CONFIG_KIND,
Expand All @@ -34,8 +39,6 @@
CONFIG_ACCOUNT_ID,
CONFIG_MAIN_ELECTRICITY_PRICE_CAP,
CONFIG_MAIN_GAS_PRICE_CAP,

CONFIG_TARGET_NAME,

DATA_CLIENT,
DATA_ELECTRICITY_RATES_COORDINATOR_KEY,
Expand All @@ -52,6 +55,12 @@

SCAN_INTERVAL = timedelta(minutes=1)

async def async_remove_config_entry_device(
hass, config_entry, device_entry
) -> bool:
"""Remove a config entry from a device."""
return True

async def async_migrate_entry(hass, config_entry):
"""Migrate old entry."""
if (config_entry.version < CONFIG_VERSION):
Expand All @@ -75,6 +84,13 @@ async def async_migrate_entry(hass, config_entry):

return True

async def _async_close_client(hass, account_id: str):
if account_id in hass.data[DOMAIN] and DATA_CLIENT in hass.data[DOMAIN][account_id]:
_LOGGER.debug('Closing client...')
client: OctopusEnergyApiClient = hass.data[DOMAIN][account_id][DATA_CLIENT]
await client.async_close()
_LOGGER.debug('Client closed.')

async def async_setup_entry(hass, entry):
"""This is called from the config flow."""
hass.data.setdefault(DOMAIN, {})
Expand All @@ -90,6 +106,22 @@ async def async_setup_entry(hass, entry):
if config[CONFIG_KIND] == CONFIG_KIND_ACCOUNT:
await async_setup_dependencies(hass, config)
await hass.config_entries.async_forward_entry_setups(entry, ACCOUNT_PLATFORMS)

async def async_close_connection(_) -> None:
"""Close client."""
await _async_close_client(hass, account_id)

entry.async_on_unload(
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_close_connection)
)

# If the main account has been reloaded, then reload all other entries to make sure they're referencing
# the correct references (e.g. rate coordinators)
child_entries = hass.config_entries.async_entries(DOMAIN)
for child_entry in child_entries:
if child_entry.data[CONFIG_KIND] != CONFIG_KIND_ACCOUNT and child_entry.data[CONFIG_ACCOUNT_ID] == account_id:
await hass.config_entries.async_reload(child_entry.entry_id)

elif config[CONFIG_KIND] == CONFIG_KIND_TARGET_RATE:
if DOMAIN not in hass.data or account_id not in hass.data[DOMAIN] or DATA_ACCOUNT not in hass.data[DOMAIN][account_id]:
raise ConfigEntryNotReady("Account has not been setup")
Expand Down Expand Up @@ -148,6 +180,8 @@ async def async_setup_dependencies(hass, config):
_LOGGER.info(f'electricity_price_cap: {electricity_price_cap}')
_LOGGER.info(f'gas_price_cap: {gas_price_cap}')

# Close any existing clients, as our new client may have changed
await _async_close_client(hass, account_id)
client = OctopusEnergyApiClient(config[CONFIG_MAIN_API_KEY], electricity_price_cap, gas_price_cap)
hass.data[DOMAIN][account_id][DATA_CLIENT] = client

Expand All @@ -163,31 +197,48 @@ async def async_setup_dependencies(hass, config):

hass.data[DOMAIN][account_id][DATA_ACCOUNT] = AccountCoordinatorResult(utcnow(), 1, account_info)

# Remove gas meter devices which had incorrect identifier
device_registry = dr.async_get(hass)
now = utcnow()

if account_info is not None and len(account_info["gas_meter_points"]) > 0:
device_registry = dr.async_get(hass)
for point in account_info["gas_meter_points"]:
mprn = point["mprn"]
for meter in point["meters"]:
serial_number = meter["serial_number"]
intelligent_device = device_registry.async_get_device(identifiers={(DOMAIN, f"electricity_{serial_number}_{mprn}")})
if intelligent_device is not None:
device_registry.async_remove_device(intelligent_device.id)

tariff_code = get_active_tariff_code(now, point["agreements"])
if tariff_code is None:
gas_device = device_registry.async_get_device(identifiers={(DOMAIN, f"gas_{serial_number}_{mprn}")})
if gas_device is not None:
_LOGGER.debug(f'Removed gas device {serial_number}/{mprn} due to no active tariff')
device_registry.async_remove_device(gas_device.id)

# Remove gas meter devices which had incorrect identifier
gas_device = device_registry.async_get_device(identifiers={(DOMAIN, f"electricity_{serial_number}_{mprn}")})
if gas_device is not None:
device_registry.async_remove_device(gas_device.id)

has_intelligent_tariff = False
intelligent_mpan = None
intelligent_serial_number = None
now = utcnow()
for point in account_info["electricity_meter_points"]:
# We only care about points that have active agreements
mpan = point["mpan"]
electricity_tariff_code = get_active_tariff_code(now, point["agreements"])
if electricity_tariff_code is not None:
for meter in point["meters"]:

for meter in point["meters"]:
serial_number = meter["serial_number"]

if electricity_tariff_code is not None:
if meter["is_export"] == False:
if is_intelligent_tariff(electricity_tariff_code):
intelligent_mpan = point["mpan"]
intelligent_serial_number = meter["serial_number"]
intelligent_mpan = mpan
intelligent_serial_number = serial_number
has_intelligent_tariff = True
else:
_LOGGER.debug(f'Removed electricity device {serial_number}/{mpan} due to no active tariff')
electricity_device = device_registry.async_get_device(identifiers={(DOMAIN, f"electricity_{serial_number}_{mpan}")})
if electricity_device is not None:
device_registry.async_remove_device(electricity_device.id)

should_mock_intelligent_data = await async_mock_intelligent_data(hass, account_id)
if should_mock_intelligent_data:
Expand All @@ -209,9 +260,10 @@ async def async_setup_dependencies(hass, config):
else:
intelligent_device = await client.async_get_intelligent_device(account_id)

hass.data[DOMAIN][account_id][DATA_INTELLIGENT_DEVICE] = intelligent_device
hass.data[DOMAIN][account_id][DATA_INTELLIGENT_MPAN] = intelligent_mpan
hass.data[DOMAIN][account_id][DATA_INTELLIGENT_SERIAL_NUMBER] = intelligent_serial_number
if intelligent_device is not None:
hass.data[DOMAIN][account_id][DATA_INTELLIGENT_DEVICE] = intelligent_device
hass.data[DOMAIN][account_id][DATA_INTELLIGENT_MPAN] = intelligent_mpan
hass.data[DOMAIN][account_id][DATA_INTELLIGENT_SERIAL_NUMBER] = intelligent_serial_number

for point in account_info["electricity_meter_points"]:
# We only care about points that have active agreements
Expand All @@ -222,8 +274,9 @@ async def async_setup_dependencies(hass, config):
serial_number = meter["serial_number"]
is_export_meter = meter["is_export"]
is_smart_meter = meter["is_smart_meter"]
planned_dispatches_supported = get_intelligent_features(intelligent_device["provider"]).planned_dispatches_supported if intelligent_device is not None else True
await async_setup_electricity_rates_coordinator(hass, account_id, mpan, serial_number, is_smart_meter, is_export_meter, planned_dispatches_supported)
tariff_override = await async_get_tariff_override(hass, mpan, serial_number)
planned_dispatches_supported = get_intelligent_features(intelligent_device.provider).planned_dispatches_supported if intelligent_device is not None else True
await async_setup_electricity_rates_coordinator(hass, account_id, mpan, serial_number, is_smart_meter, is_export_meter, planned_dispatches_supported, tariff_override)

await async_setup_account_info_coordinator(hass, account_id)

Expand All @@ -233,6 +286,8 @@ async def async_setup_dependencies(hass, config):

await async_setup_saving_sessions_coordinators(hass, account_id)

await async_setup_greenness_forecast_coordinator(hass, account_id)

async def options_update_listener(hass, entry):
"""Handle options update."""
await hass.config_entries.async_reload(entry.entry_id)
Expand All @@ -241,10 +296,12 @@ async def async_unload_entry(hass, entry):
"""Unload a config entry."""

unload_ok = False
if CONFIG_MAIN_API_KEY in entry.data:
if entry.data[CONFIG_KIND] == CONFIG_KIND_ACCOUNT:
unload_ok = await hass.config_entries.async_unload_platforms(entry, ACCOUNT_PLATFORMS)
elif CONFIG_TARGET_NAME in entry.data:
elif entry.data[CONFIG_KIND] == CONFIG_KIND_TARGET_RATE:
unload_ok = await hass.config_entries.async_unload_platforms(entry, TARGET_RATE_PLATFORMS)
elif entry.data[CONFIG_KIND] == CONFIG_KIND_COST_TRACKER:
unload_ok = await hass.config_entries.async_unload_platforms(entry, COST_TRACKER_PLATFORMS)

return unload_ok

Expand Down
Loading

0 comments on commit b82b19b

Please sign in to comment.