Skip to content

Commit

Permalink
Merge pull request #8 from illuzn/config_items_patch
Browse files Browse the repository at this point in the history
Config items patch
  • Loading branch information
illuzn authored Dec 15, 2023
2 parents 9991700 + 4275ac2 commit f67e4f6
Show file tree
Hide file tree
Showing 8 changed files with 91 additions and 57 deletions.
16 changes: 9 additions & 7 deletions custom_components/rheem_eziset/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,18 @@
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.const import CONF_HOST
from homeassistant.exceptions import ConfigEntryNotReady

from .api import RheemEziSETApi
from .const import DOMAIN, CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL, PLATFORMS
from .const import DOMAIN, CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL, LOGGER, PLATFORMS
from .coordinator import RheemEziSETDataUpdateCoordinator

async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up this integration using UI."""
LOGGER.debug(
"Setting up entry for device: %s",
entry.title,
)

if hass.data.get(DOMAIN) is None:
hass.data.setdefault(DOMAIN, {})

Expand All @@ -32,10 +36,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
update_interval=scan_interval
)

await coordinator.async_refresh()

if not coordinator.last_update_success:
raise ConfigEntryNotReady
await coordinator.async_config_entry_first_refresh()

hass.data[DOMAIN] = coordinator

Expand All @@ -44,7 +45,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
coordinator.platforms.append(platform)
hass.async_add_job(hass.config_entries.async_forward_entry_setup(entry, platform))

entry.add_update_listener(async_reload_entry)
entry.add_update_listener(async_reload_entry) # Reload the entry on configuration changes.

return True

async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
Expand Down
54 changes: 42 additions & 12 deletions custom_components/rheem_eziset/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,22 @@ def __init__(self, host: str) -> None:
self.base_url = "http://" + self.host + "/"

def getInfo_data(self) -> dict:
"""Create a session and get getInfo.cgi."""
url = self.base_url + "getInfo.cgi"
"""Create a session and gather sensor data."""
session = requests.Session()
response = session.get(url, verify=False)
LOGGER.debug(f"{DOMAIN} - getInfo.cgi response {response.text}")
if response.headers.get('content-type') == 'application/json':
try:
data_response: dict = response.json()
except Exception:
LOGGER.error(f"{DOMAIN} - couldn't convert response for {url} into json. Response was: {response}")
return data_response
else:
LOGGER.error(f"{DOMAIN} - received response for {url} but it doesn't appear to be json.")

page = "getInfo.cgi"
data_responses = get_data(session=session, base_url=self.base_url, page=page)

page = "version.cgi"
data_responses = data_responses | get_data(session=session, base_url=self.base_url, page=page)

page = "getParams.cgi"
data_responses = data_responses | get_data(session=session, base_url=self.base_url, page=page)

page = "heaterName.cgi"
data_responses = data_responses | get_data(session=session, base_url=self.base_url, page=page)

return data_responses

def get_XXXdata(self) -> dict:
"""Unused example."""
Expand Down Expand Up @@ -59,3 +62,30 @@ def get_XXXdata(self) -> dict:
return merged_response


def get_data(
session: object,
base_url: str,
page: str,
) -> dict:
"""Get page, check for valid json responses then convert to dict format."""
if base_url == "":
LOGGER.error(f"{DOMAIN} - api attempted to retrieve an empty base_url.")
return None

elif page == "":
LOGGER.error(f"{DOMAIN} - api attempted to retrieve an empty base_url.")
return None

else:
url = base_url + page
response = session.get(url, verify=False)
LOGGER.debug(f"{DOMAIN} - {page} response: {response.text}")

if isinstance(response, object) and response.headers.get('content-type') == "application/json":
try:
data_response: dict = response.json()
except Exception:
LOGGER.error(f"{DOMAIN} - couldn't convert response for {url} into json. Response was: {response.text}")
return data_response
else:
LOGGER.error(f"{DOMAIN} - received response for {url} but it doesn't appear to be json. Response: {response.text}")
34 changes: 13 additions & 21 deletions custom_components/rheem_eziset/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ async def async_step_user(self, user_input=None):
"""Handle a flow initialized by the user."""
self._errors = {}

if self._async_current_entries():
return self.async_abort(reason="single_instance_allowed")

if user_input is not None:
# Don't allow duplicates
current_entries = self._async_current_entries()
if user_input[CONF_HOST] in current_entries:
return self.async_abort(reason="host_already_exists")

# Test connectivity
valid = await self._test_host(user_input[CONF_HOST])

Expand Down Expand Up @@ -80,32 +82,22 @@ def __init__(self, config_entry):
self.config_entry = config_entry
self.options = dict(config_entry.options)

async def async_step_init(self, user_input): # pylint: disable=unused-argument
"""Handle flow."""
return await self.async_step_user()
async def async_step_init(self, user_input = None):
"""Handle an option flow."""
config = {**self.config_entry.data, **self.config_entry.options}

async def async_step_user(self, user_input=None):
"""Handle flow initiated by user."""
if user_input is not None:
self.options.update(user_input)
return await self._update_options()
config = {**config, **user_input}
return self.async_create_entry(title="", data=user_input)

return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Required(
vol.Optional(
CONF_SCAN_INTERVAL,
default=self.options.get(
CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL
),
): vol.All(vol.Coerce(int))
description={"suggested_value": DEFAULT_SCAN_INTERVAL}
): vol.All(vol.Coerce(int)),
}
)
)

async def _update_options(self):
"""Process options."""
return self.async_create_entry(
title=self.config_entry.data.get(CONF_SCAN_INTERVAL), data=self.options
)
3 changes: 2 additions & 1 deletion custom_components/rheem_eziset/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
IDPREFIX = "rheem_water_heater_"
DOMAIN = "rheem_eziset"
MANUFACTURER = "Rheem"
VERSION = "2023.12.1"
PLATFORMS: list[Platform] = [
Platform.SENSOR,
Platform.BINARY_SENSOR,
Expand All @@ -19,7 +20,7 @@

# SCAN INTERVAL
CONF_SCAN_INTERVAL = "scan_interval"
DEFAULT_SCAN_INTERVAL = 15 # seconds
DEFAULT_SCAN_INTERVAL = 5 # seconds

# Mode Dictionary
CONST_MODE_MAP = {
Expand Down
2 changes: 1 addition & 1 deletion custom_components/rheem_eziset/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from homeassistant.core import HomeAssistant
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed

from.api import RheemEziSETApi
from .api import RheemEziSETApi
from .const import DOMAIN, LOGGER


Expand Down
3 changes: 2 additions & 1 deletion custom_components/rheem_eziset/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ def device_info(self):
"""Defines the device information."""
return {
"identifiers": {(DOMAIN, self.coordinator.api.host)},
"name": NAME,
"name": self.coordinator.data.get("heaterName", NAME),
"manufacturer": MANUFACTURER,
"sw_version": self.coordinator.data.get("FWversion")
}

@property
Expand Down
33 changes: 20 additions & 13 deletions custom_components/rheem_eziset/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from homeassistant.helpers.entity import EntityCategory
from homeassistant.const import TIME_MINUTES, TIME_SECONDS, VOLUME_LITERS, STATE_UNAVAILABLE

from .const import ICON_TAPON, ICON_TAPOFF, ICON_WATERHEATER, CONST_MODE_MAP, CONST_STATUS_MAP, DOMAIN
from .const import ICON_TAPON, ICON_TAPOFF, ICON_WATERHEATER, CONST_MODE_MAP, CONST_STATUS_MAP, DOMAIN, LOGGER
from .coordinator import RheemEziSETDataUpdateCoordinator
from .entity import RheemEziSETEntity

Expand Down Expand Up @@ -63,19 +63,26 @@ def __init__(
@property
def state(self):
"""Return the state of the sensor."""
result = self.coordinator.data[self.key]
result = self.coordinator.data.get(self.key, STATE_UNAVAILABLE)
if self.description == "Status":
if int(result) in CONST_STATUS_MAP:
return CONST_STATUS_MAP[int(result)][0]
return STATE_UNAVAILABLE
try:
result = int(result)
if int(result) in CONST_STATUS_MAP:
return CONST_STATUS_MAP[int(result)][0]
return STATE_UNAVAILABLE
except Exception:
LOGGER.error(f"{DOMAIN} - Unexpected result for status, result was {result}")
return STATE_UNAVAILABLE
elif self.description == "Mode":
if int(result) in CONST_MODE_MAP:
return CONST_MODE_MAP[int(result)][0]
return STATE_UNAVAILABLE
elif result is not None:
return result
try:
result = int(result)
if int(result) in CONST_MODE_MAP:
return CONST_MODE_MAP[int(result)][0]
return STATE_UNAVAILABLE
except Exception:
LOGGER.error(f"{DOMAIN} - Unexpected result for mode, result was {result}")
else:
return STATE_UNAVAILABLE
return result

@property
def unit_of_measurement(self):
Expand All @@ -85,14 +92,14 @@ def unit_of_measurement(self):
@property
def icon(self):
"""Return the icon with processing in the case of some sensors."""
result = self.coordinator.data[self.key]
result = self.coordinator.data.get(self.key, STATE_UNAVAILABLE)
if self.description == "Flow":
try:
if float(result) != 0:
return ICON_TAPON
else:
return ICON_TAPOFF
except Exception: # pylint: disable=unused-argument
except Exception:
return ICON_TAPOFF
elif self.description == "Status":
if int(result) in CONST_STATUS_MAP:
Expand Down
3 changes: 2 additions & 1 deletion custom_components/rheem_eziset/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"title": "Rheem Eziset Configuration",
"description": "Please provide a scan interval to update the sensors. Warning: Read the documentation before changing this.",
"data": {
"scan_interval": "15"
"scan_interval": "Sensor scan interval in seconds (Default: 15)",
"config_scan_interval": "Config scan interval in seconds (Default: 60)"
}
}
}
Expand Down

0 comments on commit f67e4f6

Please sign in to comment.