forked from home-assistant/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add lawnmower entity (home-assistant#93623)
Co-authored-by: Franck Nijhof <frenck@frenck.nl> Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
- Loading branch information
1 parent
538de6d
commit 82b3ced
Showing
17 changed files
with
686 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
"""Demo platform that has a couple fake lawn mowers.""" | ||
from __future__ import annotations | ||
|
||
from homeassistant.components.lawn_mower import ( | ||
LawnMowerActivity, | ||
LawnMowerEntity, | ||
LawnMowerEntityFeature, | ||
) | ||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers.entity_platform import AddEntitiesCallback | ||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType | ||
|
||
|
||
async def async_setup_platform( | ||
hass: HomeAssistant, | ||
config: ConfigType, | ||
async_add_entities: AddEntitiesCallback, | ||
discovery_info: DiscoveryInfoType | None = None, | ||
) -> None: | ||
"""Set up the Demo lawn mowers.""" | ||
async_add_entities( | ||
[ | ||
DemoLawnMower( | ||
"kitchen_sink_mower_001", | ||
"Mower can mow", | ||
LawnMowerActivity.DOCKED, | ||
LawnMowerEntityFeature.START_MOWING, | ||
), | ||
DemoLawnMower( | ||
"kitchen_sink_mower_002", | ||
"Mower can dock", | ||
LawnMowerActivity.MOWING, | ||
LawnMowerEntityFeature.DOCK | LawnMowerEntityFeature.START_MOWING, | ||
), | ||
DemoLawnMower( | ||
"kitchen_sink_mower_003", | ||
"Mower can pause", | ||
LawnMowerActivity.DOCKED, | ||
LawnMowerEntityFeature.PAUSE | LawnMowerEntityFeature.START_MOWING, | ||
), | ||
DemoLawnMower( | ||
"kitchen_sink_mower_004", | ||
"Mower can do all", | ||
LawnMowerActivity.DOCKED, | ||
LawnMowerEntityFeature.DOCK | ||
| LawnMowerEntityFeature.PAUSE | ||
| LawnMowerEntityFeature.START_MOWING, | ||
), | ||
DemoLawnMower( | ||
"kitchen_sink_mower_005", | ||
"Mower is paused", | ||
LawnMowerActivity.PAUSED, | ||
LawnMowerEntityFeature.DOCK | ||
| LawnMowerEntityFeature.PAUSE | ||
| LawnMowerEntityFeature.START_MOWING, | ||
), | ||
] | ||
) | ||
|
||
|
||
async def async_setup_entry( | ||
hass: HomeAssistant, | ||
config_entry: ConfigEntry, | ||
async_add_entities: AddEntitiesCallback, | ||
) -> None: | ||
"""Set up the Everything but the Kitchen Sink config entry.""" | ||
await async_setup_platform(hass, {}, async_add_entities) | ||
|
||
|
||
class DemoLawnMower(LawnMowerEntity): | ||
"""Representation of a Demo lawn mower.""" | ||
|
||
def __init__( | ||
self, | ||
unique_id: str, | ||
name: str, | ||
activity: LawnMowerActivity, | ||
features: LawnMowerEntityFeature = LawnMowerEntityFeature(0), | ||
) -> None: | ||
"""Initialize the lawn mower.""" | ||
self._attr_name = name | ||
self._attr_unique_id = unique_id | ||
self._attr_supported_features = features | ||
self._attr_activity = activity | ||
|
||
async def async_start_mowing(self) -> None: | ||
"""Start mowing.""" | ||
self._attr_activity = LawnMowerActivity.MOWING | ||
self.async_write_ha_state() | ||
|
||
async def async_dock(self) -> None: | ||
"""Start docking.""" | ||
self._attr_activity = LawnMowerActivity.DOCKED | ||
self.async_write_ha_state() | ||
|
||
async def async_pause(self) -> None: | ||
"""Pause mower.""" | ||
self._attr_activity = LawnMowerActivity.PAUSED | ||
self.async_write_ha_state() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
"""The lawn mower integration.""" | ||
from __future__ import annotations | ||
|
||
from dataclasses import dataclass | ||
from datetime import timedelta | ||
import logging | ||
from typing import final | ||
|
||
from homeassistant.config_entries import ConfigEntry | ||
from homeassistant.core import HomeAssistant | ||
from homeassistant.helpers.config_validation import ( # noqa: F401 | ||
PLATFORM_SCHEMA, | ||
PLATFORM_SCHEMA_BASE, | ||
) | ||
from homeassistant.helpers.entity import Entity, EntityDescription | ||
from homeassistant.helpers.entity_component import EntityComponent | ||
from homeassistant.helpers.typing import ConfigType | ||
|
||
from .const import ( | ||
DOMAIN, | ||
SERVICE_DOCK, | ||
SERVICE_PAUSE, | ||
SERVICE_START_MOWING, | ||
LawnMowerActivity, | ||
LawnMowerEntityFeature, | ||
) | ||
|
||
SCAN_INTERVAL = timedelta(seconds=60) | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
|
||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: | ||
"""Set up the lawn_mower component.""" | ||
component = hass.data[DOMAIN] = EntityComponent[LawnMowerEntity]( | ||
_LOGGER, DOMAIN, hass, SCAN_INTERVAL | ||
) | ||
await component.async_setup(config) | ||
|
||
component.async_register_entity_service( | ||
SERVICE_START_MOWING, | ||
{}, | ||
"async_start_mowing", | ||
[LawnMowerEntityFeature.START_MOWING], | ||
) | ||
component.async_register_entity_service( | ||
SERVICE_PAUSE, {}, "async_pause", [LawnMowerEntityFeature.PAUSE] | ||
) | ||
component.async_register_entity_service( | ||
SERVICE_DOCK, {}, "async_dock", [LawnMowerEntityFeature.DOCK] | ||
) | ||
|
||
return True | ||
|
||
|
||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Set up lawn mower devices.""" | ||
component: EntityComponent[LawnMowerEntity] = hass.data[DOMAIN] | ||
return await component.async_setup_entry(entry) | ||
|
||
|
||
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: | ||
"""Unload a config entry.""" | ||
component: EntityComponent[LawnMowerEntity] = hass.data[DOMAIN] | ||
return await component.async_unload_entry(entry) | ||
|
||
|
||
@dataclass | ||
class LawnMowerEntityEntityDescription(EntityDescription): | ||
"""A class that describes lawn mower entities.""" | ||
|
||
|
||
class LawnMowerEntity(Entity): | ||
"""Base class for lawn mower entities.""" | ||
|
||
entity_description: LawnMowerEntityEntityDescription | ||
_attr_activity: LawnMowerActivity | None = None | ||
_attr_supported_features: LawnMowerEntityFeature = LawnMowerEntityFeature(0) | ||
|
||
@final | ||
@property | ||
def state(self) -> str | None: | ||
"""Return the current state.""" | ||
if (activity := self.activity) is None: | ||
return None | ||
return str(activity) | ||
|
||
@property | ||
def activity(self) -> LawnMowerActivity | None: | ||
"""Return the current lawn mower activity.""" | ||
return self._attr_activity | ||
|
||
@property | ||
def supported_features(self) -> LawnMowerEntityFeature: | ||
"""Flag lawn mower features that are supported.""" | ||
return self._attr_supported_features | ||
|
||
def start_mowing(self) -> None: | ||
"""Start or resume mowing.""" | ||
raise NotImplementedError() | ||
|
||
async def async_start_mowing(self) -> None: | ||
"""Start or resume mowing.""" | ||
await self.hass.async_add_executor_job(self.start_mowing) | ||
|
||
def dock(self) -> None: | ||
"""Dock the mower.""" | ||
raise NotImplementedError() | ||
|
||
async def async_dock(self) -> None: | ||
"""Dock the mower.""" | ||
await self.hass.async_add_executor_job(self.dock) | ||
|
||
def pause(self) -> None: | ||
"""Pause the lawn mower.""" | ||
raise NotImplementedError() | ||
|
||
async def async_pause(self) -> None: | ||
"""Pause the lawn mower.""" | ||
await self.hass.async_add_executor_job(self.pause) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
"""Constants for the lawn mower integration.""" | ||
from enum import IntFlag, StrEnum | ||
|
||
|
||
class LawnMowerActivity(StrEnum): | ||
"""Activity state of lawn mower devices.""" | ||
|
||
ERROR = "error" | ||
"""Device is in error state, needs assistance.""" | ||
|
||
PAUSED = "paused" | ||
"""Paused during activity.""" | ||
|
||
MOWING = "mowing" | ||
"""Device is mowing.""" | ||
|
||
DOCKED = "docked" | ||
"""Device is docked.""" | ||
|
||
|
||
class LawnMowerEntityFeature(IntFlag): | ||
"""Supported features of the lawn mower entity.""" | ||
|
||
START_MOWING = 1 | ||
PAUSE = 2 | ||
DOCK = 4 | ||
|
||
|
||
DOMAIN = "lawn_mower" | ||
|
||
SERVICE_START_MOWING = "start_mowing" | ||
SERVICE_PAUSE = "pause" | ||
SERVICE_DOCK = "dock" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"domain": "lawn_mower", | ||
"name": "Lawn Mower", | ||
"codeowners": ["@home-assistant/core"], | ||
"documentation": "https://www.home-assistant.io/integrations/lawn_mower", | ||
"integration_type": "entity", | ||
"quality_scale": "internal" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# Describes the format for available lawn_mower services | ||
|
||
start_mowing: | ||
target: | ||
entity: | ||
domain: lawn_mower | ||
supported_features: | ||
- lawn_mower.LawnMowerEntityFeature.START_MOWING | ||
|
||
dock: | ||
target: | ||
entity: | ||
domain: lawn_mower | ||
supported_features: | ||
- lawn_mower.LawnMowerEntityFeature.DOCK | ||
|
||
pause: | ||
target: | ||
entity: | ||
domain: lawn_mower | ||
supported_features: | ||
- lawn_mower.LawnMowerEntityFeature.PAUSE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
"title": "Lawn mower", | ||
"entity_component": { | ||
"_": { | ||
"name": "[%key:component::lawn_mower::title%]", | ||
"state": { | ||
"error": "Error", | ||
"paused": "Paused", | ||
"mowing": "Mowing", | ||
"docked": "Docked" | ||
} | ||
} | ||
}, | ||
"services": { | ||
"start_mowing": { | ||
"name": "Start mowing", | ||
"description": "Starts the mowing task." | ||
}, | ||
"dock": { | ||
"name": "Return to dock", | ||
"description": "Stops the mowing task and returns to the dock." | ||
}, | ||
"pause": { | ||
"name": "Pause", | ||
"description": "Pauses the mowing task." | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.