Skip to content

Commit

Permalink
(finally) basic working reconfigurable options flow
Browse files Browse the repository at this point in the history
  • Loading branch information
twystd committed Dec 11, 2023
1 parent b67abec commit fc4c93b
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 73 deletions.
47 changes: 21 additions & 26 deletions custom_components/uhppoted/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from homeassistant.core import HomeAssistant
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform

from .const import DOMAIN
from .const import CONF_BIND_ADDR
Expand All @@ -12,27 +13,6 @@
_LOGGER = logging.getLogger(__name__)


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data.setdefault(DOMAIN, {})

# hass.data[DOMAIN][entry.entry_id] = entry.data

hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "sensor"))
# hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "datetime"))
# hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "select"))
# hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "number"))

# data = dict(entry.data)
# unsubscribe = entry.add_update_listener(update_listener)
# hass_data["unsub_options_update_listener"] = unsub_options_update_listener
# hass.data[DOMAIN][entry.entry_id] = hass_data

# entry.async_on_unload(entry.add_update_listener(update_listener))
entry.add_update_listener(update_listener)

return True


async def async_setup(hass: HomeAssistant, config: dict) -> bool:
defaults = {
CONF_BIND_ADDR: '0.0.0.0',
Expand All @@ -56,13 +36,28 @@ async def async_setup(hass: HomeAssistant, config: dict) -> bool:

return True

async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
hass.data.setdefault(DOMAIN, {})

async def update_listener(hass: HomeAssistant, entry: ConfigEntry):
print(">>>>>>>>>>>>>>>>>>> AWOOOGAH")
print(" >>> id", entry.entry_id)
print(" >>> data", entry.data)
print(" >>> options", entry.options)
hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "sensor"))
# hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "datetime"))
# hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "select"))
# hass.async_create_task(hass.config_entries.async_forward_entry_setup(entry, "number"))

entry.async_on_unload(entry.add_update_listener(update_listener))

return True

async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
platforms = [
Platform.SENSOR,
]

ok = await hass.config_entries.async_unload_platforms(entry,platforms)

return ok

async def update_listener(hass: HomeAssistant, entry: ConfigEntry):
await hass.config_entries.async_reload(entry.entry_id)

# if self._async_current_entries():
Expand Down
138 changes: 99 additions & 39 deletions custom_components/uhppoted/options_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from homeassistant.config_entries import OptionsFlow
from homeassistant.config_entries import ConfigEntry
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import selector
import voluptuous as vol

from .const import DOMAIN
Expand All @@ -25,66 +26,125 @@
_LOGGER = logging.getLogger(__name__)


def validate_controller_id(id: int, hass: HomeAssistant) -> None:
if id < 10:
def validate_controller_id(v: int) -> None:
if not v or v.strip() == '':
raise ValueError


class UhppotedOptionsFlow(OptionsFlow):

def __init__(self, config_entry: ConfigEntry) -> None:
self.config_entry = config_entry
self.data = dict(config_entry.data)
def validate_controller_serial_no(v) -> None:
controller = int(f'{v}')
if controller < 100000000:
raise ValueError

async def async_step_init(self, user_input: dict[str, Any] | None = None) -> FlowResult:
return await self.async_step_IPv4()

async def async_step_IPv4(self, user_input: Optional[Dict[str, Any]] = None):
data = self.hass.data[DOMAIN] if DOMAIN in self.hass.data else {}
bind = '0.0.0.0'
broadcast = '255.255.255.255:60000'
listen = '0.0.0.0:60001'
debug = False
def validate_door_id(v: int) -> None:
if not v or v.strip() == '':
raise ValueError

if CONF_BIND_ADDR in data:
bind = data[CONF_BIND_ADDR]

if CONF_BROADCAST_ADDR in data:
broadcast = data[CONF_BROADCAST_ADDR]
def validate_door_controller(v: str, controllers: list[str]) -> None:
if v not in controllers:
raise ValueError

if CONF_LISTEN_ADDR in data:
listen = data[CONF_LISTEN_ADDR]

if CONF_DEBUG in data:
debug = data[CONF_DEBUG]
def validate_door_number(v) -> None:
door = int(f'{v}')
if door < 1 or door > 4:
raise ValueError

if CONF_BIND_ADDR in self.config_entry.data:
bind = self.config_entry.data[CONF_BIND_ADDR]
class UhppotedOptionsFlow(OptionsFlow):

if CONF_BROADCAST_ADDR in self.config_entry.data:
broadcast = self.config_entry.data[CONF_BROADCAST_ADDR]
def __init__(self, entry: ConfigEntry) -> None:
self.config_entry = entry
self.data = dict(entry.data)
self.options = dict(entry.options)

if CONF_LISTEN_ADDR in self.config_entry.data:
listen = self.config_entry.data[CONF_LISTEN_ADDR]
async def async_step_init(self, user_input: dict[str, Any] | None = None) -> FlowResult:
return await self.async_step_controller()

if CONF_DEBUG in self.config_entry.data:
debug = self.config_entry.data[CONF_DEBUG]
async def async_step_IPv4(self, user_input: Optional[Dict[str, Any]] = None):
pass
# data = self.hass.data[DOMAIN] if DOMAIN in self.hass.data else {}
# bind = '0.0.0.0'
# broadcast = '255.255.255.255:60000'
# listen = '0.0.0.0:60001'
# debug = False
#
# if CONF_BIND_ADDR in data:
# bind = data[CONF_BIND_ADDR]
#
# if CONF_BROADCAST_ADDR in data:
# broadcast = data[CONF_BROADCAST_ADDR]
#
# if CONF_LISTEN_ADDR in data:
# listen = data[CONF_LISTEN_ADDR]
#
# if CONF_DEBUG in data:
# debug = data[CONF_DEBUG]
#
# if CONF_BIND_ADDR in self.config_entry.data:
# bind = self.config_entry.data[CONF_BIND_ADDR]
#
# if CONF_BROADCAST_ADDR in self.config_entry.data:
# broadcast = self.config_entry.data[CONF_BROADCAST_ADDR]
#
# if CONF_LISTEN_ADDR in self.config_entry.data:
# listen = self.config_entry.data[CONF_LISTEN_ADDR]
#
# if CONF_DEBUG in self.config_entry.data:
# debug = self.config_entry.data[CONF_DEBUG]
#
# schema = vol.Schema({
# vol.Optional(CONF_BIND_ADDR, default=bind): str,
# vol.Optional(CONF_BROADCAST_ADDR, default=broadcast): str,
# vol.Optional(CONF_LISTEN_ADDR, default=listen): str,
# vol.Optional(CONF_DEBUG, default=debug): bool,
# })
#
# errors: Dict[str, str] = {}
#
# if user_input is not None:
# if not errors:
# self.data.update(user_input)
# return self.async_create_entry(title="uhppoted", data=self.data)
#
# return self.async_show_form(step_id="IPv4", data_schema=schema, errors=errors)

async def async_step_controller(self, user_input: Optional[Dict[str, Any]] = None):
name = self.options[CONF_CONTROLLER_ID]
controller = self.options[CONF_CONTROLLER_SERIAL_NUMBER]
address = self.options[CONF_CONTROLLER_ADDR]

controllers = selector.SelectSelector(
selector.SelectSelectorConfig(options=['201020304', '303986753', '405419896'],
multiple=False,
custom_value=True,
mode=selector.SelectSelectorMode.DROPDOWN))

schema = vol.Schema({
vol.Optional(CONF_BIND_ADDR, default=bind): str,
vol.Optional(CONF_BROADCAST_ADDR, default=broadcast): str,
vol.Optional(CONF_LISTEN_ADDR, default=listen): str,
vol.Optional(CONF_DEBUG, default=debug): bool,
vol.Required(CONF_CONTROLLER_ID, default=name): str,
vol.Required(CONF_CONTROLLER_SERIAL_NUMBER, default=controller): controllers,
vol.Optional(CONF_CONTROLLER_ADDR, default=address): str,
})

errors: Dict[str, str] = {}

if user_input is not None:
try:
validate_controller_id(user_input[CONF_CONTROLLER_ID])
except ValueError:
errors["base"] = f'Invalid controller ID ({user_input[CONF_CONTROLLER_ID]})'

try:
validate_controller_serial_no(user_input[CONF_CONTROLLER_SERIAL_NUMBER])
except ValueError:
errors["base"] = f'Invalid controller serial number ({user_input[CONF_CONTROLLER_SERIAL_NUMBER]})'

if not errors:
self.data.update(user_input)
return self.async_create_entry(title="uhppoted", data=self.data)
self.options.update(user_input)
# return await self.async_step_door()
return self.async_create_entry(title="uhppoted", data=self.options)

return self.async_show_form(step_id="IPv4", data_schema=schema, errors=errors)
return self.async_show_form(step_id="controller", data_schema=schema, errors=errors)

async def async_end(self):
print('>>>>>>>>>>>>>>>>>>>>>>> async_end')
Expand Down
13 changes: 6 additions & 7 deletions custom_components/uhppoted/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@
from .door import ControllerDoorMode


async def async_setup_entry(hass: core.HomeAssistant,
entry: config_entries.ConfigEntry,
async def async_setup_entry(hass: core.HomeAssistant, entry: config_entries.ConfigEntry,
async_add_entities: AddEntitiesCallback):
config = entry.data
options = entry.options
Expand All @@ -69,11 +68,11 @@ async def async_setup_entry(hass: core.HomeAssistant,

controller = [
ControllerID(u, name, cid),
# ControllerAddress(u, id, name, address),
# ControllerDoor(u, id, name, door['id'], door['name']),
# ControllerDoorOpen(u, id, name, door['id'], door['name']),
# ControllerDoorLocked(u, id, name, door['id'], door['name']),
# ControllerDoorButton(u, id, name, door['id'], door['name']),
# ControllerAddress(u, id, name, address),
# ControllerDoor(u, id, name, door['id'], door['name']),
# ControllerDoorOpen(u, id, name, door['id'], door['name']),
# ControllerDoorLocked(u, id, name, door['id'], door['name']),
# ControllerDoorButton(u, id, name, door['id'], door['name']),
]

async_add_entities(controller, update_before_add=True)
2 changes: 1 addition & 1 deletion custom_components/uhppoted/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
"entity": {
"sensor": {
"uhppoted": {
"controller_id": "THINGX",
"controller_id": "THINGX"
},
"controller_id": {
"name": "THINGQ"
Expand Down

0 comments on commit fc4c93b

Please sign in to comment.