Repository: home-assistant/core
Pull request #140843: Add matter attributes
Author: login: jvmahon
Labels: name: cla-signed
name: new-feature
name: integration: matter
name: Quality Scale: No score
Created: 2025-03-18T01:53:41Z | Merged: 2025-05-22T10:42:06Z

<!--
  You are amazing! Thanks for contributing to our project!
  Please, DO NOT DELETE ANY TEXT from this template! (unless instructed).
-->
## Breaking change
<!--
  If your PR contains a breaking change for existing users, it is important
  to tell them what breaks, how to make it work again and why we did this.
  This piece of text is published with the release notes, so it helps if you
  write it towards our users, not us.
  Note: Remove this section if this PR is NOT a breaking change.
-->


## Proposed change
<!--
  Describe the big picture of your changes here to communicate to the
  maintainers why we should accept this pull request. If it fixes a bug
  or resolves a feature request, be sure to link to that issue in the
  additional information section.
-->

Adds entities to set or report on several additional matter attributes:

**Basic Information Cluster**
LocalConfigDisabled (added as a Select entity)

**DoorLock Cluster:**
AutoRelockTimer (added as a Number entity)
SoundVolume (added as a Select entity)
EnableOneTouchLocking (added as a Select entity)
MinPINCodeLength (added as a diagnostics sensor).
MaxPINCodeLength (added as a diagnostics sensor).

**WindowCovering**
TargetPositionLiftPercent100ths (added as a diagnostic entity, converted to the % that the shade is open to match the way in which the open/close slider presents the info.)

**OccupancySensing**
PIROccupiedToUnoccupiedDelay (added as a Number entity)


## Type of change
<!--
  What type of change does your PR introduce to Home Assistant?
  NOTE: Please, check only 1! box!
  If your PR requires multiple boxes to be checked, you'll most likely need to
  split it into multiple PRs. This makes things easier and faster to code review.
-->

- [ ] Dependency upgrade
- [ ] Bugfix (non-breaking change which fixes an issue)
- [ ] New integration (thank you!)
- [x] New feature (which adds functionality to an existing integration)
- [ ] Deprecation (breaking change to happen in the future)
- [ ] Breaking change (fix/feature causing existing functionality to break)
- [ ] Code quality improvements to existing code or addition of tests

## Additional information
<!--
  Details are important, and help maintainers processing your PR.
  Please be sure to fill out additional details, if applicable.
-->

- This PR fixes or closes issue: fixes #
- This PR is related to issue: 
- Link to documentation pull request: 
- Link to developer documentation pull request: 
- Link to frontend pull request: 

## Checklist
<!--
  Put an `x` in the boxes that apply. You can also fill these out after
  creating the PR. If you're unsure about any of them, don't hesitate to ask.
  We're here to help! This is simply a reminder of what we are going to look
  for before merging your code.
-->

- [x] The code change is tested and works locally.
- [x] Local tests pass. **Your PR cannot be merged unless tests pass**
- [x] There is no commented out code in this PR.
- [x] I have followed the [development checklist][dev-checklist]
- [ ] I have followed the [perfect PR recommendations][perfect-pr]
- [x] The code has been formatted using Ruff (`ruff format homeassistant tests`)
- [ ] Tests have been added to verify that the new code works.

If user exposed functionality or configuration variables are added/changed:

- [ ] Documentation added/updated for [www.home-assistant.io][docs-repository]

If the code communicates with devices, web services, or third-party tools:

- [ ] The [manifest file][manifest-docs] has all fields filled out correctly.  
      Updated and included derived files by running: `python3 -m script.hassfest`.
- [ ] New or updated dependencies have been added to `requirements_all.txt`.  
      Updated by running `python3 -m script.gen_requirements_all`.
- [ ] For the updated dependencies - a link to the changelog, or at minimum a diff between library versions is added to the PR description.

<!--
  This project is very active and we have a high turnover of pull requests.

  Unfortunately, the number of incoming pull requests is higher than what our
  reviewers can review and merge so there is a long backlog of pull requests
  waiting for review. You can help here!
  
  By reviewing another pull request, you will help raise the code quality of
  that pull request and the final review will be faster. This way the general
  pace of pull request reviews will go up and your wait time will go down.
  
  When picking a pull request to review, try to choose one that hasn't yet
  been reviewed.

  Thanks for helping out!
-->

To help with the load of incoming pull requests:

- [ ] I have reviewed two other [open pull requests][prs] in this repository.

[prs]: https://github.com/home-assistant/core/pulls?q=is%3Aopen+is%3Apr+-author%3A%40me+-draft%3Atrue+-label%3Awaiting-for-upstream+sort%3Acreated-desc+review%3Anone+-status%3Afailure

<!--
  Thank you for contributing <3

  Below, some useful links you could explore:
-->
[dev-checklist]: https://developers.home-assistant.io/docs/development_checklist/
[manifest-docs]: https://developers.home-assistant.io/docs/creating_integration_manifest/
[quality-scale]: https://developers.home-assistant.io/docs/integration_quality_scale_index/
[docs-repository]: https://github.com/home-assistant/home-assistant.io
[perfect-pr]: https://developers.home-assistant.io/docs/review-process/#creating-the-perfect-pr



Diff:
diff --git a/homeassistant/components/matter/number.py b/homeassistant/components/matter/number.py
index 2c7a9651c60ec..4b469fa85e47d 100644
--- a/homeassistant/components/matter/number.py
+++ b/homeassistant/components/matter/number.py
@@ -183,4 +183,34 @@ def _update_from_device(self) -> None:
         ),
         vendor_id=(4874,),
     ),
+    MatterDiscoverySchema(
+        platform=Platform.NUMBER,
+        entity_description=MatterNumberEntityDescription(
+            key="PIROccupiedToUnoccupiedDelay",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="pir_occupied_to_unoccupied_delay",
+            native_max_value=65534,
+            native_min_value=0,
+            native_unit_of_measurement=UnitOfTime.SECONDS,
+            mode=NumberMode.BOX,
+        ),
+        entity_class=MatterNumber,
+        required_attributes=(
+            clusters.OccupancySensing.Attributes.PIROccupiedToUnoccupiedDelay,
+        ),
+    ),
+    MatterDiscoverySchema(
+        platform=Platform.NUMBER,
+        entity_description=MatterNumberEntityDescription(
+            key="AutoRelockTimer",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="auto_relock_timer",
+            native_max_value=65534,
+            native_min_value=0,
+            native_unit_of_measurement=UnitOfTime.SECONDS,
+            mode=NumberMode.BOX,
+        ),
+        entity_class=MatterNumber,
+        required_attributes=(clusters.DoorLock.Attributes.AutoRelockTime,),
+    ),
 ]
diff --git a/homeassistant/components/matter/select.py b/homeassistant/components/matter/select.py
index 6e77be9370595..39e1db3bf6fe9 100644
--- a/homeassistant/components/matter/select.py
+++ b/homeassistant/components/matter/select.py
@@ -436,4 +436,27 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="DoorLockSoundVolume",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="door_lock_sound_volume",
+            options=["silent", "low", "medium", "high"],
+            measurement_to_ha={
+                0: "silent",
+                1: "low",
+                3: "medium",
+                2: "high",
+            }.get,
+            ha_to_native_value={
+                "silent": 0,
+                "low": 1,
+                "medium": 3,
+                "high": 2,
+            }.get,
+        ),
+        entity_class=MatterAttributeSelectEntity,
+        required_attributes=(clusters.DoorLock.Attributes.SoundVolume,),
+    ),
 ]
diff --git a/homeassistant/components/matter/sensor.py b/homeassistant/components/matter/sensor.py
index e0d2050c8336b..83248955279e6 100644
--- a/homeassistant/components/matter/sensor.py
+++ b/homeassistant/components/matter/sensor.py
@@ -948,6 +948,42 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported state list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SENSOR,
+        entity_description=MatterSensorEntityDescription(
+            key="MinPINCodeLength",
+            translation_key="min_pin_code_length",
+            entity_category=EntityCategory.DIAGNOSTIC,
+            device_class=None,
+        ),
+        entity_class=MatterSensor,
+        required_attributes=(clusters.DoorLock.Attributes.MinPINCodeLength,),
+    ),
+    MatterDiscoverySchema(
+        platform=Platform.SENSOR,
+        entity_description=MatterSensorEntityDescription(
+            key="MaxPINCodeLength",
+            translation_key="max_pin_code_length",
+            entity_category=EntityCategory.DIAGNOSTIC,
+            device_class=None,
+        ),
+        entity_class=MatterSensor,
+        required_attributes=(clusters.DoorLock.Attributes.MaxPINCodeLength,),
+    ),
+    MatterDiscoverySchema(
+        platform=Platform.SENSOR,
+        entity_description=MatterSensorEntityDescription(
+            key="TargetPositionLiftPercent100ths",
+            entity_category=EntityCategory.DIAGNOSTIC,
+            translation_key="window_covering_target_position",
+            measurement_to_ha=lambda x: round((10000 - x) / 100),
+            native_unit_of_measurement=PERCENTAGE,
+        ),
+        entity_class=MatterSensor,
+        required_attributes=(
+            clusters.WindowCovering.Attributes.TargetPositionLiftPercent100ths,
+        ),
+    ),
     MatterDiscoverySchema(
         platform=Platform.SENSOR,
         entity_description=MatterSensorEntityDescription(
diff --git a/homeassistant/components/matter/strings.json b/homeassistant/components/matter/strings.json
index 129c6a3ab54f2..daff011550567 100644
--- a/homeassistant/components/matter/strings.json
+++ b/homeassistant/components/matter/strings.json
@@ -176,6 +176,12 @@
       },
       "temperature_offset": {
         "name": "Temperature offset"
+      },
+      "pir_occupied_to_unoccupied_delay": {
+        "name": "Occupied to unoccupied delay"
+      },
+      "auto_relock_timer": {
+        "name": "Automatic relock timer"
       }
     },
     "light": {
@@ -235,6 +241,15 @@
       },
       "water_heater_mode": {
         "name": "Water heater mode"
+      },
+      "door_lock_sound_volume": {
+        "name": "Sound volume",
+        "state": {
+          "silent": "Silent",
+          "low": "[%key:common::state::low%]",
+          "medium": "[%key:common::state::medium%]",
+          "high": "[%key:common::state::high%]"
+        }
       }
     },
     "sensor": {
@@ -341,6 +356,15 @@
       },
       "evse_user_max_charge_current": {
         "name": "User max charge current"
+      },
+      "min_pin_code_length": {
+        "name": "Min PIN code length"
+      },
+      "max_pin_code_length": {
+        "name": "Max PIN code length"
+      },
+      "window_covering_target_position": {
+        "name": "Target opening position"
       }
     },
     "switch": {
diff --git a/tests/components/matter/snapshots/test_number.ambr b/tests/components/matter/snapshots/test_number.ambr
index eb0a12bfc4da3..3240538f0a559 100644
--- a/tests/components/matter/snapshots/test_number.ambr
+++ b/tests/components/matter/snapshots/test_number.ambr
@@ -395,6 +395,120 @@
     'state': '1.0',
   })
 # ---
+# name: test_numbers[door_lock][number.mock_door_lock_automatic_relock_timer-entry]
+  EntityRegistryEntrySnapshot({
+    'aliases': set({
+    }),
+    'area_id': None,
+    'capabilities': dict({
+      'max': 65534,
+      'min': 0,
+      'mode': <NumberMode.BOX: 'box'>,
+      'step': 1.0,
+    }),
+    'config_entry_id': <ANY>,
+    'config_subentry_id': <ANY>,
+    'device_class': None,
+    'device_id': <ANY>,
+    'disabled_by': None,
+    'domain': 'number',
+    'entity_category': <EntityCategory.CONFIG: 'config'>,
+    'entity_id': 'number.mock_door_lock_automatic_relock_timer',
+    'has_entity_name': True,
+    'hidden_by': None,
+    'icon': None,
+    'id': <ANY>,
+    'labels': set({
+    }),
+    'name': None,
+    'options': dict({
+    }),
+    'original_device_class': None,
+    'original_icon': None,
+    'original_name': 'Automatic relock timer',
+    'platform': 'matter',
+    'previous_unique_id': None,
+    'supported_features': 0,
+    'translation_key': 'auto_relock_timer',
+    'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-AutoRelockTimer-257-35',
+    'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
+  })
+# ---
+# name: test_numbers[door_lock][number.mock_door_lock_automatic_relock_timer-state]
+  StateSnapshot({
+    'attributes': ReadOnlyDict({
+      'friendly_name': 'Mock Door Lock Automatic relock timer',
+      'max': 65534,
+      'min': 0,
+      'mode': <NumberMode.BOX: 'box'>,
+      'step': 1.0,
+      'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
+    }),
+    'context': <ANY>,
+    'entity_id': 'number.mock_door_lock_automatic_relock_timer',
+    'last_changed': <ANY>,
+    'last_reported': <ANY>,
+    'last_updated': <ANY>,
+    'state': '60',
+  })
+# ---
+# name: test_numbers[door_lock_with_unbolt][number.mock_door_lock_automatic_relock_timer-entry]
+  EntityRegistryEntrySnapshot({
+    'aliases': set({
+    }),
+    'area_id': None,
+    'capabilities': dict({
+      'max': 65534,
+      'min': 0,
+      'mode': <NumberMode.BOX: 'box'>,
+      'step': 1.0,
+    }),
+    'config_entry_id': <ANY>,
+    'config_subentry_id': <ANY>,
+    'device_class': None,
+    'device_id': <ANY>,
+    'disabled_by': None,
+    'domain': 'number',
+    'entity_category': <EntityCategory.CONFIG: 'config'>,
+    'entity_id': 'number.mock_door_lock_automatic_relock_timer',
+    'has_entity_name': True,
+    'hidden_by': None,
+    'icon': None,
+    'id': <ANY>,
+    'labels': set({
+    }),
+    'name': None,
+    'options': dict({
+    }),
+    'original_device_class': None,
+    'original_icon': None,
+    'original_name': 'Automatic relock timer',
+    'platform': 'matter',
+    'previous_unique_id': None,
+    'supported_features': 0,
+    'translation_key': 'auto_relock_timer',
+    'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-AutoRelockTimer-257-35',
+    'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
+  })
+# ---
+# name: test_numbers[door_lock_with_unbolt][number.mock_door_lock_automatic_relock_timer-state]
+  StateSnapshot({
+    'attributes': ReadOnlyDict({
+      'friendly_name': 'Mock Door Lock Automatic relock timer',
+      'max': 65534,
+      'min': 0,
+      'mode': <NumberMode.BOX: 'box'>,
+      'step': 1.0,
+      'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
+    }),
+    'context': <ANY>,
+    'entity_id': 'number.mock_door_lock_automatic_relock_timer',
+    'last_changed': <ANY>,
+    'last_reported': <ANY>,
+    'last_updated': <ANY>,
+    'state': '60',
+  })
+# ---
 # name: test_numbers[eve_thermo][number.eve_thermo_temperature_offset-entry]
   EntityRegistryEntrySnapshot({
     'aliases': set({
diff --git a/tests/components/matter/snapshots/test_select.ambr b/tests/components/matter/snapshots/test_select.ambr
index d05ff71964b94..089441511258f 100644
--- a/tests/components/matter/snapshots/test_select.ambr
+++ b/tests/components/matter/snapshots/test_select.ambr
@@ -433,6 +433,66 @@
     'state': 'off',
   })
 # ---
+# name: test_selects[door_lock][select.mock_door_lock_sound_volume-entry]
+  EntityRegistryEntrySnapshot({
+    'aliases': set({
+    }),
+    'area_id': None,
+    'capabilities': dict({
+      'options': list([
+        'silent',
+        'low',
+        'medium',
+        'high',
+      ]),
+    }),
+    'config_entry_id': <ANY>,
+    'config_subentry_id': <ANY>,
+    'device_class': None,
+    'device_id': <ANY>,
+    'disabled_by': None,
+    'domain': 'select',
+    'entity_category': <EntityCategory.CONFIG: 'config'>,
+    'entity_id': 'select.mock_door_lock_sound_volume',
+    'has_entity_name': True,
+    'hidden_by': None,
+    'icon': None,
+    'id': <ANY>,
+    'labels': set({
+    }),
+    'name': None,
+    'options': dict({
+    }),
+    'original_device_class': None,
+    'original_icon': None,
+    'original_name': 'Sound volume',
+    'platform': 'matter',
+    'previous_unique_id': None,
+    'supported_features': 0,
+    'translation_key': 'door_lock_sound_volume',
+    'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-DoorLockSoundVolume-257-36',
+    'unit_of_measurement': None,
+  })
+# ---
+# name: test_selects[door_lock][select.mock_door_lock_sound_volume-state]
+  StateSnapshot({
+    'attributes': ReadOnlyDict({
+      'friendly_name': 'Mock Door Lock Sound volume',
+      'options': list([
+        'silent',
+        'low',
+        'medium',
+        'high',
+      ]),
+    }),
+    'context': <ANY>,
+    'entity_id': 'select.mock_door_lock_sound_volume',
+    'last_changed': <ANY>,
+    'last_reported': <ANY>,
+    'last_updated': <ANY>,
+    'state': 'silent',
+  })
+# ---
 # name: test_selects[door_lock_with_unbolt][select.mock_door_lock_power_on_behavior_on_startup-entry]
   EntityRegistryEntrySnapshot({
     'aliases': set({
@@ -493,6 +553,66 @@
     'state': 'off',
   })
 # ---
+# name: test_selects[door_lock_with_unbolt][select.mock_door_lock_sound_volume-entry]
+  EntityRegistryEntrySnapshot({
+    'aliases': set({
+    }),
+    'area_id': None,
+    'capabilities': dict({
+      'options': list([
+        'silent',
+        'low',
+        'medium',
+        'high',
+      ]),
+    }),
+    'config_entry_id': <ANY>,
+    'config_subentry_id': <ANY>,
+    'device_class': None,
+    'device_id': <ANY>,
+    'disabled_by': None,
+    'domain': 'select',
+    'entity_category': <EntityCategory.CONFIG: 'config'>,
+    'entity_id': 'select.mock_door_lock_sound_volume',
+    'has_entity_name': True,
+    'hidden_by': None,
+    'icon': None,
+    'id': <ANY>,
+    'labels': set({
+    }),
+    'name': None,
+    'options': dict({
+    }),
+    'original_device_class': None,
+    'original_icon': None,
+    'original_name': 'Sound volume',
+    'platform': 'matter',
+    'previous_unique_id': None,
+    'supported_features': 0,
+    'translation_key': 'door_lock_sound_volume',
+    'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-DoorLockSoundVolume-257-36',
+    'unit_of_measurement': None,
+  })
+# ---
+# name: test_selects[door_lock_with_unbolt][select.mock_door_lock_sound_volume-state]
+  StateSnapshot({
+    'attributes': ReadOnlyDict({
+      'friendly_name': 'Mock Door Lock Sound volume',
+      'options': list([
+        'silent',
+        'low',
+        'medium',
+        'high',
+      ]),
+    }),
+    'context': <ANY>,
+    'entity_id': 'select.mock_door_lock_sound_volume',
+    'last_changed': <ANY>,
+    'last_reported': <ANY>,
+    'last_updated': <ANY>,
+    'state': 'silent',
+  })
+# ---
 # name: test_selects[eve_energy_plug][select.eve_energy_plug_power_on_behavior_on_startup-entry]
   EntityRegistryEntrySnapshot({
     'aliases': set({
diff --git a/tests/components/matter/snapshots/test_sensor.ambr b/tests/components/matter/snapshots/test_sensor.ambr
index 9c44be97bc9ce..93ac99bed6f04 100644
--- a/tests/components/matter/snapshots/test_sensor.ambr
+++ b/tests/components/matter/snapshots/test_sensor.ambr
@@ -1271,6 +1271,194 @@
     'state': '180.0',
   })
 # ---
+# name: test_sensors[door_lock][sensor.mock_door_lock_max_pin_code_length-entry]
+  EntityRegistryEntrySnapshot({
+    'aliases': set({
+    }),
+    'area_id': None,
+    'capabilities': None,
+    'config_entry_id': <ANY>,
+    'config_subentry_id': <ANY>,
+    'device_class': None,
+    'device_id': <ANY>,
+    'disabled_by': None,
+    'domain': 'sensor',
+    'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
+    'entity_id': 'sensor.mock_door_lock_max_pin_code_length',
+    'has_entity_name': True,
+    'hidden_by': None,
+    'icon': None,
+    'id': <ANY>,
+    'labels': set({
+    }),
+    'name': None,
+    'options': dict({
+    }),
+    'original_device_class': None,
+    'original_icon': None,
+    'original_name': 'Max PIN code length',
+    'platform': 'matter',
+    'previous_unique_id': None,
+    'supported_features': 0,
+    'translation_key': 'max_pin_code_length',
+    'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-MaxPINCodeLength-257-23',
+    'unit_of_measurement': None,
+  })
+# ---
+# name: test_sensors[door_lock][sensor.mock_door_lock_max_pin_code_length-state]
+  StateSnapshot({
+    'attributes': ReadOnlyDict({
+      'friendly_name': 'Mock Door Lock Max PIN code length',
+    }),
+    'context': <ANY>,
+    'entity_id': 'sensor.mock_door_lock_max_pin_code_length',
+    'last_changed': <ANY>,
+    'last_reported': <ANY>,
+    'last_updated': <ANY>,
+    'state': '8',
+  })
+# ---
+# name: test_sensors[door_lock][sensor.mock_door_lock_min_pin_code_length-entry]
+  EntityRegistryEntrySnapshot({
+    'aliases': set({
+    }),
+    'area_id': None,
+    'capabilities': None,
+    'config_entry_id': <ANY>,
+    'config_subentry_id': <ANY>,
+    'device_class': None,
+    'device_id': <ANY>,
+    'disabled_by': None,
+    'domain': 'sensor',
+    'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
+    'entity_id': 'sensor.mock_door_lock_min_pin_code_length',
+    'has_entity_name': True,
+    'hidden_by': None,
+    'icon': None,
+    'id': <ANY>,
+    'labels': set({
+    }),
+    'name': None,
+    'options': dict({
+    }),
+    'original_device_class': None,
+    'original_icon': None,
+    'original_name': 'Min PIN code length',
+    'platform': 'matter',
+    'previous_unique_id': None,
+    'supported_features': 0,
+    'translation_key': 'min_pin_code_length',
+    'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-MinPINCodeLength-257-24',
+    'unit_of_measurement': None,
+  })
+# ---
+# name: test_sensors[door_lock][sensor.mock_door_lock_min_pin_code_length-state]
+  StateSnapshot({
+    'attributes': ReadOnlyDict({
+      'friendly_name': 'Mock Door Lock Min PIN code length',
+    }),
+    'context': <ANY>,
+    'entity_id': 'sensor.mock_door_lock_min_pin_code_length',
+    'last_changed': <ANY>,
+    'last_reported': <ANY>,
+    'last_updated': <ANY>,
+    'state': '6',
+  })
+# ---
+# name: test_sensors[door_lock_with_unbolt][sensor.mock_door_lock_max_pin_code_length-entry]
+  EntityRegistryEntrySnapshot({
+    'aliases': set({
+    }),
+    'area_id': None,
+    'capabilities': None,
+    'config_entry_id': <ANY>,
+    'config_subentry_id': <ANY>,
+    'device_class': None,
+    'device_id': <ANY>,
+    'disabled_by': None,
+    'domain': 'sensor',
+    'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
+    'entity_id': 'sensor.mock_door_lock_max_pin_code_length',
+    'has_entity_name': True,
+    'hidden_by': None,
+    'icon': None,
+    'id': <ANY>,
+    'labels': set({
+    }),
+    'name': None,
+    'options': dict({
+    }),
+    'original_device_class': None,
+    'original_icon': None,
+    'original_name': 'Max PIN code length',
+    'platform': 'matter',
+    'previous_unique_id': None,
+    'supported_features': 0,
+    'translation_key': 'max_pin_code_length',
+    'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-MaxPINCodeLength-257-23',
+    'unit_of_measurement': None,
+  })
+# ---
+# name: test_sensors[door_lock_with_unbolt][sensor.mock_door_lock_max_pin_code_length-state]
+  StateSnapshot({
+    'attributes': ReadOnlyDict({
+      'friendly_name': 'Mock Door Lock Max PIN code length',
+    }),
+    'context': <ANY>,
+    'entity_id': 'sensor.mock_door_lock_max_pin_code_length',
+    'last_changed': <ANY>,
+    'last_reported': <ANY>,
+    'last_updated': <ANY>,
+    'state': '8',
+  })
+# ---
+# name: test_sensors[door_lock_with_unbolt][sensor.mock_door_lock_min_pin_code_length-entry]
+  EntityRegistryEntrySnapshot({
+    'aliases': set({
+    }),
+    'area_id': None,
+    'capabilities': None,
+    'config_entry_id': <ANY>,
+    'config_subentry_id': <ANY>,
+    'device_class': None,
+    'device_id': <ANY>,
+    'disabled_by': None,
+    'domain': 'sensor',
+    'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
+    'entity_id': 'sensor.mock_door_lock_min_pin_code_length',
+    'has_entity_name': True,
+    'hidden_by': None,
+    'icon': None,
+    'id': <ANY>,
+    'labels': set({
+    }),
+    'name': None,
+    'options': dict({
+    }),
+    'original_device_class': None,
+    'original_icon': None,
+    'original_name': 'Min PIN code length',
+    'platform': 'matter',
+    'previous_unique_id': None,
+    'supported_features': 0,
+    'translation_key': 'min_pin_code_length',
+    'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-MinPINCodeLength-257-24',
+    'unit_of_measurement': None,
+  })
+# ---
+# name: test_sensors[door_lock_with_unbolt][sensor.mock_door_lock_min_pin_code_length-state]
+  StateSnapshot({
+    'attributes': ReadOnlyDict({
+      'friendly_name': 'Mock Door Lock Min PIN code length',
+    }),
+    'context': <ANY>,
+    'entity_id': 'sensor.mock_door_lock_min_pin_code_length',
+    'last_changed': <ANY>,
+    'last_reported': <ANY>,
+    'last_updated': <ANY>,
+    'state': '6',
+  })
+# ---
 # name: test_sensors[eve_contact_sensor][sensor.eve_door_battery-entry]
   EntityRegistryEntrySnapshot({
     'aliases': set({
@@ -4754,6 +4942,102 @@
     'state': 'unknown',
   })
 # ---
+# name: test_sensors[window_covering_full][sensor.mock_full_window_covering_target_opening_position-entry]
+  EntityRegistryEntrySnapshot({
+    'aliases': set({
+    }),
+    'area_id': None,
+    'capabilities': None,
+    'config_entry_id': <ANY>,
+    'config_subentry_id': <ANY>,
+    'device_class': None,
+    'device_id': <ANY>,
+    'disabled_by': None,
+    'domain': 'sensor',
+    'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
+    'entity_id': 'sensor.mock_full_window_covering_target_opening_position',
+    'has_entity_name': True,
+    'hidden_by': None,
+    'icon': None,
+    'id': <ANY>,
+    'labels': set({
+    }),
+    'name': None,
+    'options': dict({
+    }),
+    'original_device_class': None,
+    'original_icon': None,
+    'original_name': 'Target opening position',
+    'platform': 'matter',
+    'previous_unique_id': None,
+    'supported_features': 0,
+    'translation_key': 'window_covering_target_position',
+    'unique_id': '00000000000004D2-0000000000000032-MatterNodeDevice-1-TargetPositionLiftPercent100ths-258-11',
+    'unit_of_measurement': '%',
+  })
+# ---
+# name: test_sensors[window_covering_full][sensor.mock_full_window_covering_target_opening_position-state]
+  StateSnapshot({
+    'attributes': ReadOnlyDict({
+      'friendly_name': 'Mock Full Window Covering Target opening position',
+      'unit_of_measurement': '%',
+    }),
+    'context': <ANY>,
+    'entity_id': 'sensor.mock_full_window_covering_target_opening_position',
+    'last_changed': <ANY>,
+    'last_reported': <ANY>,
+    'last_updated': <ANY>,
+    'state': '100',
+  })
+# ---
+# name: test_sensors[window_covering_pa_lift][sensor.longan_link_wncv_da01_target_opening_position-entry]
+  EntityRegistryEntrySnapshot({
+    'aliases': set({
+    }),
+    'area_id': None,
+    'capabilities': None,
+    'config_entry_id': <ANY>,
+    'config_subentry_id': <ANY>,
+    'device_class': None,
+    'device_id': <ANY>,
+    'disabled_by': None,
+    'domain': 'sensor',
+    'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
+    'entity_id': 'sensor.longan_link_wncv_da01_target_opening_position',
+    'has_entity_name': True,
+    'hidden_by': None,
+    'icon': None,
+    'id': <ANY>,
+    'labels': set({
+    }),
+    'name': None,
+    'options': dict({
+    }),
+    'original_device_class': None,
+    'original_icon': None,
+    'original_name': 'Target opening position',
+    'platform': 'matter',
+    'previous_unique_id': None,
+    'supported_features': 0,
+    'translation_key': 'window_covering_target_position',
+    'unique_id': '00000000000004D2-0000000000000001-MatterNodeDevice-1-TargetPositionLiftPercent100ths-258-11',
+    'unit_of_measurement': '%',
+  })
+# ---
+# name: test_sensors[window_covering_pa_lift][sensor.longan_link_wncv_da01_target_opening_position-state]
+  StateSnapshot({
+    'attributes': ReadOnlyDict({
+      'friendly_name': 'Longan link WNCV DA01 Target opening position',
+      'unit_of_measurement': '%',
+    }),
+    'context': <ANY>,
+    'entity_id': 'sensor.longan_link_wncv_da01_target_opening_position',
+    'last_changed': <ANY>,
+    'last_reported': <ANY>,
+    'last_updated': <ANY>,
+    'state': '100',
+  })
+# ---
 # name: test_sensors[yandex_smart_socket][sensor.yndx_00540_current-entry]
   EntityRegistryEntrySnapshot({
     'aliases': set({


Reviews:
user: login: NoRi2909
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T07:11:15Z
user: login: jvmahon
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-18T09:09:37Z
user: login: marcelveldt
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-28T14:46:20Z
user: login: marcelveldt
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-28T14:46:43Z
user: login: marcelveldt
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-28T14:46:47Z
user: login: marcelveldt
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-28T14:47:02Z
user: login: marcelveldt
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-04-28T14:47:07Z
user: login: jvmahon
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-28T15:05:39Z
user: login: jvmahon
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-05T10:20:13Z
user: login: jvmahon
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-05T10:20:28Z
user: login: jvmahon
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-05T10:20:53Z
user: login: joostlek
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-09T17:54:29Z
user: login: NoRi2909
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-09T18:26:49Z
user: login: jvmahon
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-10T02:26:49Z
user: login: NoRi2909
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-10T06:34:20Z
user: login: jvmahon
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-10T07:47:17Z
user: login: NoRi2909
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-10T09:48:11Z
user: login: MartinHjelmare
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-05-12T14:47:27Z
user: login: jvmahon
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T16:08:54Z
user: login: MartinHjelmare
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-13T13:52:04Z
user: login: jvmahon
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-16T10:02:50Z
user: login: MartinHjelmare
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-16T11:42:57Z
user: login: joostlek
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-22T10:28:42Z
user: login: MartinHjelmare
body: Thanks!
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-22T10:41:50Z
user: login: marcelveldt
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-27T13:03:24Z
user: login: marcelveldt
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-27T13:04:19Z
user: login: MartinHjelmare
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-27T13:42:04Z
user: login: MartinHjelmare
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-27T13:42:10Z

Review comments:
diff_hunk: @@ -220,6 +226,15 @@
       },
       "laundry_washer_spin_speed": {
         "name": "Spin speed"
+      },
+      "local_config_disabled": {
+        "name": "Local Configuration"
path: homeassistant/components/matter/strings.json
user: login: NoRi2909
body: All those new strings need to be sentence-cased -> "Local configuration", "One-touch locking", "Sound volume", " Min PIN code length", "Max PIN code length", " Target open-to position"
created_at: 2025-03-18T07:11:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -220,6 +226,15 @@
       },
       "laundry_washer_spin_speed": {
         "name": "Spin speed"
+      },
+      "local_config_disabled": {
+        "name": "Local Configuration"
path: homeassistant/components/matter/strings.json
user: login: jvmahon
body: Fixed. Thanks.
created_at: 2025-03-18T09:09:37Z
author_association: CONTRIBUTOR
diff_hunk: @@ -435,4 +435,65 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="LocalConfigDisabled",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="local_config_disabled",
+            options=["Enable Local Configuration", "Disable Local Configuration"],
path: homeassistant/components/matter/select.py
user: login: marcelveldt
body: ```suggestion
            options=["enable", "disable"],
```
Use strings.json to map this to human readable name.
That said: why is this a select entity and not a switch if its just a toggle ?
created_at: 2025-04-28T14:46:20Z
author_association: MEMBER
diff_hunk: @@ -435,4 +435,65 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="LocalConfigDisabled",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="local_config_disabled",
+            options=["Enable Local Configuration", "Disable Local Configuration"],
+            measurement_to_ha={
+                False: "Enable Local Configuration",
+                True: "Disable Local Configuration",
path: homeassistant/components/matter/select.py
user: login: marcelveldt
body: same comment as above
created_at: 2025-04-28T14:46:43Z
author_association: MEMBER
diff_hunk: @@ -435,4 +435,65 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="LocalConfigDisabled",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="local_config_disabled",
+            options=["Enable Local Configuration", "Disable Local Configuration"],
+            measurement_to_ha={
+                False: "Enable Local Configuration",
+                True: "Disable Local Configuration",
+            }.get,
+            ha_to_native_value={
+                "Enable Local Configuration": False,
+                "Disable Local Configuration": True,
path: homeassistant/components/matter/select.py
user: login: marcelveldt
body: same comment as above
created_at: 2025-04-28T14:46:47Z
author_association: MEMBER
diff_hunk: @@ -435,4 +435,65 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="LocalConfigDisabled",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="local_config_disabled",
+            options=["Enable Local Configuration", "Disable Local Configuration"],
+            measurement_to_ha={
+                False: "Enable Local Configuration",
+                True: "Disable Local Configuration",
+            }.get,
+            ha_to_native_value={
+                "Enable Local Configuration": False,
+                "Disable Local Configuration": True,
+            }.get,
+        ),
+        entity_class=MatterAttributeSelectEntity,
+        required_attributes=(clusters.BasicInformation.Attributes.LocalConfigDisabled,),
+    ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="EnableOneTouchLocking",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="enable_one_touch_locking",
+            options=["Enabled", "Disabled"],
path: homeassistant/components/matter/select.py
user: login: marcelveldt
body: same comment as above
created_at: 2025-04-28T14:47:02Z
author_association: MEMBER
diff_hunk: @@ -435,4 +435,65 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="LocalConfigDisabled",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="local_config_disabled",
+            options=["Enable Local Configuration", "Disable Local Configuration"],
+            measurement_to_ha={
+                False: "Enable Local Configuration",
+                True: "Disable Local Configuration",
+            }.get,
+            ha_to_native_value={
+                "Enable Local Configuration": False,
+                "Disable Local Configuration": True,
+            }.get,
+        ),
+        entity_class=MatterAttributeSelectEntity,
+        required_attributes=(clusters.BasicInformation.Attributes.LocalConfigDisabled,),
+    ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="EnableOneTouchLocking",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="enable_one_touch_locking",
+            options=["Enabled", "Disabled"],
+            measurement_to_ha={
+                False: "Disabled",
+                True: "Enabled",
+            }.get,
+            ha_to_native_value={
+                "Disabled": False,
+                "Enabled": True,
+            }.get,
+        ),
+        entity_class=MatterAttributeSelectEntity,
+        required_attributes=(clusters.DoorLock.Attributes.EnableOneTouchLocking,),
+    ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="DoorLockSoundVolume",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="door_lock_sound_volume",
+            options=["Silent", "Low", "Medium", "High"],
path: homeassistant/components/matter/select.py
user: login: marcelveldt
body: same comment as above
created_at: 2025-04-28T14:47:07Z
author_association: MEMBER
diff_hunk: @@ -435,4 +435,65 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="LocalConfigDisabled",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="local_config_disabled",
+            options=["Enable Local Configuration", "Disable Local Configuration"],
path: homeassistant/components/matter/select.py
user: login: jvmahon
body: Agree that making this (and similar items mentioned below) in a switch entity is a better approach.
created_at: 2025-04-28T15:05:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -435,4 +435,65 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="LocalConfigDisabled",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="local_config_disabled",
+            options=["Enable Local Configuration", "Disable Local Configuration"],
+            measurement_to_ha={
+                False: "Enable Local Configuration",
+                True: "Disable Local Configuration",
+            }.get,
+            ha_to_native_value={
+                "Enable Local Configuration": False,
+                "Disable Local Configuration": True,
path: homeassistant/components/matter/select.py
user: login: jvmahon
body: Removed these lines. Will add back in a separate PR converting these to switch entities.
created_at: 2025-05-05T10:20:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -435,4 +435,65 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="LocalConfigDisabled",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="local_config_disabled",
+            options=["Enable Local Configuration", "Disable Local Configuration"],
+            measurement_to_ha={
+                False: "Enable Local Configuration",
+                True: "Disable Local Configuration",
+            }.get,
+            ha_to_native_value={
+                "Enable Local Configuration": False,
+                "Disable Local Configuration": True,
+            }.get,
+        ),
+        entity_class=MatterAttributeSelectEntity,
+        required_attributes=(clusters.BasicInformation.Attributes.LocalConfigDisabled,),
+    ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="EnableOneTouchLocking",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="enable_one_touch_locking",
+            options=["Enabled", "Disabled"],
path: homeassistant/components/matter/select.py
user: login: jvmahon
body: Removed these lines. Will add back in a separate PR converting these to switch entities.
created_at: 2025-05-05T10:20:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -435,4 +435,65 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="LocalConfigDisabled",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="local_config_disabled",
+            options=["Enable Local Configuration", "Disable Local Configuration"],
+            measurement_to_ha={
+                False: "Enable Local Configuration",
+                True: "Disable Local Configuration",
path: homeassistant/components/matter/select.py
user: login: jvmahon
body: Removed these lines. Will add back in a separate PR converting these to switch entities.
created_at: 2025-05-05T10:20:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -341,6 +356,15 @@
       },
       "evse_user_max_charge_current": {
         "name": "User max charge current"
+      },
+      "min_pin_code_length": {
+        "name": "Min PIN code length"
+      },
+      "max_pin_code_length": {
+        "name": "Max PIN code length"
+      },
+      "window_covering_target_position": {
+        "name": "Target open-to position"
path: homeassistant/components/matter/strings.json
user: login: NoRi2909
body: I have a problem with "open-to", that word combination is nowhere to be found and confuses the machine translators, too.

Can we reword this in some way so it gets a definite meaning and translation?
created_at: 2025-05-09T18:26:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -341,6 +356,15 @@
       },
       "evse_user_max_charge_current": {
         "name": "User max charge current"
+      },
+      "min_pin_code_length": {
+        "name": "Min PIN code length"
+      },
+      "max_pin_code_length": {
+        "name": "Max PIN code length"
+      },
+      "window_covering_target_position": {
+        "name": "Target open-to position"
path: homeassistant/components/matter/strings.json
user: login: jvmahon
body: I changed it to "Target open position" which should resolve this concern.
created_at: 2025-05-10T02:26:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -341,6 +356,15 @@
       },
       "evse_user_max_charge_current": {
         "name": "User max charge current"
+      },
+      "min_pin_code_length": {
+        "name": "Min PIN code length"
+      },
+      "max_pin_code_length": {
+        "name": "Max PIN code length"
+      },
+      "window_covering_target_position": {
+        "name": "Target open-to position"
path: homeassistant/components/matter/strings.json
user: login: NoRi2909
body: Hmm, isn't this the "Target _opening_ position" or better "_Opening_ target position" in percent?

The definition in the Matter specs reads:
"Indicates the position where the window covering lift will go or is moving to as a percentage"

This can be any position, not just one that we would call "open" (as the opposite of "closed").

created_at: 2025-05-10T06:34:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -341,6 +356,15 @@
       },
       "evse_user_max_charge_current": {
         "name": "User max charge current"
+      },
+      "min_pin_code_length": {
+        "name": "Min PIN code length"
+      },
+      "max_pin_code_length": {
+        "name": "Max PIN code length"
+      },
+      "window_covering_target_position": {
+        "name": "Target open-to position"
path: homeassistant/components/matter/strings.json
user: login: jvmahon
body: OK, changed to "opening"
created_at: 2025-05-10T07:47:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -436,4 +436,27 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="DoorLockSoundVolume",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="door_lock_sound_volume",
+            options=["silent", "low", "medium", "high"],
+            measurement_to_ha={
+                0: "silent",
+                1: "low",
+                3: "medium",
+                4: "high",
+            }.get,
+            ha_to_native_value={
+                "silent": 0,
+                "low": 1,
+                "medium": 3,
+                "high": 2,
path: homeassistant/components/matter/select.py
user: login: MartinHjelmare
body: This should probably correspond to line 450, right? Either change here or there.
```suggestion
                "high": 4,
```
created_at: 2025-05-12T14:43:36Z
author_association: MEMBER
diff_hunk: @@ -436,4 +436,27 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="DoorLockSoundVolume",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="door_lock_sound_volume",
+            options=["silent", "low", "medium", "high"],
+            measurement_to_ha={
+                0: "silent",
+                1: "low",
+                3: "medium",
+                4: "high",
+            }.get,
+            ha_to_native_value={
+                "silent": 0,
+                "low": 1,
+                "medium": 3,
+                "high": 2,
path: homeassistant/components/matter/select.py
user: login: jvmahon
body: Line 450 was the mistake - Matter App. Cluster section 5.2.6.23 says the "high" value is 2. Change made. Thanks for catching this.

created_at: 2025-05-12T16:08:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -436,4 +436,27 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="DoorLockSoundVolume",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="door_lock_sound_volume",
+            options=["silent", "low", "medium", "high"],
+            measurement_to_ha={
+                0: "silent",
+                1: "low",
+                3: "medium",
+                2: "high",
+            }.get,
+            ha_to_native_value={
+                "silent": 0,
+                "low": 1,
+                "medium": 3,
+                "high": 2,
+            }.get,
+        ),
+        entity_class=MatterAttributeSelectEntity,
path: homeassistant/components/matter/select.py
user: login: MartinHjelmare
body: Side note: We're missing a test for the `MatterAttributeSelectEntity` action service call to select option.

I think we should add that before adding more entities that use that class. This can be a separate PR.
created_at: 2025-05-13T13:49:45Z
author_association: MEMBER
diff_hunk: @@ -436,4 +436,27 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="DoorLockSoundVolume",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="door_lock_sound_volume",
+            options=["silent", "low", "medium", "high"],
+            measurement_to_ha={
+                0: "silent",
+                1: "low",
+                3: "medium",
+                2: "high",
+            }.get,
+            ha_to_native_value={
+                "silent": 0,
+                "low": 1,
+                "medium": 3,
+                "high": 2,
+            }.get,
+        ),
+        entity_class=MatterAttributeSelectEntity,
path: homeassistant/components/matter/select.py
user: login: jvmahon
body: Are you asking me to add this test, or was this for the HA team members to handle at some future time? I'm assuming this is for the other HA team members to do in the future (if it was for me, I don't know how to set up test).
Otherwise, I think this is this now ready to be integrated into the "main" code, but please let me know if there anything else you are asking me to do. 
thanks.

created_at: 2025-05-16T10:02:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -436,4 +436,27 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="DoorLockSoundVolume",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="door_lock_sound_volume",
+            options=["silent", "low", "medium", "high"],
+            measurement_to_ha={
+                0: "silent",
+                1: "low",
+                3: "medium",
+                2: "high",
+            }.get,
+            ha_to_native_value={
+                "silent": 0,
+                "low": 1,
+                "medium": 3,
+                "high": 2,
+            }.get,
+        ),
+        entity_class=MatterAttributeSelectEntity,
path: homeassistant/components/matter/select.py
user: login: MartinHjelmare
body: I think we should add a test, in a separate PR, before merging this PR. You don't have to do that.
created_at: 2025-05-16T11:42:57Z
author_association: MEMBER
diff_hunk: @@ -436,4 +436,27 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported rinses list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SELECT,
+        entity_description=MatterSelectEntityDescription(
+            key="DoorLockSoundVolume",
+            entity_category=EntityCategory.CONFIG,
+            translation_key="door_lock_sound_volume",
+            options=["silent", "low", "medium", "high"],
+            measurement_to_ha={
+                0: "silent",
+                1: "low",
+                3: "medium",
+                2: "high",
+            }.get,
+            ha_to_native_value={
+                "silent": 0,
+                "low": 1,
+                "medium": 3,
+                "high": 2,
+            }.get,
+        ),
+        entity_class=MatterAttributeSelectEntity,
path: homeassistant/components/matter/select.py
user: login: joostlek
body: #145440
created_at: 2025-05-22T10:28:42Z
author_association: MEMBER
diff_hunk: @@ -948,6 +948,42 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported state list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SENSOR,
+        entity_description=MatterSensorEntityDescription(
+            key="MinPINCodeLength",
+            translation_key="min_pin_code_length",
+            entity_category=EntityCategory.DIAGNOSTIC,
+            device_class=None,
+        ),
+        entity_class=MatterSensor,
+        required_attributes=(clusters.DoorLock.Attributes.MinPINCodeLength,),
+    ),
+    MatterDiscoverySchema(
+        platform=Platform.SENSOR,
+        entity_description=MatterSensorEntityDescription(
+            key="MaxPINCodeLength",
+            translation_key="max_pin_code_length",
+            entity_category=EntityCategory.DIAGNOSTIC,
+            device_class=None,
+        ),
+        entity_class=MatterSensor,
+        required_attributes=(clusters.DoorLock.Attributes.MaxPINCodeLength,),
+    ),
path: homeassistant/components/matter/sensor.py
user: login: marcelveldt
body: these should be removed as they represent static info, not sensors
created_at: 2025-05-27T13:03:23Z
author_association: MEMBER
diff_hunk: @@ -948,6 +948,42 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported state list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SENSOR,
+        entity_description=MatterSensorEntityDescription(
+            key="MinPINCodeLength",
+            translation_key="min_pin_code_length",
+            entity_category=EntityCategory.DIAGNOSTIC,
+            device_class=None,
+        ),
+        entity_class=MatterSensor,
+        required_attributes=(clusters.DoorLock.Attributes.MinPINCodeLength,),
+    ),
+    MatterDiscoverySchema(
+        platform=Platform.SENSOR,
+        entity_description=MatterSensorEntityDescription(
+            key="MaxPINCodeLength",
+            translation_key="max_pin_code_length",
+            entity_category=EntityCategory.DIAGNOSTIC,
+            device_class=None,
+        ),
+        entity_class=MatterSensor,
+        required_attributes=(clusters.DoorLock.Attributes.MaxPINCodeLength,),
+    ),
+    MatterDiscoverySchema(
+        platform=Platform.SENSOR,
+        entity_description=MatterSensorEntityDescription(
+            key="TargetPositionLiftPercent100ths",
+            entity_category=EntityCategory.DIAGNOSTIC,
+            translation_key="window_covering_target_position",
+            measurement_to_ha=lambda x: round((10000 - x) / 100),
+            native_unit_of_measurement=PERCENTAGE,
+        ),
+        entity_class=MatterSensor,
+        required_attributes=(
+            clusters.WindowCovering.Attributes.TargetPositionLiftPercent100ths,
+        ),
+    ),
path: homeassistant/components/matter/sensor.py
user: login: marcelveldt
body: This one should be disabled by default as it covers a rather advanced scenario
created_at: 2025-05-27T13:04:19Z
author_association: MEMBER
diff_hunk: @@ -948,6 +948,42 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported state list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SENSOR,
+        entity_description=MatterSensorEntityDescription(
+            key="MinPINCodeLength",
+            translation_key="min_pin_code_length",
+            entity_category=EntityCategory.DIAGNOSTIC,
+            device_class=None,
+        ),
+        entity_class=MatterSensor,
+        required_attributes=(clusters.DoorLock.Attributes.MinPINCodeLength,),
+    ),
+    MatterDiscoverySchema(
+        platform=Platform.SENSOR,
+        entity_description=MatterSensorEntityDescription(
+            key="MaxPINCodeLength",
+            translation_key="max_pin_code_length",
+            entity_category=EntityCategory.DIAGNOSTIC,
+            device_class=None,
+        ),
+        entity_class=MatterSensor,
+        required_attributes=(clusters.DoorLock.Attributes.MaxPINCodeLength,),
+    ),
path: homeassistant/components/matter/sensor.py
user: login: MartinHjelmare
body: https://github.com/home-assistant/core/pull/145711
created_at: 2025-05-27T13:42:04Z
author_association: MEMBER
diff_hunk: @@ -948,6 +948,42 @@ def _update_from_device(self) -> None:
         # don't discover this entry if the supported state list is empty
         secondary_value_is_not=[],
     ),
+    MatterDiscoverySchema(
+        platform=Platform.SENSOR,
+        entity_description=MatterSensorEntityDescription(
+            key="MinPINCodeLength",
+            translation_key="min_pin_code_length",
+            entity_category=EntityCategory.DIAGNOSTIC,
+            device_class=None,
+        ),
+        entity_class=MatterSensor,
+        required_attributes=(clusters.DoorLock.Attributes.MinPINCodeLength,),
+    ),
+    MatterDiscoverySchema(
+        platform=Platform.SENSOR,
+        entity_description=MatterSensorEntityDescription(
+            key="MaxPINCodeLength",
+            translation_key="max_pin_code_length",
+            entity_category=EntityCategory.DIAGNOSTIC,
+            device_class=None,
+        ),
+        entity_class=MatterSensor,
+        required_attributes=(clusters.DoorLock.Attributes.MaxPINCodeLength,),
+    ),
+    MatterDiscoverySchema(
+        platform=Platform.SENSOR,
+        entity_description=MatterSensorEntityDescription(
+            key="TargetPositionLiftPercent100ths",
+            entity_category=EntityCategory.DIAGNOSTIC,
+            translation_key="window_covering_target_position",
+            measurement_to_ha=lambda x: round((10000 - x) / 100),
+            native_unit_of_measurement=PERCENTAGE,
+        ),
+        entity_class=MatterSensor,
+        required_attributes=(
+            clusters.WindowCovering.Attributes.TargetPositionLiftPercent100ths,
+        ),
+    ),
path: homeassistant/components/matter/sensor.py
user: login: MartinHjelmare
body: https://github.com/home-assistant/core/pull/145713
created_at: 2025-05-27T13:42:10Z
author_association: MEMBER

PR comments:
user: login: home-assistant[bot]
created_at: 2025-03-18T01:53:48Z
body: 
Hey there @home-assistant/matter, mind taking a look at this pull request as it has been labeled with an integration (`matter`) you are listed as a [code owner](https://github.com/home-assistant/core/blob/dev/CODEOWNERS#L898) for? Thanks!

<details>
<summary>Code owner commands</summary>


Code owners of `matter` can trigger bot actions by commenting:

- `@home-assistant close` Closes the pull request.
- `@home-assistant rename Awesome new title` Renames the pull request.
- `@home-assistant reopen` Reopen the pull request.
- `@home-assistant unassign matter` Removes the current integration label and assignees on the pull request, add the integration domain after the command.
- `@home-assistant add-label needs-more-information` Add a label (needs-more-information, problem in dependency, problem in custom component) to the pull request.
- `@home-assistant remove-label needs-more-information` Remove a label (needs-more-information, problem in dependency, problem in custom component) on the pull request.

</details>


author_association: CONTRIBUTOR
user: login: frenck
created_at: 2025-04-29T19:07:25Z
body: Marking this PR as a draft, as there is a merge conflict.

Could you take a look @jvmahon?

../Frenck
author_association: MEMBER
user: login: jvmahon
created_at: 2025-05-05T10:39:19Z
body: @marcelveldt I think all the issues you flagged in this are now fixed.
I removed a number of attributes where you suggested they would be better represented as "switch" entities. I'll add those back in a separate PR.
author_association: CONTRIBUTOR
user: login: home-assistant[bot]
created_at: 2025-05-12T14:47:29Z
body: <!-- ReviewDrafterComment -->
Please take a look at the requested changes, and use the **Ready for review** button when you are done, thanks :+1:

[_Learn more about our pull request process._](https://developers.home-assistant.io/docs/review-process#prs-are-being-drafted-when-changes-are-needed)

author_association: CONTRIBUTOR
user: login: marcelveldt
created_at: 2025-05-27T13:01:35Z
body: @jvmahon sorry for the late feedback. I just noticed that this PR brings in some additional entities which do not belong in the HA state machine:

MinPINCodeLength, MaxPINCodeLength and probably also TargetPositionLiftPercent100ths (I need to double check that).
That is just static information - there is no use for it as entity at all and it will only cause "noise" towards users in the UI.

We will remove those again in a follow-up PR.
In the future there might be a usecase to knowing this info while setting up a lock code in the HA interface but that is a different discussion and needs a proper architectural discussion first. Adding static info to the state machien is simply not allowed, hence we will reverse it.

EDIT: TargetPositionLiftPercent100ths is an actual sensor but a very advanced one - we try to limit those as much as we can to not overwhelm users. We have a setting to disable such entities by default.

Thanks for understanding.
 
author_association: MEMBER