1 min read
AutomatisierungHome Assistant Integration & Automation
Smart Home Automation mit Home Assistant. WebSocket API, Node-RED Integration, Custom Automations und YAML-Konfiguration.
Home AssistantSmart HomeAutomationNode-REDWebSocket APIYAML

Home Assistant Integration & Automation
Meta-Description: Smart Home Automation mit Home Assistant. WebSocket API, Node-RED Integration, Custom Automations und YAML-Konfiguration.
Keywords: Home Assistant, Smart Home, Automation, Node-RED, WebSocket API, YAML, IoT Platform
Einführung
Home Assistant ist die führende Open-Source Smart Home Plattform. Mit über 2.800 Integrations, lokaler Kontrolle und einer aktiven Community bietet sie die perfekte Grundlage für jedes Smart Home Projekt.
Home Assistant Architecture
┌─────────────────────────────────────────────────────────────┐
│ HOME ASSISTANT ARCHITECTURE │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Frontend │ │ Core │ │ Supervisor │ │
│ │ (React) │←──→│ (Python) │←──→│ (Docker) │ │
│ └─────────────┘ └──────┬──────┘ └─────────────┘ │
│ │ │
│ ┌─────────────────────────┼─────────────────────────┐ │
│ │ Integrations │ │
│ ├─────────────────────────┼─────────────────────────┤ │
│ │ ┌────────┐ ┌────────┐ │ ┌────────┐ ┌────────┐ │ │
│ │ │ Zigbee │ │ Z-Wave │ │ │ MQTT │ │ HTTP │ │ │
│ │ └────────┘ └────────┘ │ └────────┘ └────────┘ │ │
│ │ ┌────────┐ ┌────────┐ │ ┌────────┐ ┌────────┐ │ │
│ │ │ Thread │ │ Matter │ │ │Bluetooth│ │ Cloud │ │ │
│ │ └────────┘ └────────┘ │ └────────┘ └────────┘ │ │
│ └───────────────────────────────────────────────────┘ │
│ │
│ Protocols: WebSocket, REST API, MQTT │
│ │
└─────────────────────────────────────────────────────────────┘Installation & Setup
# Docker Installation
docker run -d \
--name homeassistant \
--privileged \
--restart=unless-stopped \
-e TZ=Europe/Berlin \
-v /path/to/config:/config \
-v /run/dbus:/run/dbus:ro \
--network=host \
ghcr.io/home-assistant/home-assistant:stable
# Oder mit Docker Compose
# docker-compose.yml
version: '3'
services:
homeassistant:
container_name: homeassistant
image: "ghcr.io/home-assistant/home-assistant:stable"
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro
restart: unless-stopped
privileged: true
network_mode: hostWebSocket API Integration
// lib/homeassistant-client.ts
import WebSocket from 'ws';
interface HAMessage {
id?: number;
type: string;
[key: string]: any;
}
interface HAState {
entity_id: string;
state: string;
attributes: Record<string, any>;
last_changed: string;
last_updated: string;
}
class HomeAssistantClient {
private ws: WebSocket | null = null;
private messageId = 1;
private pendingRequests: Map<number, {
resolve: (value: any) => void;
reject: (error: Error) => void;
}> = new Map();
private eventSubscribers: Map<string, Set<(data: any) => void>> = new Map();
constructor(
private url: string,
private token: string
) {}
async connect(): Promise<void> {
return new Promise((resolve, reject) => {
this.ws = new WebSocket(this.url);
this.ws.on('open', () => {
console.log('Connected to Home Assistant');
});
this.ws.on('message', async (data) => {
const message = JSON.parse(data.toString());
await this.handleMessage(message, resolve);
});
this.ws.on('error', (error) => {
console.error('WebSocket error:', error);
reject(error);
});
this.ws.on('close', () => {
console.log('Connection closed');
this.reconnect();
});
});
}
private async handleMessage(message: any, onAuth?: (value: void) => void) {
switch (message.type) {
case 'auth_required':
this.send({ type: 'auth', access_token: this.token });
break;
case 'auth_ok':
console.log('Authenticated with Home Assistant');
onAuth?.();
break;
case 'auth_invalid':
throw new Error('Invalid authentication');
case 'result':
const pending = this.pendingRequests.get(message.id);
if (pending) {
if (message.success) {
pending.resolve(message.result);
} else {
pending.reject(new Error(message.error?.message));
}
this.pendingRequests.delete(message.id);
}
break;
case 'event':
this.handleEvent(message.event);
break;
}
}
private handleEvent(event: any) {
const eventType = event.event_type;
const subscribers = this.eventSubscribers.get(eventType);
if (subscribers) {
subscribers.forEach(callback => callback(event.data));
}
// Wildcard subscribers
const allSubscribers = this.eventSubscribers.get('*');
if (allSubscribers) {
allSubscribers.forEach(callback => callback(event));
}
}
private send(message: HAMessage) {
if (this.ws?.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(message));
}
}
private async sendCommand<T>(message: Omit<HAMessage, 'id'>): Promise<T> {
return new Promise((resolve, reject) => {
const id = this.messageId++;
this.pendingRequests.set(id, { resolve, reject });
this.send({ ...message, id });
// Timeout nach 30 Sekunden
setTimeout(() => {
if (this.pendingRequests.has(id)) {
this.pendingRequests.delete(id);
reject(new Error('Request timeout'));
}
}, 30000);
});
}
// States abrufen
async getStates(): Promise<HAState[]> {
return this.sendCommand({ type: 'get_states' });
}
async getState(entityId: string): Promise<HAState | undefined> {
const states = await this.getStates();
return states.find(s => s.entity_id === entityId);
}
// Services aufrufen
async callService(
domain: string,
service: string,
serviceData?: Record<string, any>,
target?: { entity_id?: string | string[] }
): Promise<void> {
await this.sendCommand({
type: 'call_service',
domain,
service,
service_data: serviceData,
target
});
}
// Events abonnieren
async subscribeEvents(
eventType: string,
callback: (data: any) => void
): Promise<() => void> {
if (!this.eventSubscribers.has(eventType)) {
this.eventSubscribers.set(eventType, new Set());
// Bei HA registrieren
await this.sendCommand({
type: 'subscribe_events',
event_type: eventType === '*' ? undefined : eventType
});
}
this.eventSubscribers.get(eventType)!.add(callback);
// Unsubscribe Function
return () => {
this.eventSubscribers.get(eventType)?.delete(callback);
};
}
// Trigger State Change
async subscribeStateChanges(
entityId: string,
callback: (newState: HAState, oldState: HAState) => void
): Promise<() => void> {
return this.subscribeEvents('state_changed', (data) => {
if (data.entity_id === entityId) {
callback(data.new_state, data.old_state);
}
});
}
private reconnect() {
setTimeout(() => {
console.log('Reconnecting...');
this.connect();
}, 5000);
}
disconnect() {
this.ws?.close();
}
}
// Verwendung
const ha = new HomeAssistantClient(
'ws://homeassistant.local:8123/api/websocket',
process.env.HA_TOKEN!
);
await ha.connect();
// Alle States abrufen
const states = await ha.getStates();
console.log(`${states.length} entities found`);
// Licht einschalten
await ha.callService('light', 'turn_on', {
brightness: 255,
color_temp: 300
}, {
entity_id: 'light.wohnzimmer'
});
// State Changes beobachten
ha.subscribeStateChanges('sensor.temperature', (newState, oldState) => {
console.log(`Temperature changed: ${oldState.state} → ${newState.state}`);
});REST API Integration
// lib/homeassistant-rest.ts
interface HARestConfig {
baseUrl: string;
token: string;
}
class HomeAssistantREST {
private baseUrl: string;
private headers: HeadersInit;
constructor(config: HARestConfig) {
this.baseUrl = config.baseUrl.replace(/\/$/, '');
this.headers = {
'Authorization': `Bearer ${config.token}`,
'Content-Type': 'application/json'
};
}
private async request<T>(
method: string,
endpoint: string,
body?: any
): Promise<T> {
const response = await fetch(`${this.baseUrl}/api${endpoint}`, {
method,
headers: this.headers,
body: body ? JSON.stringify(body) : undefined
});
if (!response.ok) {
throw new Error(`HA API Error: ${response.status}`);
}
return response.json();
}
// API Status
async getApiStatus(): Promise<{ message: string }> {
return this.request('GET', '/');
}
// Config
async getConfig(): Promise<any> {
return this.request('GET', '/config');
}
// States
async getStates(): Promise<HAState[]> {
return this.request('GET', '/states');
}
async getState(entityId: string): Promise<HAState> {
return this.request('GET', `/states/${entityId}`);
}
async setState(entityId: string, state: string, attributes?: Record<string, any>): Promise<HAState> {
return this.request('POST', `/states/${entityId}`, {
state,
attributes
});
}
// Services
async getServices(): Promise<Record<string, any>> {
return this.request('GET', '/services');
}
async callService(
domain: string,
service: string,
data?: Record<string, any>
): Promise<HAState[]> {
return this.request('POST', `/services/${domain}/${service}`, data);
}
// History
async getHistory(
entityId: string,
startTime?: Date,
endTime?: Date
): Promise<HAState[][]> {
const params = new URLSearchParams();
if (startTime) params.set('start_time', startTime.toISOString());
if (endTime) params.set('end_time', endTime.toISOString());
params.set('filter_entity_id', entityId);
return this.request('GET', `/history/period?${params}`);
}
// Logbook
async getLogbook(
entityId?: string,
startTime?: Date,
endTime?: Date
): Promise<any[]> {
const params = new URLSearchParams();
if (entityId) params.set('entity', entityId);
if (startTime) params.set('start_time', startTime.toISOString());
if (endTime) params.set('end_time', endTime.toISOString());
return this.request('GET', `/logbook?${params}`);
}
// Template Rendering
async renderTemplate(template: string): Promise<string> {
const result = await this.request<{ result: string }>('POST', '/template', { template });
return result.result;
}
}
// API Route für Next.js
// app/api/home/lights/route.ts
import { NextRequest, NextResponse } from 'next/server';
const ha = new HomeAssistantREST({
baseUrl: process.env.HA_URL!,
token: process.env.HA_TOKEN!
});
export async function GET() {
const states = await ha.getStates();
const lights = states.filter(s => s.entity_id.startsWith('light.'));
return NextResponse.json(lights.map(light => ({
id: light.entity_id,
name: light.attributes.friendly_name,
state: light.state,
brightness: light.attributes.brightness,
color_temp: light.attributes.color_temp
})));
}
export async function POST(request: NextRequest) {
const { entityId, action, ...params } = await request.json();
await ha.callService('light', action, {
entity_id: entityId,
...params
});
return NextResponse.json({ success: true });
}YAML Automations
# automations.yaml
# Licht bei Bewegung einschalten
- id: 'motion_light_on'
alias: 'Flur Licht bei Bewegung'
description: 'Schaltet das Flur-Licht bei Bewegung ein'
trigger:
- platform: state
entity_id: binary_sensor.flur_motion
to: 'on'
condition:
- condition: state
entity_id: sun.sun
state: 'below_horizon'
- condition: state
entity_id: input_boolean.guest_mode
state: 'off'
action:
- service: light.turn_on
target:
entity_id: light.flur
data:
brightness_pct: 80
transition: 2
- delay: '00:05:00'
- service: light.turn_off
target:
entity_id: light.flur
data:
transition: 5
mode: restart
# Temperatur-basierte Heizungssteuerung
- id: 'heating_control'
alias: 'Heizung Temperatur Kontrolle'
trigger:
- platform: numeric_state
entity_id: sensor.wohnzimmer_temperature
below: 20
condition:
- condition: state
entity_id: input_boolean.heating_enabled
state: 'on'
- condition: time
after: '06:00:00'
before: '22:00:00'
action:
- service: climate.set_temperature
target:
entity_id: climate.wohnzimmer
data:
temperature: 22
hvac_mode: heat
# Guten Morgen Routine
- id: 'morning_routine'
alias: 'Guten Morgen Routine'
trigger:
- platform: time
at: input_datetime.wakeup_time
condition:
- condition: state
entity_id: input_boolean.alarm_enabled
state: 'on'
- condition: state
entity_id: person.user
state: 'home'
action:
- service: light.turn_on
target:
entity_id: light.schlafzimmer
data:
brightness_pct: 10
color_temp: 500
- delay: '00:05:00'
- service: light.turn_on
data:
brightness_pct: 50
color_temp: 370
transition: 300
- service: media_player.play_media
target:
entity_id: media_player.schlafzimmer_speaker
data:
media_content_type: music
media_content_id: 'spotify:playlist:morning'
- service: notify.mobile_app
data:
message: "Guten Morgen! Es sind {{ states('sensor.outside_temperature') }}°C draußen."Node-RED Integration
// Node-RED Flow für Home Assistant
[
{
"id": "ha-server",
"type": "server",
"name": "Home Assistant",
"addon": true
},
{
"id": "motion-trigger",
"type": "server-state-changed",
"name": "Motion Detected",
"server": "ha-server",
"entityId": "binary_sensor.motion",
"entityIdType": "exact",
"outputInitially": false,
"stateType": "str",
"ifState": "on",
"ifStateType": "str",
"outputOnlyOnStateChange": true,
"wires": [["check-conditions"]]
},
{
"id": "check-conditions",
"type": "api-current-state",
"name": "Check Sun State",
"server": "ha-server",
"entityId": "sun.sun",
"outputProperties": [
{
"property": "payload",
"propertyType": "msg",
"value": "",
"valueType": "entityState"
}
],
"wires": [["filter-night"]]
},
{
"id": "filter-night",
"type": "switch",
"name": "Night Only",
"property": "payload",
"rules": [
{ "t": "eq", "v": "below_horizon", "vt": "str" }
],
"wires": [["turn-on-light"]]
},
{
"id": "turn-on-light",
"type": "api-call-service",
"name": "Turn On Light",
"server": "ha-server",
"service_domain": "light",
"service": "turn_on",
"entityId": "light.hallway",
"data": "{\"brightness_pct\": 80, \"transition\": 2}",
"wires": [[]]
}
]// Custom Node-RED Node
import { Red, Node, NodeProperties } from 'node-red';
interface SmartLightConfig extends NodeProperties {
server: string;
entityId: string;
brightness: number;
colorTemp: number;
}
module.exports = function(RED: Red) {
function SmartLightNode(this: Node, config: SmartLightConfig) {
RED.nodes.createNode(this, config);
const server = RED.nodes.getNode(config.server) as any;
this.on('input', async (msg: any) => {
try {
const brightness = msg.brightness || config.brightness;
const colorTemp = msg.colorTemp || config.colorTemp;
await server.websocket.callService('light', 'turn_on', {
entity_id: config.entityId,
brightness_pct: brightness,
color_temp: colorTemp
});
this.status({ fill: 'green', shape: 'dot', text: 'Light on' });
this.send({ ...msg, payload: { success: true } });
} catch (error) {
this.status({ fill: 'red', shape: 'ring', text: 'Error' });
this.error(error);
}
});
}
RED.nodes.registerType('smart-light', SmartLightNode);
};Custom Integration Development
# custom_components/my_sensor/sensor.py
"""Custom sensor integration for Home Assistant."""
from homeassistant.components.sensor import (
SensorEntity,
SensorDeviceClass,
SensorStateClass,
)
from homeassistant.const import UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.entity_platform import AddEntitiesCallback
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the sensor platform."""
async_add_entities([
MySensor(config_entry),
])
class MySensor(SensorEntity):
"""Representation of a custom sensor."""
_attr_name = "My Custom Sensor"
_attr_device_class = SensorDeviceClass.TEMPERATURE
_attr_state_class = SensorStateClass.MEASUREMENT
_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
def __init__(self, config_entry: ConfigEntry) -> None:
"""Initialize the sensor."""
self._attr_unique_id = f"{config_entry.entry_id}_temperature"
self._attr_native_value = None
async def async_update(self) -> None:
"""Fetch new state data for the sensor."""
# API Call oder Sensor-Abfrage
self._attr_native_value = await self._fetch_temperature()
async def _fetch_temperature(self) -> float:
"""Fetch temperature from external source."""
# Implementierung
return 21.5Dashboard Configuration
# ui-lovelace.yaml
title: Smart Home
views:
- title: Übersicht
path: overview
icon: mdi:home
cards:
- type: weather-forecast
entity: weather.home
- type: grid
columns: 3
cards:
- type: button
entity: light.wohnzimmer
name: Wohnzimmer
icon: mdi:sofa
tap_action:
action: toggle
- type: button
entity: light.schlafzimmer
name: Schlafzimmer
icon: mdi:bed
- type: button
entity: script.movie_mode
name: Kino Modus
icon: mdi:movie
- type: entities
title: Temperaturen
entities:
- entity: sensor.wohnzimmer_temperature
- entity: sensor.schlafzimmer_temperature
- entity: sensor.aussen_temperature
- type: history-graph
title: Temperaturverlauf
hours_to_show: 24
entities:
- entity: sensor.wohnzimmer_temperature
- entity: sensor.aussen_temperatureFazit
Home Assistant bietet:
- Lokale Kontrolle: Keine Cloud-Abhängigkeit
- 2800+ Integrations: Alle Smart Home Protokolle
- Flexible APIs: WebSocket, REST, MQTT
- Node-RED: Visual Automation Flows
Die perfekte Plattform für Smart Home Projekte.
Bildprompts
- "Smart home dashboard with device controls, Home Assistant interface"
- "Automation flow connecting sensors and actuators, Node-RED visual programming"
- "Home network diagram with IoT devices, local smart home server"