Die Variante, die CSV Datei per Java-Script über die Button-Card zu erzeugen, ist für ad-hoc Auswertungen hervorragend.
Als regelmäßiges Backup ist sie daher nicht optimal, und daher habe ich (mit Hilfe einer KI für die Syntax) einen Weg über Skripte in HA und Shell gewählt.
Die erzeugte Datei ist direkt in Excel einlesbar. und wird mit einem Zeitstempel im Dateinamen versehen.
Falls man den Speicherpfad auf z.b. ein NAS legt, ist sie auch bei einem Ausfall von HA verfügbar.
CSV Export aller Entitäten per Skript
Insgesamt brauchen wir:
- Ein HA Skript, das alle Entitäten und deren Daten zusammenstellt und in eine Datei schreibt
- Etwas, was per HA in eine Datei schreiben kann.Dafür habe ich bislang nur eine Datei-Entität mit Einsatzzweck „Benachrichtigung“ gefunden
- Ein Shell Skript, das im Dateisystem für Ordnung sorgt.
- Eine Automation, die regelmäßig einen Export anstößt
ich verwende hier <<<Zielverzeichnis für den Export>>>, dies muss für die eigene Verwendung angepasst werden
Skript: Entittäten zusammenstellen
sequence:
- variables:
entity_ids_sorted: "{{ states | map(attribute='entity_id') | list | sort }}"
- data:
entity_id: notify.entity_dump
message: >-
"entity_id";"friendly_name";"device";"domain";"area";"floor";"active";"state"
action: notify.send_message
- repeat:
count: "{{ entity_ids_sorted | count }}"
sequence:
- variables:
id: "{{ entity_ids_sorted[repeat.index-1] }}"
obj: "{{ states(id) }}"
- choose:
- conditions:
- condition: template
value_template: "{{ obj is not none }}"
sequence:
- variables:
name: "{{ obj.name | default('') }}"
dev: "{{ device_id(id) | default('') }}"
dev_name: "{{ device_name(id) or dev }}"
dom: "{{ id.split('.',1)[0] }}"
area: "{{ area_name(id) | default('') }}"
area_identifier: "{{ area_id(id) | default('') }}"
flo_id: "{{ floor_id(area_identifier) | default('') }}"
flo_name: "{{ floor_name(flo_id) | default('') }}"
aktiv: >-
{{ states(id) not in ['unavailable','unknown','none','']
}}
state: "{{ states(id) | default('') }}"
state_tr: "{{ state_translated(id) | default('') }}"
- data:
entity_id: notify.entity_dump
message: >-
"{{ id }}";"{{ name }}";"{{ dev_name }}";"{{ dom }}";"{{
area }}";"{{ flo_name }}";"{{ aktiv }}";"{{ state }}";"{{
state_tr }}"
action: notify.send_message
- action: shell_command.manage_entity_dump
data:
action: trim
- action: shell_command.manage_entity_dump
data:
action: rename
- action: shell_command.manage_entity_dump
data:
action: purge
alias: Entity Dump to File
description: ""
Datei-Entität für Benachrichtigungen
Integration File hinzufügen
Dort einen Benachrichtigungsdienst auswählen
Den Pfad inkl Dateiname zur export datei eintragen, der Dateiname, der im Shellscript verwendet wird, ist entity_dump.csv - er sollte beibehalten werden.
und es soll kein Zeitstempel geschrieben werden
anschließend die File Entität finden (sieht ähnlich aus wie im Screenshot)
und dann umbenennen wie im Screenshot, dann passt es zum HA Skript
Shell Skript für’s Dateisystem
um das Skript aus HA aufrufen zu können, muss ein shell_command definiert werden.
configuration.yaml:
shell_command: !include shell_command.yaml
shell_command.yaml:
/config/custom_scripts/entity_dump/manage_entity_dump.sh --action "{{ action }}"
Shell Script
#!/bin/bash
# === Konfiguration ===
DUMP_DIR="<<<Zielverzeichnis für den Export>>>"
BASENAME="entity_dump"
EXTENSION="csv"
DUMP_FILE="${BASENAME}.${EXTENSION}"
DUMP_PATH="${DUMP_DIR}/${DUMP_FILE}"
# === Logging ===
SCRIPT_NAME="$(basename "$0" .sh)"
LOG_FILE="${DUMP_DIR}/${SCRIPT_NAME}.log"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"
}
# === Hilfe anzeigen ===
show_help() {
echo "Usage: $SCRIPT_NAME --action [purge|trim|rename] [--dry-run]"
echo ""
echo " --action purge Löscht alle Dateien mit Präfix außer den 5 neuesten"
echo " --action trim Entfernt die ersten zwei Zeilen aus der Dump-Datei"
echo " --action rename Benennt die Dump-Datei mit Zeitstempel um"
echo " --dry-run Zeigt nur an, was passieren würde"
echo " --help Zeigt diese Hilfe"
}
# === Parameterverarbeitung ===
DRY_RUN=false
while [[ $# -gt 0 ]]; do
case "$1" in
--action)
ACTION="$2"
shift 2
;;
--dry-run)
DRY_RUN=true
shift
;;
--help)
show_help
exit 0
;;
*)
echo "❌ Unbekannter Parameter: $1"
show_help
exit 1
;;
esac
done
if [ -z "$ACTION" ]; then
echo "❌ Fehler: --action fehlt"
show_help
exit 1
fi
# === Aktionen ===
case "$ACTION" in
purge)
log "🔁 purge – Ältere Dumps löschen (nur 5 neueste behalten)"
cd "$DUMP_DIR" || { log "❌ Verzeichnis nicht gefunden: $DUMP_DIR"; exit 1; }
FILES_TO_DELETE=$(ls -t "${BASENAME}"*".${EXTENSION}" 2>/dev/null | tail -n +6)
if [ -z "$FILES_TO_DELETE" ]; then
log "ℹ️ Keine Dateien zum Löschen gefunden"
else
for file in $FILES_TO_DELETE; do
if $DRY_RUN; then
log "🧪 [dry-run] Würde löschen: $file"
else
log "🗑️ Lösche: $file"
rm -f "$file"
fi
done
fi
;;
trim)
log "✂️ trim – Entferne erste zwei Zeilen aus $DUMP_PATH"
if [ -f "$DUMP_PATH" ]; then
if $DRY_RUN; then
log "🧪 [dry-run] Würde erste zwei Zeilen aus $DUMP_PATH entfernen"
else
tail -n +3 "$DUMP_PATH" > "${DUMP_PATH}.tmp" && mv "${DUMP_PATH}.tmp" "$DUMP_PATH"
log "✅ Trim erfolgreich"
fi
else
log "❌ Datei nicht gefunden: $DUMP_PATH"
exit 1
fi
;;
rename)
TIMESTAMP=$(date -r "$DUMP_PATH" +"%Y%m%d_%H%M%S")
NEW_NAME="${DUMP_DIR}/${BASENAME}_${TIMESTAMP}.${EXTENSION}"
log "📦 rename – Benenne $DUMP_PATH → $NEW_NAME"
if [ -f "$DUMP_PATH" ]; then
if $DRY_RUN; then
log "🧪 [dry-run] Würde umbenennen: $DUMP_PATH → $NEW_NAME"
else
mv "$DUMP_PATH" "$NEW_NAME"
log "✅ Umbenennung erfolgreich"
fi
else
log "❌ Datei nicht gefunden: $DUMP_PATH"
exit 1
fi
;;
*)
echo "❌ Unbekannte Aktion: $ACTION"
show_help
exit 1
;;
esac
Automation
alias: Dump Entities to File
description: ""
triggers:
- trigger: time
at: "02:17:00"
conditions: []
actions:
- action: script.entity_dump_to_file
metadata: {}
data: {}
mode: single




