Documentation Index
Fetch the complete documentation index at: https://mintlify.com/home-assistant/core/llms.txt
Use this file to discover all available pages before exploring further.
Entities are the building blocks of Home Assistant. They represent devices, sensors, switches, and other controllable or monitorable objects. This guide covers how to create entity components for your integration.
Entity Basics
What is an Entity?
An entity represents a single piece of functionality from a device or service. Examples:
- A temperature sensor
- A light bulb
- A media player
- A switch
Each entity has:
- A unique ID for identification
- A state (on/off, temperature value, etc.)
- attributes with additional information
- An entity ID like
sensor.living_room_temperature
Home Assistant has different entity platforms for different types of entities:
sensor - Read-only measurements
binary_sensor - On/off sensors
switch - On/off switches
light - Lights with brightness, color, etc.
climate - Thermostats and climate control
cover - Blinds, garage doors, etc.
- And many more…
Each entity platform is a separate Python file in your integration directory.
Every platform must have an async_setup_entry function:
"""Sensor platform for Your Integration."""
from __future__ import annotations
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the sensor platform."""
# Get the API client or coordinator from hass.data
client = hass.data[DOMAIN][entry.entry_id]["client"]
# Fetch the list of sensors
sensors = await client.get_sensors()
# Create entity objects
entities = [
YourTemperatureSensor(client, sensor_id)
for sensor_id in sensors
]
# Add entities to Home Assistant
async_add_entities(entities)
Creating an Entity Class
Entity classes inherit from a base entity class specific to their platform.
Basic Entity Example
class YourTemperatureSensor(SensorEntity):
"""Representation of a temperature sensor."""
# Specify the device class
_attr_device_class = SensorDeviceClass.TEMPERATURE
# Specify the state class for statistics
_attr_state_class = SensorStateClass.MEASUREMENT
# Specify the unit
_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
def __init__(self, client, sensor_id: str) -> None:
"""Initialize the sensor."""
self._client = client
self._sensor_id = sensor_id
# Set a unique ID - important for customization
self._attr_unique_id = f"{DOMAIN}_{sensor_id}"
# Set the entity name
self._attr_name = f"Temperature {sensor_id}"
async def async_update(self) -> None:
"""Fetch new state data for the sensor."""
# Get the current temperature from the API
temperature = await self._client.get_temperature(self._sensor_id)
self._attr_native_value = temperature
Entity Properties
The Entity base class provides many properties you can override:
Essential Properties
class YourEntity(SensorEntity):
"""Your entity."""
# Unique identifier for this entity
_attr_unique_id = "unique_entity_id"
# Display name
_attr_name = "My Sensor"
# Whether the entity is available
_attr_available = True
# Icon to display (from Material Design Icons)
_attr_icon = "mdi:thermometer"
Modern Entity Naming
Use the modern naming pattern with device info:
from homeassistant.helpers.device_registry import DeviceInfo
class YourSensor(SensorEntity):
"""Representation of a sensor."""
# This entity represents a device
_attr_has_entity_name = True
# The entity name (will be combined with device name)
_attr_name = "Temperature"
def __init__(self, device_id: str) -> None:
"""Initialize the sensor."""
self._attr_unique_id = f"{device_id}_temperature"
# Associate this entity with a device
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, device_id)},
name="My Device",
manufacturer="Your Company",
model="Model X",
sw_version="1.0.0",
)
This creates an entity named “My Device Temperature” and groups it with other entities from the same device.
State Updates
There are several ways to update entity state:
Method 1: async_update (Polling)
class YourSensor(SensorEntity):
"""Polling sensor."""
# Enable polling (default is True)
_attr_should_poll = True
async def async_update(self) -> None:
"""Fetch new state data for the sensor."""
# This will be called periodically by Home Assistant
self._attr_native_value = await self._client.get_value()
Method 2: Push Updates (Recommended)
class YourSensor(SensorEntity):
"""Push-based sensor."""
# Disable polling since we'll push updates
_attr_should_poll = False
def __init__(self, client) -> None:
"""Initialize the sensor."""
self._client = client
# Register a callback for updates
self._client.register_callback(self._handle_update)
def _handle_update(self, value) -> None:
"""Handle a pushed update from the API."""
self._attr_native_value = value
# Tell Home Assistant the state changed
self.async_write_ha_state()
async def async_will_remove_from_hass(self) -> None:
"""Clean up when entity is removed."""
# Unregister the callback
self._client.unregister_callback(self._handle_update)
Method 3: DataUpdateCoordinator (Best Practice)
from homeassistant.helpers.update_coordinator import (
CoordinatorEntity,
DataUpdateCoordinator,
)
class YourSensor(CoordinatorEntity, SensorEntity):
"""Sensor using coordinator."""
def __init__(
self,
coordinator: DataUpdateCoordinator,
sensor_id: str,
) -> None:
"""Initialize the sensor."""
super().__init__(coordinator)
self._sensor_id = sensor_id
self._attr_unique_id = f"{DOMAIN}_{sensor_id}"
@property
def native_value(self):
"""Return the state of the sensor."""
# Access coordinated data
return self.coordinator.data[self._sensor_id]
See the DataUpdateCoordinator documentation for setup details.
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorStateClass,
)
class YourSensor(SensorEntity):
"""A sensor entity."""
# Device class affects how the entity is displayed
_attr_device_class = SensorDeviceClass.TEMPERATURE
# State class enables statistics and long-term data
_attr_state_class = SensorStateClass.MEASUREMENT
# Native value and unit
_attr_native_value = 20.5
_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
# Precision for rounding
_attr_suggested_display_precision = 1
from homeassistant.components.switch import SwitchEntity
class YourSwitch(SwitchEntity):
"""A switch entity."""
@property
def is_on(self) -> bool:
"""Return true if switch is on."""
return self._attr_is_on
async def async_turn_on(self, **kwargs) -> None:
"""Turn the switch on."""
await self._client.turn_on(self._device_id)
self._attr_is_on = True
self.async_write_ha_state()
async def async_turn_off(self, **kwargs) -> None:
"""Turn the switch off."""
await self._client.turn_off(self._device_id)
self._attr_is_on = False
self.async_write_ha_state()
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ColorMode,
LightEntity,
)
class YourLight(LightEntity):
"""A light entity."""
# Supported color modes
_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
_attr_color_mode = ColorMode.BRIGHTNESS
@property
def brightness(self) -> int | None:
"""Return the brightness of this light between 0..255."""
return self._attr_brightness
@property
def is_on(self) -> bool:
"""Return true if light is on."""
return self._attr_is_on
async def async_turn_on(self, **kwargs) -> None:
"""Turn the light on."""
if ATTR_BRIGHTNESS in kwargs:
brightness = kwargs[ATTR_BRIGHTNESS]
await self._client.set_brightness(self._device_id, brightness)
self._attr_brightness = brightness
await self._client.turn_on(self._device_id)
self._attr_is_on = True
self.async_write_ha_state()
async def async_turn_off(self, **kwargs) -> None:
"""Turn the light off."""
await self._client.turn_off(self._device_id)
self._attr_is_on = False
self.async_write_ha_state()
Entity Attributes
You can add extra attributes to entities:
class YourSensor(SensorEntity):
"""Sensor with extra attributes."""
@property
def extra_state_attributes(self) -> dict[str, Any]:
"""Return extra state attributes."""
return {
"last_update": self._last_update,
"battery_level": self._battery_level,
"signal_strength": self._signal_strength,
}
Entity Categories
Use entity categories to organize entities:
from homeassistant.const import EntityCategory
class YourDiagnosticSensor(SensorEntity):
"""A diagnostic sensor."""
# This entity is diagnostic (shown in advanced section)
_attr_entity_category = EntityCategory.DIAGNOSTIC
class YourConfigSwitch(SwitchEntity):
"""A configuration switch."""
# This entity is for configuration
_attr_entity_category = EntityCategory.CONFIG
Categories:
EntityCategory.CONFIG - Configuration entities
EntityCategory.DIAGNOSTIC - Diagnostic information
None - Primary entities (default)
Entity Registry
When you set a unique_id, entities are automatically registered:
class YourEntity(SensorEntity):
"""Entity with unique ID."""
def __init__(self, device_id: str) -> None:
"""Initialize."""
# This enables entity registry features:
# - User can customize the entity
# - Entity survives integration reload
# - Entity can be disabled
self._attr_unique_id = f"{DOMAIN}_{device_id}"
Benefits of entity registry:
- Users can customize entity names and icons
- Users can disable entities they don’t need
- Entity IDs are stable across restarts
- Entities can be tracked across config changes
Dynamic Entity Addition
For devices that support dynamic entities:
from homeassistant.helpers.entity_platform import AddEntitiesCallback
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the platform."""
client = hass.data[DOMAIN][entry.entry_id]["client"]
# Add initial entities
async_add_entities([YourSensor(client, "sensor1")])
# Store the callback for later use
hass.data[DOMAIN][entry.entry_id]["add_entities"] = async_add_entities
# Later, when a new device is discovered:
def handle_new_device(hass, entry_id, device_id):
"""Handle a newly discovered device."""
add_entities = hass.data[DOMAIN][entry_id]["add_entities"]
client = hass.data[DOMAIN][entry_id]["client"]
# Add the new entity
add_entities([YourSensor(client, device_id)])
Entity Availability
Indicate when an entity is unavailable:
class YourSensor(SensorEntity):
"""Sensor that may become unavailable."""
async def async_update(self) -> None:
"""Update the sensor."""
try:
self._attr_native_value = await self._client.get_value()
self._attr_available = True
except ConnectionError:
# Device is offline
self._attr_available = False
Best Practices
Always Use Unique IDs
Provide unique IDs for all entities to enable customization:
self._attr_unique_id = f"{entry.entry_id}_{device_id}_{sensor_type}"
Use Device Info
Group related entities under a single device:
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, device_id)},
name="Device Name",
manufacturer="Manufacturer",
model="Model",
)
Use DataUpdateCoordinator
For polling integrations, use DataUpdateCoordinator to efficiently manage updates.
Disable Polling When Possible
If your API supports push updates, disable polling:
_attr_should_poll = False
Handle Exceptions
Gracefully handle API errors:
try:
value = await self._client.get_value()
except APIError:
_LOGGER.error("Failed to update sensor")
self._attr_available = False
Use Modern Naming
Set _attr_has_entity_name = True and provide device info for better entity naming.
Common Patterns
Entity Descriptions
For multiple similar entities, use entity descriptions:
from dataclasses import dataclass
from homeassistant.components.sensor import SensorEntityDescription
@dataclass
class YourSensorDescription(SensorEntityDescription):
"""Describes a sensor."""
api_key: str | None = None
SENSOR_TYPES: tuple[YourSensorDescription, ...] = (
YourSensorDescription(
key="temperature",
name="Temperature",
device_class=SensorDeviceClass.TEMPERATURE,
api_key="temp",
),
YourSensorDescription(
key="humidity",
name="Humidity",
device_class=SensorDeviceClass.HUMIDITY,
api_key="humid",
),
)
class YourSensor(SensorEntity):
"""Sensor using description."""
def __init__(self, description: YourSensorDescription) -> None:
"""Initialize."""
self.entity_description = description
self._attr_unique_id = f"{DOMAIN}_{description.key}"
Next Steps