diff --git a/scripts/py_matter_idl/matter_idl/generators/types.py b/scripts/py_matter_idl/matter_idl/generators/types.py
index 393c444ae46060..dd9ed047584012 100644
--- a/scripts/py_matter_idl/matter_idl/generators/types.py
+++ b/scripts/py_matter_idl/matter_idl/generators/types.py
@@ -412,3 +412,29 @@ def ParseDataType(data_type: DataType, lookup: TypeLookupContext) -> Union[Basic
"Data type %s is NOT known, but treating it as a generic IDL type." % data_type)
return result
+
+
+def IsSignedDataType(data_type: DataType) -> bool:
+ """
+ Returns if the data type is a signed type.
+ Returns if the data type is a signed data type of False if the data type can not be found.
+ """
+ lowercase_name = data_type.name.lower()
+ sized_type = __CHIP_SIZED_TYPES__.get(lowercase_name, None)
+ if sized_type is None:
+ return False
+
+ return sized_type.is_signed
+
+
+def GetDataTypeSizeInBits(data_type: DataType) -> int:
+ """
+ Returns the size in bits for a given data type or None if the data type can not be found.
+ """
+
+ lowercase_name = data_type.name.lower()
+ sized_type = __CHIP_SIZED_TYPES__.get(lowercase_name, None)
+ if sized_type is None:
+ return None
+
+ return sized_type.power_of_two_bits
diff --git a/scripts/py_matter_idl/matter_idl/matter_idl_types.py b/scripts/py_matter_idl/matter_idl/matter_idl_types.py
index 9e3b4beb53ed79..eb86e3ec4b99fc 100644
--- a/scripts/py_matter_idl/matter_idl/matter_idl_types.py
+++ b/scripts/py_matter_idl/matter_idl/matter_idl_types.py
@@ -99,8 +99,13 @@ class DataType:
name: str
# Applies for strings (char or binary)
+ min_length: Optional[int] = None
max_length: Optional[int] = None
+ # Applies for numbers
+ min_value: Optional[int] = None
+ max_value: Optional[int] = None
+
@dataclass
class Field:
diff --git a/scripts/py_matter_idl/matter_idl/test_xml_parser.py b/scripts/py_matter_idl/matter_idl/test_xml_parser.py
index 7828c4219694fd..d8c7bb0a6c5dc1 100755
--- a/scripts/py_matter_idl/matter_idl/test_xml_parser.py
+++ b/scripts/py_matter_idl/matter_idl/test_xml_parser.py
@@ -59,6 +59,9 @@ def testCluster(self):
0x1234
Test
+ SomeCharStringAttribute
+
SomeIntAttribute
@@ -93,7 +96,17 @@ def testCluster(self):
description="Test",
attributes=[
Attribute(definition=Field(
- data_type=DataType(name='INT32U'),
+ data_type=DataType(
+ name='CHAR_STRING', min_length=2, max_length=10),
+ code=10,
+ name='SomeCharStringAttribute',
+ qualities=FieldQuality.NULLABLE),
+ qualities=AttributeQuality.READABLE,
+ readacl=AccessPrivilege.VIEW, writeacl=AccessPrivilege.OPERATE),
+
+ Attribute(definition=Field(
+ data_type=DataType(
+ name='INT32U', min_value=0, max_value=2),
code=11,
name='SomeIntAttribute',
qualities=FieldQuality.NULLABLE),
@@ -101,7 +114,8 @@ def testCluster(self):
readacl=AccessPrivilege.VIEW, writeacl=AccessPrivilege.OPERATE),
Attribute(definition=Field(
- data_type=DataType(name='INT8U'),
+ data_type=DataType(
+ name='INT8U', min_value=0, max_value=10),
code=22, name='AttributeWithAccess',
qualities=FieldQuality.OPTIONAL),
qualities=AttributeQuality.READABLE | AttributeQuality.WRITABLE,
@@ -214,7 +228,10 @@ def testFabricScopedAndSensitive(self):
name='Field3',
qualities=FieldQuality.FABRIC_SENSITIVE),
Field(data_type=DataType(name='int32u',
- max_length=None),
+ min_length=None,
+ max_length=None,
+ min_value=None,
+ max_value=None),
code=10,
name='Field10')],
qualities=StructQuality.FABRIC_SCOPED)],
@@ -369,7 +386,7 @@ def testSkipsNotProcessedFields(self):
Attribute(
definition=Field(
data_type=DataType(
- name='Type'),
+ name='Type', min_value=0, max_value=9),
code=0,
name='Type',
),
diff --git a/scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py b/scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py
index 09243a627fea5e..c6f057b992f611 100644
--- a/scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py
+++ b/scripts/py_matter_idl/matter_idl/zapxml/handlers/parsing.py
@@ -12,16 +12,23 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+from matter_idl.generators.types import GetDataTypeSizeInBits, IsSignedDataType
from matter_idl.matter_idl_types import AccessPrivilege, Attribute, AttributeQuality, DataType, Field, FieldQuality
-def ParseInt(value: str) -> int:
- """Convert a string that is a known integer into an actual number.
+def ParseInt(value: str, data_type: DataType = None) -> int:
+ """
+ Convert a string that is a known integer into an actual number.
- Supports decimal or hex values prefixed with '0x'
+ Supports decimal or hex values prefixed with '0x'
"""
if value.startswith('0x'):
- return int(value[2:], 16)
+ value = int(value[2:], 16)
+ if data_type and IsSignedDataType(data_type):
+ bits = GetDataTypeSizeInBits(data_type)
+ if value & (1 << (bits - 1)):
+ value -= 1 << bits
+ return value
else:
return int(value)
@@ -60,9 +67,18 @@ def AttrsToAttribute(attrs) -> Attribute:
else:
data_type = DataType(name=attrs['type'])
+ if 'minLength' in attrs:
+ data_type.min_length = ParseInt(attrs['minLength'])
+
if 'length' in attrs:
data_type.max_length = ParseInt(attrs['length'])
+ if 'min' in attrs:
+ data_type.min_value = ParseInt(attrs['min'], data_type)
+
+ if 'max' in attrs:
+ data_type.max_value = ParseInt(attrs['max'], data_type)
+
field = Field(
data_type=data_type,
code=ParseInt(attrs['code']),