Skip to content

Commit

Permalink
Tolerate certain API failures, allow config migration, charge graph r…
Browse files Browse the repository at this point in the history
…eading tweak, allow credential changes (#40)

* Tolerate certain coordinator setup failures

* Version bump

* Updated issue templates

* Fix no end time in the last charge slot

* Deduplicate entity types

* Added config migration support

* Allow credential changes
  • Loading branch information
dan-r authored Jan 15, 2024
1 parent ef838ba commit dbac414
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 13 deletions.
6 changes: 3 additions & 3 deletions .github/ISSUE_TEMPLATE/bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ assignees: dan-r

---

**Describe the bug**
**What happened?**
A clear and concise description of what the bug is.

**To Reproduce**
Expand All @@ -16,8 +16,8 @@ Steps to reproduce the behavior.
**Expected behavior**
A clear and concise description of what you expected to happen.

**Screenshots**
If applicable, add screenshots to help explain your problem.
**Log Output**
Any relevant logs from Home Assistant.

**Home Assistant Version**
Find this in Settings > About.
Expand Down
8 changes: 8 additions & 0 deletions .github/ISSUE_TEMPLATE/enquiry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
name: Enquiry
about: Ask a question
title: ''
labels: enquiry
assignees: dan-r

---
46 changes: 42 additions & 4 deletions custom_components/ohme/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import logging
from homeassistant import core
from .const import *
from .api_client import OhmeApiClient
from .coordinator import OhmeChargeSessionsCoordinator, OhmeStatisticsCoordinator, OhmeAccountInfoCoordinator, OhmeAdvancedSettingsCoordinator, OhmeChargeSchedulesCoordinator
from homeassistant.exceptions import ConfigEntryNotReady

_LOGGER = logging.getLogger(__name__)

async def async_setup(hass: core.HomeAssistant, config: dict) -> bool:
"""Set up the Ohme EV Charger component."""
Expand Down Expand Up @@ -39,14 +42,30 @@ async def async_setup_entry(hass, entry):
OhmeChargeSchedulesCoordinator(hass=hass) # COORDINATOR_SCHEDULES
]

# We can function without these so setup can continue
coordinators_optional = [
OhmeStatisticsCoordinator,
OhmeAdvancedSettingsCoordinator
]

for coordinator in coordinators:
await coordinator.async_config_entry_first_refresh()
# Catch failures if this is an 'optional' coordinator
try:
await coordinator.async_config_entry_first_refresh()
except ConfigEntryNotReady as ex:
allow_failure = False
for optional in coordinators_optional:
allow_failure = True if isinstance(coordinator, optional) else allow_failure

if allow_failure:
_LOGGER.error(f"{coordinator.__class__.__name__} failed to setup. This coordinator is optional so the integration will still function, but please raise an issue if this persists.")
else:
raise ex

hass.data[DOMAIN][DATA_COORDINATORS] = coordinators

# Create tasks for each entity type
entity_types = ["sensor", "binary_sensor", "switch", "button", "number", "time"]
for entity_type in entity_types:
for entity_type in ENTITY_TYPES:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(entry, entity_type)
)
Expand All @@ -57,4 +76,23 @@ async def async_setup_entry(hass, entry):
async def async_unload_entry(hass, entry):
"""Unload a config entry."""

return await hass.config_entries.async_unload_platforms(entry, ['binary_sensor', 'sensor', 'switch'])
return await hass.config_entries.async_unload_platforms(entry, ENTITY_TYPES)

async def async_migrate_entry(hass: core.HomeAssistant, config_entry) -> bool:
"""Migrate old entry."""
# Version number has gone backwards
if CONFIG_VERSION < config_entry.version:
_LOGGER.error("Backwards migration not possible. Please update the integration.")
return False

# Version number has gone up
if config_entry.version < CONFIG_VERSION:
_LOGGER.debug("Migrating from version %s", config_entry.version)
new_data = config_entry.data

config_entry.version = CONFIG_VERSION
hass.config_entries.async_update_entry(config_entry, data=new_data)

_LOGGER.debug("Migration to version %s successful", config_entry.version)

return True
41 changes: 40 additions & 1 deletion custom_components/ohme/config_flow.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import voluptuous as vol
from homeassistant.config_entries import (ConfigFlow, OptionsFlow)
from .const import DOMAIN
from .const import DOMAIN, CONFIG_VERSION
from .api_client import OhmeApiClient


Expand All @@ -9,8 +9,10 @@
vol.Required("password"): str
})


class OhmeConfigFlow(ConfigFlow, domain=DOMAIN):
"""Config flow."""
VERSION = CONFIG_VERSION

async def async_step_user(self, info):
errors = {}
Expand All @@ -30,3 +32,40 @@ async def async_step_user(self, info):
return self.async_show_form(
step_id="user", data_schema=USER_SCHEMA, errors=errors
)

def async_get_options_flow(entry):
return OhmeOptionsFlow(entry)


class OhmeOptionsFlow(OptionsFlow):
"""Options flow."""

def __init__(self, entry) -> None:
self._config_entry = entry

async def async_step_init(self, info):
errors = {}
if info is not None:
instance = OhmeApiClient(info['email'], info['password'])
if await instance.async_refresh_session() is None:
errors["base"] = "auth_error"
else:
self.hass.config_entries.async_update_entry(
self._config_entry, data=info
)
return self.async_create_entry(
title="",
data={}
)

return self.async_show_form(
step_id="init", data_schema=vol.Schema(
{
vol.Required(
"email", default=self._config_entry.data['email']
): str,
vol.Required(
"password"
): str
}), errors=errors
)
4 changes: 3 additions & 1 deletion custom_components/ohme/const.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
"""Component constants"""
DOMAIN = "ohme"
USER_AGENT = "dan-r-homeassistant-ohme"
INTEGRATION_VERSION = "0.3.1"
INTEGRATION_VERSION = "0.3.2"
CONFIG_VERSION = 1
ENTITY_TYPES = ["sensor", "binary_sensor", "switch", "button", "number", "time"]

DATA_CLIENT = "client"
DATA_COORDINATORS = "coordinators"
Expand Down
4 changes: 2 additions & 2 deletions custom_components/ohme/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
},
"options": {
"step": {
"user": {
"init": {
"title": "Update Account Info",
"description": "Update your basic account information.",
"description": "Update your Ohme account information.",
"data": {
"email": "Email address",
"password": "Password"
Expand Down
4 changes: 2 additions & 2 deletions custom_components/ohme/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ def charge_graph_next_slot(charge_start, points, skip_format=False):
# Filter to points from now onwards
data = [x for x in data if x["t"] > now]

# Give up if we have less than 3 points
if len(data) < 3:
# Give up if we have less than 2 points
if len(data) < 2:
return {"start": None, "end": None}

start_ts = None
Expand Down

0 comments on commit dbac414

Please sign in to comment.