Skip to content

Commit 1b94119

Browse files
Merge pull request #21 from andrew-dddd/master
Added multi module support and humidity
2 parents 4cbd5e8 + ee52558 commit 1b94119

File tree

5 files changed

+77
-31
lines changed

5 files changed

+77
-31
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
__pycache__/
1+
__pycache__/
2+
.vscode

custom_components/tech/__init__.py

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ async def async_setup(hass: HomeAssistant, config: dict):
2424
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
2525
"""Set up Tech Controllers from a config entry."""
2626
_LOGGER.debug("Setting up component's entry.")
27+
_LOGGER.debug("Entry id: " + str(entry.entry_id))
2728
_LOGGER.debug("Entry -> title: " + entry.title + ", data: " + str(entry.data) + ", id: " + entry.entry_id + ", domain: " + entry.domain)
2829
# Store an API object for your platforms to access
2930
hass.data.setdefault(DOMAIN, {})

custom_components/tech/climate.py

+31-21
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
CURRENT_HVAC_OFF,
1515
SUPPORT_PRESET_MODE,
1616
SUPPORT_TARGET_TEMPERATURE,
17+
ATTR_CURRENT_HUMIDITY
1718
)
1819
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS
1920
from .const import DOMAIN
@@ -24,32 +25,32 @@
2425

2526
async def async_setup_entry(hass, config_entry, async_add_entities):
2627
"""Set up entry."""
27-
_LOGGER.debug("Setting up entry, module udid: " + config_entry.data["udid"])
28+
udid = config_entry.data["module"]["udid"]
29+
_LOGGER.debug("Setting up entry, module udid: " + udid)
2830
api = hass.data[DOMAIN][config_entry.entry_id]
29-
zones = await api.get_module_zones(config_entry.data["udid"])
31+
zones = await api.get_module_zones(udid)
32+
thermostats = [
33+
TechThermostat(
34+
zones[zone],
35+
api,
36+
udid
37+
)
38+
for zone in zones
39+
]
3040

31-
async_add_entities(
32-
[
33-
TechThermostat(
34-
zones[zone],
35-
api,
36-
config_entry,
37-
)
38-
for zone in zones
39-
],
40-
True,
41-
)
41+
async_add_entities(thermostats, True)
4242

4343

4444
class TechThermostat(ClimateEntity):
4545
"""Representation of a Tech climate."""
4646

47-
def __init__(self, device, api, config_entry):
47+
def __init__(self, device, api, udid):
4848
"""Initialize the Tech device."""
4949
_LOGGER.debug("Init TechThermostat...")
50-
self._config_entry = config_entry
50+
self._udid = udid
5151
self._api = api
5252
self._id = device["zone"]["id"]
53+
self._unique_id = udid + "_" + str(device["zone"]["id"])
5354
self.update_properties(device)
5455

5556
def update_properties(self, device):
@@ -62,6 +63,10 @@ def update_properties(self, device):
6263
self._temperature = device["zone"]["currentTemperature"] / 10
6364
else:
6465
self._temperature = None
66+
if device["zone"]["humidity"] is not None:
67+
self._humidity = device["zone"]["humidity"]
68+
else:
69+
self._humidity = None
6570
state = device["zone"]["flags"]["relayState"]
6671
if state == "on":
6772
self._state = CURRENT_HVAC_HEAT
@@ -78,7 +83,7 @@ def update_properties(self, device):
7883
@property
7984
def unique_id(self) -> str:
8085
"""Return a unique ID."""
81-
return self._id
86+
return self._unique_id
8287

8388
@property
8489
def name(self):
@@ -116,8 +121,8 @@ def hvac_action(self) -> Optional[str]:
116121

117122
async def async_update(self):
118123
"""Call by the Tech device callback to update state."""
119-
_LOGGER.debug("Updating Tech zone: %s, udid: %s, id: %s", self._name, self._config_entry.data["udid"], self._id)
120-
device = await self._api.get_zone(self._config_entry.data["udid"], self._id)
124+
_LOGGER.debug("Updating Tech zone: %s, udid: %s, id: %s", self._name, self._udid, self._id)
125+
device = await self._api.get_zone(self._udid, self._id)
121126
self.update_properties(device)
122127

123128
@property
@@ -130,6 +135,11 @@ def current_temperature(self):
130135
"""Return the current temperature."""
131136
return self._temperature
132137

138+
@property
139+
def current_humidity(self):
140+
"""Return current humidity."""
141+
return self._humidity
142+
133143
@property
134144
def target_temperature(self):
135145
"""Return the temperature we try to reach."""
@@ -141,13 +151,13 @@ async def async_set_temperature(self, **kwargs):
141151
if temperature:
142152
_LOGGER.debug("%s: Setting temperature to %s", self._name, temperature)
143153
self._temperature = temperature
144-
await self._api.set_const_temp(self._config_entry.data["udid"], self._id, temperature)
154+
await self._api.set_const_temp(self._udid, self._id, temperature)
145155

146156
async def async_set_hvac_mode(self, hvac_mode):
147157
"""Set new target hvac mode."""
148158
_LOGGER.debug("%s: Setting hvac mode to %s", self._name, hvac_mode)
149159
if hvac_mode == HVAC_MODE_OFF:
150-
await self._api.set_zone(self._config_entry.data["udid"], self._id, False)
160+
await self._api.set_zone(self._udid, self._id, False)
151161
elif hvac_mode == HVAC_MODE_HEAT:
152-
await self._api.set_zone(self._config_entry.data["udid"], self._id, True)
162+
await self._api.set_zone(self._udid, self._id, True)
153163

custom_components/tech/config_flow.py

+40-7
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
"""Config flow for Tech Sterowniki integration."""
2-
import logging
2+
import logging, uuid
33
import voluptuous as vol
44
from homeassistant import config_entries, core, exceptions
55
from homeassistant.helpers import aiohttp_client
6+
from homeassistant.config_entries import ConfigEntry
67
from .const import DOMAIN # pylint:disable=unused-import
78
from .tech import Tech
89

910
_LOGGER = logging.getLogger(__name__)
1011

1112
DATA_SCHEMA = vol.Schema({
1213
vol.Required("username"): str,
13-
vol.Required("password"): str
14+
vol.Required("password"): str,
1415
})
1516

1617

@@ -26,16 +27,14 @@ async def validate_input(hass: core.HomeAssistant, data):
2627
if not await api.authenticate(data["username"], data["password"]):
2728
raise InvalidAuth
2829
modules = await api.list_modules()
29-
# Currently only one Tech controller supported
30-
module = modules[0]
3130

3231
# If you cannot connect:
3332
# throw CannotConnect
3433
# If the authentication is wrong:
3534
# InvalidAuth
3635

3736
# Return info that you want to store in the config entry.
38-
return {"user_id": api.user_id, "token": api.token, "udid": module["udid"], "version": module["version"]}
37+
return { "user_id": api.user_id, "token": api.token, "modules": modules }
3938

4039

4140
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
@@ -50,9 +49,19 @@ async def async_step_user(self, user_input=None):
5049
errors = {}
5150
if user_input is not None:
5251
try:
53-
info = await validate_input(self.hass, user_input)
52+
_LOGGER.debug("Context: " + str(self.context))
53+
validated_input = await validate_input(self.hass, user_input)
5454

55-
return self.async_create_entry(title=info["version"], data=info)
55+
modules = self._create_modules_array(validated_input=validated_input)
56+
57+
if len(modules) == 0:
58+
return self.async_abort("no_modules")
59+
60+
if len(modules) > 1:
61+
for module in modules[1:len(modules)]:
62+
await self.hass.config_entries.async_add(self._create_config_entry(module=module))
63+
64+
return self.async_create_entry(title=modules[0]["version"], data=modules[0])
5665
except CannotConnect:
5766
errors["base"] = "cannot_connect"
5867
except InvalidAuth:
@@ -65,6 +74,30 @@ async def async_step_user(self, user_input=None):
6574
step_id="user", data_schema=DATA_SCHEMA, errors=errors
6675
)
6776

77+
def _create_config_entry(self, module: dict) -> ConfigEntry:
78+
return ConfigEntry(
79+
data=module,
80+
title=module["version"],
81+
entry_id=uuid.uuid4().hex,
82+
domain=DOMAIN,
83+
version=ConfigFlow.VERSION,
84+
minor_version=ConfigFlow.MINOR_VERSION,
85+
source=ConfigFlow.CONNECTION_CLASS)
86+
87+
def _create_modules_array(self, validated_input: dict) -> [dict]:
88+
return [
89+
self._create_module_dict(validated_input, module_dict)
90+
for module_dict in validated_input["modules"]
91+
]
92+
93+
def _create_module_dict(self, validated_input: dict, module_dict: dict) -> dict:
94+
return {
95+
"user_id": validated_input["user_id"],
96+
"token": validated_input["token"],
97+
"module": module_dict,
98+
"version": module_dict["version"] + ": " + module_dict["name"]
99+
}
100+
68101

69102
class CannotConnect(exceptions.HomeAssistantError):
70103
"""Error to indicate we cannot connect."""

custom_components/tech/translations/en.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"config": {
33
"abort": {
4-
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
4+
"already_configured": "Device already configured",
5+
"no_modules": "No modules detected"
56
},
67
"error": {
78
"cannot_connect": "Cannot connect to Tech API.",
@@ -20,4 +21,4 @@
2021
}
2122
},
2223
"title": "Tech Controllers"
23-
}
24+
}

0 commit comments

Comments
 (0)