From de7ef4ac99cbbaeb5f612ed73699028e43869a19 Mon Sep 17 00:00:00 2001 From: techartdev Date: Fri, 20 Feb 2026 23:37:58 +0200 Subject: [PATCH] Update version to 0.1.41 and enhance integration with voice mode fixes, gateway connection status, and updated documentation --- CHANGELOG.md | 10 +++ README.md | 16 +++-- custom_components/openclaw/__init__.py | 8 +-- .../__pycache__/__init__.cpython-312.pyc | Bin 33773 -> 33604 bytes .../__pycache__/config_flow.cpython-312.pyc | Bin 13154 -> 17818 bytes .../__pycache__/const.cpython-312.pyc | Bin 1680 -> 3312 bytes custom_components/openclaw/config_flow.py | 9 --- custom_components/openclaw/const.py | 2 - custom_components/openclaw/manifest.json | 2 +- custom_components/openclaw/strings.json | 1 - .../openclaw/translations/en.json | 1 - .../openclaw/www/openclaw-chat-card.js | 64 ++++++++++++++---- www/openclaw-chat-card.js | 2 +- 13 files changed, 74 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0cdd6c4..4256fca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,16 @@ All notable changes to the OpenClaw Home Assistant Integration will be documented in this file. +## [0.1.41] - 2026-02-20 + +### Fixed +- Fixed voice-mode option sync so wake-word enabled/disabled changes are reloaded before toggling voice mode. +- Removed legacy always-on voice mode behavior that could force sticky voice-mode state. +- Added live gateway connection badge to the chat card header using existing OpenClaw status entities. + +### Changed +- Removed "Always-on voice mode" option from integration options UI and translations. + ## [0.1.40] - 2026-02-20 ### Added diff --git a/README.md b/README.md index df9779f..90eb7fe 100644 --- a/README.md +++ b/README.md @@ -28,15 +28,17 @@ OpenClaw is a Home Assistant custom integration that connects your HA instance t - `openclaw_message_received` - `openclaw_tool_invoked` - **Sensors / status entities** for model and connection state + - Includes tool telemetry sensors (`Last Tool`, `Last Tool Status`, `Last Tool Duration`, `Last Tool Invoked`) --- ## Requirements -- Home Assistant with Supervisor support for addon discovery +- Home Assistant Core `2025.1.0+` (declared minimum) +- Supervisor is optional (used for auto-discovery) - OpenClaw Assistant addon installed and running -The integration auto-detects the addon. You do not need to manually set an API base URL. +The integration can auto-detect the addon when Supervisor is available. You can always configure host/port/token manually. --- @@ -73,6 +75,8 @@ The integration auto-detects the addon. You do not need to manually set an API b The card is registered automatically by the integration. +The card header shows live gateway state (`Online` / `Offline`) using existing OpenClaw status entities. + ```yaml type: custom:openclaw-chat-card title: OpenClaw Chat @@ -125,7 +129,6 @@ When enabled, OpenClaw tool-call responses can execute Home Assistant services. - **Wake word enabled** - **Wake word** (default: `hey openclaw`) -- **Always voice mode** (continuous listening while card is open) - **Voice input provider** (`browser` or `assist_stt`) ### Voice provider usage @@ -138,7 +141,7 @@ When enabled, OpenClaw tool-call responses can execute Home Assistant services. - **`assist_stt`** - Uses Home Assistant STT provider via `/api/stt/`. - Intended for manual mic input (press mic, speak, auto-stop, transcribe, send). - - Continuous voice mode is not used in this provider. + - If continuous Voice Mode is enabled while this provider is selected, the card uses browser speech for continuous listening. For `assist_stt`, make sure an STT engine is configured in **Settings → Voice assistants**. @@ -291,6 +294,11 @@ action: - For `browser`: open browser console for `OpenClaw: Speech recognition error`; repeated `network` usually means browser speech backend failure - For `assist_stt`: check network calls to `/api/stt/` and verify Home Assistant Voice/STT provider is configured +### Tool sensors show `Unknown` + +- `Last Tool*` sensors stay `Unknown` until at least one `openclaw.invoke_tool` service call has executed. +- `Session Count` remains `0` if gateway policy blocks `sessions_list` for `/tools/invoke`. + ### Responses do not appear after sending - Verify `openclaw_message_received` is being fired in Developer Tools → Events diff --git a/custom_components/openclaw/__init__.py b/custom_components/openclaw/__init__.py index 27169de..bddc0d9 100644 --- a/custom_components/openclaw/__init__.py +++ b/custom_components/openclaw/__init__.py @@ -57,7 +57,6 @@ from .const import ( CONF_INCLUDE_EXPOSED_CONTEXT, CONF_WAKE_WORD, CONF_WAKE_WORD_ENABLED, - CONF_ALWAYS_VOICE_MODE, CONF_ALLOW_BRAVE_WEBSPEECH, CONF_VOICE_PROVIDER, CONTEXT_STRATEGY_TRUNCATE, @@ -67,7 +66,6 @@ from .const import ( DEFAULT_INCLUDE_EXPOSED_CONTEXT, DEFAULT_WAKE_WORD, DEFAULT_WAKE_WORD_ENABLED, - DEFAULT_ALWAYS_VOICE_MODE, DEFAULT_ALLOW_BRAVE_WEBSPEECH, DEFAULT_VOICE_PROVIDER, DOMAIN, @@ -92,7 +90,7 @@ _CARD_PATH = Path(__file__).parent / "www" / _CARD_FILENAME # URL at which the card JS is served (registered via register_static_path) _CARD_STATIC_URL = f"/openclaw/{_CARD_FILENAME}" # Versioned URL used for Lovelace resource registration to avoid stale browser cache -_CARD_URL = f"{_CARD_STATIC_URL}?v=0.1.40" +_CARD_URL = f"{_CARD_STATIC_URL}?v=0.1.41" OpenClawConfigEntry = ConfigEntry @@ -802,10 +800,6 @@ def _async_register_websocket_api(hass: HomeAssistant) -> None: DEFAULT_WAKE_WORD_ENABLED, ), CONF_WAKE_WORD: options.get(CONF_WAKE_WORD, DEFAULT_WAKE_WORD), - CONF_ALWAYS_VOICE_MODE: options.get( - CONF_ALWAYS_VOICE_MODE, - DEFAULT_ALWAYS_VOICE_MODE, - ), CONF_ALLOW_BRAVE_WEBSPEECH: options.get( CONF_ALLOW_BRAVE_WEBSPEECH, DEFAULT_ALLOW_BRAVE_WEBSPEECH, diff --git a/custom_components/openclaw/__pycache__/__init__.cpython-312.pyc b/custom_components/openclaw/__pycache__/__init__.cpython-312.pyc index 217e6120cc5856d5fe71bca9fac8f479cbd41c86..4a5a231434f381c3edcb1259652583bb1f829121 100644 GIT binary patch delta 4866 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 DC&s{z delta 3107 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 O7<+B}p9Gn;&;I~Oe~?H3 diff --git a/custom_components/openclaw/__pycache__/const.cpython-312.pyc b/custom_components/openclaw/__pycache__/const.cpython-312.pyc index 7cfc7071e377ede25f68fbc93e1d959178652c70..231a41e6ca4399339007096edd0f5cfe95585f2f 100644 GIT binary patch literal 3312 zcmZ`*%TF8I86QY^*w_Z+2R4DkfxO5~AaIi#lAD`*2YUc3#$(M4CLBdN8vLCLZj8s8 z86Y54@~-NxyGE+I>8^iBr7Lwq)s1^rk-F+G>fLqKZ_dmZ!fine-}!y7-}g8k|1}hmHMmZ$!w?yQVKNLOWCTXZ zC`3pEq9h7qWDH^?25}OH1WCX+8HWin0ZEdCNiqp3l7cizLxyA^OR_LUrXWXhkSBTk zn}%s}1OLy!4Kj=PO_(9KV3ri%Cb;3*-?zB#+@MvIvjJ(!K? zJSETJ8Ck`AFW?*U5}uQ9VU@gs7vwv5NnXRZBUet_?Y46n%=d{2t-11W(_6j&qc zP$U~rBAchm!ur|$qSba>v+X*CA1%A!9!==i%;-( zxyj0s^sk#}&13tf%TCNwdSE&3#i?W2E{}&g*Lu&|eB{Vs)Nxuod6^6CnC=0eY9jw5 zV3d96SPlb^sLMXMJQ)b|(ELCf2d3@ti4byJYyjIo?Osr_CBJ13n&h?3me}D<3}UxXnYxM?+3L5mtZFY=d>e6C#+XyltZ8#Kk$F zles|P$X^+H=v(7j#@6ZhaETB$-*@(n6(|WiSISr zrhQ6-V+<*J1&HnBNqUHVF!vd?S%Wo?vCOzXsUR(np&x`+JT96^4{&=e`;?FQR>Fgi z1fh5|>}?bHnCZG^GhhO)a!iT*+V<)eh_P)c%LcjOyl#c*%#@X`m zkRdJ@j-th*W}{)@&?trR3Wp*7jqdAtZ!pCFjuPbT1BCTs#a)Gu2l2@-;v)a zbVt=n)VC<{gb35e`LsBri@HPCG`WuE%9>tNl;S2&30+++7ZqC5)Oxw3X#7^#wEtH? zJ~RlqUeu7gs_K`~clu=|eN~@yznEkgudm{>A@sjX%7*GIRpmpnAtP#N+tniWSai~x z4DG9m6-CzgSV=Zy1Z87e=TULkQcFsOPx=Z)*UPxsMRmJs@c3m+4@@euZcw>slZ~>JIlokxHybRYu2* zu)F|+DyFZ%rET0YuZS(3=db9>)jIBciOSyX@|a#kQ#4K0a1vjlnxcF6vZg8Zva-V? zwTf)4s~U#RDs{ZobPGEsZzy<|i%PkU9hmfSK|4st(>h*KZy|N1S_)lwCPc+(=w?|r zRBe~1LfH2f_k+h|!_fMk;?=<+AhT%!%w(Ne7wt!3sB)cFS#hzha#^LVWz$b^7!4v zk5A9pZ@AC=^30-gtxUyI>X-&)jBemYZq+J^N7EyRsMlZ}KmWXe{#p9j`x5(~yNmA{ zNBAN-#4jX=9jooVW8Q^d0N&wy&T$tzr+oAkz5tF|?6v({^ulkwlJggQe!ey^Fz^rQ z@ux_tJN$WAO5E#4KaWb;d*{+*Z|cRllnS zxQkf>*+={=1;l52dCZvoG=ui}UcTTb8=vZq_2TJnG+;6@-HivL$Tao9W1h&Ol~9SC ze&&Fj&t+!Ci|Sh!UShU?4@>dYZUpO@o&UIcKL7MQ{|r<1ayNhX;p4B*Gmo)uuRq8J zJ9FPFGmCvmAvTf6ZcN_nj`vc?a>A!4*u*Bg5uc2Ze6?tvpIJCX6WtNtNYo{aKF6fQ VG!{99Y16&b+~1@L`!_hw{{pZJT>St5 delta 343 zcmew$If0k&G%qg~0}zNw&B*L#o5&}@w1{D%Mv7B9LyE*A#wdwY#@P%hl5?4&BvYiK zq*A1#q*G*~WKv|KWK-m#Bihm$LdwhR+~B{NhN? z&nqs`E2zB1VUwGmQks)$SL6n1E8AOU)fffM(Bc);h diff --git a/custom_components/openclaw/config_flow.py b/custom_components/openclaw/config_flow.py index 6062c30..0c17b31 100644 --- a/custom_components/openclaw/config_flow.py +++ b/custom_components/openclaw/config_flow.py @@ -44,7 +44,6 @@ from .const import ( CONF_INCLUDE_EXPOSED_CONTEXT, CONF_WAKE_WORD, CONF_WAKE_WORD_ENABLED, - CONF_ALWAYS_VOICE_MODE, CONF_ALLOW_BRAVE_WEBSPEECH, CONF_VOICE_PROVIDER, CONTEXT_STRATEGY_CLEAR, @@ -57,7 +56,6 @@ from .const import ( DEFAULT_INCLUDE_EXPOSED_CONTEXT, DEFAULT_WAKE_WORD, DEFAULT_WAKE_WORD_ENABLED, - DEFAULT_ALWAYS_VOICE_MODE, DEFAULT_ALLOW_BRAVE_WEBSPEECH, DEFAULT_VOICE_PROVIDER, DOMAIN, @@ -462,13 +460,6 @@ class OpenClawOptionsFlow(OptionsFlow): DEFAULT_WAKE_WORD, ), ): str, - vol.Optional( - CONF_ALWAYS_VOICE_MODE, - default=options.get( - CONF_ALWAYS_VOICE_MODE, - DEFAULT_ALWAYS_VOICE_MODE, - ), - ): bool, vol.Optional( CONF_ALLOW_BRAVE_WEBSPEECH, default=options.get( diff --git a/custom_components/openclaw/const.py b/custom_components/openclaw/const.py index f71d5a5..b92b1b1 100644 --- a/custom_components/openclaw/const.py +++ b/custom_components/openclaw/const.py @@ -30,7 +30,6 @@ CONF_CONTEXT_STRATEGY = "context_strategy" CONF_ENABLE_TOOL_CALLS = "enable_tool_calls" CONF_WAKE_WORD_ENABLED = "wake_word_enabled" CONF_WAKE_WORD = "wake_word" -CONF_ALWAYS_VOICE_MODE = "always_voice_mode" CONF_ALLOW_BRAVE_WEBSPEECH = "allow_brave_webspeech" CONF_VOICE_PROVIDER = "voice_provider" @@ -40,7 +39,6 @@ DEFAULT_CONTEXT_STRATEGY = "truncate" DEFAULT_ENABLE_TOOL_CALLS = False DEFAULT_WAKE_WORD_ENABLED = False DEFAULT_WAKE_WORD = "hey openclaw" -DEFAULT_ALWAYS_VOICE_MODE = False DEFAULT_ALLOW_BRAVE_WEBSPEECH = False DEFAULT_VOICE_PROVIDER = "browser" diff --git a/custom_components/openclaw/manifest.json b/custom_components/openclaw/manifest.json index 2257a49..df68a06 100644 --- a/custom_components/openclaw/manifest.json +++ b/custom_components/openclaw/manifest.json @@ -8,7 +8,7 @@ "iot_class": "local_polling", "issue_tracker": "https://github.com/techartdev/OpenClawHomeAssistant/issues", "requirements": [], - "version": "0.1.40", + "version": "0.1.41", "dependencies": ["conversation"], "after_dependencies": ["hassio", "lovelace"] } diff --git a/custom_components/openclaw/strings.json b/custom_components/openclaw/strings.json index acc7940..dab5a33 100644 --- a/custom_components/openclaw/strings.json +++ b/custom_components/openclaw/strings.json @@ -43,7 +43,6 @@ "enable_tool_calls": "Enable tool calls (execute services)", "wake_word_enabled": "Require wake word", "wake_word": "Wake word", - "always_voice_mode": "Always-on voice mode", "allow_brave_webspeech": "Allow Web Speech in Brave (experimental)", "voice_provider": "Voice input provider (browser or HA STT)" } diff --git a/custom_components/openclaw/translations/en.json b/custom_components/openclaw/translations/en.json index acc7940..dab5a33 100644 --- a/custom_components/openclaw/translations/en.json +++ b/custom_components/openclaw/translations/en.json @@ -43,7 +43,6 @@ "enable_tool_calls": "Enable tool calls (execute services)", "wake_word_enabled": "Require wake word", "wake_word": "Wake word", - "always_voice_mode": "Always-on voice mode", "allow_brave_webspeech": "Allow Web Speech in Brave (experimental)", "voice_provider": "Voice input provider (browser or HA STT)" } diff --git a/custom_components/openclaw/www/openclaw-chat-card.js b/custom_components/openclaw/www/openclaw-chat-card.js index 0d76cab..8c26ce1 100644 --- a/custom_components/openclaw/www/openclaw-chat-card.js +++ b/custom_components/openclaw/www/openclaw-chat-card.js @@ -13,7 +13,7 @@ * + subscribes to openclaw_message_received events. */ -const CARD_VERSION = "0.3.4"; +const CARD_VERSION = "0.3.5"; // Max time (ms) to show the thinking indicator before falling back to an error const THINKING_TIMEOUT_MS = 120_000; @@ -62,7 +62,6 @@ class OpenClawChatCard extends HTMLElement { this._historySyncRetryTimer = null; this._wakeWordEnabled = false; this._wakeWord = "hey openclaw"; - this._alwaysVoiceMode = false; this._voiceStatus = ""; this._voiceRetryTimer = null; this._voiceRetryCount = 0; @@ -123,8 +122,24 @@ class OpenClawChatCard extends HTMLElement { this._subscribeToEvents(); this._syncHistoryFromBackend(); this._loadIntegrationSettings(); - this._render(); } + this._render(); + } + + _getGatewayConnectionState() { + const statusEntity = this._hass?.states?.["sensor.openclaw_status"]; + const binaryEntity = this._hass?.states?.["binary_sensor.openclaw_connected"]; + const status = String(statusEntity?.state || "").toLowerCase(); + const connected = String(binaryEntity?.state || "").toLowerCase() === "on"; + + if (connected || status === "online") { + return { label: "Online", css: "online" }; + } + if (status === "offline" || String(binaryEntity?.state || "").toLowerCase() === "off") { + return { label: "Offline", css: "offline" }; + } + + return { label: "Unknown", css: "unknown" }; } getCardSize() { @@ -321,7 +336,7 @@ class OpenClawChatCard extends HTMLElement { } } - async _loadIntegrationSettings() { + async _loadIntegrationSettings(includePipeline = true) { if (!this._hass) return; try { @@ -336,7 +351,6 @@ class OpenClawChatCard extends HTMLElement { this._wakeWordEnabled = !!result?.wake_word_enabled; this._wakeWord = (result?.wake_word || "hey openclaw").toString().trim().toLowerCase(); - this._alwaysVoiceMode = !!result?.always_voice_mode; this._allowBraveWebSpeechIntegration = !!result?.allow_brave_webspeech; this._voiceProviderIntegration = result?.voice_provider === "assist_stt" ? "assist_stt" : "browser"; @@ -344,7 +358,8 @@ class OpenClawChatCard extends HTMLElement { ? this._normalizeSpeechLanguage(result.language) : null; - try { + if (includePipeline) { + try { let pipelineResult; if (typeof this._hass.callWS === "function") { pipelineResult = await this._hass.callWS({ type: "assist_pipeline/pipeline/list" }); @@ -372,13 +387,9 @@ class OpenClawChatCard extends HTMLElement { if (ttsLanguage) { this._integrationTtsLanguage = this._normalizeSpeechLanguage(ttsLanguage); } - } catch (pipelineErr) { - console.debug("OpenClaw: assist pipeline language detection skipped:", pipelineErr); - } - - if (this._alwaysVoiceMode && !this._isVoiceMode) { - this._isVoiceMode = true; - this._startVoiceRecognition(); + } catch (pipelineErr) { + console.debug("OpenClaw: assist pipeline language detection skipped:", pipelineErr); + } } this._render(); } catch (err) { @@ -1162,7 +1173,8 @@ class OpenClawChatCard extends HTMLElement { }, delayMs); } - _toggleVoiceMode() { + async _toggleVoiceMode() { + await this._loadIntegrationSettings(false); this._isVoiceMode = !this._isVoiceMode; if (this._isVoiceMode) { this._startVoiceRecognition(); @@ -1303,6 +1315,7 @@ class OpenClawChatCard extends HTMLElement { .join(""); const voiceActive = this._recognition !== null; + const gatewayState = this._getGatewayConnectionState(); this.shadowRoot.innerHTML = `