Skip to content

Commit

Permalink
Redo approach
Browse files Browse the repository at this point in the history
  • Loading branch information
CoMPaTech committed Jun 3, 2024
1 parent 3f63d29 commit 45499f5
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 23 deletions.
3 changes: 3 additions & 0 deletions custom_components/stromer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
# Initialize connection to stromer
stromer = Stromer(username, password, client_id, client_secret)
try:
stromer.bike_id = entry.data["bike_id"]
stromer.bike_name = entry.data["nickname"]
stromer.bike_model = entry.data["model"]
await stromer.stromer_connect()
except ApiError as ex:
raise ConfigEntryNotReady("Error while communicating to Stromer API") from ex
Expand Down
59 changes: 50 additions & 9 deletions custom_components/stromer/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from homeassistant.data_entry_flow import FlowResult
from homeassistant.exceptions import HomeAssistantError

from .const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, DOMAIN, LOGGER
from .const import BIKE_DETAILS, CONF_CLIENT_ID, CONF_CLIENT_SECRET, DOMAIN, LOGGER
from .stromer import Stromer

STEP_USER_DATA_SCHEMA = vol.Schema(
Expand All @@ -24,7 +24,7 @@
)


async def validate_input(_: HomeAssistant, data: dict[str, Any]) -> dict[str, Any]:
async def validate_input(_: HomeAssistant, data: dict[str, Any]) -> dict:
"""Validate the user input allows us to connect."""
username = data[CONF_USERNAME]
password = data[CONF_PASSWORD]
Expand All @@ -36,15 +36,47 @@ async def validate_input(_: HomeAssistant, data: dict[str, Any]) -> dict[str, An
if not await stromer.stromer_connect():
raise InvalidAuth

bikes_data = await stromer.stromer_detect()

# Return info that you want to store in the config entry.
return {"title": stromer.bike_name}
return bikes_data


class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): # type: ignore[call-arg, misc]
"""Handle a config flow for Stromer."""

VERSION = 1

async def async_step_bike(
self, user_input: dict[str, Any] | None = None,
) -> FlowResult:
"""Handle selecting bike step."""
if user_input is None:
STEP_BIKE_DATA_SCHEMA = vol.Schema(
{ vol.Required(BIKE_DETAILS): vol.In(self.bikes), }
)
log = f"bikes = {self.bikes}"
LOGGER.debug(log)
LOGGER.debug("calling show form on bike")
return self.async_show_form(
step_id="bike", data_schema=STEP_BIKE_DATA_SCHEMA
)

# log = f"Completed bike selection = {user_input}"
# LOGGER.debug(log)
bike_data = user_input[BIKE_DETAILS].split(":")
self.user_input_data["bike_id"] = bike_data[0]
self.user_input_data["nickname"] = bike_data[1]
self.user_input_data["model"] = bike_data[2]
log = f"Completed bike data = {self.user_input_data}"

LOGGER.debug("processing")

await self.async_set_unique_id(f"stromerbike-{self.user_input_data['bike_id']}")
self._abort_if_unique_id_configured()

return self.async_create_entry(title=self.user_input_data["nickname"], data=self.user_input_data)

async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
Expand All @@ -56,20 +88,29 @@ async def async_step_user(

errors = {}

await self.async_set_unique_id("stromerbike")
self._abort_if_unique_id_configured()

try:
info = await validate_input(self.hass, user_input)
bikes_data = await validate_input(self.hass, user_input)
# Handle single bike as multi-bike
self.bikes = []
for bike in bikes_data:
self.bikes.append(f"{bike['bikeid']}:{bike['nickname']}:{bike['biketype']}")

# Save account info
self.user_input_data = user_input
# log = f"User input: {user_input}"
# LOGGER.debug(log)
log = f"Bikes: {self.bikes}"
LOGGER.debug(log)
# Display available bikes
return await self.async_step_bike()

except CannotConnect:
errors["base"] = "cannot_connect"
except InvalidAuth:
errors["base"] = "invalid_auth"
except Exception: # pylint: disable=broad-except
LOGGER.exception("Unexpected exception")
errors["base"] = "unknown"
else:
return self.async_create_entry(title=info["title"], data=user_input)

return self.async_show_form(
step_id="user", data_schema=STEP_USER_DATA_SCHEMA, errors=errors
Expand Down
3 changes: 3 additions & 0 deletions custom_components/stromer/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@

CONF_CLIENT_ID = "client_id"
CONF_CLIENT_SECRET = "client_secret"

BIKE_DETAILS = "bike_details"

2 changes: 1 addition & 1 deletion custom_components/stromer/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "cloud_polling",
"issue_tracker": "https://github.com/CoMPaTech/stromer/issues",
"requirements": [],
"version": "0.3.2"
"version": "0.4.0a2"
}
41 changes: 28 additions & 13 deletions custom_components/stromer/stromer.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Stromer module for Home Assistant Core."""

__version__ = "0.1.1"
__version__ = "0.2.0"

import json
import logging
Expand Down Expand Up @@ -36,6 +36,7 @@ def __init__(self, username: str, password: str, client_id: str, client_secret:
self._code: str | None = None
self._token: str | None = None

self.full_data: dict = {}
self.bike_id: str | None = None
self.bike_name: str | None = None
self.bike_model: str | None = None
Expand All @@ -51,15 +52,28 @@ async def stromer_connect(self) -> dict:
# Retrieve access token
await self.stromer_get_access_token()

# try:
# await self.stromer_update()
# except Exception as e:
# log = f"Stromer unable to update: {e}"
# LOGGER.error(log)

LOGGER.debug("Stromer connected!")

# return self.status
return True

async def stromer_detect(self) -> dict:
"""Get full data (to determine bike(s))."""
try:
await self.stromer_update()
self.full_data = await self.stromer_call_api(endpoint="bike/", full=True)
except Exception as e:
log = f"Stromer unable to update: {e}"
log = f"Stromer unable to fetch full data: {e}"
LOGGER.error(log)

LOGGER.debug("Stromer connected!")

return self.status
log = f"Stromer full_data : {self.full_data}"
LOGGER.debug(log)
return self.full_data

async def stromer_update(self) -> None:
"""Update stromer data through API."""
Expand All @@ -72,13 +86,12 @@ async def stromer_update(self) -> None:
try:
log = f"Stromer attempt: {attempts}/10"
LOGGER.debug(log)
self.bike = await self.stromer_call_api(endpoint="bike/")
log = f"Stromer bike: {self.bike}"
LOGGER.debug(log)
# self.full_data = await self.stromer_call_api(endpoint="bike/")
# log = f"Stromer bike: {self.full_data}"
# LOGGER.debug(log)

self.bike_id = self.bike["bikeid"]
self.bike_name = self.bike["nickname"]
self.bike_model = self.bike["biketype"]
# self.bike_name = self.bike["nickname"]
# self.bike_model = self.bike["biketype"]

endpoint = f"bike/{self.bike_id}/state/"
self.status = await self.stromer_call_api(endpoint=endpoint)
Expand Down Expand Up @@ -206,7 +219,7 @@ async def stromer_reset_trip_data(self) -> None:
if res.status != 204:
raise ApiError

async def stromer_call_api(self, endpoint: str) -> Any:
async def stromer_call_api(self, endpoint: str, full=False) -> Any:
"""Retrieve data from the API."""
url = f"{self.base_url}/rapi/mobile/v4.1/{endpoint}"
if self._api_version == "v3":
Expand All @@ -219,6 +232,8 @@ async def stromer_call_api(self, endpoint: str) -> Any:
LOGGER.debug(log)
log = "API call returns: %s" % ret
LOGGER.debug(log)
if full:
return ret["data"]
return ret["data"][0]


Expand Down

0 comments on commit 45499f5

Please sign in to comment.