Add binary sensors to fyta (#134900)

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
dontinelli 2025-01-08 14:41:33 +01:00 committed by GitHub
parent ec7d2f3731
commit 99e65c38b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 1014 additions and 8 deletions

View File

@ -24,6 +24,7 @@ from .coordinator import FytaCoordinator
_LOGGER = logging.getLogger(__name__)
PLATFORMS = [
Platform.BINARY_SENSOR,
Platform.SENSOR,
]
type FytaConfigEntry = ConfigEntry[FytaCoordinator]

View File

@ -0,0 +1,117 @@
"""Binary sensors for Fyta."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from typing import Final
from fyta_cli.fyta_models import Plant
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import FytaConfigEntry
from .entity import FytaPlantEntity
@dataclass(frozen=True, kw_only=True)
class FytaBinarySensorEntityDescription(BinarySensorEntityDescription):
"""Describes Fyta binary sensor entity."""
value_fn: Callable[[Plant], bool]
BINARY_SENSORS: Final[list[FytaBinarySensorEntityDescription]] = [
FytaBinarySensorEntityDescription(
key="low_battery",
device_class=BinarySensorDeviceClass.BATTERY,
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda plant: plant.low_battery,
),
FytaBinarySensorEntityDescription(
key="notification_light",
translation_key="notification_light",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda plant: plant.notification_light,
),
FytaBinarySensorEntityDescription(
key="notification_nutrition",
translation_key="notification_nutrition",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda plant: plant.notification_nutrition,
),
FytaBinarySensorEntityDescription(
key="notification_temperature",
translation_key="notification_temperature",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda plant: plant.notification_temperature,
),
FytaBinarySensorEntityDescription(
key="notification_water",
translation_key="notification_water",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda plant: plant.notification_water,
),
FytaBinarySensorEntityDescription(
key="sensor_update_available",
device_class=BinarySensorDeviceClass.UPDATE,
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda plant: plant.sensor_update_available,
),
FytaBinarySensorEntityDescription(
key="productive_plant",
translation_key="productive_plant",
value_fn=lambda plant: plant.productive_plant,
),
FytaBinarySensorEntityDescription(
key="repotted",
translation_key="repotted",
value_fn=lambda plant: plant.repotted,
),
]
async def async_setup_entry(
hass: HomeAssistant, entry: FytaConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the FYTA binary sensors."""
coordinator = entry.runtime_data
async_add_entities(
FytaPlantBinarySensor(coordinator, entry, sensor, plant_id)
for plant_id in coordinator.fyta.plant_list
for sensor in BINARY_SENSORS
if sensor.key in dir(coordinator.data.get(plant_id))
)
def _async_add_new_device(plant_id: int) -> None:
async_add_entities(
FytaPlantBinarySensor(coordinator, entry, sensor, plant_id)
for sensor in BINARY_SENSORS
if sensor.key in dir(coordinator.data.get(plant_id))
)
coordinator.new_device_callbacks.append(_async_add_new_device)
class FytaPlantBinarySensor(FytaPlantEntity, BinarySensorEntity):
"""Represents a Fyta binary sensor."""
entity_description: FytaBinarySensorEntityDescription
@property
def is_on(self) -> bool:
"""Return value of the binary sensor."""
return self.entity_description.value_fn(self.plant)

View File

@ -2,8 +2,8 @@
from fyta_cli.fyta_models import Plant
from homeassistant.components.sensor import SensorEntityDescription
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import FytaConfigEntry
@ -20,7 +20,7 @@ class FytaPlantEntity(CoordinatorEntity[FytaCoordinator]):
self,
coordinator: FytaCoordinator,
entry: FytaConfigEntry,
description: SensorEntityDescription,
description: EntityDescription,
plant_id: int,
) -> None:
"""Initialize the Fyta sensor."""

View File

@ -1,5 +1,25 @@
{
"entity": {
"binary_sensor": {
"notification_light": {
"default": "mdi:lightbulb-alert-outline"
},
"notification_nutrition": {
"default": "mdi:beaker-alert-outline"
},
"notification_temperature": {
"default": "mdi:thermometer-alert"
},
"notification_water": {
"default": "mdi:watering-can-outline"
},
"productive_plant": {
"default": "mdi:fruit-grapes"
},
"repotted": {
"default": "mdi:shovel"
}
},
"sensor": {
"status": {
"default": "mdi:flower"

View File

@ -38,6 +38,29 @@
}
},
"entity": {
"binary_sensor": {
"notification_light": {
"name": "Light notification"
},
"notification_nutrition": {
"name": "Nutrition notification"
},
"notification_temperature": {
"name": "Temperature notification"
},
"notification_water": {
"name": "Water notification"
},
"productive_plant": {
"name": "Productive plant"
},
"repotted": {
"name": "Repotted"
},
"sensor_update_available": {
"name": "Sensor update available"
}
},
"sensor": {
"scientific_name": {
"name": "Scientific name"

View File

@ -1,6 +1,9 @@
{
"battery_level": 80,
"low_battery": true,
"fertilisation": {
"was_repotted": true
},
"low_battery": false,
"last_updated": "2023-01-10 10:10:00",
"light": 2,
"light_status": 3,
@ -10,7 +13,7 @@
"moisture_status": 3,
"sensor_available": true,
"sensor_id": "FD:1D:B7:E3:D0:E2",
"sensor_update_available": false,
"sensor_update_available": true,
"sw_version": "1.0",
"status": 1,
"online": true,

View File

@ -1,5 +1,8 @@
{
"battery_level": 80,
"fertilisation": {
"was_repotted": true
},
"low_battery": true,
"last_updated": "2023-01-02 10:10:00",
"light": 2,

View File

@ -1,5 +1,8 @@
{
"battery_level": 80,
"fertilisation": {
"was_repotted": false
},
"low_battery": true,
"last_updated": "2023-01-02 10:10:00",
"light": 2,

View File

@ -0,0 +1,741 @@
# serializer version: 1
# name: test_all_entities[binary_sensor.gummibaum_battery-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.gummibaum_battery',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.BATTERY: 'battery'>,
'original_icon': None,
'original_name': 'Battery',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'ce5f5431554d101905d31797e1232da8-0-low_battery',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_battery-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'battery',
'friendly_name': 'Gummibaum Battery',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.gummibaum_battery',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_light_notification-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.gummibaum_light_notification',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Light notification',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'notification_light',
'unique_id': 'ce5f5431554d101905d31797e1232da8-0-notification_light',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_light_notification-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Gummibaum Light notification',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.gummibaum_light_notification',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_nutrition_notification-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.gummibaum_nutrition_notification',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Nutrition notification',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'notification_nutrition',
'unique_id': 'ce5f5431554d101905d31797e1232da8-0-notification_nutrition',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_nutrition_notification-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Gummibaum Nutrition notification',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.gummibaum_nutrition_notification',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_productive_plant-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.gummibaum_productive_plant',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Productive plant',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'productive_plant',
'unique_id': 'ce5f5431554d101905d31797e1232da8-0-productive_plant',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_productive_plant-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Gummibaum Productive plant',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.gummibaum_productive_plant',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_repotted-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.gummibaum_repotted',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Repotted',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'repotted',
'unique_id': 'ce5f5431554d101905d31797e1232da8-0-repotted',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_repotted-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Gummibaum Repotted',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.gummibaum_repotted',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_temperature_notification-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.gummibaum_temperature_notification',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Temperature notification',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'notification_temperature',
'unique_id': 'ce5f5431554d101905d31797e1232da8-0-notification_temperature',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_temperature_notification-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Gummibaum Temperature notification',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.gummibaum_temperature_notification',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_update-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.gummibaum_update',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.UPDATE: 'update'>,
'original_icon': None,
'original_name': 'Update',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'ce5f5431554d101905d31797e1232da8-0-sensor_update_available',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_update-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'update',
'friendly_name': 'Gummibaum Update',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.gummibaum_update',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_water_notification-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.gummibaum_water_notification',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Water notification',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'notification_water',
'unique_id': 'ce5f5431554d101905d31797e1232da8-0-notification_water',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.gummibaum_water_notification-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Gummibaum Water notification',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.gummibaum_water_notification',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_battery-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.kakaobaum_battery',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.BATTERY: 'battery'>,
'original_icon': None,
'original_name': 'Battery',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'ce5f5431554d101905d31797e1232da8-1-low_battery',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_battery-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'battery',
'friendly_name': 'Kakaobaum Battery',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.kakaobaum_battery',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_light_notification-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.kakaobaum_light_notification',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Light notification',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'notification_light',
'unique_id': 'ce5f5431554d101905d31797e1232da8-1-notification_light',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_light_notification-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Kakaobaum Light notification',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.kakaobaum_light_notification',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_nutrition_notification-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.kakaobaum_nutrition_notification',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Nutrition notification',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'notification_nutrition',
'unique_id': 'ce5f5431554d101905d31797e1232da8-1-notification_nutrition',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_nutrition_notification-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Kakaobaum Nutrition notification',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.kakaobaum_nutrition_notification',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_productive_plant-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.kakaobaum_productive_plant',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Productive plant',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'productive_plant',
'unique_id': 'ce5f5431554d101905d31797e1232da8-1-productive_plant',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_productive_plant-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Kakaobaum Productive plant',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.kakaobaum_productive_plant',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_repotted-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.kakaobaum_repotted',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Repotted',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'repotted',
'unique_id': 'ce5f5431554d101905d31797e1232da8-1-repotted',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_repotted-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Kakaobaum Repotted',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.kakaobaum_repotted',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_temperature_notification-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.kakaobaum_temperature_notification',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Temperature notification',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'notification_temperature',
'unique_id': 'ce5f5431554d101905d31797e1232da8-1-notification_temperature',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_temperature_notification-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Kakaobaum Temperature notification',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.kakaobaum_temperature_notification',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_update-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.kakaobaum_update',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': <BinarySensorDeviceClass.UPDATE: 'update'>,
'original_icon': None,
'original_name': 'Update',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': None,
'unique_id': 'ce5f5431554d101905d31797e1232da8-1-sensor_update_available',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_update-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'update',
'friendly_name': 'Kakaobaum Update',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.kakaobaum_update',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_water_notification-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
'entity_id': 'binary_sensor.kakaobaum_water_notification',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Water notification',
'platform': 'fyta',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'notification_water',
'unique_id': 'ce5f5431554d101905d31797e1232da8-1-notification_water',
'unit_of_measurement': None,
})
# ---
# name: test_all_entities[binary_sensor.kakaobaum_water_notification-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'Kakaobaum Water notification',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.kakaobaum_water_notification',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'off',
})
# ---

View File

@ -31,7 +31,7 @@
'last_updated': '2023-01-10T10:10:00',
'light': 2.0,
'light_status': 3,
'low_battery': True,
'low_battery': False,
'moisture': 61.0,
'moisture_status': 3,
'name': 'Gummibaum',
@ -46,14 +46,14 @@
'plant_origin_path': '',
'plant_thumb_path': '',
'productive_plant': False,
'repotted': False,
'repotted': True,
'salinity': 1.0,
'salinity_status': 4,
'scientific_name': 'Ficus elastica',
'sensor_available': True,
'sensor_id': 'FD:1D:B7:E3:D0:E2',
'sensor_status': 0,
'sensor_update_available': False,
'sensor_update_available': True,
'status': 1,
'sw_version': '1.0',
'temperature': 25.2,
@ -81,7 +81,7 @@
'plant_origin_path': '',
'plant_thumb_path': '',
'productive_plant': False,
'repotted': False,
'repotted': True,
'salinity': 1.0,
'salinity_status': 4,
'scientific_name': 'Theobroma cacao',

View File

@ -0,0 +1,95 @@
"""Test the Home Assistant fyta binary sensor module."""
from datetime import timedelta
from unittest.mock import AsyncMock
from freezegun.api import FrozenDateTimeFactory
from fyta_cli.fyta_exceptions import FytaConnectionError, FytaPlantError
from fyta_cli.fyta_models import Plant
import pytest
from syrupy import SnapshotAssertion
from homeassistant.components.fyta.const import DOMAIN as FYTA_DOMAIN
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import setup_platform
from tests.common import (
MockConfigEntry,
async_fire_time_changed,
load_json_object_fixture,
snapshot_platform,
)
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_all_entities(
hass: HomeAssistant,
snapshot: SnapshotAssertion,
mock_fyta_connector: AsyncMock,
mock_config_entry: MockConfigEntry,
entity_registry: er.EntityRegistry,
) -> None:
"""Test all entities."""
await setup_platform(hass, mock_config_entry, [Platform.BINARY_SENSOR])
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
@pytest.mark.parametrize(
"exception",
[
FytaConnectionError,
FytaPlantError,
],
)
async def test_connection_error(
hass: HomeAssistant,
exception: Exception,
mock_fyta_connector: AsyncMock,
mock_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test connection error."""
await setup_platform(hass, mock_config_entry, [Platform.BINARY_SENSOR])
mock_fyta_connector.update_all_plants.side_effect = exception
freezer.tick(delta=timedelta(hours=12))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert (
hass.states.get("binary_sensor.gummibaum_repotted").state == STATE_UNAVAILABLE
)
async def test_add_remove_entities(
hass: HomeAssistant,
mock_fyta_connector: AsyncMock,
mock_config_entry: MockConfigEntry,
freezer: FrozenDateTimeFactory,
) -> None:
"""Test if entities are added and old are removed."""
await setup_platform(hass, mock_config_entry, [Platform.BINARY_SENSOR])
assert hass.states.get("binary_sensor.gummibaum_repotted").state == STATE_ON
plants: dict[int, Plant] = {
0: Plant.from_dict(load_json_object_fixture("plant_status1.json", FYTA_DOMAIN)),
2: Plant.from_dict(load_json_object_fixture("plant_status3.json", FYTA_DOMAIN)),
}
mock_fyta_connector.update_all_plants.return_value = plants
mock_fyta_connector.plant_list = {
0: "Kautschukbaum",
2: "Tomatenpflanze",
}
freezer.tick(delta=timedelta(minutes=10))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert hass.states.get("binary_sensor.kakaobaum_repotted") is None
assert hass.states.get("binary_sensor.tomatenpflanze_repotted").state == STATE_OFF