@matter-server/dashboard 1.2.7 → 1.2.8-alpha.0-20260718-c874702

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/esm/components/webrtc-stream-view.d.ts +1 -0
  2. package/dist/esm/components/webrtc-stream-view.d.ts.map +1 -1
  3. package/dist/esm/components/webrtc-stream-view.js +11 -1
  4. package/dist/esm/components/webrtc-stream-view.js.map +1 -1
  5. package/dist/esm/pages/camera-overlay.d.ts +1 -0
  6. package/dist/esm/pages/camera-overlay.d.ts.map +1 -1
  7. package/dist/esm/pages/camera-overlay.js +13 -2
  8. package/dist/esm/pages/camera-overlay.js.map +1 -1
  9. package/dist/esm/pages/components/node-details.d.ts.map +1 -1
  10. package/dist/esm/pages/components/node-details.js +9 -10
  11. package/dist/esm/pages/components/node-details.js.map +1 -1
  12. package/dist/esm/pages/network/update-connections-dialog.d.ts.map +1 -1
  13. package/dist/esm/pages/network/update-connections-dialog.js +1 -1
  14. package/dist/esm/pages/network/update-connections-dialog.js.map +1 -1
  15. package/dist/esm/util/device-icons.d.ts +2 -0
  16. package/dist/esm/util/device-icons.d.ts.map +1 -1
  17. package/dist/esm/util/device-icons.js +6 -0
  18. package/dist/esm/util/device-icons.js.map +1 -1
  19. package/dist/web/js/{attribute-write-dialog-CtEW9qD_.js → attribute-write-dialog-CB7oucjt.js} +1 -1
  20. package/dist/web/js/{command-invoke-dialog-D7KF-xwE.js → command-invoke-dialog-C9rdQjTo.js} +1 -1
  21. package/dist/web/js/{commission-node-dialog-Co9T2m1_.js → commission-node-dialog-BwkiZy8i.js} +5 -5
  22. package/dist/web/js/{commission-node-existing-Vcsia5Qz.js → commission-node-existing-BWTlMlwi.js} +1 -1
  23. package/dist/web/js/{commission-node-thread-CCb6UUm_.js → commission-node-thread-WDo3_tCy.js} +1 -1
  24. package/dist/web/js/{commission-node-wifi-7CGfcbm9.js → commission-node-wifi-Drj7Z0rY.js} +1 -1
  25. package/dist/web/js/{dialog-box-CN_Qk_4S.js → dialog-box-Dq6fTPQH.js} +1 -1
  26. package/dist/web/js/{fabric-label-dialog-Bh6yCaOl.js → fabric-label-dialog-FE4tGieS.js} +1 -1
  27. package/dist/web/js/main.js +4 -3
  28. package/dist/web/js/{matter-dashboard-app-DLe-yfrV.js → matter-dashboard-app-Ditf9BYC.js} +410 -386
  29. package/dist/web/js/{node-acl-add-dialog-IyD1EoTu.js → node-acl-add-dialog-BA3u0qYj.js} +1 -1
  30. package/dist/web/js/{node-binding-dialog-CahBxL34.js → node-binding-dialog-BV_fMc0a.js} +1 -1
  31. package/dist/web/js/{node-label-dialog-Xu8QQuQX.js → node-label-dialog-DG5CqG1e.js} +1 -1
  32. package/dist/web/js/{settings-dialog-BU2nn7IQ.js → settings-dialog-VafGbl7R.js} +1 -1
  33. package/package.json +3 -3
  34. package/src/components/webrtc-stream-view.ts +10 -1
  35. package/src/pages/camera-overlay.ts +14 -2
  36. package/src/pages/components/node-details.ts +9 -10
  37. package/src/pages/network/update-connections-dialog.ts +4 -3
  38. package/src/util/device-icons.ts +7 -0
@@ -4812,7 +4812,7 @@ MdListItem = __decorate([t$1('md-list-item')], MdListItem);
4812
4812
  * SPDX-License-Identifier: Apache-2.0
4813
4813
  */
4814
4814
  const showSettingsDialog = async section => {
4815
- await import('./settings-dialog-BU2nn7IQ.js');
4815
+ await import('./settings-dialog-VafGbl7R.js');
4816
4816
  const dialog = document.createElement("settings-dialog");
4817
4817
  if (section) dialog.scrollToSection = section;
4818
4818
  document.querySelector("matter-dashboard-app")?.renderRoot.appendChild(dialog);
@@ -23028,7 +23028,7 @@ const clusters = {
23028
23028
  * SPDX-License-Identifier: Apache-2.0
23029
23029
  */
23030
23030
  const showDialogBox = async (type, dialogParams) => {
23031
- await import('./dialog-box-CN_Qk_4S.js');
23031
+ await import('./dialog-box-Dq6fTPQH.js');
23032
23032
  return new Promise(resolve => {
23033
23033
  const dialog = document.createElement("dialog-box");
23034
23034
  dialog.params = dialogParams;
@@ -23046,7 +23046,7 @@ const showPromptDialog = dialogParams => showDialogBox("prompt", dialogParams);
23046
23046
  * SPDX-License-Identifier: Apache-2.0
23047
23047
  */
23048
23048
  const showAttributeWriteDialog = async options => {
23049
- await import('./attribute-write-dialog-CtEW9qD_.js');
23049
+ await import('./attribute-write-dialog-CB7oucjt.js');
23050
23050
  const dialog = document.createElement("attribute-write-dialog");
23051
23051
  dialog.client = options.client;
23052
23052
  dialog.nodeId = options.nodeId;
@@ -23064,7 +23064,7 @@ const showAttributeWriteDialog = async options => {
23064
23064
  * SPDX-License-Identifier: Apache-2.0
23065
23065
  */
23066
23066
  const showCommandInvokeDialog = async options => {
23067
- await import('./command-invoke-dialog-D7KF-xwE.js');
23067
+ await import('./command-invoke-dialog-C9rdQjTo.js');
23068
23068
  const dialog = document.createElement("command-invoke-dialog");
23069
23069
  dialog.client = options.client;
23070
23070
  dialog.nodeId = options.nodeId;
@@ -23240,7 +23240,7 @@ MdTextButton = __decorate([t$1('md-text-button')], MdTextButton);
23240
23240
  * SPDX-License-Identifier: Apache-2.0
23241
23241
  */
23242
23242
  const showNodeLabelDialog = async (client, node) => {
23243
- await import('./node-label-dialog-Xu8QQuQX.js');
23243
+ await import('./node-label-dialog-DG5CqG1e.js');
23244
23244
  const dialog = document.createElement("node-label-dialog");
23245
23245
  dialog.client = client;
23246
23246
  dialog.node = node;
@@ -27604,6 +27604,7 @@ function parseProvideOfferResponse(value) {
27604
27604
  let WebRtcStreamView = class extends i$4 {
27605
27605
  constructor() {
27606
27606
  super(...arguments);
27607
+ this.liveViewSupported = true;
27607
27608
  this.resolution = null;
27608
27609
  this.watermarkEnabled = false;
27609
27610
  this.osdEnabled = false;
@@ -27656,7 +27657,9 @@ let WebRtcStreamView = class extends i$4 {
27656
27657
  ></video>
27657
27658
  ${this._state === "idle" ? b`<div class="placeholder">
27658
27659
  <ha-svg-icon class="placeholder-icon" .path=${mdiVideoOutline}></ha-svg-icon>
27659
- <div class="placeholder-text">Click <b>Start</b> to begin streaming</div>
27660
+ <div class="placeholder-text">
27661
+ ${this.liveViewSupported ? b`Click <b>Start</b> to begin streaming` : "Live view not supported \u2014 use Snapshot"}
27662
+ </div>
27660
27663
  </div>` : null}
27661
27664
  ${this._state === "connecting" ? b`<div class="placeholder">
27662
27665
  <div class="spinner"></div>
@@ -27669,6 +27672,10 @@ let WebRtcStreamView = class extends i$4 {
27669
27672
  `;
27670
27673
  }
27671
27674
  async start() {
27675
+ if (!this.liveViewSupported) {
27676
+ this._fireStateChange("error", "Live view is not supported on this device");
27677
+ return;
27678
+ }
27672
27679
  if (!this.client) throw new Error("Matter client not available");
27673
27680
  if (this._state === "connecting" || this._state === "streaming") return;
27674
27681
  this._fireStateChange("connecting", null);
@@ -28359,6 +28366,9 @@ __decorateClass$q([n$5({
28359
28366
  __decorateClass$q([n$5({
28360
28367
  type: Number
28361
28368
  })], WebRtcStreamView.prototype, "endpointId", 2);
28369
+ __decorateClass$q([n$5({
28370
+ type: Boolean
28371
+ })], WebRtcStreamView.prototype, "liveViewSupported", 2);
28362
28372
  __decorateClass$q([n$5({
28363
28373
  type: Object
28364
28374
  })], WebRtcStreamView.prototype, "resolution", 2);
@@ -28866,6 +28876,377 @@ __decorateClass$p([r$3()], AvsumPtzStrip.prototype, "_mode", 2);
28866
28876
  __decorateClass$p([r$3()], AvsumPtzStrip.prototype, "_toast", 2);
28867
28877
  AvsumPtzStrip = __decorateClass$p([t$1("avsum-ptz-strip")], AvsumPtzStrip);
28868
28878
 
28879
+ /**
28880
+ * @license
28881
+ * Copyright 2025-2026 Open Home Foundation
28882
+ * SPDX-License-Identifier: Apache-2.0
28883
+ */
28884
+ function getDefaultIconColor() {
28885
+ return getCssVar("--node-color-default", "#666666");
28886
+ }
28887
+ const DeviceTypes = {
28888
+ // Utility (per Matter spec - deprioritized for icon selection)
28889
+ ROOT_NODE: 22,
28890
+ POWER_SOURCE: 17,
28891
+ OTA_REQUESTOR: 18,
28892
+ OTA_PROVIDER: 20,
28893
+ BRIDGED_NODE: 19,
28894
+ ELECTRICAL_SENSOR: 1296,
28895
+ DEVICE_ENERGY_MANAGEMENT: 1293,
28896
+ SECONDARY_NETWORK_INTERFACE: 25,
28897
+ JOINT_FABRIC_ADMINISTRATOR: 304,
28898
+ // Lighting
28899
+ ON_OFF_LIGHT: 256,
28900
+ DIMMABLE_LIGHT: 257,
28901
+ COLOR_TEMPERATURE_LIGHT: 268,
28902
+ EXTENDED_COLOR_LIGHT: 269,
28903
+ // Smart Plugs/Outlets and Other Actuators
28904
+ ON_OFF_PLUG: 266,
28905
+ DIMMABLE_PLUG: 267,
28906
+ MOUNTED_ON_OFF_CONTROL: 271,
28907
+ MOUNTED_DIMMABLE_LOAD_CONTROL: 272,
28908
+ PUMP: 771,
28909
+ WATER_VALVE: 66,
28910
+ IRRIGATION_SYSTEM: 64,
28911
+ // Switches and Controls
28912
+ ON_OFF_SWITCH: 259,
28913
+ DIMMER_SWITCH: 260,
28914
+ COLOR_DIMMER_SWITCH: 261,
28915
+ CONTROL_BRIDGE: 2112,
28916
+ PUMP_CONTROLLER: 772,
28917
+ GENERIC_SWITCH: 15,
28918
+ // Sensors
28919
+ CONTACT_SENSOR: 21,
28920
+ LIGHT_SENSOR: 262,
28921
+ OCCUPANCY_SENSOR: 263,
28922
+ TEMPERATURE_SENSOR: 770,
28923
+ PRESSURE_SENSOR: 773,
28924
+ FLOW_SENSOR: 774,
28925
+ HUMIDITY_SENSOR: 775,
28926
+ ON_OFF_SENSOR: 2128,
28927
+ SMOKE_CO_ALARM: 118,
28928
+ AIR_QUALITY_SENSOR: 44,
28929
+ WATER_FREEZE_DETECTOR: 65,
28930
+ WATER_LEAK_DETECTOR: 67,
28931
+ RAIN_SENSOR: 68,
28932
+ SOIL_SENSOR: 69,
28933
+ // Closures
28934
+ DOOR_LOCK: 10,
28935
+ DOOR_LOCK_CONTROLLER: 11,
28936
+ WINDOW_COVERING: 514,
28937
+ WINDOW_COVERING_CONTROLLER: 515,
28938
+ CLOSURE: 560,
28939
+ CLOSURE_PANEL: 561,
28940
+ CLOSURE_CONTROLLER: 574,
28941
+ // HVAC
28942
+ THERMOSTAT: 769,
28943
+ FAN: 43,
28944
+ AIR_PURIFIER: 45,
28945
+ THERMOSTAT_CONTROLLER: 778,
28946
+ HEAT_PUMP: 777,
28947
+ ROOM_AIR_CONDITIONER: 114,
28948
+ // Media
28949
+ SPEAKER: 34,
28950
+ CASTING_VIDEO_PLAYER: 35,
28951
+ CONTENT_APP: 36,
28952
+ BASIC_VIDEO_PLAYER: 40,
28953
+ CASTING_VIDEO_CLIENT: 41,
28954
+ VIDEO_REMOTE_CONTROL: 42,
28955
+ // Generic
28956
+ AGGREGATOR: 14,
28957
+ // Appliances
28958
+ REFRIGERATOR: 112,
28959
+ TEMPERATURE_CONTROLLED_CABINET: 113,
28960
+ LAUNDRY_WASHER: 115,
28961
+ ROBOTIC_VACUUM_CLEANER: 116,
28962
+ DISHWASHER: 117,
28963
+ COOK_SURFACE: 119,
28964
+ COOKTOP: 120,
28965
+ MICROWAVE_OVEN: 121,
28966
+ EXTRACTOR_HOOD: 122,
28967
+ OVEN: 123,
28968
+ LAUNDRY_DRYER: 124,
28969
+ // Energy
28970
+ EVSE: 1292,
28971
+ WATER_HEATER: 1295,
28972
+ SOLAR_POWER: 23,
28973
+ BATTERY_STORAGE: 24,
28974
+ // Network Infrastructure
28975
+ NETWORK_INFRASTRUCTURE_MANAGER: 144,
28976
+ THREAD_BORDER_ROUTER: 145,
28977
+ // Cameras
28978
+ CAMERA: 322,
28979
+ SNAPSHOT_CAMERA: 325,
28980
+ VIDEO_DOORBELL: 323,
28981
+ AUDIO_DOORBELL: 321,
28982
+ FLOODLIGHT_CAMERA: 324,
28983
+ DOORBELL: 328,
28984
+ CHIME: 326,
28985
+ CAMERA_CONTROLLER: 327,
28986
+ INTERCOM: 320
28987
+ };
28988
+ const LIVE_VIEW_DEVICE_TYPE_IDS = Object.freeze([DeviceTypes.CAMERA, DeviceTypes.VIDEO_DOORBELL, DeviceTypes.FLOODLIGHT_CAMERA]);
28989
+ const deviceTypeToIcon = {
28990
+ // Utility
28991
+ [DeviceTypes.ROOT_NODE]: mdiHome,
28992
+ [DeviceTypes.ELECTRICAL_SENSOR]: mdiMeterElectric,
28993
+ [DeviceTypes.DEVICE_ENERGY_MANAGEMENT]: mdiMeterElectric,
28994
+ // Lighting
28995
+ [DeviceTypes.ON_OFF_LIGHT]: mdiLightbulb,
28996
+ [DeviceTypes.DIMMABLE_LIGHT]: mdiLightbulb,
28997
+ [DeviceTypes.COLOR_TEMPERATURE_LIGHT]: mdiLightbulb,
28998
+ [DeviceTypes.EXTENDED_COLOR_LIGHT]: mdiLightbulb,
28999
+ // Smart Plugs/Outlets and Other Actuators
29000
+ [DeviceTypes.ON_OFF_PLUG]: mdiPowerPlug,
29001
+ [DeviceTypes.DIMMABLE_PLUG]: mdiPowerPlug,
29002
+ [DeviceTypes.MOUNTED_ON_OFF_CONTROL]: mdiPowerPlug,
29003
+ [DeviceTypes.MOUNTED_DIMMABLE_LOAD_CONTROL]: mdiPowerPlug,
29004
+ [DeviceTypes.PUMP]: mdiPump,
29005
+ [DeviceTypes.WATER_VALVE]: mdiWater,
29006
+ [DeviceTypes.IRRIGATION_SYSTEM]: mdiSprinkler,
29007
+ // Switches and Controls
29008
+ [DeviceTypes.ON_OFF_SWITCH]: mdiToggleSwitch,
29009
+ [DeviceTypes.DIMMER_SWITCH]: mdiToggleSwitch,
29010
+ [DeviceTypes.COLOR_DIMMER_SWITCH]: mdiToggleSwitch,
29011
+ [DeviceTypes.CONTROL_BRIDGE]: mdiRouter,
29012
+ [DeviceTypes.PUMP_CONTROLLER]: mdiPump,
29013
+ [DeviceTypes.GENERIC_SWITCH]: mdiToggleSwitch,
29014
+ // Sensors
29015
+ [DeviceTypes.CONTACT_SENSOR]: mdiDoorOpen,
29016
+ [DeviceTypes.LIGHT_SENSOR]: mdiBrightnessPercent,
29017
+ [DeviceTypes.OCCUPANCY_SENSOR]: mdiMotionSensor,
29018
+ [DeviceTypes.TEMPERATURE_SENSOR]: mdiThermometer,
29019
+ [DeviceTypes.PRESSURE_SENSOR]: mdiGauge,
29020
+ [DeviceTypes.FLOW_SENSOR]: mdiWater,
29021
+ [DeviceTypes.HUMIDITY_SENSOR]: mdiWaterPercent,
29022
+ [DeviceTypes.ON_OFF_SENSOR]: mdiMotionSensor,
29023
+ [DeviceTypes.SMOKE_CO_ALARM]: mdiSmokeDetector,
29024
+ [DeviceTypes.AIR_QUALITY_SENSOR]: mdiAirFilter,
29025
+ [DeviceTypes.WATER_FREEZE_DETECTOR]: mdiSnowflakeAlert,
29026
+ [DeviceTypes.WATER_LEAK_DETECTOR]: mdiWater,
29027
+ [DeviceTypes.RAIN_SENSOR]: mdiWeatherRainy,
29028
+ [DeviceTypes.SOIL_SENSOR]: mdiLeaf,
29029
+ // Closures
29030
+ [DeviceTypes.DOOR_LOCK]: mdiLock,
29031
+ [DeviceTypes.DOOR_LOCK_CONTROLLER]: mdiLock,
29032
+ [DeviceTypes.WINDOW_COVERING]: mdiBlindsHorizontal,
29033
+ [DeviceTypes.WINDOW_COVERING_CONTROLLER]: mdiBlindsHorizontal,
29034
+ [DeviceTypes.CLOSURE]: mdiDoorOpen,
29035
+ [DeviceTypes.CLOSURE_PANEL]: mdiDoorOpen,
29036
+ [DeviceTypes.CLOSURE_CONTROLLER]: mdiDoorOpen,
29037
+ // HVAC
29038
+ [DeviceTypes.THERMOSTAT]: mdiThermometer,
29039
+ [DeviceTypes.FAN]: mdiFan,
29040
+ [DeviceTypes.AIR_PURIFIER]: mdiAirPurifier,
29041
+ [DeviceTypes.THERMOSTAT_CONTROLLER]: mdiThermometer,
29042
+ [DeviceTypes.HEAT_PUMP]: mdiHeatPump,
29043
+ [DeviceTypes.ROOM_AIR_CONDITIONER]: mdiAirConditioner,
29044
+ // Media
29045
+ [DeviceTypes.SPEAKER]: mdiSpeaker,
29046
+ [DeviceTypes.CASTING_VIDEO_PLAYER]: mdiTelevision,
29047
+ [DeviceTypes.CONTENT_APP]: mdiTelevision,
29048
+ [DeviceTypes.BASIC_VIDEO_PLAYER]: mdiTelevision,
29049
+ [DeviceTypes.CASTING_VIDEO_CLIENT]: mdiCast,
29050
+ [DeviceTypes.VIDEO_REMOTE_CONTROL]: mdiRemote,
29051
+ // Generic
29052
+ [DeviceTypes.AGGREGATOR]: mdiRouter,
29053
+ // Appliances
29054
+ [DeviceTypes.REFRIGERATOR]: mdiFridge,
29055
+ [DeviceTypes.TEMPERATURE_CONTROLLED_CABINET]: mdiFridge,
29056
+ [DeviceTypes.LAUNDRY_WASHER]: mdiWashingMachine,
29057
+ [DeviceTypes.ROBOTIC_VACUUM_CLEANER]: mdiRobotVacuum,
29058
+ [DeviceTypes.DISHWASHER]: mdiDishwasher,
29059
+ [DeviceTypes.COOK_SURFACE]: mdiStove,
29060
+ [DeviceTypes.COOKTOP]: mdiStove,
29061
+ [DeviceTypes.MICROWAVE_OVEN]: mdiMicrowave,
29062
+ [DeviceTypes.EXTRACTOR_HOOD]: mdiFan,
29063
+ [DeviceTypes.OVEN]: mdiStove,
29064
+ [DeviceTypes.LAUNDRY_DRYER]: mdiTumbleDryer,
29065
+ // Energy
29066
+ [DeviceTypes.EVSE]: mdiEvStation,
29067
+ [DeviceTypes.WATER_HEATER]: mdiWaterBoiler,
29068
+ [DeviceTypes.SOLAR_POWER]: mdiSolarPower,
29069
+ [DeviceTypes.BATTERY_STORAGE]: mdiMeterElectric,
29070
+ // Network Infrastructure
29071
+ [DeviceTypes.NETWORK_INFRASTRUCTURE_MANAGER]: mdiRouter,
29072
+ [DeviceTypes.THREAD_BORDER_ROUTER]: mdiAccessPoint,
29073
+ // Cameras
29074
+ [DeviceTypes.CAMERA]: mdiCamera,
29075
+ [DeviceTypes.SNAPSHOT_CAMERA]: mdiCamera,
29076
+ [DeviceTypes.VIDEO_DOORBELL]: mdiDoorbellVideo,
29077
+ [DeviceTypes.AUDIO_DOORBELL]: mdiDoorbell,
29078
+ [DeviceTypes.FLOODLIGHT_CAMERA]: mdiCctv,
29079
+ [DeviceTypes.DOORBELL]: mdiDoorbell,
29080
+ [DeviceTypes.CHIME]: mdiBell,
29081
+ [DeviceTypes.CAMERA_CONTROLLER]: mdiCamera,
29082
+ [DeviceTypes.INTERCOM]: mdiDoorbell
29083
+ };
29084
+ const threadRoleToIcon = {
29085
+ 5: mdiRouter,
29086
+ // Router
29087
+ 6: mdiAccessPoint
29088
+ // Leader
29089
+ };
29090
+ const THREAD_ROLE_BADGES = {
29091
+ 2: {
29092
+ iconPath: mdiSleep,
29093
+ colorVar: "--node-color-thread-enddevice",
29094
+ colorFallback: "#90a4ae"
29095
+ },
29096
+ // Sleepy End Device
29097
+ 3: {
29098
+ iconPath: mdiCircleMedium,
29099
+ colorVar: "--node-color-thread-enddevice",
29100
+ colorFallback: "#90a4ae"
29101
+ },
29102
+ // End Device
29103
+ 4: {
29104
+ iconPath: mdiCircleMedium,
29105
+ colorVar: "--node-color-thread-enddevice",
29106
+ colorFallback: "#90a4ae"
29107
+ },
29108
+ // REED
29109
+ 5: {
29110
+ iconPath: mdiSwapHorizontal,
29111
+ colorVar: "--node-color-thread-router",
29112
+ colorFallback: "#1e88e5"
29113
+ },
29114
+ // Router
29115
+ 6: {
29116
+ iconPath: mdiCrown,
29117
+ colorVar: "--node-color-thread-leader",
29118
+ colorFallback: "#f9a825"
29119
+ }
29120
+ // Leader
29121
+ };
29122
+ const UTILITY_TYPES = /* @__PURE__ */new Set([DeviceTypes.ROOT_NODE, DeviceTypes.POWER_SOURCE, DeviceTypes.OTA_REQUESTOR, DeviceTypes.OTA_PROVIDER, DeviceTypes.BRIDGED_NODE, DeviceTypes.ELECTRICAL_SENSOR, DeviceTypes.DEVICE_ENERGY_MANAGEMENT, DeviceTypes.SECONDARY_NETWORK_INTERFACE, DeviceTypes.JOINT_FABRIC_ADMINISTRATOR]);
29123
+ function extractDeviceType(entry) {
29124
+ return entry?.["0"] ?? entry?.deviceType;
29125
+ }
29126
+ function selectBestDeviceType(deviceTypeList) {
29127
+ if (!deviceTypeList?.length) return void 0;
29128
+ let firstFound;
29129
+ for (const entry of deviceTypeList) {
29130
+ const deviceType = extractDeviceType(entry);
29131
+ if (deviceType === void 0) continue;
29132
+ firstFound ?? (firstFound = deviceType);
29133
+ if (deviceTypeToIcon[deviceType] && !UTILITY_TYPES.has(deviceType)) {
29134
+ return deviceType;
29135
+ }
29136
+ }
29137
+ return firstFound;
29138
+ }
29139
+ function getPrimaryDeviceType(node) {
29140
+ const endpoints = [];
29141
+ for (const key of Object.keys(node.attributes)) {
29142
+ const match = key.match(/^(\d+)\/29\/0$/);
29143
+ if (match) {
29144
+ endpoints.push(Number(match[1]));
29145
+ }
29146
+ }
29147
+ endpoints.sort((a, b) => a === 0 ? 1 : b === 0 ? -1 : a - b);
29148
+ let firstFound;
29149
+ for (const ep of endpoints) {
29150
+ const deviceTypeList = node.attributes[`${ep}/29/0`];
29151
+ const deviceType = selectBestDeviceType(deviceTypeList);
29152
+ if (deviceType === void 0) continue;
29153
+ firstFound ?? (firstFound = deviceType);
29154
+ if (deviceTypeToIcon[deviceType] && !UTILITY_TYPES.has(deviceType)) {
29155
+ return deviceType;
29156
+ }
29157
+ }
29158
+ return firstFound;
29159
+ }
29160
+ function getEndpointIcon(node, endpoint) {
29161
+ const deviceTypeList = node.attributes[`${endpoint}/29/0`];
29162
+ const deviceType = selectBestDeviceType(deviceTypeList);
29163
+ if (deviceType !== void 0 && deviceTypeToIcon[deviceType]) {
29164
+ return deviceTypeToIcon[deviceType];
29165
+ }
29166
+ return mdiChip;
29167
+ }
29168
+ function getDeviceIcon(node, threadRole) {
29169
+ if (threadRole !== void 0 && threadRoleToIcon[threadRole]) {
29170
+ const deviceType2 = getPrimaryDeviceType(node);
29171
+ if (deviceType2 === DeviceTypes.ROOT_NODE || deviceType2 === DeviceTypes.AGGREGATOR || node.is_bridge) {
29172
+ return threadRoleToIcon[threadRole];
29173
+ }
29174
+ }
29175
+ if (node.is_bridge) {
29176
+ return mdiRouter;
29177
+ }
29178
+ const deviceType = getPrimaryDeviceType(node);
29179
+ if (deviceType !== void 0 && deviceTypeToIcon[deviceType]) {
29180
+ return deviceTypeToIcon[deviceType];
29181
+ }
29182
+ return mdiChip;
29183
+ }
29184
+ function createIconDataUrl(iconPath, color, size = 48, badge) {
29185
+ const badgeMarkup = badge !== void 0 ? `<circle cx="18" cy="6" r="4" fill="${badge.color}"/>
29186
+ <path d="${badge.iconPath}" fill="white" transform="translate(14.64,2.64) scale(0.28)"/>` : "";
29187
+ const svg = `
29188
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="${size}" height="${size}">
29189
+ <circle cx="12" cy="12" r="11" fill="white" stroke="${color}" stroke-width="1"/>
29190
+ <path d="${iconPath}" fill="${color}" transform="scale(0.6) translate(8,8)"/>
29191
+ ${badgeMarkup}
29192
+ </svg>
29193
+ `.trim();
29194
+ return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
29195
+ }
29196
+ function createNodeIconDataUrl(node, threadRole, isSelected = false, isOffline = false) {
29197
+ const iconPath = getDeviceIcon(node, threadRole);
29198
+ let color;
29199
+ if (isSelected) {
29200
+ color = isOffline ? getCssVar("--node-color-selected-offline", "#b71c1c") : getCssVar("--node-color-selected", "#1976d2");
29201
+ } else if (isOffline) {
29202
+ color = getCssVar("--node-color-offline", "#d32f2f");
29203
+ } else {
29204
+ color = getDefaultIconColor();
29205
+ }
29206
+ const roleBadge = threadRole !== void 0 ? THREAD_ROLE_BADGES[threadRole] : void 0;
29207
+ const badge = roleBadge !== void 0 ? {
29208
+ iconPath: roleBadge.iconPath,
29209
+ color: getCssVar(roleBadge.colorVar, roleBadge.colorFallback)
29210
+ } : void 0;
29211
+ return createIconDataUrl(iconPath, color, 48, badge);
29212
+ }
29213
+ function createUnknownDeviceIconDataUrl(isRouter = false, isSelected = false) {
29214
+ const iconPath = isRouter ? mdiAccessPoint : mdiHelp;
29215
+ const color = isSelected ? getCssVar("--node-color-selected", "#1976d2") : getCssVar("--node-color-unknown", "#ff9800");
29216
+ return createIconDataUrl(iconPath, color);
29217
+ }
29218
+ function createBorderRouterIconDataUrl(isSelected = false, isLeader = false, isPrimaryBbr = false) {
29219
+ const glyph = isLeader ? mdiCrown : mdiRouterWireless;
29220
+ const color = isSelected ? getCssVar("--node-color-selected", "#1976d2") : isLeader ? getCssVar("--node-color-thread-leader", "#f9a825") : getCssVar("--md-sys-color-primary", "#03a9f4");
29221
+ const badge = isPrimaryBbr ? {
29222
+ iconPath: mdiStar,
29223
+ color: getCssVar("--node-color-primary-bbr", "#00897b")
29224
+ } : void 0;
29225
+ return createIconDataUrl(glyph, color, 48, badge);
29226
+ }
29227
+ function createWiFiRouterIconDataUrl(isSelected = false) {
29228
+ const color = isSelected ? getCssVar("--node-color-selected", "#1976d2") : getCssVar("--node-color-unknown", "#ff9800");
29229
+ return createIconDataUrl(mdiWifi, color);
29230
+ }
29231
+
29232
+ /**
29233
+ * @license
29234
+ * Copyright 2025-2026 Open Home Foundation
29235
+ * SPDX-License-Identifier: Apache-2.0
29236
+ */
29237
+ function getEndpointDeviceTypes(node, endpoint) {
29238
+ const rawValues = node.attributes[`${endpoint}/29/0`];
29239
+ if (!rawValues) return new Array();
29240
+ return rawValues.map(rawValue => {
29241
+ const id = rawValue["0"] ?? rawValue["deviceType"];
29242
+ return device_types[id] ?? {
29243
+ id: id ?? -1,
29244
+ label: `Unknown Device Type (${id})`,
29245
+ clusters: []
29246
+ };
29247
+ });
29248
+ }
29249
+
28869
29250
  var __defProp$l = Object.defineProperty;
28870
29251
  var __getOwnPropDesc$m = Object.getOwnPropertyDescriptor;
28871
29252
  var __decorateClass$o = (decorators, target, key, kind) => {
@@ -28909,6 +29290,12 @@ let CameraOverlay = class extends i$4 {
28909
29290
  this._selectedSnapshotResolution = null;
28910
29291
  this._streamViewRef = e$1();
28911
29292
  }
29293
+ get _liveViewSupported() {
29294
+ const node = this.client?.nodes[String(this.nodeId)];
29295
+ if (!node) return false;
29296
+ const deviceTypeIds = getEndpointDeviceTypes(node, this.endpointId).map(d => d.id);
29297
+ return LIVE_VIEW_DEVICE_TYPE_IDS.some(id => deviceTypeIds.includes(id));
29298
+ }
28912
29299
  get _snapshotSupported() {
28913
29300
  const node = this.client?.nodes[String(this.nodeId)];
28914
29301
  const accepted = node?.attributes[`${this.endpointId}/1361/65529`];
@@ -29096,7 +29483,9 @@ let CameraOverlay = class extends i$4 {
29096
29483
  };
29097
29484
  }
29098
29485
  render() {
29099
- const canStart = this._state === "idle" || this._state === "error";
29486
+ const liveViewSupported = this._liveViewSupported;
29487
+ const idleOrError = this._state === "idle" || this._state === "error";
29488
+ const canStart = liveViewSupported && idleOrError;
29100
29489
  return b`
29101
29490
  <div class="backdrop" @click=${this._closing ? void 0 : this._close}></div>
29102
29491
  <div class="frame" @click=${e => e.stopPropagation()}>
@@ -29117,6 +29506,7 @@ let CameraOverlay = class extends i$4 {
29117
29506
  ${n(this._streamViewRef)}
29118
29507
  .nodeId=${this.nodeId}
29119
29508
  .endpointId=${this.endpointId}
29509
+ .liveViewSupported=${liveViewSupported}
29120
29510
  .resolution=${this._selectedResolution}
29121
29511
  .watermarkEnabled=${this._watermarkEnabled}
29122
29512
  .osdEnabled=${this._osdEnabled}
@@ -29160,7 +29550,7 @@ let CameraOverlay = class extends i$4 {
29160
29550
  `)}
29161
29551
  </md-outlined-select>
29162
29552
  ` : A}
29163
- ${canStart && this._snapshotSupported && this._snapshotResolutions.length > 0 ? b`
29553
+ ${idleOrError && this._snapshotSupported && this._snapshotResolutions.length > 0 ? b`
29164
29554
  <md-outlined-select
29165
29555
  label="Snapshot"
29166
29556
  .value=${this._selectedSnapshotResolution ? `${this._selectedSnapshotResolution.width}x${this._selectedSnapshotResolution.height}` : ""}
@@ -29374,376 +29764,6 @@ __decorateClass$o([r$3()], CameraOverlay.prototype, "_snapshotResolutions", 2);
29374
29764
  __decorateClass$o([r$3()], CameraOverlay.prototype, "_selectedSnapshotResolution", 2);
29375
29765
  CameraOverlay = __decorateClass$o([t$1("camera-overlay")], CameraOverlay);
29376
29766
 
29377
- /**
29378
- * @license
29379
- * Copyright 2025-2026 Open Home Foundation
29380
- * SPDX-License-Identifier: Apache-2.0
29381
- */
29382
- function getDefaultIconColor() {
29383
- return getCssVar("--node-color-default", "#666666");
29384
- }
29385
- const DeviceTypes = {
29386
- // Utility (per Matter spec - deprioritized for icon selection)
29387
- ROOT_NODE: 22,
29388
- POWER_SOURCE: 17,
29389
- OTA_REQUESTOR: 18,
29390
- OTA_PROVIDER: 20,
29391
- BRIDGED_NODE: 19,
29392
- ELECTRICAL_SENSOR: 1296,
29393
- DEVICE_ENERGY_MANAGEMENT: 1293,
29394
- SECONDARY_NETWORK_INTERFACE: 25,
29395
- JOINT_FABRIC_ADMINISTRATOR: 304,
29396
- // Lighting
29397
- ON_OFF_LIGHT: 256,
29398
- DIMMABLE_LIGHT: 257,
29399
- COLOR_TEMPERATURE_LIGHT: 268,
29400
- EXTENDED_COLOR_LIGHT: 269,
29401
- // Smart Plugs/Outlets and Other Actuators
29402
- ON_OFF_PLUG: 266,
29403
- DIMMABLE_PLUG: 267,
29404
- MOUNTED_ON_OFF_CONTROL: 271,
29405
- MOUNTED_DIMMABLE_LOAD_CONTROL: 272,
29406
- PUMP: 771,
29407
- WATER_VALVE: 66,
29408
- IRRIGATION_SYSTEM: 64,
29409
- // Switches and Controls
29410
- ON_OFF_SWITCH: 259,
29411
- DIMMER_SWITCH: 260,
29412
- COLOR_DIMMER_SWITCH: 261,
29413
- CONTROL_BRIDGE: 2112,
29414
- PUMP_CONTROLLER: 772,
29415
- GENERIC_SWITCH: 15,
29416
- // Sensors
29417
- CONTACT_SENSOR: 21,
29418
- LIGHT_SENSOR: 262,
29419
- OCCUPANCY_SENSOR: 263,
29420
- TEMPERATURE_SENSOR: 770,
29421
- PRESSURE_SENSOR: 773,
29422
- FLOW_SENSOR: 774,
29423
- HUMIDITY_SENSOR: 775,
29424
- ON_OFF_SENSOR: 2128,
29425
- SMOKE_CO_ALARM: 118,
29426
- AIR_QUALITY_SENSOR: 44,
29427
- WATER_FREEZE_DETECTOR: 65,
29428
- WATER_LEAK_DETECTOR: 67,
29429
- RAIN_SENSOR: 68,
29430
- SOIL_SENSOR: 69,
29431
- // Closures
29432
- DOOR_LOCK: 10,
29433
- DOOR_LOCK_CONTROLLER: 11,
29434
- WINDOW_COVERING: 514,
29435
- WINDOW_COVERING_CONTROLLER: 515,
29436
- CLOSURE: 560,
29437
- CLOSURE_PANEL: 561,
29438
- CLOSURE_CONTROLLER: 574,
29439
- // HVAC
29440
- THERMOSTAT: 769,
29441
- FAN: 43,
29442
- AIR_PURIFIER: 45,
29443
- THERMOSTAT_CONTROLLER: 778,
29444
- HEAT_PUMP: 777,
29445
- ROOM_AIR_CONDITIONER: 114,
29446
- // Media
29447
- SPEAKER: 34,
29448
- CASTING_VIDEO_PLAYER: 35,
29449
- CONTENT_APP: 36,
29450
- BASIC_VIDEO_PLAYER: 40,
29451
- CASTING_VIDEO_CLIENT: 41,
29452
- VIDEO_REMOTE_CONTROL: 42,
29453
- // Generic
29454
- AGGREGATOR: 14,
29455
- // Appliances
29456
- REFRIGERATOR: 112,
29457
- TEMPERATURE_CONTROLLED_CABINET: 113,
29458
- LAUNDRY_WASHER: 115,
29459
- ROBOTIC_VACUUM_CLEANER: 116,
29460
- DISHWASHER: 117,
29461
- COOK_SURFACE: 119,
29462
- COOKTOP: 120,
29463
- MICROWAVE_OVEN: 121,
29464
- EXTRACTOR_HOOD: 122,
29465
- OVEN: 123,
29466
- LAUNDRY_DRYER: 124,
29467
- // Energy
29468
- EVSE: 1292,
29469
- WATER_HEATER: 1295,
29470
- SOLAR_POWER: 23,
29471
- BATTERY_STORAGE: 24,
29472
- // Network Infrastructure
29473
- NETWORK_INFRASTRUCTURE_MANAGER: 144,
29474
- THREAD_BORDER_ROUTER: 145,
29475
- // Cameras
29476
- CAMERA: 322,
29477
- SNAPSHOT_CAMERA: 325,
29478
- VIDEO_DOORBELL: 323,
29479
- AUDIO_DOORBELL: 321,
29480
- FLOODLIGHT_CAMERA: 324,
29481
- DOORBELL: 328,
29482
- CHIME: 326,
29483
- CAMERA_CONTROLLER: 327,
29484
- INTERCOM: 320
29485
- };
29486
- const deviceTypeToIcon = {
29487
- // Utility
29488
- [DeviceTypes.ROOT_NODE]: mdiHome,
29489
- [DeviceTypes.ELECTRICAL_SENSOR]: mdiMeterElectric,
29490
- [DeviceTypes.DEVICE_ENERGY_MANAGEMENT]: mdiMeterElectric,
29491
- // Lighting
29492
- [DeviceTypes.ON_OFF_LIGHT]: mdiLightbulb,
29493
- [DeviceTypes.DIMMABLE_LIGHT]: mdiLightbulb,
29494
- [DeviceTypes.COLOR_TEMPERATURE_LIGHT]: mdiLightbulb,
29495
- [DeviceTypes.EXTENDED_COLOR_LIGHT]: mdiLightbulb,
29496
- // Smart Plugs/Outlets and Other Actuators
29497
- [DeviceTypes.ON_OFF_PLUG]: mdiPowerPlug,
29498
- [DeviceTypes.DIMMABLE_PLUG]: mdiPowerPlug,
29499
- [DeviceTypes.MOUNTED_ON_OFF_CONTROL]: mdiPowerPlug,
29500
- [DeviceTypes.MOUNTED_DIMMABLE_LOAD_CONTROL]: mdiPowerPlug,
29501
- [DeviceTypes.PUMP]: mdiPump,
29502
- [DeviceTypes.WATER_VALVE]: mdiWater,
29503
- [DeviceTypes.IRRIGATION_SYSTEM]: mdiSprinkler,
29504
- // Switches and Controls
29505
- [DeviceTypes.ON_OFF_SWITCH]: mdiToggleSwitch,
29506
- [DeviceTypes.DIMMER_SWITCH]: mdiToggleSwitch,
29507
- [DeviceTypes.COLOR_DIMMER_SWITCH]: mdiToggleSwitch,
29508
- [DeviceTypes.CONTROL_BRIDGE]: mdiRouter,
29509
- [DeviceTypes.PUMP_CONTROLLER]: mdiPump,
29510
- [DeviceTypes.GENERIC_SWITCH]: mdiToggleSwitch,
29511
- // Sensors
29512
- [DeviceTypes.CONTACT_SENSOR]: mdiDoorOpen,
29513
- [DeviceTypes.LIGHT_SENSOR]: mdiBrightnessPercent,
29514
- [DeviceTypes.OCCUPANCY_SENSOR]: mdiMotionSensor,
29515
- [DeviceTypes.TEMPERATURE_SENSOR]: mdiThermometer,
29516
- [DeviceTypes.PRESSURE_SENSOR]: mdiGauge,
29517
- [DeviceTypes.FLOW_SENSOR]: mdiWater,
29518
- [DeviceTypes.HUMIDITY_SENSOR]: mdiWaterPercent,
29519
- [DeviceTypes.ON_OFF_SENSOR]: mdiMotionSensor,
29520
- [DeviceTypes.SMOKE_CO_ALARM]: mdiSmokeDetector,
29521
- [DeviceTypes.AIR_QUALITY_SENSOR]: mdiAirFilter,
29522
- [DeviceTypes.WATER_FREEZE_DETECTOR]: mdiSnowflakeAlert,
29523
- [DeviceTypes.WATER_LEAK_DETECTOR]: mdiWater,
29524
- [DeviceTypes.RAIN_SENSOR]: mdiWeatherRainy,
29525
- [DeviceTypes.SOIL_SENSOR]: mdiLeaf,
29526
- // Closures
29527
- [DeviceTypes.DOOR_LOCK]: mdiLock,
29528
- [DeviceTypes.DOOR_LOCK_CONTROLLER]: mdiLock,
29529
- [DeviceTypes.WINDOW_COVERING]: mdiBlindsHorizontal,
29530
- [DeviceTypes.WINDOW_COVERING_CONTROLLER]: mdiBlindsHorizontal,
29531
- [DeviceTypes.CLOSURE]: mdiDoorOpen,
29532
- [DeviceTypes.CLOSURE_PANEL]: mdiDoorOpen,
29533
- [DeviceTypes.CLOSURE_CONTROLLER]: mdiDoorOpen,
29534
- // HVAC
29535
- [DeviceTypes.THERMOSTAT]: mdiThermometer,
29536
- [DeviceTypes.FAN]: mdiFan,
29537
- [DeviceTypes.AIR_PURIFIER]: mdiAirPurifier,
29538
- [DeviceTypes.THERMOSTAT_CONTROLLER]: mdiThermometer,
29539
- [DeviceTypes.HEAT_PUMP]: mdiHeatPump,
29540
- [DeviceTypes.ROOM_AIR_CONDITIONER]: mdiAirConditioner,
29541
- // Media
29542
- [DeviceTypes.SPEAKER]: mdiSpeaker,
29543
- [DeviceTypes.CASTING_VIDEO_PLAYER]: mdiTelevision,
29544
- [DeviceTypes.CONTENT_APP]: mdiTelevision,
29545
- [DeviceTypes.BASIC_VIDEO_PLAYER]: mdiTelevision,
29546
- [DeviceTypes.CASTING_VIDEO_CLIENT]: mdiCast,
29547
- [DeviceTypes.VIDEO_REMOTE_CONTROL]: mdiRemote,
29548
- // Generic
29549
- [DeviceTypes.AGGREGATOR]: mdiRouter,
29550
- // Appliances
29551
- [DeviceTypes.REFRIGERATOR]: mdiFridge,
29552
- [DeviceTypes.TEMPERATURE_CONTROLLED_CABINET]: mdiFridge,
29553
- [DeviceTypes.LAUNDRY_WASHER]: mdiWashingMachine,
29554
- [DeviceTypes.ROBOTIC_VACUUM_CLEANER]: mdiRobotVacuum,
29555
- [DeviceTypes.DISHWASHER]: mdiDishwasher,
29556
- [DeviceTypes.COOK_SURFACE]: mdiStove,
29557
- [DeviceTypes.COOKTOP]: mdiStove,
29558
- [DeviceTypes.MICROWAVE_OVEN]: mdiMicrowave,
29559
- [DeviceTypes.EXTRACTOR_HOOD]: mdiFan,
29560
- [DeviceTypes.OVEN]: mdiStove,
29561
- [DeviceTypes.LAUNDRY_DRYER]: mdiTumbleDryer,
29562
- // Energy
29563
- [DeviceTypes.EVSE]: mdiEvStation,
29564
- [DeviceTypes.WATER_HEATER]: mdiWaterBoiler,
29565
- [DeviceTypes.SOLAR_POWER]: mdiSolarPower,
29566
- [DeviceTypes.BATTERY_STORAGE]: mdiMeterElectric,
29567
- // Network Infrastructure
29568
- [DeviceTypes.NETWORK_INFRASTRUCTURE_MANAGER]: mdiRouter,
29569
- [DeviceTypes.THREAD_BORDER_ROUTER]: mdiAccessPoint,
29570
- // Cameras
29571
- [DeviceTypes.CAMERA]: mdiCamera,
29572
- [DeviceTypes.SNAPSHOT_CAMERA]: mdiCamera,
29573
- [DeviceTypes.VIDEO_DOORBELL]: mdiDoorbellVideo,
29574
- [DeviceTypes.AUDIO_DOORBELL]: mdiDoorbell,
29575
- [DeviceTypes.FLOODLIGHT_CAMERA]: mdiCctv,
29576
- [DeviceTypes.DOORBELL]: mdiDoorbell,
29577
- [DeviceTypes.CHIME]: mdiBell,
29578
- [DeviceTypes.CAMERA_CONTROLLER]: mdiCamera,
29579
- [DeviceTypes.INTERCOM]: mdiDoorbell
29580
- };
29581
- const threadRoleToIcon = {
29582
- 5: mdiRouter,
29583
- // Router
29584
- 6: mdiAccessPoint
29585
- // Leader
29586
- };
29587
- const THREAD_ROLE_BADGES = {
29588
- 2: {
29589
- iconPath: mdiSleep,
29590
- colorVar: "--node-color-thread-enddevice",
29591
- colorFallback: "#90a4ae"
29592
- },
29593
- // Sleepy End Device
29594
- 3: {
29595
- iconPath: mdiCircleMedium,
29596
- colorVar: "--node-color-thread-enddevice",
29597
- colorFallback: "#90a4ae"
29598
- },
29599
- // End Device
29600
- 4: {
29601
- iconPath: mdiCircleMedium,
29602
- colorVar: "--node-color-thread-enddevice",
29603
- colorFallback: "#90a4ae"
29604
- },
29605
- // REED
29606
- 5: {
29607
- iconPath: mdiSwapHorizontal,
29608
- colorVar: "--node-color-thread-router",
29609
- colorFallback: "#1e88e5"
29610
- },
29611
- // Router
29612
- 6: {
29613
- iconPath: mdiCrown,
29614
- colorVar: "--node-color-thread-leader",
29615
- colorFallback: "#f9a825"
29616
- }
29617
- // Leader
29618
- };
29619
- const UTILITY_TYPES = /* @__PURE__ */new Set([DeviceTypes.ROOT_NODE, DeviceTypes.POWER_SOURCE, DeviceTypes.OTA_REQUESTOR, DeviceTypes.OTA_PROVIDER, DeviceTypes.BRIDGED_NODE, DeviceTypes.ELECTRICAL_SENSOR, DeviceTypes.DEVICE_ENERGY_MANAGEMENT, DeviceTypes.SECONDARY_NETWORK_INTERFACE, DeviceTypes.JOINT_FABRIC_ADMINISTRATOR]);
29620
- function extractDeviceType(entry) {
29621
- return entry?.["0"] ?? entry?.deviceType;
29622
- }
29623
- function selectBestDeviceType(deviceTypeList) {
29624
- if (!deviceTypeList?.length) return void 0;
29625
- let firstFound;
29626
- for (const entry of deviceTypeList) {
29627
- const deviceType = extractDeviceType(entry);
29628
- if (deviceType === void 0) continue;
29629
- firstFound ?? (firstFound = deviceType);
29630
- if (deviceTypeToIcon[deviceType] && !UTILITY_TYPES.has(deviceType)) {
29631
- return deviceType;
29632
- }
29633
- }
29634
- return firstFound;
29635
- }
29636
- function getPrimaryDeviceType(node) {
29637
- const endpoints = [];
29638
- for (const key of Object.keys(node.attributes)) {
29639
- const match = key.match(/^(\d+)\/29\/0$/);
29640
- if (match) {
29641
- endpoints.push(Number(match[1]));
29642
- }
29643
- }
29644
- endpoints.sort((a, b) => a === 0 ? 1 : b === 0 ? -1 : a - b);
29645
- let firstFound;
29646
- for (const ep of endpoints) {
29647
- const deviceTypeList = node.attributes[`${ep}/29/0`];
29648
- const deviceType = selectBestDeviceType(deviceTypeList);
29649
- if (deviceType === void 0) continue;
29650
- firstFound ?? (firstFound = deviceType);
29651
- if (deviceTypeToIcon[deviceType] && !UTILITY_TYPES.has(deviceType)) {
29652
- return deviceType;
29653
- }
29654
- }
29655
- return firstFound;
29656
- }
29657
- function getEndpointIcon(node, endpoint) {
29658
- const deviceTypeList = node.attributes[`${endpoint}/29/0`];
29659
- const deviceType = selectBestDeviceType(deviceTypeList);
29660
- if (deviceType !== void 0 && deviceTypeToIcon[deviceType]) {
29661
- return deviceTypeToIcon[deviceType];
29662
- }
29663
- return mdiChip;
29664
- }
29665
- function getDeviceIcon(node, threadRole) {
29666
- if (threadRole !== void 0 && threadRoleToIcon[threadRole]) {
29667
- const deviceType2 = getPrimaryDeviceType(node);
29668
- if (deviceType2 === DeviceTypes.ROOT_NODE || deviceType2 === DeviceTypes.AGGREGATOR || node.is_bridge) {
29669
- return threadRoleToIcon[threadRole];
29670
- }
29671
- }
29672
- if (node.is_bridge) {
29673
- return mdiRouter;
29674
- }
29675
- const deviceType = getPrimaryDeviceType(node);
29676
- if (deviceType !== void 0 && deviceTypeToIcon[deviceType]) {
29677
- return deviceTypeToIcon[deviceType];
29678
- }
29679
- return mdiChip;
29680
- }
29681
- function createIconDataUrl(iconPath, color, size = 48, badge) {
29682
- const badgeMarkup = badge !== void 0 ? `<circle cx="18" cy="6" r="4" fill="${badge.color}"/>
29683
- <path d="${badge.iconPath}" fill="white" transform="translate(14.64,2.64) scale(0.28)"/>` : "";
29684
- const svg = `
29685
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="${size}" height="${size}">
29686
- <circle cx="12" cy="12" r="11" fill="white" stroke="${color}" stroke-width="1"/>
29687
- <path d="${iconPath}" fill="${color}" transform="scale(0.6) translate(8,8)"/>
29688
- ${badgeMarkup}
29689
- </svg>
29690
- `.trim();
29691
- return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`;
29692
- }
29693
- function createNodeIconDataUrl(node, threadRole, isSelected = false, isOffline = false) {
29694
- const iconPath = getDeviceIcon(node, threadRole);
29695
- let color;
29696
- if (isSelected) {
29697
- color = isOffline ? getCssVar("--node-color-selected-offline", "#b71c1c") : getCssVar("--node-color-selected", "#1976d2");
29698
- } else if (isOffline) {
29699
- color = getCssVar("--node-color-offline", "#d32f2f");
29700
- } else {
29701
- color = getDefaultIconColor();
29702
- }
29703
- const roleBadge = threadRole !== void 0 ? THREAD_ROLE_BADGES[threadRole] : void 0;
29704
- const badge = roleBadge !== void 0 ? {
29705
- iconPath: roleBadge.iconPath,
29706
- color: getCssVar(roleBadge.colorVar, roleBadge.colorFallback)
29707
- } : void 0;
29708
- return createIconDataUrl(iconPath, color, 48, badge);
29709
- }
29710
- function createUnknownDeviceIconDataUrl(isRouter = false, isSelected = false) {
29711
- const iconPath = isRouter ? mdiAccessPoint : mdiHelp;
29712
- const color = isSelected ? getCssVar("--node-color-selected", "#1976d2") : getCssVar("--node-color-unknown", "#ff9800");
29713
- return createIconDataUrl(iconPath, color);
29714
- }
29715
- function createBorderRouterIconDataUrl(isSelected = false, isLeader = false, isPrimaryBbr = false) {
29716
- const glyph = isLeader ? mdiCrown : mdiRouterWireless;
29717
- const color = isSelected ? getCssVar("--node-color-selected", "#1976d2") : isLeader ? getCssVar("--node-color-thread-leader", "#f9a825") : getCssVar("--md-sys-color-primary", "#03a9f4");
29718
- const badge = isPrimaryBbr ? {
29719
- iconPath: mdiStar,
29720
- color: getCssVar("--node-color-primary-bbr", "#00897b")
29721
- } : void 0;
29722
- return createIconDataUrl(glyph, color, 48, badge);
29723
- }
29724
- function createWiFiRouterIconDataUrl(isSelected = false) {
29725
- const color = isSelected ? getCssVar("--node-color-selected", "#1976d2") : getCssVar("--node-color-unknown", "#ff9800");
29726
- return createIconDataUrl(mdiWifi, color);
29727
- }
29728
-
29729
- /**
29730
- * @license
29731
- * Copyright 2025-2026 Open Home Foundation
29732
- * SPDX-License-Identifier: Apache-2.0
29733
- */
29734
- function getEndpointDeviceTypes(node, endpoint) {
29735
- const rawValues = node.attributes[`${endpoint}/29/0`];
29736
- if (!rawValues) return new Array();
29737
- return rawValues.map(rawValue => {
29738
- const id = rawValue["0"] ?? rawValue["deviceType"];
29739
- return device_types[id] ?? {
29740
- id: id ?? -1,
29741
- label: `Unknown Device Type (${id})`,
29742
- clusters: []
29743
- };
29744
- });
29745
- }
29746
-
29747
29767
  var _staticBlock$3, _staticBlock2;
29748
29768
  /**
29749
29769
  * @license
@@ -31771,7 +31791,7 @@ var __decorateClass$n = (decorators, target, key, kind) => {
31771
31791
  if (kind && result) __defProp$k(target, key, result);
31772
31792
  return result;
31773
31793
  };
31774
- const CAMERA_DEVICE_TYPE_IDS = [DeviceTypes.CAMERA, DeviceTypes.VIDEO_DOORBELL, DeviceTypes.FLOODLIGHT_CAMERA, DeviceTypes.SNAPSHOT_CAMERA];
31794
+ const CAMERA_DEVICE_TYPE_IDS = [...LIVE_VIEW_DEVICE_TYPE_IDS, DeviceTypes.SNAPSHOT_CAMERA];
31775
31795
  const UPDATE_STATE_LABELS = {
31776
31796
  1: "Idle",
31777
31797
  2: "Querying",
@@ -31809,6 +31829,7 @@ let NodeDetails = class extends i$4 {
31809
31829
  if (!this.node) return b``;
31810
31830
  const deviceTypeIds = getEndpointDeviceTypes(this.node, this.endpoint).map(d => d.id);
31811
31831
  const isCamera = CAMERA_DEVICE_TYPE_IDS.some(id => deviceTypeIds.includes(id));
31832
+ const isLiveViewCamera = LIVE_VIEW_DEVICE_TYPE_IDS.some(id => deviceTypeIds.includes(id));
31812
31833
  const badge = icdBadge(this.node.attributes, this.node.available);
31813
31834
  return b`
31814
31835
  <md-list>
@@ -31871,8 +31892,11 @@ let NodeDetails = class extends i$4 {
31871
31892
  @click=${() => this._openCameraOverlay()}
31872
31893
  ?disabled=${!this.node.available}
31873
31894
  >
31874
- Live View
31875
- <ha-svg-icon slot="icon" .path=${mdiVideo}></ha-svg-icon>
31895
+ ${isLiveViewCamera ? "Live View" : "Snapshot"}
31896
+ <ha-svg-icon
31897
+ slot="icon"
31898
+ .path=${isLiveViewCamera ? mdiVideo : mdiCamera}
31899
+ ></ha-svg-icon>
31876
31900
  </md-outlined-button>
31877
31901
  ` : A}
31878
31902
  <md-outlined-button @click=${handleAsync(() => this._openCommissioningWindow())}
@@ -32364,7 +32388,7 @@ async function downgradeToOperate(client, nodeId, keys) {
32364
32388
  * SPDX-License-Identifier: Apache-2.0
32365
32389
  */
32366
32390
  const showNodeAclAddDialog = async node => {
32367
- await import('./node-acl-add-dialog-IyD1EoTu.js');
32391
+ await import('./node-acl-add-dialog-BA3u0qYj.js');
32368
32392
  const dialog = document.createElement("node-acl-add-dialog");
32369
32393
  dialog.node = node;
32370
32394
  document.querySelector("matter-dashboard-app")?.renderRoot.appendChild(dialog);
@@ -34661,7 +34685,7 @@ async function deleteBindingAtIndex(client, sourceNode, sourceEndpoint, index) {
34661
34685
  * SPDX-License-Identifier: Apache-2.0
34662
34686
  */
34663
34687
  const showNodeBindingDialog = async (node, endpoint) => {
34664
- await import('./node-binding-dialog-CahBxL34.js');
34688
+ await import('./node-binding-dialog-BV_fMc0a.js');
34665
34689
  const dialog = document.createElement("node-binding-dialog");
34666
34690
  dialog.node = node;
34667
34691
  dialog.endpoint = endpoint;
@@ -39048,7 +39072,7 @@ let UpdateConnectionsDialog = class extends i$4 {
39048
39072
  if (!node) return;
39049
39073
  const paths = this._getAttributePathsForNode(nodeIdStr);
39050
39074
  if (paths.length === 0) return;
39051
- await this.client.readAttribute(node.node_id, paths);
39075
+ await this.client.readAttribute(node.node_id, paths, void 0, true);
39052
39076
  });
39053
39077
  await Promise.all(updatePromises);
39054
39078
  this._closeDialog();
@@ -50867,7 +50891,7 @@ MatterNodeView = __decorateClass$3([t$1("matter-node-view")], MatterNodeView);
50867
50891
  * SPDX-License-Identifier: Apache-2.0
50868
50892
  */
50869
50893
  const showCommissionNodeDialog = async () => {
50870
- await import('./commission-node-dialog-Co9T2m1_.js');
50894
+ await import('./commission-node-dialog-BwkiZy8i.js');
50871
50895
  const dialog = document.createElement("commission-node-dialog");
50872
50896
  document.querySelector("matter-dashboard-app")?.renderRoot.appendChild(dialog);
50873
50897
  };
@@ -50878,7 +50902,7 @@ const showCommissionNodeDialog = async () => {
50878
50902
  * SPDX-License-Identifier: Apache-2.0
50879
50903
  */
50880
50904
  const showFabricLabelDialog = async (client, currentLabel, onSaved) => {
50881
- await import('./fabric-label-dialog-Bh6yCaOl.js');
50905
+ await import('./fabric-label-dialog-FE4tGieS.js');
50882
50906
  const dialog = document.createElement("fabric-label-dialog");
50883
50907
  dialog.client = client;
50884
50908
  dialog.currentLabel = currentLabel;