Skill
ha-entity-platforms
Create Home Assistant entity platforms (sensor, binary_sensor, switch, light, cover, climate, button, number, select, etc.). Use when creating entities, adding platforms, implementing switches or sensors, or working with any HA entity type.
From home-assistant-devInstall
1
Run in your terminal$
npx claudepluginhub l3digitalnet/claude-code-plugins --plugin home-assistant-devTool Access
This skill uses the workspace's default tool permissions.
Supporting Assets
View in Repositoryreference/device-classes.mdSkill Content
Home Assistant Entity Platforms
Platform Setup Pattern
Every platform implements async_setup_entry:
"""Sensor platform for {Name}."""
from __future__ import annotations
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import {Name}ConfigEntry
from .coordinator import {Name}Coordinator
async def async_setup_entry(
hass: HomeAssistant,
entry: {Name}ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up sensors from a config entry."""
coordinator = entry.runtime_data
entities = []
for device_id in coordinator.get_device_ids():
for description in SENSOR_DESCRIPTIONS:
entities.append({Name}Sensor(coordinator, description, device_id))
async_add_entities(entities)
Entity Description Pattern
Use EntityDescription dataclasses for declarative definitions:
from dataclasses import dataclass
from collections.abc import Callable
from typing import Any
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import PERCENTAGE, UnitOfTemperature
@dataclass(frozen=True, kw_only=True)
class {Name}SensorDescription(SensorEntityDescription):
"""Describe a {Name} sensor."""
value_fn: Callable[[dict[str, Any]], Any]
SENSOR_DESCRIPTIONS: tuple[{Name}SensorDescription, ...] = (
{Name}SensorDescription(
key="temperature",
translation_key="temperature",
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda data: data.get("temperature"),
),
{Name}SensorDescription(
key="humidity",
translation_key="humidity",
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda data: data.get("humidity"),
),
)
Base Entity Class
"""Base entity for {Name}."""
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN
from .coordinator import {Name}Coordinator
class {Name}Entity(CoordinatorEntity[{Name}Coordinator]):
"""Base class for {Name} entities."""
_attr_has_entity_name = True
def __init__(self, coordinator: {Name}Coordinator, device_id: str) -> None:
super().__init__(coordinator)
self._device_id = device_id
@property
def device_info(self) -> DeviceInfo:
device = self.coordinator.get_device_data(self._device_id)
return DeviceInfo(
identifiers={(DOMAIN, self._device_id)},
name=device.get("name") if device else self._device_id,
manufacturer="Manufacturer",
model=device.get("model") if device else None,
sw_version=device.get("firmware") if device else None,
)
@property
def available(self) -> bool:
return super().available and self.coordinator.get_device_data(self._device_id) is not None
Sensor Entity
class {Name}Sensor({Name}Entity, SensorEntity):
entity_description: {Name}SensorDescription
def __init__(self, coordinator, description, device_id):
super().__init__(coordinator, device_id)
self.entity_description = description
self._attr_unique_id = f"{DOMAIN}_{device_id}_{description.key}"
@property
def native_value(self) -> float | str | None:
if (data := self.coordinator.get_device_data(self._device_id)) is None:
return None
return self.entity_description.value_fn(data)
Switch Entity
from homeassistant.components.switch import SwitchDeviceClass, SwitchEntity
class {Name}Switch({Name}Entity, SwitchEntity):
_attr_device_class = SwitchDeviceClass.SWITCH
def __init__(self, coordinator, key, device_id):
super().__init__(coordinator, device_id)
self._key = key
self._attr_unique_id = f"{DOMAIN}_{device_id}_{key}"
self._attr_translation_key = key
@property
def is_on(self) -> bool | None:
if (data := self.coordinator.get_device_data(self._device_id)) is None:
return None
return data.get(self._key)
async def async_turn_on(self, **kwargs) -> None:
await self.coordinator.client.async_set_switch(self._device_id, self._key, True)
await self.coordinator.async_request_refresh()
async def async_turn_off(self, **kwargs) -> None:
await self.coordinator.client.async_set_switch(self._device_id, self._key, False)
await self.coordinator.async_request_refresh()
Platform Quick Reference
| Platform | Base Class | Key Property | Device Classes |
|---|---|---|---|
sensor | SensorEntity | native_value | TEMPERATURE, HUMIDITY, POWER, ENERGY, BATTERY... |
binary_sensor | BinarySensorEntity | is_on | MOTION, DOOR, WINDOW, SMOKE, MOISTURE... |
switch | SwitchEntity | is_on + turn_on/off | SWITCH, OUTLET |
light | LightEntity | is_on + brightness | — |
cover | CoverEntity | is_closed + open/close | BLIND, GARAGE, SHUTTER... |
climate | ClimateEntity | hvac_mode + temps | — |
button | ButtonEntity | async_press() | RESTART, UPDATE, IDENTIFY |
number | NumberEntity | native_value + set_value | — |
select | SelectEntity | current_option + select_option | — |
Additional Resources
For complete device class reference, see reference/device-classes.md.
Critical Rules
- Always set
_attr_has_entity_name = True - Always provide stable
unique_id - Always provide
device_infowith stableidentifiers - Use
translation_keyfor names, not hardcoded_attr_name - Add
state_classto numeric sensors (MEASUREMENT, TOTAL, TOTAL_INCREASING) - Use
native_unit_of_measurementnotunit_of_measurement - Call
async_request_refresh()after commands
Similar Skills
Stats
Parent Repo Stars3
Parent Repo Forks0
Last CommitFeb 17, 2026