BETA-Tester: ESC Einfach und schnell Sensoren und Auswertungen erstellen -ohne Vorkenntnisse

Hey Bernd,

ich verstehe, was du meinst, aber die Sache ist in der Praxis leider etwas komplizierter. Du hast einen Fehler in deiner Annahme, dass alle Werte den gleichen Weg durch die Datenbank nehmen.

Nicht alle Sensordaten landen in der statistics_short_term Tabelle! Da liegen in der Regel nur hochaufgelöste Energie- (total_increasing) und Leistungssensoren. Andere Sensoren, die zum Beispiel Einheiten wie °C, W/m² oder km/h ausgeben, werden stündlich aggregiert und landen direkt in der langfristigen statistics Tabelle.

Genau das ist das Problem, das ich seit Stunden zu lösen versuche: Ich muss mein Skript intelligent machen, damit es basierend auf dem Sensortyp entscheidet, ob es in der Short-Term- oder der Long-Term-Tabelle nach den Daten suchen muss. Das perfekte Beispiel ist der Unterschied zwischen Temperatur und Watt.

Und da kommt dann eben das Problem zum Tragen, dass bei einem recorder.purge unter bestimmten Umständen eben doch auch Daten aus der statistics Tabelle beeinflusst oder gelöscht werden können, was die Sache noch fragiler macht.

Ich glaube, wir können uns darauf einigen, dass die Struktur im Laufe der Jahre immer “wilder” und komplexer geworden ist und es nicht die eine, einfache Lösung gibt. Hinzu kommt noch, dass die Spaltennamen in MariaDB (die dem SQL-Standard folgen) und die internen Bezeichner in Home Assistant nicht übereinstimmen, was beim direkten Datenbankzugriff ein einziger Kampf ist.

Wenn du möchtest, kann ich dir den Code gern schicken, dann kannst du es selber probieren. Es ist wirklich nicht trivial.

Nein das ist nicht korrekt. Wie die Daten in der db behandelt werden hängt nicht von der Device Class und der Einheit ab. Sondern von der State Class. Nur Sensoren mit Angabe der State Class wandern in die Langzeit Statistik.

DIe Daten sind ja alle da, lassen sich ja uch über den Dienst recorder.get_statistics auwerten, auch die aus der Langzeit Statistik.

recorder.get_statistics

Gruß Osorkon

Ich gehe nun über die API… das sollte den ganzen Trouble umgehen

STRIKE… das war die Lösung… ich muss es nur noch finalisieren aber es lässt sich gut an

@bbernhard @Osorkon @dp20eic

Moin zusammen,

ich dachte, ich teile mal die ungeschönte Wahrheit hinter dem, was es bedeutet, eine “funktionierende” Home Assistant Integration in etwas wirklich Stabiles zu verwandeln. Ich habe die letzten Stunden damit verbracht, meine “ESC Easy Sensor Creation”-Integration von Grund auf zu sanieren, und dabei einige Lektionen auf die harte Tour gelernt. Vielleicht bewahrt das ja den einen oder anderen vor den gleichen Fehlern.

Ausgangslage: Lief, aber irgendwie… falsch.

Meine Integration hatte drei Features: Einen Summen-Sensor, einen Statistik-Sensor und einen selbstgestrickten kWh-Sensor. Auf den ersten Blick tat alles, was es sollte. Aber unter der Haube war es Murks.

  1. Das Rad neu erfunden: Mein ganzer Stolz, ein eigener Riemann-Sensor für die kWh-Berechnung. Spoiler: War eine dumme Idee.
  2. Geräte-Chaos: Jeder Sensor, den man erstellte, hat sich als eigenes Gerät in HA registriert. 10 Sensoren = 10 neue Geräte, die alles zumüllen.
  3. Peinlicher Git-Fail: Dazu komme ich später…

Lektion 1: Begrab dein Ego und lass den HA-Core die Arbeit machen.

Mein eigener kWh-Sensor war mein Baby. Ich hab ihn Zeile für Zeile geschrieben, er hat den Recorder gepollt und irgendwie kWh ausgespuckt. Aber ehrlich gesagt war er langsam, ungenau und ein Wartungsalbtraum.

Die Lösung war brutal, aber richtig: Ich habe die komplette Klasse ESCKwhIntegrationSensor gelöscht. Weg damit. Stattdessen ruft der config_flow jetzt einfach den nativen integration-Helfer von Home Assistant auf.

Der Code dafür ist lächerlich einfach:

`Python# Im Config Flow…
await self.hass.config_entries.flow.async_init(
“integration”,
context={“source”: “user”},
data={
“name”: “Name des neuen Sensors”,
“source”: “sensor.mein_power_sensor”,
# …und der Rest der Config
},
)

Eigenen Flow abbrechen, fertig.

return self.async_abort(reason=“kwh_helper_created”)`

Die Verantwortung liegt jetzt zu 100% beim HA-Core. Stabiler, schneller, zukunftssicher. Manchmal ist der beste Code der, den man löscht.

Lektion 2: Ein Gerät, sie alle zu knechten.

Kennt ihr das? Man will nur schnell ein paar Sensoren hinzufügen und hat plötzlich eine überflutete Geräteliste. Genau das hat meine Integration gemacht.

Der Fix war zum Glück einfacher als gedacht:

  1. In __init__.py: Ich erstelle jetzt EIN einziges Gerät für die ganze Integration. Der Trick ist ein statischer Identifier, der nicht von der ConfigEntry abhängt.Python# identifiers ist jetzt immer gleich device_registry.async_get_or_create( identifiers={(DOMAIN, DOMAIN)}, name="ESC Easy Sensor Creation", ... )
  2. In sensor.py: Jede Entität, die ich erstelle, verweist auf genau diesen statischen Identifier.Pythonself._attr_device_info = { "identifiers": {(DOMAIN, DOMAIN)}, }Das Ergebnis ist so viel sauberer. Ein Gerät, unter dem alle meine erstellten Sensoren als Entitäten hängen. So wie es sein soll.

Lektion 3: PRÜFT EURE GIT CONFIG, BEVOR IHR PUSHED!

Und dann kam der peinlichste Teil. Alles fertig, Code sauber, bereit für den Release-Candidate. Ich pushe den Commit, erstelle den Release und sehe es: Alles verschachtelt und wirr… Die Reparatur war ein Ritt durch die Hölle (ich weiß schon warum sonst nie auf GitHub veröffentliche)

Bonus-Tipp: Wenn ihr ein Skript in die zsh auf dem Mac kopiert, passt auf das #! am Anfang auf. Die Shell hält das für einen History-Befehl und wirft einen “event not found”-Fehler. Hat mich auch noch mal 10 Minuten gekostet.

TL;DR

  • Wirf deinen eigenen Code weg, wenn der HA-Core eine native Funktion dafür hat.
  • Ein Gerät pro Integration, nicht pro Sensor. Deine Nutzer werden es dir danken.
  • Prüf deine verdammte git config, bevor du einen öffentlichen Commit machst.

War ein langer Weg, aber die Integration ist jetzt um Welten besser. Hoffe, das hilft jemandem.

Viel Spaß beim Testen… und nochmals vielen Dank (besonders für den Hinweis mit den Geräten)

Zara,

What`s next release…

  • Experten-Modus um SQL-Befehle anhand der Meta_ID Werte auszuführen und in einen Sensor zu überführen ( Jahresvergleiche, Langzeit-Statistiken VOR Erstellung eines Senors und unabhängig von PURGE)
  • Merge via SQL um Daten eines alten Sensors einem neuen zuzuweisen,
  • Datenbank Dumps
  • Import von alten Sensoren mit unterschiedlicher ID
2 „Gefällt mir“

Respekt für Deinen Einsatz! :saluting_face:
Hast wohl die Nacht durchgeschafft. :scream:

Werde mal im laufe des Tages testen und berichten.

Edit: Das sieht schon mal besser aus. :grin:

Obwohl jetzt nur noch ein Gerät erstellt wird, gibt es in der Geräteübersicht trotzdem für jeden Sensor einen Eintrag.

Ich fände es immer noch gut, wenn man den Sensor einem bestehenden Gerät zuordnen könnte, wie es bei den Helfern der Fall ist.

Danke & Gruß
Osorkon

1 „Gefällt mir“

Pfoah, ich kämpf die halbe Nacht mit ein paar läpigen Plotly Konfigurationen und du haust sowas raus.
bb

1 „Gefällt mir“

Ich verstehe Deinen Punkt, aber das ist eine Restriktion, die ich leider nicht umgehen kann :frowning: Aber Du hast zumindest schon einmal deine Klassen :slight_smile: und auch kannst Du alle Sensoren auf einmal sehen, wenn du einen von Ihnen öffnest :slight_smile:

Vor 2 Stunden haben 4 von 5 Sensoren die Einheit verloren?

Was dementsprechend zur dieser Reparatur Meldungen führt.

Des Weiteren wird bei jedem neuen Sensor, hier ein zusätzlicher Eintrag erzeugt.

Jeder davon navigiert zum gleichen Ziel.

Besser wäre es umgesetzt, wenn man es Entitäten und nicht Geräte benennt, wie bei Deiner Solar Forecast ML Integration der Fall ist.

So:

Und nicht so:

Hier hätte ich anstatt 1 Gerät, 5 Entitäten erwartet.

Gruß Osorkon

Hat sonst keiner der Beta Tester das Problem, dass die Einheit der Sensoren mit der Zeit verschwindet? Wenn ich neue erstelle, kommen diese mit der Einheit. Betrifft auch nicht alle sind 4 von 5.

Gruß Osorkon

1 „Gefällt mir“

Ich habe es bereits auf die To-do. Liste genommen wird mit dem nächsten Update gefixt.

1 „Gefällt mir“

@Osorkon @bbernhard @dp20eic

Hallo Community,

die RC6 von ESC Easy Sensor Creation ist nun verfügbar. Basierend auf eurem Feedback wurden mehrere neue Sensor-Typen hinzugefügt und Stabilitätsprobleme behoben. Die Integration bleibt vollständig HA-Best-Practice-konform und erfordert keine YAML-Konfiguration.

Neue Features in RC6

Der Konfigurationsflow wurde erweitert, um weitere Use-Cases abzudecken:

  • Delta-Sensor: Vergleicht historische Mittelwerte (z. B. heute vs. gestern oder Monat vs. Vormonat) über die HA-Stats-API. Dynamische Perioden (stündlich/täglich) und Behandlung fehlender Daten (Status “waiting for history” statt 0).
  • Battery Charge/Discharge-Sensor: Filtert Power-Sensoren auf positive Werte (Ladung, z. B. PV) oder absolute Negative (Entladung, z. B. Akku). Erstellt einen dedizierten W-Sensor und einen Riemann-kWh-Helper für die Energy Dashboard.
  • Binary Threshold-Sensor: Event-gesteuerter On/Off-Sensor bei Überschreitung einer Schwelle (z. B. Temperatur > 25 °C). Unterstützt Device-Classes für Icons und Automations.
  • Toggle Switch: Virtueller Schalter zum Pausieren oder Zurücksetzen verknüpfter Sensoren, mit optimistischen Updates und Attribut-Synchronisation.

Alle neuen Entitäten werden dem zentralen ESC-Gerät zugeordnet. Der Flow ist nun multilingual (Deutsch/Englisch).

Wichtige Fixes

Folgende Probleme wurden behoben:

  • Unit-Verlust in Sensoren: Sensoren behalten nun Einheiten (z. B. °C, W) persistent durch Caching, Quellen-Updates und Fallbacks aus der Device-Class. Dies sorgt für korrekte Anzeige in UI und Charts.
  • Delta-Sensor zeigt immer 0: Verbesserte Stats-Abfrage mit Long-Term-Fallback, Debug-Logs und None-Zustand bei fehlenden Daten.
  • Fehler im Battery-Flow: NameError (z. B. DEVICE_CLASS_POWER) behoben durch robuste Imports und Konfigurations-Handling.
  • Allgemein: Erweiterte Logs, Status-Attribute (z. B. “data_status: waiting_for_history”) und Validierungen für bessere Fehlersuche.

Update und Test

Feedback zu Stabilität oder Verbesserungsvorschlägen (z. B. weitere Threshold-Optionen) bitte in den GitHub-Issues oder diesem Thread. Ziel ist ein stabiles Final-Release.

Vielen Dank für eure Unterstützung.

Zara

1 „Gefällt mir“

Easy Sensor Creation – Delta-Stats mit Long-Term-Fallback, Battery-Filtering & Unit-Caching (Nerd-Edition)

Hallo HA-Nerds,

RC6 ist live – und ja, ich hab wieder tief in die Recorder-API und Entity-Registry gegraben, um eure Lieblings-Macke (der ewige 0 in Stats) zu killen. Kein Over-Engineering, aber genug um eure Debugger-Herzen höher schlagen zu lassen. Fokus: Was neu, was gefixt – alles async-safe und Best-Practice-konform (keine raw SQL, nur HA’s Executor-Jobs).

Was neu? (Code-Highlights)

  • DeltaSensor: Jetzt mit dynamischer Perioden-Auswahl ("hour" für today-vs-yesterday, "day" für Monats-Diffs via statistics_during_period). Berechnet current_mean - prev_mean aus short/long-term Buckets – und bei empty stats.get(entity_id, []): Graceful None + Extra-Attr "data_status": "waiting_for_history". Kein round(0, 2) mehr, der euch nachts wach hält. Debug-Logs wie f"Delta current_mean: {mean} (values: {len(values)})" für eure Log-Dives.

  • BatteryWSensor: Filtert im _async_update_state: max(0, value) für Charge oder max(0, -value) für Discharge. Baut 'nen SensorStateClass.MEASUREMENT mit Event-Tracking (async_track_state_change_event), plus Riemann-Helper-Init im Flow ("method": "left", "state_class": "total_increasing"). Perfekt für Energy-Dashboard, wo Negative-Werte sonst die Integration killen.

  • BinaryThresholdSensor: Callback-basiert (_handle_state_change), checkt float(state) > threshold und setzt _attr_is_on. Erbt von BinarySensorEntity mit device_class: PROBLEM – ready für automation Triggers ohne Polling-Overhead.

  • ToggleSwitch: async_turn_on/off mit hass.states.async_set(target, state, {"esc_paused": True/False}) – optimistic, also UI-Update vor Confirm. Sync via async_update aus Target-Attrs.

Flow-Erweiterung: Neue Branches (z.B. async_step_battery_mode mit Select-Options), multilingual via de/en.json.

Was gefixt? (Die Pain-Points)

  • Unit-Loss (der Klassiker): ESCBaseSensor cached jetzt _cached_unit aus primary Source-Attr oder DEVICE_CLASS_TO_UNIT (z.B. 'power': 'W'). update_unit_from_sources(units: set) refreshed dynamisch, setzt native_unit_of_measurement + suggested_unit_of_measurement – persistent über Restarts dank _attr_has_entity_name = True. Kein “9.35” ohne Kontext mehr; Charts atmen auf.

  • Delta immer 0: Früher: Empty Values → mean([]) = 0. Jetzt: if not values: current_mean = None, plus Fallback zu Long-Term für Monate (nie purgen). Logs zeigen Counts – debuggt sich selbst.

  • Battery-Flow-NameError: from .const import ... DEVICE_CLASS_POWER – trivial, aber killte den Wizard. Robustified mit get("key", default) überall.

  • Sonstiges: Mehr try/except in Executor-Jobs, Extra-Attrs für Errors/Status, und available = False bei Mix-Units in Sum. Weniger Logs-Spam, mehr Insights.

Update & Debug

Feedback willkommen: Welcher Fix hat euch am meisten gefreut? Oder 'n Edge-Case, den ich übersehe (z.B. Unit-Conversion W→kW)? Issues oder hier – auf zu RC7?

Grüße,
Zara

1 „Gefällt mir“

Klasse Arbeit! Das habe ich auch gerade gesucht.

Was mir fehlt wäre ein Differenzsensor.

Beispiel hierfür:

Gesamtwasserverbrauch des Hauses - Gartenwasserverbrauch

Ich hätte sonst keine andere Möglichkeit den eigentlichen Wasserverbrauch ins Energiedashboard zu bekommen

Gute idee.. nehme ich mit auf für die nächste Version

1 „Gefällt mir“