feat: custom node labels with HA name sync#413
feat: custom node labels with HA name sync#413markvp wants to merge 19 commits intomatter-js:mainfrom
Conversation
Add ability for users to assign custom labels to nodes, stored server-side in persistent storage. This addresses the difficulty of identifying multiple identical devices (e.g. dozen "GRILLPLATS plug") in the dashboard. - New `set_custom_node_label` WebSocket command - Labels stored in ConfigStorage `node-labels` context, persisted across restarts - Dashboard: pencil edit button on node details, labels shown in node list and network views - `getDeviceName()` priority: customLabel > nodeLabel > productName - ws-client: `MatterNode.customLabel` getter and `setCustomNodeLabel()` method - Unit tests (ws-client) and integration tests for the new command Closes matter-js#409 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add server-side plumbing for syncing device names between matterjs-server and Home Assistant. Auto-detects HA add-on environment via SUPERVISOR_TOKEN, with manual URL+token config for standalone installs. New WS commands: - set_ha_credentials: store HA URL + long-lived access token - sync_ha_names: pull device names from HA device registry → custom labels - push_node_label_to_ha: push a node's custom label to HA device registry Also adds: - HomeAssistantClient: stateless HTTP client for HA REST API - Device matching via HA identifier format (deviceid_<fabric>-<node>-<endpoint>) - ha_url_set field on ServerInfoMessage for dashboard awareness - Unit tests for device matching (7) and WS commands (3) Dashboard UI for triggering sync will be a separate commit. Refs matter-js#409 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Settings gear now opens a menu with "Log Level" and "Home Assistant" options - HA integration dialog: configure URL + token, sync names from HA - After editing a node label, prompts "Also update in Home Assistant?" if HA is configured - Server details shows HA integration status New files: - ha-integration-dialog.ts: credentials form + sync button - settings-menu-dialog.ts: replaces direct log-level launch with menu - show-ha-integration-dialog.ts, show-settings-menu-dialog.ts: show functions Refs matter-js#409 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds server-backed custom node labels and Home Assistant name synchronization, with dashboard UI to edit labels and manage HA integration.
Changes:
- Introduces
custom_labelsupport across ws-controller/ws-client, plus a WS command to persistently set/clear labels. - Adds a
HomeAssistantClientand WS commands to configure HA credentials, sync names from HA, and push label updates back to HA. - Updates dashboard UI to edit node labels inline and configure HA integration via a new settings menu/dialogs.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/ws-controller/src/types/WebSocketMessageTypes.ts | Extends WS types with custom_label, HA commands, and ha_url_set server info flag |
| packages/ws-controller/src/server/WebSocketControllerHandler.ts | Implements new WS commands, persistence hookup, HA sync/push logic, and node detail augmentation |
| packages/ws-controller/src/server/HomeAssistantClient.ts | Adds HA REST client and device-registry matching utility |
| packages/ws-controller/src/server/ConfigStorage.ts | Persists HA credentials and custom node labels (new storage context) |
| packages/ws-controller/src/index.ts | Exports HomeAssistantClient from ws-controller package |
| packages/ws-client/test/WsClientTest.ts | Adds ws-client tests for new commands and custom_label model behavior |
| packages/ws-client/src/models/node.ts | Adds custom_label field and customLabel getter |
| packages/ws-client/src/models/model.ts | Adds new APICommands and ha_url_set to ws-client types |
| packages/ws-client/src/client.ts | Adds ws-client methods for label set/clear + HA credentials/sync/push commands |
| packages/matter-server/test/IntegrationTest.ts | Adds integration coverage for label set/clear and propagation in events/responses |
| packages/matter-server/test/HomeAssistantClientTest.ts | Adds unit coverage for HA device→node matching logic |
| packages/dashboard/src/pages/network/network-utils.ts | Uses custom label as highest priority name in UI |
| packages/dashboard/src/pages/matter-server-view.ts | Displays customLabel alongside nodeLabel/vendor/product in list |
| packages/dashboard/src/pages/components/server-details.ts | Shows HA integration configured status |
| packages/dashboard/src/pages/components/node-details.ts | Adds label edit UX and optional push-to-HA prompt |
| packages/dashboard/src/pages/components/header.ts | Routes settings gear to new settings menu |
| packages/dashboard/src/components/dialogs/settings/show-settings-menu-dialog.ts | Lazy-loads and mounts settings menu dialog |
| packages/dashboard/src/components/dialogs/settings/show-ha-integration-dialog.ts | Lazy-loads and mounts HA integration dialog |
| packages/dashboard/src/components/dialogs/settings/settings-menu-dialog.ts | New settings menu dialog offering Log Level + Home Assistant |
| packages/dashboard/src/components/dialogs/settings/ha-integration-dialog.ts | New HA credentials/sync dialog |
| packages/dashboard/src/components/dialog-box/show-dialog-box.ts | Adds showInputDialog helper and params type |
| packages/dashboard/src/components/dialog-box/input-dialog-box.ts | New generic text input dialog component |
packages/ws-controller/src/server/WebSocketControllerHandler.ts
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Addresses PR feedback: HA requests had no timeout, so a hung HA endpoint could block WS command handling indefinitely. Now uses AbortController with a 30-second default timeout and surfaces a clear error message. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
packages/dashboard/src/components/dialogs/settings/ha-integration-dialog.ts
Outdated
Show resolved
Hide resolved
- Rename ha_url_set to ha_credentials_set across all packages - Use Headers object in HomeAssistantClient to prevent Authorization override - Store endpoint number on HaNodeMatch to simplify preference logic - Downgrade node label logging from info to debug, omit label value - Use stable element IDs in ha-integration-dialog instead of label queries Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
packages/ws-controller/src/server/WebSocketControllerHandler.ts
Outdated
Show resolved
Hide resolved
packages/dashboard/src/components/dialogs/settings/ha-integration-dialog.ts
Outdated
Show resolved
Hide resolved
packages/dashboard/src/components/dialogs/settings/show-settings-menu-dialog.ts
Outdated
Show resolved
Hide resolved
- Replace setTimeout with deterministic nodes_changed listener in test - Append settings/HA dialogs to document.body instead of renderRoot - Change HA status label from "Connected" to "Configured" - Use fromConfig instead of create when user sets HA credentials, so user-provided credentials take effect even under Supervisor Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
packages/dashboard/src/components/dialogs/settings/settings-menu-dialog.ts
Outdated
Show resolved
Hide resolved
- Allow settings menu dialog to close via Escape/scrim click - Validate nodeId and endpoint are strictly decimal digits before parsing to prevent partial numeric matches (e.g. "1abc" → 1) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
packages/ws-controller/src/server/WebSocketControllerHandler.ts
Outdated
Show resolved
Hide resolved
- Validate node exists before pushing label to HA - Trim whitespace from custom labels server-side, treat whitespace-only as empty (clear) - Prevent double-submission in input dialog by guarding with resolved flag and stopping Enter key propagation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
packages/ws-controller/src/server/WebSocketControllerHandler.ts
Outdated
Show resolved
Hide resolved
- Fall back to Supervisor client when stored HA credentials are cleared/invalid, keeping ha_credentials_set and actual capability in sync - Resolve input dialog promise in _handleClosed to prevent dangling awaits when dialog is closed externally Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
packages/dashboard/src/components/dialogs/settings/ha-integration-dialog.ts
Show resolved
Hide resolved
packages/ws-controller/src/server/WebSocketControllerHandler.ts
Outdated
Show resolved
Hide resolved
- Extract #applyCustomLabel helper to centralize custom_label injection - Fix log wording: "invalid" → "missing" for absent credentials - Add Clear button to HA integration dialog to allow clearing stored credentials Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
packages/dashboard/src/components/dialogs/settings/ha-integration-dialog.ts
Show resolved
Hide resolved
packages/ws-controller/src/server/WebSocketControllerHandler.ts
Outdated
Show resolved
Hide resolved
packages/ws-controller/src/server/WebSocketControllerHandler.ts
Outdated
Show resolved
Hide resolved
packages/dashboard/src/components/dialog-box/input-dialog-box.ts
Outdated
Show resolved
Hide resolved
packages/dashboard/src/components/dialogs/settings/settings-menu-dialog.ts
Outdated
Show resolved
Hide resolved
- Replace parentNode!.removeChild with this.remove() in all dialogs - Add error type guards (instanceof Error) in node-details catch blocks - Make #applyCustomLabel non-mutating (shallow clone) - Add URL validation (http/https only) in set_ha_credentials handler - Remove @cancel=${preventDefault} from ha-integration and input dialogs - Update HA status labels: "Credentials saved" / "Stored credentials cleared" - Remove stray console.log in ws-client event handler - Replace setTimeout with deterministic event listeners in tests - Downgrade HA URL log from info to debug Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
packages/ws-controller/src/server/WebSocketControllerHandler.ts
Outdated
Show resolved
Hide resolved
packages/ws-controller/src/server/WebSocketControllerHandler.ts
Outdated
Show resolved
Hide resolved
- Fix stale comment about Supervisor credential precedence - Enforce both-or-neither for HA URL/token, trim whitespace - Batch sync_ha_names: persist all labels first, then broadcast updates - Add aria-label fallback on input dialog text field for screen readers - Downgrade push-label log to debug, omit label value from message - Fix remaining "invalid" → "missing" in comment Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Flip create() to prefer stored config over Supervisor token, consistent with set_ha_credentials behavior - Use String(nodeId) instead of String(node_id) in push handler for consistent config key format - Treat empty/whitespace name_by_user as unset in HA device matching Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Apollon77
left a comment
There was a problem hiding this comment.
Sorry but we will not connect the matterjs server with HomeAssistant because the server is also planned to be used as a standalone component. As already discussed in the issue this is not the way to go!
The way to go is to have a way to store node specific meta data in the matterjs-server (maximum short term solution) or better in matter,js when we add more to the controller layer anyway.
I mark the PR now as "request changes", and sure you can gibve it anpther try but I would more love to build the real solution into matter.js because any such special solution just increases the migration efforts
|
if you really have time constrains for this please join the Matter Community sync to discuss these |
Summary
Implements custom node labels for matterjs-server (#409), allowing users to assign friendly names to nodes directly in the dashboard — addressing the difficulty of identifying multiple identical devices (e.g. a dozen "GRILLPLATS plug").
Changes
Commit 1: Custom node labels (server-side naming)
set_custom_node_labelWS command with persistent storagecustom_labelfield onMatterNode,customLabelgetter on ws-clientinput-dialog-boxcomponent for text input dialogsgetDeviceName()priority: customLabel > nodeLabel > productNameCommit 2: Server-side Home Assistant name sync
HomeAssistantClient— stateless HTTP client for HA REST APISUPERVISOR_TOKENenv varset_ha_credentials,sync_ha_names,push_node_label_to_hadeviceid_<fabric>-<node>-<endpoint>ha_url_setfield onServerInfoMessageCommit 3: Dashboard UI for HA integration
Test plan
npm run format && npm run lint && npm run build— all passCloses #409
🤖 Generated with Claude Code