Releases: SkyTechNerds/ha-soft-presence
2026.6.22.3 — light-on no longer holds an empty room + translations
Fixed
-
A light left on no longer keeps an empty room OCCUPIED (feedback loop).
WEIGHT_LIGHT_MANUALwas20, exactly equal toDEFAULT_CLEAR_THRESHOLD,
so a manually-on light pinned the score at the clear threshold and the room
never cleared (reason: "Light on"). With lighting automations driven by
*_presence_soft, that caused: light on → room "occupied" → automation keeps
the light on → never clears; and a manual light-off was switched back on
shortly after. Lowered to10(below the clear threshold) — a lit light is
still a weak hint but can no longer hold a room on its own. Real presence
(mmWave/PIR/BLE) is unaffected. -
Translations for the new config options (all locales). The entry-gate
field (require_door_entry) and the Direct-HTTP provider fields
(llm_provider,llm_base_url,llm_api_key,llm_model) were English-only
(the locale files predated those features). German got full labels +
descriptions; bg/es/fr/it/nl/pl/pt/ru/sv got the new field labels in the
config and options flows.
Full changelog: https://github.com/SkyTechNerds/ha-soft-presence/blob/main/CHANGELOG.md
2026.6.22.1 — slugify: German umlaut transliteration
🐛 Fix — readable entity IDs for rooms with umlauts
slugify replaced every non-ASCII char with _, producing ugly IDs like
binary_sensor.k_che_presence_soft (Küche) and g_stezimmer_presence_soft
(Gästezimmer). Now German umlauts/eszett are transliterated before the
ASCII strip: ä→ae, ö→oe, ü→ue, ß→ss.
- „Küche" →
kueche - „Gästezimmer" →
gaestezimmer - Rooms without umlauts unchanged.
Per-entity unique_id is entry_id-based, so existing installs are unaffected
until their entity_id is renamed in the entity registry.
2026.6.22 — entry-gate: never suppress proven presence
🐛 Fix — entry-gate no longer suppresses real presence
The entry-gate (2026.6.19) blocked occupancy until a door-open was captured since the last CLEAR — trusting that every door-open is recorded. Two real situations broke that:
- a contact misses an open (Zigbee glitch), or
- the door is left open to air the room and the occupant walks in and closes it behind them → only a close-event fires.
In both cases a genuinely present occupant was suppressed. Observed live: an office showed CLEAR for ~83 min while BLE placed the phone in the room and mmWave fired continuously.
_entry_gate_blocks() now has two exemptions beyond "entry captured":
- Door currently open → free access, the gate stands down.
- Strong presence signal active — BLE device located in the room, or person-count > 0 — positive proof of presence, never suppressed.
Only ambiguous motion (PIR/mmWave) with a closed, never-opened door is still gated, preserving the anti-false-positive value for noisy motion sensors.
No config change — the gated rooms keep require_door_entry.
2026.6.19 — MiniMax HTTP provider + door entry-gate
HACS update bundling everything since 2026.5.22 (the 2026.5.23, 2026.6.17 and 2026.6.18 changes ship here too — no separate releases were cut).
✨ Direct HTTP AI provider (MiniMax & any OpenAI-compatible API)
The LLM advisory can now call an OpenAI-compatible /chat/completions endpoint directly — no Home Assistant conversation agent required. Per-room Provider toggle (HA conversation agent or Direct HTTP) plus base URL / key / model (defaults https://api.minimax.io/v1, MiniMax-M3). Enables flat-rate / prompt-quota backends as a drop-in when a per-token agent (e.g. Gemini) hits a spending cap. Rooms sharing a backend still batch into one call; reasoning-model output (<think> blocks, ```json fences) is parsed correctly.
🚪 Door entry-gate (opt-in per room)
Mirror image of the door-closed lock-in: for a room with door contacts, presence may only mark it OCCUPIED if a door has opened since the room was last CLEAR. A closed door that never opened proves nobody entered → false PIR/mmWave triggers are rejected. Opt-in (require_door_entry, default off), fail-open at startup, never releases an already-occupied room.
🐛 Fixes
- LLM advisory froze after ~30 events (event-counter saturation) — now uses a monotonic counter.
- Restart/reconnect no longer fakes events — transitions out of
unavailable/unknown(entity coming back online) are ignored, so a restored door reportingonis not logged as "door opened" (which had reset the lock-in / started a false score decay / would lift the entry-gate). - Diagnostics, repair issues, config-entry
unique_id, brand icon (from earlier unreleased versions).
Full details in CHANGELOG.md.
2026.6.17 — LLM advisory fix + quality-scale rollup
HACS update bundling everything since 2026.5.22 (the 2026.5.23 changes were never published as a release, so they ship here too).
🐛 Fixed — LLM advisory froze after ~30 sensor events
needs_llm_update() detected new activity by comparing len(self._event_log) against the count stored at the last LLM call — but _event_log is capped at 30. Once a room logged 30 events its length saturated at 30, so the check became 30 > 30 == False permanently: the room was never again included in a batch LLM call and its four AI entities froze at their last value. No call was attempted, so nothing appeared in the log — the failure was invisible.
Fix: a monotonic _event_total counter (never reset, never capped) is now used for the "new events" comparison, so the AI advisory keeps updating for the life of the integration.
Existing setups recover immediately after the HACS update + HA restart.
✨ Added (rolled up from 2026.5.23)
diagnostics.py— Download Diagnostics button on the integration device page (redacted config, coordinator output, internal lock-in / clear-pending state, event log, and the new LLM gating countersevent_total/llm_last_event_count/llm_last_called).- Repair Issues — three actionable warnings in Settings → System → Repairs: no presence sensors,
has_doorwithout a door contact, and missing/renamed entities. - Config-entry
unique_id— set to the room slug; prevents duplicate room entries.
Full details in CHANGELOG.md.
2026.5.22
Fixed
- Icon now displayed in HACS overview and HA update view. The
brand/folder was missingicon@2x.png(512×512). Since HA 2026.3, custom integrations serve brand images directly from their ownbrand/folder — no external brands-repo PR needed. Addedicon@2x.pngvia LANCZOS upscale.
Full Changelog: 2026.5.21...2026.5.22
2026.5.21
Fixed
- Door-closed lock-in no longer fast-clears the room.
_effective_clear_timeouthad inverted semantics — sitting still at a desk with the door closed would clear the room after 30 s. Now extended to a 4 h sanity cap when lock-in is armed.
Changed
- Replaced the brittle "door never opened since OCCUPIED" check with a solid-streak flag (
_has_been_solid). The flag is armed once the room has been continuously above the occupied threshold AND all doors closed forDOOR_LOCK_SOLID_DURATIONseconds (default 120 s). A score dip with doors still closed no longer drops the flag — that is exactly the situation lock-in is meant to bridge. A door-open event or the OCCUPIED → CLEAR transition resets it. - A brief visit by another person (door opens, visitor talks, leaves, door closes) now correctly re-engages lock-in once the streak rebuilds (~2 min after the door closes again), instead of permanently disabling it for the rest of the session.
- When lock-in is armed AND every configured door is currently closed, the no-presence timeout is extended to 4 h (
DEFAULT_DOOR_LOCKED_IN_TIMEOUT) as a sanity cap against a stuck door sensor. - Renamed constant
DEFAULT_DOOR_VALIDATED_TIMEOUT→DEFAULT_DOOR_LOCKED_IN_TIMEOUT. New constantDOOR_LOCK_SOLID_DURATION.
Added
.gitignorecovering__pycache__/.
Full Changelog: 2026.4.28...2026.5.21