Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Fyta integration #110816

Merged
merged 107 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from 94 commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
f14f17e
Initial commit for fyta integration
dontinelli Feb 17, 2024
2690cc9
Merge pull request #1 from dontinelli/fyta-integration
dontinelli Feb 17, 2024
73f53cf
Update __init__.py
dontinelli Feb 17, 2024
d3b6e3d
Update __init__.py
dontinelli Feb 17, 2024
7023155
Delete homeassistant/components/fyta/binary_sensor.py
dontinelli Feb 17, 2024
6ac59b2
Merge branch 'dev' into dev
dontinelli Feb 17, 2024
4eff0d2
Update manifest.json
dontinelli Feb 17, 2024
bc0f388
Update requirements_test_all.txt
dontinelli Feb 17, 2024
2b88e35
Update requirements_all.txt
dontinelli Feb 17, 2024
6f7718f
Merge branch 'dev' into dev
dontinelli Feb 17, 2024
79446f1
Merge branch 'dev' into dev
dontinelli Feb 18, 2024
76ae5ff
Merge branch 'home-assistant:dev' into dev
dontinelli Feb 18, 2024
9eee9bb
Update test_config_flow.py
dontinelli Feb 18, 2024
6115c67
Update config_flow.py
dontinelli Feb 18, 2024
5523d77
Merge branch 'dev' into dev
dontinelli Feb 18, 2024
1f986f2
Merge branch 'home-assistant:dev' into dev
dontinelli Feb 19, 2024
2bdc7f2
Merge branch 'home-assistant:dev' into dev
dontinelli Feb 19, 2024
1cdfe26
Fyta integration - update initial PR based on review in initial PR #1…
dontinelli Feb 19, 2024
ec0537d
Update homeassistant/components/fyta/sensor.py
dontinelli Feb 19, 2024
9a8d754
Update homeassistant/components/fyta/config_flow.py
dontinelli Feb 19, 2024
140d64e
Update homeassistant/components/fyta/config_flow.py
dontinelli Feb 19, 2024
96f6d96
Update homeassistant/components/fyta/sensor.py
dontinelli Feb 19, 2024
d49287f
Update homeassistant/components/fyta/sensor.py
dontinelli Feb 19, 2024
bf8eac3
Update homeassistant/components/fyta/coordinator.py
dontinelli Feb 19, 2024
b4c4cc8
Update homeassistant/components/fyta/config_flow.py
dontinelli Feb 19, 2024
983c099
Update homeassistant/components/fyta/strings.json
dontinelli Feb 21, 2024
39182fe
Update homeassistant/components/fyta/strings.json
dontinelli Feb 21, 2024
0642733
Update homeassistant/components/fyta/manifest.json
dontinelli Feb 21, 2024
8ef5260
Merge branch 'home-assistant:dev' into dev
dontinelli Feb 21, 2024
d506837
Merge branch 'home-assistant:dev' into dev
dontinelli Feb 21, 2024
ffbd69c
Merge branch 'home-assistant:dev' into dev
dontinelli Feb 21, 2024
4276fec
Adjustments based on PR-commet of Feb 19 (#3)
dontinelli Feb 21, 2024
c54843e
Merge branch 'home-assistant:dev' into dev
dontinelli Feb 22, 2024
c2ca6ea
add test for config_flow.validate_input
dontinelli Feb 22, 2024
07c192e
Merge branch 'dev' into dev
dontinelli Feb 22, 2024
e328cc7
Merge branch 'home-assistant:dev' into dev
dontinelli Feb 23, 2024
3c3f23b
update based on pr review
dontinelli Feb 23, 2024
11eadd4
Merge branch 'home-assistant:dev' into dev
dontinelli Feb 23, 2024
5017a8a
update based on pr review
dontinelli Feb 23, 2024
263550c
Merge branch 'home-assistant:dev' into dev
dontinelli Feb 23, 2024
d47dae6
further refinings based on PR review
dontinelli Feb 23, 2024
5cae405
Merge branch 'dev' into update-fyta-pr
dontinelli Feb 23, 2024
8253d5b
Merge branch 'dev' into dev
dontinelli Feb 23, 2024
4258d9d
Merge pull request #7 from dontinelli/update-fyta-pr
dontinelli Feb 23, 2024
779e733
Update tests/components/fyta/test_config_flow.py
dontinelli Feb 24, 2024
2e15950
Update test_config_flow.py
dontinelli Feb 24, 2024
634a810
Update homeassistant/components/fyta/sensor.py
dontinelli Feb 24, 2024
c277b35
Update homeassistant/components/fyta/sensor.py
dontinelli Feb 24, 2024
62d4c8c
Merge branch 'home-assistant:dev' into dev
dontinelli Feb 24, 2024
1bab9d8
add handling and test for duplicate entry
dontinelli Feb 24, 2024
3440149
Merge branch 'dev' into update-fyta-pr2
dontinelli Feb 24, 2024
1dbe054
Merge pull request #8 from dontinelli/update-fyta-pr2
dontinelli Feb 24, 2024
6524f09
Update homeassistant/components/fyta/coordinator.py
dontinelli Feb 26, 2024
a2ca1c8
Update homeassistant/components/fyta/sensor.py
dontinelli Feb 26, 2024
096fd5a
Update homeassistant/components/fyta/entity.py
dontinelli Feb 26, 2024
a462b60
Update test_config_flow.py
dontinelli Feb 26, 2024
cb7a790
Update config_flow.py
dontinelli Feb 26, 2024
ecd7a93
Update coordinator.py
dontinelli Feb 26, 2024
c8b3480
Update typing in coordinator.py
dontinelli Feb 26, 2024
3e2f4ee
Update coordinator.py
dontinelli Feb 26, 2024
515c1bb
Update coordinator.py
dontinelli Feb 26, 2024
f4a24d6
Update coordinator.py
dontinelli Feb 26, 2024
97b97a2
Update entity.py
dontinelli Feb 26, 2024
c5e7251
Update sensor.py
dontinelli Feb 26, 2024
bd85cef
Update icons.json
dontinelli Feb 26, 2024
1861134
Update homeassistant/components/fyta/entity.py
dontinelli Feb 26, 2024
9d78a87
Update homeassistant/components/fyta/entity.py
dontinelli Feb 26, 2024
b239dc6
Update entity.py
dontinelli Feb 26, 2024
3f3dada
Update test_config_flow.py
dontinelli Feb 26, 2024
09abfef
Merge branch 'dev' into dev
dontinelli Feb 29, 2024
d39b998
Merge branch 'dev' into dev
dontinelli Mar 1, 2024
fe703d7
Merge branch 'dev' into dev
dontinelli Mar 5, 2024
4fba33e
Update config_flow.py (change FlowResult to ConfigFlowResult)
dontinelli Mar 5, 2024
11bb8b2
Update config_flow.py
dontinelli Mar 5, 2024
33649bf
Merge branch 'dev' into dev
dontinelli Mar 5, 2024
884e815
Update homeassistant/components/fyta/config_flow.py
dontinelli Mar 5, 2024
e1a2917
Update homeassistant/components/fyta/config_flow.py
dontinelli Mar 5, 2024
cf874a0
Update homeassistant/components/fyta/coordinator.py
dontinelli Mar 5, 2024
9fe2714
Merge branch 'dev' into dev
dontinelli Mar 5, 2024
92180c2
Update coordinator.py
dontinelli Mar 5, 2024
d05378a
Update config_flow.py (typing FlowResult -> ConfigFlowResult)
dontinelli Mar 5, 2024
aa9e530
Update config_flow.py
dontinelli Mar 5, 2024
93ffff6
Merge branch 'dev' into dev
dontinelli Mar 5, 2024
c7d75c3
Aktualisieren von config_flow.py
dontinelli Mar 5, 2024
5c42fd5
Merge branch 'home-assistant:dev' into dev
dontinelli Mar 6, 2024
ac3a143
remove coordinator entities
dontinelli Mar 6, 2024
d101b7d
Merge pull request #9 from dontinelli/update-pr
dontinelli Mar 6, 2024
e5de810
Update strings.json
dontinelli Mar 6, 2024
e014ccc
Update icons.json
dontinelli Mar 6, 2024
7385f71
Update manifest.json
dontinelli Mar 6, 2024
9581dc3
Update requirements_all.txt
dontinelli Mar 6, 2024
cdca3d2
Update requirements_test_all.txt
dontinelli Mar 6, 2024
19a59f4
Merge branch 'home-assistant:dev' into dev
dontinelli Mar 6, 2024
502577e
Merge branch 'dev' into dev
dontinelli Mar 11, 2024
998a1e7
Update homeassistant/components/fyta/sensor.py
joostlek Mar 12, 2024
1f563da
Update homeassistant/components/fyta/sensor.py
joostlek Mar 12, 2024
5e23890
Update homeassistant/components/fyta/coordinator.py
dontinelli Mar 15, 2024
727be39
Update homeassistant/components/fyta/coordinator.py
dontinelli Mar 15, 2024
ae261df
Update homeassistant/components/fyta/coordinator.py
dontinelli Mar 15, 2024
42256bb
Update homeassistant/components/fyta/entity.py
dontinelli Mar 15, 2024
5b04ea1
Update homeassistant/components/fyta/strings.json
dontinelli Mar 15, 2024
3685c68
Update homeassistant/components/fyta/strings.json
dontinelli Mar 15, 2024
e3e5ea6
Update tests/components/fyta/test_config_flow.py
dontinelli Mar 15, 2024
29d93ec
Update tests/components/fyta/test_config_flow.py
dontinelli Mar 15, 2024
822cb46
move test-helpers into conftest.py, adjust import of coordinator.py
dontinelli Mar 15, 2024
4b8f340
Merge pull request #10 from dontinelli/dontinelli-pr-update
dontinelli Mar 15, 2024
8fdc66e
Merge branch 'home-assistant:dev' into dev
dontinelli Mar 15, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -461,6 +461,10 @@ omit =
homeassistant/components/frontier_silicon/browse_media.py
homeassistant/components/frontier_silicon/media_player.py
homeassistant/components/futurenow/light.py
homeassistant/components/fyta/__init__.py
dontinelli marked this conversation as resolved.
Show resolved Hide resolved
homeassistant/components/fyta/coordinator.py
homeassistant/components/fyta/entity.py
homeassistant/components/fyta/sensor.py
homeassistant/components/garadget/cover.py
homeassistant/components/garages_amsterdam/__init__.py
homeassistant/components/garages_amsterdam/binary_sensor.py
Expand Down
2 changes: 2 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,8 @@ build.json @home-assistant/supervisor
/tests/components/frontier_silicon/ @wlcrs
/homeassistant/components/fully_kiosk/ @cgarwood
/tests/components/fully_kiosk/ @cgarwood
/homeassistant/components/fyta/ @dontinelli
/tests/components/fyta/ @dontinelli
/homeassistant/components/garages_amsterdam/ @klaasnicolaas
/tests/components/garages_amsterdam/ @klaasnicolaas
/homeassistant/components/gardena_bluetooth/ @elupus
Expand Down
48 changes: 48 additions & 0 deletions homeassistant/components/fyta/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
"""Initialization of FYTA integration."""
from __future__ import annotations

import logging

from fyta_cli.fyta_connector import FytaConnector

from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform
from homeassistant.core import HomeAssistant

from .const import DOMAIN
from .coordinator import FytaCoordinator

_LOGGER = logging.getLogger(__name__)

PLATFORMS = [
Platform.SENSOR,
]


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up the Fyta integration."""

username = entry.data[CONF_USERNAME]
password = entry.data[CONF_PASSWORD]

fyta = FytaConnector(username, password)

coordinator = FytaCoordinator(hass, fyta)

await coordinator.async_config_entry_first_refresh()

hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator

await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

return True


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload Fyta entity."""

unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
if unload_ok:
hass.data[DOMAIN].pop(entry.entry_id)

return unload_ok
64 changes: 64 additions & 0 deletions homeassistant/components/fyta/config_flow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""Config flow for FYTA integration."""
from __future__ import annotations

import logging
from typing import Any

from fyta_cli.fyta_connector import FytaConnector
from fyta_cli.fyta_exceptions import (
FytaAuthentificationError,
FytaConnectionError,
FytaPasswordError,
)
import voluptuous as vol

from homeassistant import config_entries
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME

from .const import DOMAIN

_LOGGER = logging.getLogger(__name__)


DATA_SCHEMA = vol.Schema(
{vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str}
)


class FytaConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a config flow for Fyta."""

VERSION = 1

async def async_step_user(
dontinelli marked this conversation as resolved.
Show resolved Hide resolved
self, user_input: dict[str, Any] | None = None
) -> config_entries.ConfigFlowResult:
"""Handle the initial step."""

errors = {}
if user_input:
self._async_abort_entries_match({CONF_USERNAME: user_input[CONF_USERNAME]})

fyta = FytaConnector(user_input[CONF_USERNAME], user_input[CONF_PASSWORD])

try:
await fyta.login()
except FytaConnectionError:
errors["base"] = "cannot_connect"
except FytaAuthentificationError:
errors["base"] = "invalid_auth"
except FytaPasswordError:
errors["base"] = "invalid_auth"
errors[CONF_PASSWORD] = "password_error"
except Exception: # pylint: disable=broad-except
errors["base"] = "unknown"
else:
return self.async_create_entry(
title=user_input[CONF_USERNAME], data=user_input
)
dontinelli marked this conversation as resolved.
Show resolved Hide resolved
finally:
await fyta.client.close()

return self.async_show_form(
step_id="user", data_schema=DATA_SCHEMA, errors=errors
)
2 changes: 2 additions & 0 deletions homeassistant/components/fyta/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
"""Const for fyta integration."""
DOMAIN = "fyta"
59 changes: 59 additions & 0 deletions homeassistant/components/fyta/coordinator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""Coordinator for FYTA integration."""

from datetime import datetime, timedelta
import logging
from typing import Any

from fyta_cli.fyta_connector import FytaConnector
from fyta_cli.fyta_exceptions import (
FytaAuthentificationError,
FytaConnectionError,
FytaPasswordError,
)

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator

_LOGGER = logging.getLogger(__name__)


class FytaCoordinator(DataUpdateCoordinator[dict[int, dict[str, Any]]]):
"""Fyta custom coordinator."""

config_entry: ConfigEntry

def __init__(self, hass: HomeAssistant, fyta: FytaConnector) -> None:
"""Initialize my coordinator."""
super().__init__(
hass,
_LOGGER,
name="FYTA Coordinator",
update_interval=timedelta(seconds=60),
)
self.fyta = fyta

async def _async_update_data(
self,
) -> dict[int, dict[str, Any]]:
"""Fetch data from API endpoint."""

if self.fyta.expiration is None or self.fyta.expiration < datetime.now():
await self.renew_authentication()

data = await self.fyta.update_all_plants()

return data
dontinelli marked this conversation as resolved.
Show resolved Hide resolved

async def renew_authentication(self) -> bool:
dontinelli marked this conversation as resolved.
Show resolved Hide resolved
"""Renew access token for FYTA API."""

try:
await self.fyta.login()
except FytaConnectionError as ex:
raise ConfigEntryNotReady from ex
except (FytaAuthentificationError, FytaPasswordError) as ex:
raise ConfigEntryAuthFailed from ex
dontinelli marked this conversation as resolved.
Show resolved Hide resolved

return True
47 changes: 47 additions & 0 deletions homeassistant/components/fyta/entity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
"""Entities for FYTA integration."""
from typing import Any

from homeassistant.components.sensor import SensorEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.update_coordinator import CoordinatorEntity

from .const import DOMAIN
from .coordinator import FytaCoordinator


class FytaPlantEntity(CoordinatorEntity[FytaCoordinator]):
"""Base Fyta Plant entity."""

_attr_has_entity_name = True

def __init__(
self,
coordinator: FytaCoordinator,
entry: ConfigEntry,
description: SensorEntityDescription,
plant_id: int,
) -> None:
"""Initialize the Fyta sensor."""
super().__init__(coordinator)

self.plant_id = plant_id
self._attr_unique_id = f"{entry.entry_id}-{plant_id}-{description.key}"
self._attr_device_info = DeviceInfo(
manufacturer="Fyta",
model="Plant",
identifiers={(DOMAIN, f"{entry.entry_id}-{plant_id}")},
name=self.plant.get("name"),
sw_version=self.plant.get("sw_version"),
)
self.entity_description = description

@property
def plant(self) -> dict[str, Any]:
"""Get plant data."""
return self.coordinator.data.get(self.plant_id, {})
dontinelli marked this conversation as resolved.
Show resolved Hide resolved
dontinelli marked this conversation as resolved.
Show resolved Hide resolved

@property
def available(self) -> bool:
"""Test if entity is available."""
return super().available and self.plant_id in self.coordinator.data
27 changes: 27 additions & 0 deletions homeassistant/components/fyta/icons.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"entity": {
"sensor": {
"status": {
"default": "mdi:flower"
},
"temperature_status": {
"default": "mdi:thermometer-lines"
},
"light_status": {
"default": "mdi:sun-clock-outline"
},
"moisture_status": {
"default": "mdi:water-percent-alert"
},
"salinity_status": {
"default": "mdi:sprout-outline"
},
"light": {
"default": "mdi:weather-sunny"
},
"salinity": {
"default": "mdi:sprout-outline"
}
}
}
}
10 changes: 10 additions & 0 deletions homeassistant/components/fyta/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"domain": "fyta",
"name": "FYTA",
"codeowners": ["@dontinelli"],
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/fyta",
"integration_type": "hub",
"iot_class": "cloud_polling",
"requirements": ["fyta_cli==0.3.3"]
}
Loading
Loading