Skip to content

Commit 052b122

Browse files
committed
config options to store in config data
1 parent 188bdac commit 052b122

File tree

3 files changed

+79
-66
lines changed

3 files changed

+79
-66
lines changed

custom_components/apsystems_ecu_proxy/__init__.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,18 @@ def __init__(self, hass: HomeAssistant, config_entry: ConfigEntry) -> None:
9292
"""Initialize coordinator."""
9393
self.hass = hass
9494
self.config_entry = config_entry
95-
95+
9696
# Add listener for midnight reset.
9797
self.midnight_tracker_unregister = async_track_utc_time_change(
9898
hass, self.midnight_reset, "0", "0", "0", local=True
9999
)
100+
101+
# Get configuration. If initial data else options.
102+
self.no_update_timeout = int(self.config_entry.data.get("no_update_timeout"))
103+
100104
# Add listener for 0 or None if no update.
101105
self.no_update_timer_unregister = None
102106

103-
104107
async def midnight_reset(self, *args):
105108
"""Send dispatcher message to all listeners to reset."""
106109
_LOGGER.debug("midnight reset")
@@ -118,7 +121,9 @@ async def setup_socket_servers(self) -> None:
118121

119122
for port in SOCKET_PORTS:
120123
_LOGGER.debug("Creating server for port %s", port)
121-
server = MySocketAPI(host, port, self.async_update_callback, self.config_entry)
124+
server = MySocketAPI(
125+
host, port, self.async_update_callback, self.config_entry
126+
)
122127
await server.start()
123128
self.socket_servers.append(server)
124129

@@ -233,13 +238,6 @@ def async_update_callback(self, data: dict[str, Any]):
233238
_LOGGER.warning("There was a value or index error")
234239
continue
235240

236-
237-
# Get configuration. If initial data else options.
238-
self.no_update_timeout = int(
239-
self.config_entry.options.get('no_update_timeout',
240-
self.config_entry.data.get('no_update_timeout'))
241-
)
242-
243241
# Start the no update timer with the updated value.
244242
self.no_update_timer_unregister = async_call_later(
245243
self.hass, timedelta(seconds=self.no_update_timeout), self.fire_no_update

custom_components/apsystems_ecu_proxy/api.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
import logging
77
import re
88
import traceback
9-
from homeassistant.config_entries import ConfigEntry
109
from typing import Any
1110

11+
from homeassistant.config_entries import ConfigEntry
1212

1313
_LOGGER = logging.getLogger(__name__)
1414

@@ -55,7 +55,9 @@
5555
class MySocketAPI:
5656
"""API class."""
5757

58-
def __init__(self, host: str, port: int, callback: Callable, config_entry: ConfigEntry) -> None:
58+
def __init__(
59+
self, host: str, port: int, callback: Callable, config_entry: ConfigEntry
60+
) -> None:
5961
"""Initialize API."""
6062
self.host = host
6163
self.port = port
@@ -65,9 +67,13 @@ def __init__(self, host: str, port: int, callback: Callable, config_entry: Confi
6567
self.ecu_mem = {}
6668
self.config_entry = config_entry
6769

70+
self.send_to_ema = self.get_config_value("send_to_ema", bool)
71+
self.message_ignore_age = self.get_config_value("message_ignore_age", int)
72+
self.ema_host = self.get_config_value("ema_host", str)
6873

6974
def get_config_value(self, key, default_type):
70-
return default_type(self.config_entry.options.get(key, self.config_entry.data.get(key)))
75+
"""Get config value."""
76+
return default_type(self.config_entry.data.get(key))
7177

7278
async def start(self) -> bool:
7379
"""Start listening socket server."""
@@ -116,7 +122,6 @@ async def data_received(
116122
# Send data to EMA and send response from EMA to ECU
117123
# send_to_ema is used to stop sending for testing purposes.
118124
# Get configuration. If initial data else options.
119-
self.send_to_ema = self.get_config_value('send_to_ema', bool)
120125
_LOGGER.debug("Send to EMA = %s", self.send_to_ema)
121126
if self.send_to_ema:
122127
response = await self.send_data_to_ema(self.port, data)
@@ -147,13 +152,12 @@ async def data_received(
147152
ecu["timestamp"] = datetime.strptime(message[60:74], "%Y%m%d%H%M%S")
148153

149154
# MessageFilter: Ignore old messages.
150-
self.message_ignore_age = self.get_config_value('message_ignore_age', int)
151155
_LOGGER.debug("Message ignore age = %s", self.message_ignore_age)
152156
if (
153157
message_age := (datetime.now() - ecu["timestamp"]).total_seconds()
154158
) > self.message_ignore_age:
155159
_LOGGER.debug(
156-
"Message told old with %s sec.",
160+
"Message told old with %s sec",
157161
int(message_age),
158162
)
159163
return None
@@ -220,9 +224,9 @@ def msg_slice(start_pos: int, end_pos: int, m: re.Match = m) -> int:
220224
return inverters
221225

222226
async def send_data_to_ema(self, port: int, data: bytes) -> bytes:
223-
self.ema_host = self.get_config_value('ema_host', str)
224-
_LOGGER.debug("EMA host = %s", self.ema_host)
225227
"""Send data over async socket."""
228+
_LOGGER.debug("EMA host = %s", self.ema_host)
229+
226230
reader, writer = await asyncio.open_connection(self.ema_host, port)
227231
writer.write(data)
228232
await writer.drain()
Lines changed: 59 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,36 @@
1+
"""Config flow."""
2+
3+
import asyncio
14
import logging
5+
26
import voluptuous as vol
3-
import asyncio
4-
from homeassistant import config_entries, exceptions
7+
8+
from homeassistant import config_entries
59
from homeassistant.core import callback
610

711
from .const import DOMAIN, KEYS
812

913
_LOGGER = logging.getLogger(__name__)
1014

1115

16+
async def validate_ip(ip_address: str) -> bool:
17+
"""Validate EMA server ip."""
18+
try:
19+
reader, writer = await asyncio.wait_for(
20+
asyncio.open_connection(ip_address, 8995), timeout=3.0
21+
)
22+
# Close the connection neatly
23+
writer.close()
24+
await writer.wait_closed()
25+
except (OSError, TimeoutError):
26+
return False
27+
else:
28+
return True
29+
30+
1231
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
1332
"""Integration configuration."""
33+
1434
VERSION = 1
1535
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_PUSH
1636

@@ -24,71 +44,62 @@ def async_get_options_flow(config_entry):
2444
async def async_step_user(self, user_input=None):
2545
"""First step: Initial set-up of integration options."""
2646
_LOGGER.debug("async_step_user")
27-
schema = vol.Schema({
28-
vol.Required(KEYS[0], default="3.67.1.32"): str,
29-
vol.Required(KEYS[1], default="1800"): str,
30-
vol.Required(KEYS[2], default="300"): str,
31-
vol.Required(KEYS[3], default="660"): str,
32-
vol.Required(KEYS[4], default=True): bool,
33-
})
47+
schema = vol.Schema(
48+
{
49+
vol.Required(KEYS[0], default="3.67.1.32"): str,
50+
vol.Required(KEYS[1], default="1800"): str,
51+
vol.Required(KEYS[2], default="300"): str,
52+
vol.Required(KEYS[3], default="660"): str,
53+
vol.Required(KEYS[4], default=True): bool,
54+
}
55+
)
3456

3557
if user_input is not None:
36-
if await OptionsFlowHandler.validate_ip(user_input["ema_host"]):
37-
return self.async_create_entry(title="APsystems ECU proxy", data=user_input)
38-
else:
39-
return self.async_show_form(
40-
step_id="user",
41-
data_schema=schema,
42-
errors={"base": "Could not connect to the specified EMA host"},
58+
if await validate_ip(user_input["ema_host"]):
59+
return self.async_create_entry(
60+
title="APsystems ECU proxy", data=user_input
4361
)
62+
63+
return self.async_show_form(
64+
step_id="user",
65+
data_schema=schema,
66+
errors={"base": "Could not connect to the specified EMA host"},
67+
)
4468
return self.async_show_form(step_id="user", data_schema=schema)
4569

4670

4771
class OptionsFlowHandler(config_entries.OptionsFlow):
4872
"""Regular change of integration options."""
73+
4974
def __init__(self, config_entry: config_entries.ConfigEntry) -> None:
75+
"""Init options handler."""
5076
self.config_entry = config_entry
5177

5278
async def async_step_init(self, user_input=None):
5379
"""Second step: Altering the integration options."""
80+
errors = {}
5481
current_options = (
55-
self.config_entry.data
56-
if not self.config_entry.options
82+
self.config_entry.data
83+
if not self.config_entry.options
5784
else self.config_entry.options
5885
)
5986
_LOGGER.debug("async_step_init with configuration: %s", current_options)
60-
61-
schema = vol.Schema({
62-
vol.Required(key, default=current_options.get(key)): (
63-
str if key != "send_to_ema" else bool
64-
)
65-
for key in KEYS
66-
})
6787

88+
schema = vol.Schema(
89+
{
90+
vol.Required(key, default=current_options.get(key)): (
91+
str if key != "send_to_ema" else bool
92+
)
93+
for key in KEYS
94+
}
95+
)
6896

6997
if user_input is not None:
70-
if await self.validate_ip(user_input["ema_host"]):
71-
updated_options = current_options.copy()
72-
updated_options.update(user_input)
73-
return self.async_create_entry(title="", data=updated_options)
74-
else:
75-
return self.async_show_form(
76-
step_id="init",
77-
data_schema=schema,
78-
errors={"base": "Could not connect to the specified EMA host"},
98+
if await validate_ip(user_input["ema_host"]):
99+
self.hass.config_entries.async_update_entry(
100+
self.config_entry, data=user_input
79101
)
80-
return self.async_show_form(step_id="init", data_schema=schema)
102+
return self.async_create_entry(title="", data={})
81103

82-
@staticmethod
83-
async def validate_ip(ip_address: str) -> bool:
84-
try:
85-
reader, writer = await asyncio.wait_for(
86-
asyncio.open_connection(ip_address, 8995),
87-
timeout=3.0
88-
)
89-
# Close the connection neatly
90-
writer.close()
91-
await writer.wait_closed()
92-
return True
93-
except (OSError, asyncio.TimeoutError):
94-
return False
104+
errors["base"] = "Could not connect to the specified EMA host"
105+
return self.async_show_form(step_id="init", data_schema=schema, errors=errors)

0 commit comments

Comments
 (0)