Skip to content

Commit

Permalink
Support Cozytouch, Rexel and Connexoon RTS. (#332)
Browse files Browse the repository at this point in the history
Co-authored-by: Vincent Le Bourlot <[email protected]>
  • Loading branch information
iMicknl and vlebourl authored Jan 13, 2021
1 parent 9efda58 commit 740f40f
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 21 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@
This component builds upon the work of [@philklei](https://github.com/philklei) and is an updated version of his [original Tahoma integration](https://www.home-assistant.io/integrations/tahoma/) in Home Assistant with the goal of merging into core. The installation of this component will replace the original Tahoma integration and thus allows you to beta-test [all changes](./CHANGELOG.md).

## Supported Somfy gateways
## Supported (Somfy) hubs

- Somfy TaHoma Box
- Somfy Connexoon IO
- Somfy Connexoon RTS
- Cozytouch
- Rexel

## Installation

Expand Down
14 changes: 12 additions & 2 deletions custom_components/tahoma/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,13 @@
import voluptuous as vol

from .const import (
CONF_HUB,
CONF_UPDATE_INTERVAL,
DEFAULT_HUB,
DEFAULT_UPDATE_INTERVAL,
DOMAIN,
IGNORED_TAHOMA_TYPES,
SUPPORTED_ENDPOINTS,
TAHOMA_TYPES,
)
from .coordinator import TahomaDataUpdateCoordinator
Expand Down Expand Up @@ -86,9 +89,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):

username = entry.data.get(CONF_USERNAME)
password = entry.data.get(CONF_PASSWORD)
hub = entry.data.get(CONF_HUB) or DEFAULT_HUB
endpoint = SUPPORTED_ENDPOINTS[hub]

session = async_get_clientsession(hass)
client = TahomaClient(username, password, session=session)
client = TahomaClient(
username,
password,
session=session,
api_url=endpoint,
)

try:
await client.login()
Expand Down Expand Up @@ -137,7 +147,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
if platform:
entities[platform].append(device)
_LOGGER.debug(
"Added Device (%s - %s - %s - %s)",
"Added TaHoma device (%s - %s - %s - %s)",
device.controllable_name,
device.ui_class,
device.widget,
Expand Down
25 changes: 21 additions & 4 deletions custom_components/tahoma/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,24 @@
)
import voluptuous as vol

from .const import CONF_UPDATE_INTERVAL, DEFAULT_UPDATE_INTERVAL, MIN_UPDATE_INTERVAL
from .const import (
CONF_HUB,
CONF_UPDATE_INTERVAL,
DEFAULT_HUB,
DEFAULT_UPDATE_INTERVAL,
MIN_UPDATE_INTERVAL,
SUPPORTED_ENDPOINTS,
)
from .const import DOMAIN # pylint: disable=unused-import

_LOGGER = logging.getLogger(__name__)

DATA_SCHEMA = vol.Schema(
{vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str}
{
vol.Required(CONF_USERNAME): str,
vol.Required(CONF_PASSWORD): str,
vol.Required(CONF_HUB, default=DEFAULT_HUB): vol.In(SUPPORTED_ENDPOINTS.keys()),
}
)


Expand All @@ -41,9 +52,15 @@ async def async_validate_input(self, user_input):
username = user_input.get(CONF_USERNAME)
password = user_input.get(CONF_PASSWORD)

async with TahomaClient(username, password) as client:
hub = user_input.get(CONF_HUB) or DEFAULT_HUB
endpoint = SUPPORTED_ENDPOINTS[hub]

async with TahomaClient(username, password, api_url=endpoint) as client:
await client.login()
return self.async_create_entry(title=username, data=user_input)
return self.async_create_entry(
title=username,
data=user_input,
)

async def async_step_user(self, user_input=None):
"""Handle the initial step via config flow."""
Expand Down
10 changes: 10 additions & 0 deletions custom_components/tahoma/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,18 @@
from homeassistant.components.sensor import DOMAIN as SENSOR
from homeassistant.components.switch import DOMAIN as SWITCH

CONF_HUB = "hub"
DOMAIN = "tahoma"

DEFAULT_HUB = "Somfy TaHoma"
SUPPORTED_ENDPOINTS = {
"Cozytouch": "https://ha110-1.overkiz.com/enduser-mobile-web/enduserAPI/",
"Somfy TaHoma": "https://tahomalink.com/enduser-mobile-web/enduserAPI/",
"Somfy Connexoon IO": "https://tahomalink.com/enduser-mobile-web/enduserAPI/",
"Somfy Connexoon RTS": "https://ha201-1.overkiz.com/enduser-mobile-web/enduserAPI/",
"Rexel": "https://ha112-1.overkiz.com/enduser-mobile-web/enduserAPI/",
}

MIN_UPDATE_INTERVAL = 30
DEFAULT_UPDATE_INTERVAL = 30

Expand Down
3 changes: 2 additions & 1 deletion custom_components/tahoma/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"description": "Enter your TaHoma credentials for the TaHoma App or the tahomalink.com platform.",
"data": {
"username": "[%key:common::config_flow::data::username%]",
"password": "[%key:common::config_flow::data::password%]"
"password": "[%key:common::config_flow::data::password%]",
"hub": "Hub"
}
}
},
Expand Down
3 changes: 2 additions & 1 deletion custom_components/tahoma/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"description": "Enter your TaHoma credentials for the TaHoma App or the tahomalink.com platform.",
"data": {
"username": "Email address",
"password": "Password"
"password": "Password",
"hub": "Hub"
}
}
},
Expand Down
5 changes: 3 additions & 2 deletions custom_components/tahoma/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"description": "Entrez vos identifiants TaHoma.",
"data": {
"username": "Courriel",
"password": "Mot de passe"
"password": "Mot de passe",
"hub": "Hub"
}
}
},
Expand All @@ -31,4 +32,4 @@
}
}
}
}
}
3 changes: 2 additions & 1 deletion custom_components/tahoma/translations/nl.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"description": "Voer uw TaHoma inloggegevens in voor de TaHoma-app of het tahomalink.com platform.",
"data": {
"username": "E-mailadres",
"password": "Wachtwoord"
"password": "Wachtwoord",
"hub": "Hub"
}
}
},
Expand Down
22 changes: 13 additions & 9 deletions tests/test_config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

TEST_EMAIL = "[email protected]"
TEST_PASSWORD = "test-password"
DEFAULT_HUB = "Somfy TaHoma"


async def test_form(hass):
Expand All @@ -30,14 +31,15 @@ async def test_form(hass):
"custom_components.tahoma.async_setup_entry", return_value=True
) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], {"username": TEST_EMAIL, "password": TEST_PASSWORD},
result["flow_id"], {"username": TEST_EMAIL, "password": TEST_PASSWORD, "hub": DEFAULT_HUB},
)

assert result2["type"] == "create_entry"
assert result2["title"] == TEST_EMAIL
assert result2["data"] == {
"username": TEST_EMAIL,
"password": TEST_PASSWORD,
"hub": DEFAULT_HUB
}

await hass.async_block_till_done()
Expand All @@ -64,7 +66,7 @@ async def test_form_invalid(hass, side_effect, error):

with patch("pyhoma.client.TahomaClient.login", side_effect=side_effect):
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], {"username": TEST_EMAIL, "password": TEST_PASSWORD},
result["flow_id"], {"username": TEST_EMAIL, "password": TEST_PASSWORD, "hub": DEFAULT_HUB},
)

assert result2["type"] == "form"
Expand All @@ -76,7 +78,7 @@ async def test_abort_on_duplicate_entry(hass):
MockConfigEntry(
domain=config_flow.DOMAIN,
unique_id=TEST_EMAIL,
data={"username": TEST_EMAIL, "password": TEST_PASSWORD},
data={"username": TEST_EMAIL, "password": TEST_PASSWORD, "hub": DEFAULT_HUB},
).add_to_hass(hass)

result = await hass.config_entries.flow.async_init(
Expand All @@ -89,7 +91,7 @@ async def test_abort_on_duplicate_entry(hass):
"custom_components.tahoma.async_setup_entry", return_value=True
) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], {"username": TEST_EMAIL, "password": TEST_PASSWORD},
result["flow_id"], {"username": TEST_EMAIL, "password": TEST_PASSWORD, "hub": DEFAULT_HUB},
)

assert result2["type"] == "abort"
Expand All @@ -101,7 +103,7 @@ async def test_allow_multiple_unique_entries(hass):
MockConfigEntry(
domain=config_flow.DOMAIN,
unique_id="[email protected]",
data={"username": "[email protected]", "password": TEST_PASSWORD},
data={"username": "[email protected]", "password": TEST_PASSWORD, "hub": DEFAULT_HUB},
).add_to_hass(hass)

result = await hass.config_entries.flow.async_init(
Expand All @@ -114,14 +116,15 @@ async def test_allow_multiple_unique_entries(hass):
"custom_components.tahoma.async_setup_entry", return_value=True
) as mock_setup_entry:
result2 = await hass.config_entries.flow.async_configure(
result["flow_id"], {"username": TEST_EMAIL, "password": TEST_PASSWORD},
result["flow_id"], {"username": TEST_EMAIL, "password": TEST_PASSWORD, "hub": DEFAULT_HUB},
)

assert result2["type"] == "create_entry"
assert result2["title"] == TEST_EMAIL
assert result2["data"] == {
"username": TEST_EMAIL,
"password": TEST_PASSWORD,
"hub": DEFAULT_HUB
}


Expand All @@ -135,13 +138,14 @@ async def test_import(hass):
result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data={"username": TEST_EMAIL, "password": TEST_PASSWORD},
data={"username": TEST_EMAIL, "password": TEST_PASSWORD, "hub": DEFAULT_HUB},
)
assert result["type"] == "create_entry"
assert result["title"] == TEST_EMAIL
assert result["data"] == {
"username": TEST_EMAIL,
"password": TEST_PASSWORD,
"hub": DEFAULT_HUB
}

await hass.async_block_till_done()
Expand All @@ -166,7 +170,7 @@ async def test_import_failing(hass, side_effect, error):
await hass.config_entries.flow.async_init(
config_flow.DOMAIN,
context={"source": config_entries.SOURCE_IMPORT},
data={"username": TEST_EMAIL, "password": TEST_PASSWORD},
data={"username": TEST_EMAIL, "password": TEST_PASSWORD, "hub": DEFAULT_HUB},
)

# Should write Exception to the log
Expand All @@ -178,7 +182,7 @@ async def test_options_flow(hass):
entry = MockConfigEntry(
domain=config_flow.DOMAIN,
unique_id=TEST_EMAIL,
data={"username": TEST_EMAIL, "password": TEST_PASSWORD},
data={"username": TEST_EMAIL, "password": TEST_PASSWORD, "hub": DEFAULT_HUB},
)

with patch("pyhoma.client.TahomaClient.login", return_value=True), patch(
Expand Down

2 comments on commit 740f40f

@hamzazzi
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello,
I tested with the rexel box, and it works

@iMicknl
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello,
I tested with the rexel box, and it works

Great to hear, @hamzazzi! In case you encounter any issues or if you have a feature request, feel free to create an issue on GitHub. https://github.com/iMicknl/ha-tahoma/issues/new/choose

Please sign in to comment.